blob: 0f3d65efa485d671efc44b10567f8b859a1a9cc3 [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,
YAMAMOTO Takashia2cc2e52018-07-31 18:54:02 +0900203 test_qos.QoSTestMixin,
204 base.BaseTempestTestCase):
LIU Yulong5ba88ef2017-12-22 10:50:15 +0800205
206 same_network = True
207
208 @classmethod
209 @utils.requires_ext(extension="router", service="network")
210 @utils.requires_ext(extension="qos", service="network")
YAMAMOTO Takashi9c072a02018-03-22 22:49:09 +0900211 @utils.requires_ext(extension="qos-fip", service="network")
LIU Yulong5ba88ef2017-12-22 10:50:15 +0800212 @base_api.require_qos_rule_type(qos_consts.RULE_TYPE_BANDWIDTH_LIMIT)
213 def resource_setup(cls):
214 super(FloatingIPQosTest, cls).resource_setup()
215
216 @decorators.idempotent_id('5eb48aea-eaba-4c20-8a6f-7740070a0aa3')
217 def test_qos(self):
218 """Test floating IP is binding to a QoS policy with
219
220 ingress and egress bandwidth limit rules. And it applied correctly
221 by sending a file from the instance to the test node.
222 Then calculating the bandwidth every ~1 sec by the number of bits
223 received / elapsed time.
224 """
225
226 self._test_basic_resources()
227 policy_id = self._create_qos_policy()
228 ssh_client = self._create_ssh_client()
229 self.os_admin.network_client.create_bandwidth_limit_rule(
230 policy_id, max_kbps=constants.LIMIT_KILO_BITS_PER_SECOND,
231 max_burst_kbps=constants.LIMIT_KILO_BYTES,
232 direction=lib_constants.INGRESS_DIRECTION)
233 self.os_admin.network_client.create_bandwidth_limit_rule(
234 policy_id, max_kbps=constants.LIMIT_KILO_BITS_PER_SECOND,
235 max_burst_kbps=constants.LIMIT_KILO_BYTES,
236 direction=lib_constants.EGRESS_DIRECTION)
237
238 rules = self.os_admin.network_client.list_bandwidth_limit_rules(
239 policy_id)
240 self.assertEqual(2, len(rules['bandwidth_limit_rules']))
241
242 fip = self.os_admin.network_client.get_floatingip(
243 self.fip['id'])['floatingip']
244 self.assertEqual(self.port['id'], fip['port_id'])
245
246 self.os_admin.network_client.update_floatingip(
247 self.fip['id'],
248 qos_policy_id=policy_id)
249
250 fip = self.os_admin.network_client.get_floatingip(
251 self.fip['id'])['floatingip']
252 self.assertEqual(policy_id, fip['qos_policy_id'])
253
254 self._create_file_for_bw_tests(ssh_client)
255 common_utils.wait_until_true(lambda: self._check_bw(
256 ssh_client,
257 self.fip['floating_ip_address'],
258 port=self.NC_PORT),
259 timeout=120,
260 sleep=1)