blob: 9b6bf8453ef65a9182e84c6b45b4d1a4b1796dba [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
Dan Smith7249e2a2023-07-21 09:53:06 -0700298 1. Create two servers in Nova.
299 2. Create a port in Neutron.
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400300 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']
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400307
Artom Lifshitzb4775942018-09-05 16:24:01 +0300308 # NOTE(artom) We create two servers one at a time because
309 # create_test_server doesn't support multiple validatable servers.
310 validation_resources = self.get_test_validation_resources(
311 self.os_primary)
312
313 def _create_validatable_server():
314 _, servers = compute.create_test_server(
315 self.os_primary, tenant_network=network,
Dan Smith7249e2a2023-07-21 09:53:06 -0700316 validatable=True,
Artom Lifshitzb4775942018-09-05 16:24:01 +0300317 validation_resources=validation_resources)
318 return servers[0]
319
Dan Smith7249e2a2023-07-21 09:53:06 -0700320 # NOTE(danms): We create these with no waiters because we will wait
321 # for them to be validatable (i.e. SSHABLE) below. That way some of
322 # the server creation overlap each other and with create_port.
Artom Lifshitzb4775942018-09-05 16:24:01 +0300323 servers = [_create_validatable_server(), _create_validatable_server()]
324
Dan Smith7249e2a2023-07-21 09:53:06 -0700325 port = self.ports_client.create_port(
326 network_id=network_id,
327 name=data_utils.rand_name(self.__class__.__name__))
328 port_id = port['port']['id']
329 self.addCleanup(self.ports_client.delete_port, port_id)
330
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400331 # add our cleanups for the servers since we bypassed the base class
332 for server in servers:
zhufl1355d982017-01-05 12:06:20 +0800333 self.addCleanup(self.delete_server, server['id'])
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400334
335 for server in servers:
Mark Goddardfa30d2f2019-09-02 14:41:02 +0100336 # NOTE(mgoddard): Get detailed server to ensure addresses are
337 # present in fixed IP case.
338 server = self.servers_client.show_server(server['id'])['server']
Dan Smith7249e2a2023-07-21 09:53:06 -0700339 compute.wait_for_ssh_or_ping(server, self.os_primary, network,
340 True, validation_resources,
341 'SSHABLE', True)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400342 # attach the port to the server
lkuchlan87b5a2d2016-09-27 15:46:16 +0300343 iface = self.interfaces_client.create_interface(
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400344 server['id'], port_id=port_id)['interfaceAttachment']
lianghao16353342017-11-28 21:08:12 +0800345 self._check_interface(iface, server_id=server['id'],
346 port_id=port_id)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400347
348 # detach the port from the server; this is a cast in the compute
349 # API so we have to poll the port until the device_id is unset.
lkuchlan87b5a2d2016-09-27 15:46:16 +0300350 self.interfaces_client.delete_interface(server['id'], port_id)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400351 self.wait_for_port_detach(port_id)
zhufl615e63b2018-08-01 17:23:38 +0800352
353
354class AttachInterfacesUnderV243Test(AttachInterfacesTestBase):
zhufl735e1692020-08-13 16:46:50 +0800355 """Test attaching interfaces with compute microversion less than 2.44"""
356
zhufl615e63b2018-08-01 17:23:38 +0800357 max_microversion = '2.43'
358
359 @decorators.attr(type='smoke')
360 @decorators.idempotent_id('c7e0e60b-ee45-43d0-abeb-8596fd42a2f9')
361 @utils.services('network')
362 def test_add_remove_fixed_ip(self):
zhufl735e1692020-08-13 16:46:50 +0800363 """Test adding and removing fixed ip from server"""
Matthew Treinishc68546f2018-10-12 10:53:45 -0400364 # NOTE(zhufl) By default only project that is admin or network owner
365 # or project with role advsvc is authorised to add interfaces with
366 # fixed-ip, so if we don't create network for each project, do not
367 # test
368 if not (CONF.auth.use_dynamic_credentials and
369 CONF.auth.create_isolated_networks and
370 not CONF.network.shared_physical_network):
371 raise self.skipException("Only owner network supports "
372 "creating interface by fixed ip.")
zhufl615e63b2018-08-01 17:23:38 +0800373 # Add and Remove the fixed IP to server.
David Sedlák61a3c8e2019-10-30 15:38:21 +0100374 server, ifs, fip = self._create_server_get_interfaces()
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400375 original_interface_count = len(ifs) # This is the number of ports.
376 self.assertGreater(original_interface_count, 0)
377 # Get the starting list of IPs on the server.
378 addresses = self.os_primary.servers_client.list_addresses(
379 server['id'])['addresses']
380 # There should be one entry for the single network mapped to a list of
381 # addresses, which at this point should have at least one entry.
382 # Note that we could start with two addresses depending on how tempest
383 # is configured for using floating IPs.
384 self.assertEqual(1, len(addresses), addresses) # number of networks
385 # Keep track of the original addresses so we can know which IP is new.
386 original_ips = [addr['addr'] for addr in list(addresses.values())[0]]
David Sedlák61a3c8e2019-10-30 15:38:21 +0100387 # Make sure the floating IP possibly assigned during
388 # server creation is always present in the set of original ips.
389 original_ips = set(original_ips).union(fip)
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400390 original_ip_count = len(original_ips)
391 self.assertGreater(original_ip_count, 0, addresses) # at least 1
zhufl615e63b2018-08-01 17:23:38 +0800392 network_id = ifs[0]['net_id']
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400393 # Add another fixed IP to the server. This should result in another
394 # fixed IP on the same network (and same port since we only have one
395 # port).
zhufl615e63b2018-08-01 17:23:38 +0800396 self.servers_client.add_fixed_ip(server['id'], networkId=network_id)
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400397
David Sedlák61a3c8e2019-10-30 15:38:21 +0100398 def _wait_for_ip_change(expected_count):
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400399 _addresses = self.os_primary.servers_client.list_addresses(
400 server['id'])['addresses']
David Sedlák61a3c8e2019-10-30 15:38:21 +0100401 _ips = set([addr['addr'] for addr in list(_addresses.values())[0]])
402 # Make sure possible floating ip is always present in the set.
403 _ips = _ips.union(fip)
404 LOG.debug("Wait for change of IPs. All IPs still associated to "
Slawek Kaplonskib3daeb42019-06-29 23:49:59 +0200405 "the server %(id)s: %(ips)s",
406 {'id': server['id'], 'ips': _ips})
David Sedlák61a3c8e2019-10-30 15:38:21 +0100407 return len(_ips) == expected_count
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400408
David Sedlák61a3c8e2019-10-30 15:38:21 +0100409 # Wait for the ips count to increase by one.
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400410 if not test_utils.call_until_true(
David Sedlák61a3c8e2019-10-30 15:38:21 +0100411 _wait_for_ip_change, CONF.compute.build_timeout,
412 CONF.compute.build_interval, original_ip_count + 1):
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400413 raise lib_exc.TimeoutException(
414 'Timed out while waiting for IP count to increase.')
415
416 # Remove the fixed IP that we just added.
zhufl615e63b2018-08-01 17:23:38 +0800417 server_detail = self.os_primary.servers_client.show_server(
418 server['id'])['server']
419 # Get the Fixed IP from server.
420 fixed_ip = None
421 for ip_set in server_detail['addresses']:
422 for ip in server_detail['addresses'][ip_set]:
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400423 if (ip['OS-EXT-IPS:type'] == 'fixed' and
424 ip['addr'] not in original_ips):
zhufl615e63b2018-08-01 17:23:38 +0800425 fixed_ip = ip['addr']
426 break
427 if fixed_ip is not None:
428 break
429 self.servers_client.remove_fixed_ip(server['id'], address=fixed_ip)
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400430 # Wait for the interface count to decrease by one.
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400431 if not test_utils.call_until_true(
David Sedlák61a3c8e2019-10-30 15:38:21 +0100432 _wait_for_ip_change, CONF.compute.build_timeout,
433 CONF.compute.build_interval, original_ip_count):
Matt Riedemannd4cb10f2018-09-26 13:03:08 -0400434 raise lib_exc.TimeoutException(
435 'Timed out while waiting for IP count to decrease.')
zhufl77618592020-11-17 15:41:20 +0800436
437
438class AttachInterfacesV270Test(AttachInterfacesTestBase):
439 """Test interface API with microversion greater than 2.69"""
440 min_microversion = '2.70'
441
442 @decorators.idempotent_id('2853f095-8277-4067-92bd-9f10bd4f8e0c')
443 @utils.services('network')
444 def test_create_get_list_interfaces(self):
445 """Test interface API with microversion greater than 2.69
446
447 Checking create, get, list interface APIs response schema.
448 """
449 server = self.create_test_server(wait_until='ACTIVE')
450 try:
451 iface = self.interfaces_client.create_interface(server['id'])[
452 'interfaceAttachment']
453 iface = waiters.wait_for_interface_status(
454 self.interfaces_client, server['id'], iface['port_id'],
455 'ACTIVE')
456 except lib_exc.BadRequest as e:
457 msg = ('Multiple possible networks found, use a Network ID to be '
458 'more specific.')
likui19b70a32020-12-02 13:25:18 +0800459 if not CONF.compute.fixed_network_name and str(e) == msg:
zhufl77618592020-11-17 15:41:20 +0800460 raise
461 else:
462 # just to check the response schema
463 self.interfaces_client.show_interface(
464 server['id'], iface['port_id'])
465 self.interfaces_client.list_interfaces(server['id'])