blob: 8062a460a7c759bb82318071744c1ea4d6d35b32 [file] [log] [blame]
YAMAMOTO Takashi25935722017-01-23 15:34:11 +09001# Copyright (c) 2017 Midokura SARL
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
LIU Yulong5ba88ef2017-12-22 10:50:15 +080016from neutron_lib import constants as lib_constants
17from neutron_lib.services.qos import constants as qos_consts
Chandan Kumarc125fd12017-11-15 19:41:01 +053018from tempest.common import utils
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090019from tempest.common import waiters
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090020from tempest.lib.common.utils import data_utils
Sławek Kapłońskic0caa2e2017-02-25 10:11:32 +000021from tempest.lib import decorators
Ihar Hrachyshkace9c4862018-01-18 18:26:14 +000022import testscenarios
YAMAMOTO Takashi60faf4f2017-01-25 08:03:07 +090023from testscenarios.scenarios import multiply_scenarios
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090024
LIU Yulong5ba88ef2017-12-22 10:50:15 +080025from neutron_tempest_plugin.api import base as base_api
Chandan Kumar667d3d32017-09-22 12:24:06 +053026from neutron_tempest_plugin.common import ssh
Brian Haleyba800452017-12-14 10:30:48 -050027from neutron_tempest_plugin.common import utils as common_utils
Chandan Kumar667d3d32017-09-22 12:24:06 +053028from neutron_tempest_plugin import config
29from neutron_tempest_plugin.scenario import base
30from neutron_tempest_plugin.scenario import constants
LIU Yulong5ba88ef2017-12-22 10:50:15 +080031from neutron_tempest_plugin.scenario import test_qos
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090032
33
34CONF = config.CONF
35
36
37load_tests = testscenarios.load_tests_apply_scenarios
38
39
40class FloatingIpTestCasesMixin(object):
41 credentials = ['primary', 'admin']
42
43 @classmethod
Chandan Kumarc125fd12017-11-15 19:41:01 +053044 @utils.requires_ext(extension="router", service="network")
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090045 def resource_setup(cls):
46 super(FloatingIpTestCasesMixin, cls).resource_setup()
47 cls.network = cls.create_network()
48 cls.subnet = cls.create_subnet(cls.network)
49 cls.router = cls.create_router_by_client()
50 cls.create_router_interface(cls.router['id'], cls.subnet['id'])
51 cls.keypair = cls.create_keypair()
52
rajat294495c042017-06-28 15:37:16 +053053 cls.secgroup = cls.os_primary.network_client.create_security_group(
Chandan Kumarc125fd12017-11-15 19:41:01 +053054 name=data_utils.rand_name('secgroup'))['security_group']
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090055 cls.security_groups.append(cls.secgroup)
56 cls.create_loginable_secgroup_rule(secgroup_id=cls.secgroup['id'])
57 cls.create_pingable_secgroup_rule(secgroup_id=cls.secgroup['id'])
58
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090059 if cls.same_network:
60 cls._dest_network = cls.network
61 else:
62 cls._dest_network = cls._create_dest_network()
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090063
64 @classmethod
Itzik Browna31510f2018-01-19 11:09:48 +020065 def _get_external_gateway(cls):
66 if CONF.network.public_network_id:
67 subnets = cls.os_admin.network_client.list_subnets(
68 network_id=CONF.network.public_network_id)
69
70 for subnet in subnets['subnets']:
Brian Haley33ef4602018-04-26 14:37:49 -040071 if (subnet['gateway_ip'] and
72 subnet['ip_version'] == lib_constants.IP_VERSION_4):
Itzik Browna31510f2018-01-19 11:09:48 +020073 return subnet['gateway_ip']
74
75 @classmethod
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090076 def _create_dest_network(cls):
77 network = cls.create_network()
Federico Ressi0ddc93b2018-04-09 12:01:48 +020078 subnet = cls.create_subnet(network)
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090079 cls.create_router_interface(cls.router['id'], subnet['id'])
80 return network
81
Genadi Chereshnya918dd0b2017-05-17 13:02:20 +000082 def _create_server(self, create_floating_ip=True, network=None):
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090083 if network is None:
Genadi Chereshnya918dd0b2017-05-17 13:02:20 +000084 network = self.network
85 port = self.create_port(network, security_groups=[self.secgroup['id']])
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090086 if create_floating_ip:
Genadi Chereshnya918dd0b2017-05-17 13:02:20 +000087 fip = self.create_and_associate_floatingip(port['id'])
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090088 else:
89 fip = None
Genadi Chereshnya918dd0b2017-05-17 13:02:20 +000090 server = self.create_server(
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090091 flavor_ref=CONF.compute.flavor_ref,
92 image_ref=CONF.compute.image_ref,
Genadi Chereshnya918dd0b2017-05-17 13:02:20 +000093 key_name=self.keypair['name'],
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090094 networks=[{'port': port['id']}])['server']
rajat294495c042017-06-28 15:37:16 +053095 waiters.wait_for_server_status(self.os_primary.servers_client,
YAMAMOTO Takashi25935722017-01-23 15:34:11 +090096 server['id'],
97 constants.SERVER_STATUS_ACTIVE)
98 return {'port': port, 'fip': fip, 'server': server}
99
100 def _test_east_west(self):
YAMAMOTO Takashi60faf4f2017-01-25 08:03:07 +0900101 # The proxy VM is used to control the source VM when it doesn't
102 # have a floating-ip.
103 if self.src_has_fip:
104 proxy = None
105 proxy_client = None
106 else:
107 proxy = self._create_server()
108 proxy_client = ssh.Client(proxy['fip']['floating_ip_address'],
109 CONF.validation.image_ssh_user,
110 pkey=self.keypair['private_key'])
111
YAMAMOTO Takashi25935722017-01-23 15:34:11 +0900112 # Source VM
YAMAMOTO Takashi60faf4f2017-01-25 08:03:07 +0900113 if self.src_has_fip:
114 src_server = self._create_server()
115 src_server_ip = src_server['fip']['floating_ip_address']
116 else:
117 src_server = self._create_server(create_floating_ip=False)
118 src_server_ip = src_server['port']['fixed_ips'][0]['ip_address']
119 ssh_client = ssh.Client(src_server_ip,
YAMAMOTO Takashi25935722017-01-23 15:34:11 +0900120 CONF.validation.image_ssh_user,
YAMAMOTO Takashi60faf4f2017-01-25 08:03:07 +0900121 pkey=self.keypair['private_key'],
122 proxy_client=proxy_client)
YAMAMOTO Takashi25935722017-01-23 15:34:11 +0900123
124 # Destination VM
125 if self.dest_has_fip:
Genadi Chereshnya918dd0b2017-05-17 13:02:20 +0000126 dest_server = self._create_server(network=self._dest_network)
YAMAMOTO Takashi25935722017-01-23 15:34:11 +0900127 else:
Genadi Chereshnya918dd0b2017-05-17 13:02:20 +0000128 dest_server = self._create_server(create_floating_ip=False,
129 network=self._dest_network)
YAMAMOTO Takashi25935722017-01-23 15:34:11 +0900130
131 # Check connectivity
132 self.check_remote_connectivity(ssh_client,
133 dest_server['port']['fixed_ips'][0]['ip_address'])
134 if self.dest_has_fip:
135 self.check_remote_connectivity(ssh_client,
136 dest_server['fip']['floating_ip_address'])
137
138
139class FloatingIpSameNetwork(FloatingIpTestCasesMixin,
140 base.BaseTempestTestCase):
YAMAMOTO Takashi60faf4f2017-01-25 08:03:07 +0900141 scenarios = multiply_scenarios([
142 ('SRC with FIP', dict(src_has_fip=True)),
143 ('SRC without FIP', dict(src_has_fip=False)),
144 ], [
YAMAMOTO Takashi25935722017-01-23 15:34:11 +0900145 ('DEST with FIP', dict(dest_has_fip=True)),
146 ('DEST without FIP', dict(dest_has_fip=False)),
YAMAMOTO Takashi60faf4f2017-01-25 08:03:07 +0900147 ])
YAMAMOTO Takashi25935722017-01-23 15:34:11 +0900148
149 same_network = True
150
Brian Haleyba800452017-12-14 10:30:48 -0500151 @common_utils.unstable_test("bug 1717302")
Sławek Kapłońskic0caa2e2017-02-25 10:11:32 +0000152 @decorators.idempotent_id('05c4e3b3-7319-4052-90ad-e8916436c23b')
YAMAMOTO Takashi25935722017-01-23 15:34:11 +0900153 def test_east_west(self):
154 self._test_east_west()
155
156
157class FloatingIpSeparateNetwork(FloatingIpTestCasesMixin,
158 base.BaseTempestTestCase):
YAMAMOTO Takashi60faf4f2017-01-25 08:03:07 +0900159 scenarios = multiply_scenarios([
160 ('SRC with FIP', dict(src_has_fip=True)),
161 ('SRC without FIP', dict(src_has_fip=False)),
162 ], [
YAMAMOTO Takashi25935722017-01-23 15:34:11 +0900163 ('DEST with FIP', dict(dest_has_fip=True)),
164 ('DEST without FIP', dict(dest_has_fip=False)),
YAMAMOTO Takashi60faf4f2017-01-25 08:03:07 +0900165 ])
YAMAMOTO Takashi25935722017-01-23 15:34:11 +0900166
167 same_network = False
168
Brian Haleyba800452017-12-14 10:30:48 -0500169 @common_utils.unstable_test("bug 1717302")
Sławek Kapłońskic0caa2e2017-02-25 10:11:32 +0000170 @decorators.idempotent_id('f18f0090-3289-4783-b956-a0f8ac511e8b')
YAMAMOTO Takashi25935722017-01-23 15:34:11 +0900171 def test_east_west(self):
172 self._test_east_west()
Itzik Browna31510f2018-01-19 11:09:48 +0200173
174
175class DefaultSnatToExternal(FloatingIpTestCasesMixin,
176 base.BaseTempestTestCase):
177 same_network = True
178
179 @decorators.idempotent_id('3d73ea1a-27c6-45a9-b0f8-04a283d9d764')
180 def test_snat_external_ip(self):
181 """Check connectivity to an external IP"""
182 gateway_external_ip = self._get_external_gateway()
183
184 if not gateway_external_ip:
185 raise self.skipTest("IPv4 gateway is not configured for public "
186 "network or public_network_id is not "
187 "configured")
188 proxy = self._create_server()
189 proxy_client = ssh.Client(proxy['fip']['floating_ip_address'],
190 CONF.validation.image_ssh_user,
191 pkey=self.keypair['private_key'])
192 src_server = self._create_server(create_floating_ip=False)
193 src_server_ip = src_server['port']['fixed_ips'][0]['ip_address']
194 ssh_client = ssh.Client(src_server_ip,
195 CONF.validation.image_ssh_user,
196 pkey=self.keypair['private_key'],
197 proxy_client=proxy_client)
198 self.check_remote_connectivity(ssh_client,
199 gateway_external_ip)
LIU Yulong5ba88ef2017-12-22 10:50:15 +0800200
201
202class FloatingIPQosTest(FloatingIpTestCasesMixin,
203 test_qos.QoSTest):
204
205 same_network = True
206
207 @classmethod
208 @utils.requires_ext(extension="router", service="network")
209 @utils.requires_ext(extension="qos", service="network")
YAMAMOTO Takashi9c072a02018-03-22 22:49:09 +0900210 @utils.requires_ext(extension="qos-fip", service="network")
LIU Yulong5ba88ef2017-12-22 10:50:15 +0800211 @base_api.require_qos_rule_type(qos_consts.RULE_TYPE_BANDWIDTH_LIMIT)
212 def resource_setup(cls):
213 super(FloatingIPQosTest, cls).resource_setup()
214
Sławek Kapłoński17950072018-03-23 12:59:09 +0100215 @classmethod
216 def skip_checks(cls):
217 super(FloatingIPQosTest, cls).skip_checks()
218 if utils.is_extension_enabled("dvr", "network"):
219 raise cls.skipException(
220 "Skip until bug "
221 "https://bugs.launchpad.net/neutron/+bug/1758316 "
222 "will be fixed.")
223
LIU Yulong5ba88ef2017-12-22 10:50:15 +0800224 @decorators.idempotent_id('5eb48aea-eaba-4c20-8a6f-7740070a0aa3')
225 def test_qos(self):
226 """Test floating IP is binding to a QoS policy with
227
228 ingress and egress bandwidth limit rules. And it applied correctly
229 by sending a file from the instance to the test node.
230 Then calculating the bandwidth every ~1 sec by the number of bits
231 received / elapsed time.
232 """
233
234 self._test_basic_resources()
235 policy_id = self._create_qos_policy()
236 ssh_client = self._create_ssh_client()
237 self.os_admin.network_client.create_bandwidth_limit_rule(
238 policy_id, max_kbps=constants.LIMIT_KILO_BITS_PER_SECOND,
239 max_burst_kbps=constants.LIMIT_KILO_BYTES,
240 direction=lib_constants.INGRESS_DIRECTION)
241 self.os_admin.network_client.create_bandwidth_limit_rule(
242 policy_id, max_kbps=constants.LIMIT_KILO_BITS_PER_SECOND,
243 max_burst_kbps=constants.LIMIT_KILO_BYTES,
244 direction=lib_constants.EGRESS_DIRECTION)
245
246 rules = self.os_admin.network_client.list_bandwidth_limit_rules(
247 policy_id)
248 self.assertEqual(2, len(rules['bandwidth_limit_rules']))
249
250 fip = self.os_admin.network_client.get_floatingip(
251 self.fip['id'])['floatingip']
252 self.assertEqual(self.port['id'], fip['port_id'])
253
254 self.os_admin.network_client.update_floatingip(
255 self.fip['id'],
256 qos_policy_id=policy_id)
257
258 fip = self.os_admin.network_client.get_floatingip(
259 self.fip['id'])['floatingip']
260 self.assertEqual(policy_id, fip['qos_policy_id'])
261
262 self._create_file_for_bw_tests(ssh_client)
263 common_utils.wait_until_true(lambda: self._check_bw(
264 ssh_client,
265 self.fip['floating_ip_address'],
266 port=self.NC_PORT),
267 timeout=120,
268 sleep=1)