blob: efecd6ce7e6607bb0b87be14c2df40888d1374b4 [file] [log] [blame]
Dan Smith8ad1c472013-02-26 13:03:16 -05001# Copyright 2013 IBM Corp.
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
Rohan Kanade9ce97df2013-12-10 18:59:35 +053016import time
17
Slawek Kaplonskib3daeb42019-06-29 23:49:59 +020018from oslo_log import log
junbolibc2ae862017-07-29 15:46:48 +080019
Sean Dague1937d092013-05-17 16:36:38 -040020from tempest.api.compute import base
Matt Riedemanna8c641a2016-07-12 17:07:33 -040021from tempest.common import compute
Andrea Frittolicd368412017-08-14 21:37:56 +010022from tempest.common import utils
Ryan Tidwell1964a262016-05-04 15:13:23 -070023from tempest.common.utils import net_utils
Matt Riedemanna8c641a2016-07-12 17:07:33 -040024from tempest.common import waiters
Matthew Treinishb0a78fc2014-01-29 16:49:12 +000025from tempest import config
Doug Schveninger24675aa2019-08-16 22:28:39 -050026from tempest.lib.common.utils import data_utils
Lucas Alvares Gomes692422b2018-10-10 10:33:45 +010027from tempest.lib.common.utils.linux import remote_client
Matt Riedemannd4cb10f2018-09-26 13:03:08 -040028from tempest.lib.common.utils import test_utils
Matt Riedemann3570c1e2016-07-29 12:15:38 -040029from tempest.lib import decorators
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050030from tempest.lib import exceptions as lib_exc
Dan Smith8ad1c472013-02-26 13:03:16 -050031
Matthew Treinishb0a78fc2014-01-29 16:49:12 +000032CONF = config.CONF
33
Slawek Kaplonskib3daeb42019-06-29 23:49:59 +020034LOG = log.getLogger(__name__)
35
Dan Smith8ad1c472013-02-26 13:03:16 -050036
zhufl615e63b2018-08-01 17:23:38 +080037class AttachInterfacesTestBase(base.BaseV2ComputeTest):
Dan Smith8ad1c472013-02-26 13:03:16 -050038
39 @classmethod
Emily Hugenbruche7991d92014-12-12 16:53:36 +000040 def skip_checks(cls):
zhufl615e63b2018-08-01 17:23:38 +080041 super(AttachInterfacesTestBase, cls).skip_checks()
Matthew Treinishb0a78fc2014-01-29 16:49:12 +000042 if not CONF.service_available.neutron:
Mark McClainf2982e82013-07-06 17:48:03 -040043 raise cls.skipException("Neutron is required")
Adam Gandelman7186f7a2014-07-23 09:28:56 -040044 if not CONF.compute_feature_enabled.interface_attach:
45 raise cls.skipException("Interface attachment is not available.")
Artom Lifshitzb4775942018-09-05 16:24:01 +030046 if not CONF.validation.run_validation:
47 raise cls.skipException('Validation should be enabled to ensure '
48 'guest OS is running and capable of '
49 'processing ACPI events.')
Emily Hugenbruche7991d92014-12-12 16:53:36 +000050
51 @classmethod
52 def setup_credentials(cls):
Salvatore Orlando5a337242014-01-15 22:49:22 +000053 # This test class requires network and subnet
Artom Lifshitzb4775942018-09-05 16:24:01 +030054 cls.set_network_resources(network=True, subnet=True, router=True,
55 dhcp=True)
zhufl615e63b2018-08-01 17:23:38 +080056 super(AttachInterfacesTestBase, cls).setup_credentials()
Emily Hugenbruche7991d92014-12-12 16:53:36 +000057
58 @classmethod
59 def setup_clients(cls):
zhufl615e63b2018-08-01 17:23:38 +080060 super(AttachInterfacesTestBase, cls).setup_clients()
Jordan Pittier8160d312017-04-18 11:52:23 +020061 cls.subnets_client = cls.os_primary.subnets_client
62 cls.ports_client = cls.os_primary.ports_client
Dan Smith8ad1c472013-02-26 13:03:16 -050063
Artom Lifshitzb4775942018-09-05 16:24:01 +030064 def _wait_for_validation(self, server, validation_resources):
65 linux_client = remote_client.RemoteClient(
66 self.get_server_ip(server, validation_resources),
67 self.image_ssh_user,
68 self.image_ssh_password,
69 validation_resources['keypair']['private_key'],
70 server=server,
Ade Lee6ded0702021-09-04 15:56:34 -040071 servers_client=self.servers_client,
72 ssh_key_type=CONF.validation.ssh_key_type)
Artom Lifshitzb4775942018-09-05 16:24:01 +030073 linux_client.validate_authentication()
74
zhufl615e63b2018-08-01 17:23:38 +080075 def _create_server_get_interfaces(self):
Artom Lifshitzb4775942018-09-05 16:24:01 +030076 validation_resources = self.get_test_validation_resources(
77 self.os_primary)
78 server = self.create_test_server(
79 validatable=True,
80 validation_resources=validation_resources,
81 wait_until='ACTIVE')
Mark Goddardfa30d2f2019-09-02 14:41:02 +010082 # NOTE(mgoddard): Get detailed server to ensure addresses are present
83 # in fixed IP case.
84 server = self.servers_client.show_server(server['id'])['server']
Artom Lifshitzb4775942018-09-05 16:24:01 +030085 # NOTE(artom) self.create_test_server adds cleanups, but this is
86 # apparently not enough? Add cleanup here.
87 self.addCleanup(self.delete_server, server['id'])
88 self._wait_for_validation(server, validation_resources)
David Sedlák61a3c8e2019-10-30 15:38:21 +010089 try:
90 fip = set([validation_resources['floating_ip']['ip']])
91 except KeyError:
92 fip = ()
zhufl615e63b2018-08-01 17:23:38 +080093 ifs = (self.interfaces_client.list_interfaces(server['id'])
94 ['interfaceAttachments'])
95 body = waiters.wait_for_interface_status(
96 self.interfaces_client, server['id'], ifs[0]['port_id'], 'ACTIVE')
97 ifs[0]['port_state'] = body['port_state']
David Sedlák61a3c8e2019-10-30 15:38:21 +010098 return server, ifs, fip
zhufl615e63b2018-08-01 17:23:38 +080099
100
101class AttachInterfacesTestJSON(AttachInterfacesTestBase):
zhufl735e1692020-08-13 16:46:50 +0800102 """Test attaching interfaces"""
zhufl615e63b2018-08-01 17:23:38 +0800103
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400104 def wait_for_port_detach(self, port_id):
105 """Waits for the port's device_id to be unset.
106
107 :param port_id: The id of the port being detached.
108 :returns: The final port dict from the show_port response.
109 """
110 port = self.ports_client.show_port(port_id)['port']
111 device_id = port['device_id']
112 start = int(time.time())
113
114 # NOTE(mriedem): Nova updates the port's device_id to '' rather than
115 # None, but it's not contractual so handle Falsey either way.
116 while device_id:
117 time.sleep(self.build_interval)
118 port = self.ports_client.show_port(port_id)['port']
119 device_id = port['device_id']
120
121 timed_out = int(time.time()) - start >= self.build_timeout
122
123 if device_id and timed_out:
124 message = ('Port %s failed to detach (device_id %s) within '
125 'the required time (%s s).' %
126 (port_id, device_id, self.build_timeout))
guo yunxianebb15f22016-11-01 21:03:35 +0800127 raise lib_exc.TimeoutException(message)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400128
129 return port
130
lianghao16353342017-11-28 21:08:12 +0800131 def _check_interface(self, iface, server_id=None, port_id=None,
132 network_id=None, fixed_ip=None, mac_addr=None):
133 if server_id:
134 iface = waiters.wait_for_interface_status(
135 self.interfaces_client, server_id, iface['port_id'], 'ACTIVE')
Dan Smith8ad1c472013-02-26 13:03:16 -0500136 if port_id:
137 self.assertEqual(iface['port_id'], port_id)
138 if network_id:
139 self.assertEqual(iface['net_id'], network_id)
140 if fixed_ip:
141 self.assertEqual(iface['fixed_ips'][0]['ip_address'], fixed_ip)
venkata anil45375302014-12-30 10:41:43 +0000142 if mac_addr:
143 self.assertEqual(iface['mac_addr'], mac_addr)
Dan Smith8ad1c472013-02-26 13:03:16 -0500144
Dan Smith8ad1c472013-02-26 13:03:16 -0500145 def _test_create_interface(self, server):
lkuchlan87b5a2d2016-09-27 15:46:16 +0300146 iface = (self.interfaces_client.create_interface(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900147 ['interfaceAttachment'])
zhufl7b638332016-11-14 10:23:30 +0800148 iface = waiters.wait_for_interface_status(
149 self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
Dan Smith8ad1c472013-02-26 13:03:16 -0500150 return iface
151
152 def _test_create_interface_by_network_id(self, server, ifs):
153 network_id = ifs[0]['net_id']
lkuchlan87b5a2d2016-09-27 15:46:16 +0300154 iface = self.interfaces_client.create_interface(
ghanshyama2364f12015-08-24 15:45:37 +0900155 server['id'], net_id=network_id)['interfaceAttachment']
lianghao16353342017-11-28 21:08:12 +0800156 self._check_interface(iface, server_id=server['id'],
157 network_id=network_id)
Dan Smith8ad1c472013-02-26 13:03:16 -0500158 return iface
159
Maho Koshiya3fc12462015-12-14 19:03:12 +0900160 def _test_create_interface_by_port_id(self, server, ifs):
161 network_id = ifs[0]['net_id']
Doug Schveninger24675aa2019-08-16 22:28:39 -0500162 port = self.ports_client.create_port(
163 network_id=network_id,
164 name=data_utils.rand_name(self.__class__.__name__))
Maho Koshiya3fc12462015-12-14 19:03:12 +0900165 port_id = port['port']['id']
166 self.addCleanup(self.ports_client.delete_port, port_id)
lkuchlan87b5a2d2016-09-27 15:46:16 +0300167 iface = self.interfaces_client.create_interface(
Maho Koshiya3fc12462015-12-14 19:03:12 +0900168 server['id'], port_id=port_id)['interfaceAttachment']
lianghao16353342017-11-28 21:08:12 +0800169 self._check_interface(iface, server_id=server['id'], port_id=port_id,
170 network_id=network_id)
Maho Koshiya3fc12462015-12-14 19:03:12 +0900171 return iface
172
Maho Koshiya7b629582016-02-22 10:59:01 +0900173 def _test_create_interface_by_fixed_ips(self, server, ifs):
174 network_id = ifs[0]['net_id']
Ryan Tidwell1964a262016-05-04 15:13:23 -0700175 subnet_id = ifs[0]['fixed_ips'][0]['subnet_id']
176 ip_list = net_utils.get_unused_ip_addresses(self.ports_client,
177 self.subnets_client,
178 network_id,
179 subnet_id,
180 1)
Maho Koshiya7b629582016-02-22 10:59:01 +0900181
Ryan Tidwell1964a262016-05-04 15:13:23 -0700182 fixed_ips = [{'ip_address': ip_list[0]}]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300183 iface = self.interfaces_client.create_interface(
Maho Koshiya7b629582016-02-22 10:59:01 +0900184 server['id'], net_id=network_id,
185 fixed_ips=fixed_ips)['interfaceAttachment']
Attila Fazekas3588bb32018-11-04 12:40:27 +0100186 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
187 self.ports_client.delete_port,
188 iface['port_id'])
lianghao16353342017-11-28 21:08:12 +0800189 self._check_interface(iface, server_id=server['id'],
190 fixed_ip=ip_list[0])
Maho Koshiya7b629582016-02-22 10:59:01 +0900191 return iface
192
Dan Smith8ad1c472013-02-26 13:03:16 -0500193 def _test_show_interface(self, server, ifs):
194 iface = ifs[0]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300195 _iface = self.interfaces_client.show_interface(
ghanshyama2364f12015-08-24 15:45:37 +0900196 server['id'], iface['port_id'])['interfaceAttachment']
venkata anil45375302014-12-30 10:41:43 +0000197 self._check_interface(iface, port_id=_iface['port_id'],
198 network_id=_iface['net_id'],
199 fixed_ip=_iface['fixed_ips'][0]['ip_address'],
200 mac_addr=_iface['mac_addr'])
Dan Smith8ad1c472013-02-26 13:03:16 -0500201
202 def _test_delete_interface(self, server, ifs):
203 # NOTE(danms): delete not the first or last, but one in the middle
204 iface = ifs[1]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300205 self.interfaces_client.delete_interface(server['id'], iface['port_id'])
206 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900207 ['interfaceAttachments'])
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400208 start = int(time.time())
Dan Smith8ad1c472013-02-26 13:03:16 -0500209
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400210 while len(ifs) == len(_ifs):
211 time.sleep(self.build_interval)
lkuchlan87b5a2d2016-09-27 15:46:16 +0300212 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900213 ['interfaceAttachments'])
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400214 timed_out = int(time.time()) - start >= self.build_timeout
215 if len(ifs) == len(_ifs) and timed_out:
216 message = ('Failed to delete interface within '
217 'the required time: %s sec.' % self.build_timeout)
guo yunxianebb15f22016-11-01 21:03:35 +0800218 raise lib_exc.TimeoutException(message)
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400219
220 self.assertNotIn(iface['port_id'], [i['port_id'] for i in _ifs])
Dan Smith8ad1c472013-02-26 13:03:16 -0500221 return _ifs
222
223 def _compare_iface_list(self, list1, list2):
224 # NOTE(danms): port_state will likely have changed, so just
225 # confirm the port_ids are the same at least
226 list1 = [x['port_id'] for x in list1]
227 list2 = [x['port_id'] for x in list2]
228
229 self.assertEqual(sorted(list1), sorted(list2))
230
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800231 @decorators.idempotent_id('73fe8f02-590d-4bf1-b184-e9ca81065051')
Andrea Frittolicd368412017-08-14 21:37:56 +0100232 @utils.services('network')
zhufl607cfbf2017-12-28 14:55:08 +0800233 def test_create_list_show_delete_interfaces_by_network_port(self):
zhufl735e1692020-08-13 16:46:50 +0800234 """Test create/list/show/delete interfaces by network port"""
David Sedlák61a3c8e2019-10-30 15:38:21 +0100235 server, ifs, _ = self._create_server_get_interfaces()
Dan Smith8ad1c472013-02-26 13:03:16 -0500236 interface_count = len(ifs)
zhufl080dcfb2016-10-21 17:45:38 +0800237 self.assertGreater(interface_count, 0)
Dan Smith8ad1c472013-02-26 13:03:16 -0500238
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530239 try:
240 iface = self._test_create_interface(server)
241 except lib_exc.BadRequest as e:
242 msg = ('Multiple possible networks found, use a Network ID to be '
243 'more specific.')
likui19b70a32020-12-02 13:25:18 +0800244 if not CONF.compute.fixed_network_name and str(e) == msg:
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530245 raise
246 else:
247 ifs.append(iface)
Dan Smith8ad1c472013-02-26 13:03:16 -0500248
249 iface = self._test_create_interface_by_network_id(server, ifs)
250 ifs.append(iface)
251
Maho Koshiya3fc12462015-12-14 19:03:12 +0900252 iface = self._test_create_interface_by_port_id(server, ifs)
253 ifs.append(iface)
254
zhufl607cfbf2017-12-28 14:55:08 +0800255 _ifs = (self.interfaces_client.list_interfaces(server['id'])
256 ['interfaceAttachments'])
257 self._compare_iface_list(ifs, _ifs)
258
259 self._test_show_interface(server, ifs)
260
261 _ifs = self._test_delete_interface(server, ifs)
262 self.assertEqual(len(ifs) - 1, len(_ifs))
263
264 @decorators.idempotent_id('d290c06c-f5b3-11e7-8ec8-002293781009')
265 @utils.services('network')
266 def test_create_list_show_delete_interfaces_by_fixed_ip(self):
zhufl735e1692020-08-13 16:46:50 +0800267 """Test create/list/show/delete interfaces by fixed ip"""
zhufl607cfbf2017-12-28 14:55:08 +0800268 # NOTE(zhufl) By default only project that is admin or network owner
269 # or project with role advsvc is authorised to create interfaces with
270 # fixed-ip, so if we don't create network for each project, do not
271 # test _test_create_interface_by_fixed_ips.
272 if not (CONF.auth.use_dynamic_credentials and
273 CONF.auth.create_isolated_networks and
274 not CONF.network.shared_physical_network):
Matt Riedemann91d92422019-01-29 16:19:49 -0500275 raise self.skipException("Only owner network supports "
276 "creating interface by fixed ip.")
zhufl607cfbf2017-12-28 14:55:08 +0800277
David Sedlák61a3c8e2019-10-30 15:38:21 +0100278 server, ifs, _ = self._create_server_get_interfaces()
zhufl607cfbf2017-12-28 14:55:08 +0800279 interface_count = len(ifs)
280 self.assertGreater(interface_count, 0)
281
Maho Koshiya7b629582016-02-22 10:59:01 +0900282 iface = self._test_create_interface_by_fixed_ips(server, ifs)
283 ifs.append(iface)
284
lkuchlan87b5a2d2016-09-27 15:46:16 +0300285 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900286 ['interfaceAttachments'])
Dan Smith8ad1c472013-02-26 13:03:16 -0500287 self._compare_iface_list(ifs, _ifs)
288
289 self._test_show_interface(server, ifs)
290
291 _ifs = self._test_delete_interface(server, ifs)
292 self.assertEqual(len(ifs) - 1, len(_ifs))
293
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800294 @decorators.idempotent_id('2f3a0127-95c7-4977-92d2-bc5aec602fb4')
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400295 def test_reassign_port_between_servers(self):
zhufl735e1692020-08-13 16:46:50 +0800296 """Tests reassigning port between servers
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400297
298 1. Create a port in Neutron.
299 2. Create two servers in Nova.
300 3. Attach the port to the first server.
301 4. Detach the port from the first server.
302 5. Attach the port to the second server.
303 6. Detach the port from the second server.
304 """
305 network = self.get_tenant_network()
306 network_id = network['id']
Doug Schveninger24675aa2019-08-16 22:28:39 -0500307 port = self.ports_client.create_port(
308 network_id=network_id,
309 name=data_utils.rand_name(self.__class__.__name__))
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400310 port_id = port['port']['id']
311 self.addCleanup(self.ports_client.delete_port, port_id)
312
Artom Lifshitzb4775942018-09-05 16:24:01 +0300313 # NOTE(artom) We create two servers one at a time because
314 # create_test_server doesn't support multiple validatable servers.
315 validation_resources = self.get_test_validation_resources(
316 self.os_primary)
317
318 def _create_validatable_server():
319 _, servers = compute.create_test_server(
320 self.os_primary, tenant_network=network,
321 wait_until='ACTIVE', validatable=True,
322 validation_resources=validation_resources)
323 return servers[0]
324
325 servers = [_create_validatable_server(), _create_validatable_server()]
326
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400327 # add our cleanups for the servers since we bypassed the base class
328 for server in servers:
zhufl1355d982017-01-05 12:06:20 +0800329 self.addCleanup(self.delete_server, server['id'])
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400330
331 for server in servers:
Mark Goddardfa30d2f2019-09-02 14:41:02 +0100332 # NOTE(mgoddard): Get detailed server to ensure addresses are
333 # present in fixed IP case.
334 server = self.servers_client.show_server(server['id'])['server']
Artom Lifshitzb4775942018-09-05 16:24:01 +0300335 self._wait_for_validation(server, validation_resources)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400336 # attach the port to the server
lkuchlan87b5a2d2016-09-27 15:46:16 +0300337 iface = self.interfaces_client.create_interface(
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400338 server['id'], port_id=port_id)['interfaceAttachment']
lianghao16353342017-11-28 21:08:12 +0800339 self._check_interface(iface, server_id=server['id'],
340 port_id=port_id)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400341
342 # detach the port from the server; this is a cast in the compute
343 # API so we have to poll the port until the device_id is unset.
lkuchlan87b5a2d2016-09-27 15:46:16 +0300344 self.interfaces_client.delete_interface(server['id'], port_id)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400345 self.wait_for_port_detach(port_id)
zhufl615e63b2018-08-01 17:23:38 +0800346
347
348class AttachInterfacesUnderV243Test(AttachInterfacesTestBase):
zhufl735e1692020-08-13 16:46:50 +0800349 """Test attaching interfaces with compute microversion less than 2.44"""
350
zhufl615e63b2018-08-01 17:23:38 +0800351 max_microversion = '2.43'
352
353 @decorators.attr(type='smoke')
354 @decorators.idempotent_id('c7e0e60b-ee45-43d0-abeb-8596fd42a2f9')
355 @utils.services('network')
356 def test_add_remove_fixed_ip(self):
zhufl735e1692020-08-13 16:46:50 +0800357 """Test adding and removing fixed ip from server"""
Matthew Treinishc68546f2018-10-12 10:53:45 -0400358 # NOTE(zhufl) By default only project that is admin or network owner
359 # or project with role advsvc is authorised to add interfaces with
360 # fixed-ip, so if we don't create network for each project, do not
361 # test
362 if not (CONF.auth.use_dynamic_credentials and
363 CONF.auth.create_isolated_networks and
364 not CONF.network.shared_physical_network):
365 raise self.skipException("Only owner network supports "
366 "creating interface by fixed ip.")
zhufl615e63b2018-08-01 17:23:38 +0800367 # Add and Remove the fixed IP to server.
David Sedlák61a3c8e2019-10-30 15:38:21 +0100368 server, ifs, fip = self._create_server_get_interfaces()
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400369 original_interface_count = len(ifs) # This is the number of ports.
370 self.assertGreater(original_interface_count, 0)
371 # Get the starting list of IPs on the server.
372 addresses = self.os_primary.servers_client.list_addresses(
373 server['id'])['addresses']
374 # There should be one entry for the single network mapped to a list of
375 # addresses, which at this point should have at least one entry.
376 # Note that we could start with two addresses depending on how tempest
377 # is configured for using floating IPs.
378 self.assertEqual(1, len(addresses), addresses) # number of networks
379 # Keep track of the original addresses so we can know which IP is new.
380 original_ips = [addr['addr'] for addr in list(addresses.values())[0]]
David Sedlák61a3c8e2019-10-30 15:38:21 +0100381 # Make sure the floating IP possibly assigned during
382 # server creation is always present in the set of original ips.
383 original_ips = set(original_ips).union(fip)
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400384 original_ip_count = len(original_ips)
385 self.assertGreater(original_ip_count, 0, addresses) # at least 1
zhufl615e63b2018-08-01 17:23:38 +0800386 network_id = ifs[0]['net_id']
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400387 # Add another fixed IP to the server. This should result in another
388 # fixed IP on the same network (and same port since we only have one
389 # port).
zhufl615e63b2018-08-01 17:23:38 +0800390 self.servers_client.add_fixed_ip(server['id'], networkId=network_id)
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400391
David Sedlák61a3c8e2019-10-30 15:38:21 +0100392 def _wait_for_ip_change(expected_count):
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400393 _addresses = self.os_primary.servers_client.list_addresses(
394 server['id'])['addresses']
David Sedlák61a3c8e2019-10-30 15:38:21 +0100395 _ips = set([addr['addr'] for addr in list(_addresses.values())[0]])
396 # Make sure possible floating ip is always present in the set.
397 _ips = _ips.union(fip)
398 LOG.debug("Wait for change of IPs. All IPs still associated to "
Slawek Kaplonskib3daeb42019-06-29 23:49:59 +0200399 "the server %(id)s: %(ips)s",
400 {'id': server['id'], 'ips': _ips})
David Sedlák61a3c8e2019-10-30 15:38:21 +0100401 return len(_ips) == expected_count
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400402
David Sedlák61a3c8e2019-10-30 15:38:21 +0100403 # Wait for the ips count to increase by one.
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400404 if not test_utils.call_until_true(
David Sedlák61a3c8e2019-10-30 15:38:21 +0100405 _wait_for_ip_change, CONF.compute.build_timeout,
406 CONF.compute.build_interval, original_ip_count + 1):
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400407 raise lib_exc.TimeoutException(
408 'Timed out while waiting for IP count to increase.')
409
410 # Remove the fixed IP that we just added.
zhufl615e63b2018-08-01 17:23:38 +0800411 server_detail = self.os_primary.servers_client.show_server(
412 server['id'])['server']
413 # Get the Fixed IP from server.
414 fixed_ip = None
415 for ip_set in server_detail['addresses']:
416 for ip in server_detail['addresses'][ip_set]:
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400417 if (ip['OS-EXT-IPS:type'] == 'fixed' and
418 ip['addr'] not in original_ips):
zhufl615e63b2018-08-01 17:23:38 +0800419 fixed_ip = ip['addr']
420 break
421 if fixed_ip is not None:
422 break
423 self.servers_client.remove_fixed_ip(server['id'], address=fixed_ip)
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400424 # Wait for the interface count to decrease by one.
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400425 if not test_utils.call_until_true(
David Sedlák61a3c8e2019-10-30 15:38:21 +0100426 _wait_for_ip_change, CONF.compute.build_timeout,
427 CONF.compute.build_interval, original_ip_count):
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400428 raise lib_exc.TimeoutException(
429 'Timed out while waiting for IP count to decrease.')
zhufl77618592020-11-17 15:41:20 +0800430
431
432class AttachInterfacesV270Test(AttachInterfacesTestBase):
433 """Test interface API with microversion greater than 2.69"""
434 min_microversion = '2.70'
435
436 @decorators.idempotent_id('2853f095-8277-4067-92bd-9f10bd4f8e0c')
437 @utils.services('network')
438 def test_create_get_list_interfaces(self):
439 """Test interface API with microversion greater than 2.69
440
441 Checking create, get, list interface APIs response schema.
442 """
443 server = self.create_test_server(wait_until='ACTIVE')
444 try:
445 iface = self.interfaces_client.create_interface(server['id'])[
446 'interfaceAttachment']
447 iface = waiters.wait_for_interface_status(
448 self.interfaces_client, server['id'], iface['port_id'],
449 'ACTIVE')
450 except lib_exc.BadRequest as e:
451 msg = ('Multiple possible networks found, use a Network ID to be '
452 'more specific.')
likui19b70a32020-12-02 13:25:18 +0800453 if not CONF.compute.fixed_network_name and str(e) == msg:
zhufl77618592020-11-17 15:41:20 +0800454 raise
455 else:
456 # just to check the response schema
457 self.interfaces_client.show_interface(
458 server['id'], iface['port_id'])
459 self.interfaces_client.list_interfaces(server['id'])