blob: 0636ee49a3a9435de3c7cac9e284b258ef40eb2e [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
junbolibc2ae862017-07-29 15:46:48 +080018import six
19
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
Matt Riedemann3570c1e2016-07-29 12:15:38 -040026from tempest.lib import decorators
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050027from tempest.lib import exceptions as lib_exc
Dan Smith8ad1c472013-02-26 13:03:16 -050028
Matthew Treinishb0a78fc2014-01-29 16:49:12 +000029CONF = config.CONF
30
Dan Smith8ad1c472013-02-26 13:03:16 -050031
zhufl615e63b2018-08-01 17:23:38 +080032class AttachInterfacesTestBase(base.BaseV2ComputeTest):
Dan Smith8ad1c472013-02-26 13:03:16 -050033
34 @classmethod
Emily Hugenbruche7991d92014-12-12 16:53:36 +000035 def skip_checks(cls):
zhufl615e63b2018-08-01 17:23:38 +080036 super(AttachInterfacesTestBase, cls).skip_checks()
Matthew Treinishb0a78fc2014-01-29 16:49:12 +000037 if not CONF.service_available.neutron:
Mark McClainf2982e82013-07-06 17:48:03 -040038 raise cls.skipException("Neutron is required")
Adam Gandelman7186f7a2014-07-23 09:28:56 -040039 if not CONF.compute_feature_enabled.interface_attach:
40 raise cls.skipException("Interface attachment is not available.")
Emily Hugenbruche7991d92014-12-12 16:53:36 +000041
42 @classmethod
43 def setup_credentials(cls):
Salvatore Orlando5a337242014-01-15 22:49:22 +000044 # This test class requires network and subnet
45 cls.set_network_resources(network=True, subnet=True)
zhufl615e63b2018-08-01 17:23:38 +080046 super(AttachInterfacesTestBase, cls).setup_credentials()
Emily Hugenbruche7991d92014-12-12 16:53:36 +000047
48 @classmethod
49 def setup_clients(cls):
zhufl615e63b2018-08-01 17:23:38 +080050 super(AttachInterfacesTestBase, cls).setup_clients()
Jordan Pittier8160d312017-04-18 11:52:23 +020051 cls.subnets_client = cls.os_primary.subnets_client
52 cls.ports_client = cls.os_primary.ports_client
Dan Smith8ad1c472013-02-26 13:03:16 -050053
zhufl615e63b2018-08-01 17:23:38 +080054 def _create_server_get_interfaces(self):
55 server = self.create_test_server(wait_until='ACTIVE')
56 ifs = (self.interfaces_client.list_interfaces(server['id'])
57 ['interfaceAttachments'])
58 body = waiters.wait_for_interface_status(
59 self.interfaces_client, server['id'], ifs[0]['port_id'], 'ACTIVE')
60 ifs[0]['port_state'] = body['port_state']
61 return server, ifs
62
63
64class AttachInterfacesTestJSON(AttachInterfacesTestBase):
65
Matt Riedemanna8c641a2016-07-12 17:07:33 -040066 def wait_for_port_detach(self, port_id):
67 """Waits for the port's device_id to be unset.
68
69 :param port_id: The id of the port being detached.
70 :returns: The final port dict from the show_port response.
71 """
72 port = self.ports_client.show_port(port_id)['port']
73 device_id = port['device_id']
74 start = int(time.time())
75
76 # NOTE(mriedem): Nova updates the port's device_id to '' rather than
77 # None, but it's not contractual so handle Falsey either way.
78 while device_id:
79 time.sleep(self.build_interval)
80 port = self.ports_client.show_port(port_id)['port']
81 device_id = port['device_id']
82
83 timed_out = int(time.time()) - start >= self.build_timeout
84
85 if device_id and timed_out:
86 message = ('Port %s failed to detach (device_id %s) within '
87 'the required time (%s s).' %
88 (port_id, device_id, self.build_timeout))
guo yunxianebb15f22016-11-01 21:03:35 +080089 raise lib_exc.TimeoutException(message)
Matt Riedemanna8c641a2016-07-12 17:07:33 -040090
91 return port
92
lianghao16353342017-11-28 21:08:12 +080093 def _check_interface(self, iface, server_id=None, port_id=None,
94 network_id=None, fixed_ip=None, mac_addr=None):
95 if server_id:
96 iface = waiters.wait_for_interface_status(
97 self.interfaces_client, server_id, iface['port_id'], 'ACTIVE')
Dan Smith8ad1c472013-02-26 13:03:16 -050098 if port_id:
99 self.assertEqual(iface['port_id'], port_id)
100 if network_id:
101 self.assertEqual(iface['net_id'], network_id)
102 if fixed_ip:
103 self.assertEqual(iface['fixed_ips'][0]['ip_address'], fixed_ip)
venkata anil45375302014-12-30 10:41:43 +0000104 if mac_addr:
105 self.assertEqual(iface['mac_addr'], mac_addr)
Dan Smith8ad1c472013-02-26 13:03:16 -0500106
Dan Smith8ad1c472013-02-26 13:03:16 -0500107 def _test_create_interface(self, server):
lkuchlan87b5a2d2016-09-27 15:46:16 +0300108 iface = (self.interfaces_client.create_interface(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900109 ['interfaceAttachment'])
zhufl7b638332016-11-14 10:23:30 +0800110 iface = waiters.wait_for_interface_status(
111 self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
Dan Smith8ad1c472013-02-26 13:03:16 -0500112 return iface
113
114 def _test_create_interface_by_network_id(self, server, ifs):
115 network_id = ifs[0]['net_id']
lkuchlan87b5a2d2016-09-27 15:46:16 +0300116 iface = self.interfaces_client.create_interface(
ghanshyama2364f12015-08-24 15:45:37 +0900117 server['id'], net_id=network_id)['interfaceAttachment']
lianghao16353342017-11-28 21:08:12 +0800118 self._check_interface(iface, server_id=server['id'],
119 network_id=network_id)
Dan Smith8ad1c472013-02-26 13:03:16 -0500120 return iface
121
Maho Koshiya3fc12462015-12-14 19:03:12 +0900122 def _test_create_interface_by_port_id(self, server, ifs):
123 network_id = ifs[0]['net_id']
124 port = self.ports_client.create_port(network_id=network_id)
125 port_id = port['port']['id']
126 self.addCleanup(self.ports_client.delete_port, port_id)
lkuchlan87b5a2d2016-09-27 15:46:16 +0300127 iface = self.interfaces_client.create_interface(
Maho Koshiya3fc12462015-12-14 19:03:12 +0900128 server['id'], port_id=port_id)['interfaceAttachment']
lianghao16353342017-11-28 21:08:12 +0800129 self._check_interface(iface, server_id=server['id'], port_id=port_id,
130 network_id=network_id)
Maho Koshiya3fc12462015-12-14 19:03:12 +0900131 return iface
132
Maho Koshiya7b629582016-02-22 10:59:01 +0900133 def _test_create_interface_by_fixed_ips(self, server, ifs):
134 network_id = ifs[0]['net_id']
Ryan Tidwell1964a262016-05-04 15:13:23 -0700135 subnet_id = ifs[0]['fixed_ips'][0]['subnet_id']
136 ip_list = net_utils.get_unused_ip_addresses(self.ports_client,
137 self.subnets_client,
138 network_id,
139 subnet_id,
140 1)
Maho Koshiya7b629582016-02-22 10:59:01 +0900141
Ryan Tidwell1964a262016-05-04 15:13:23 -0700142 fixed_ips = [{'ip_address': ip_list[0]}]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300143 iface = self.interfaces_client.create_interface(
Maho Koshiya7b629582016-02-22 10:59:01 +0900144 server['id'], net_id=network_id,
145 fixed_ips=fixed_ips)['interfaceAttachment']
146 self.addCleanup(self.ports_client.delete_port, iface['port_id'])
lianghao16353342017-11-28 21:08:12 +0800147 self._check_interface(iface, server_id=server['id'],
148 fixed_ip=ip_list[0])
Maho Koshiya7b629582016-02-22 10:59:01 +0900149 return iface
150
Dan Smith8ad1c472013-02-26 13:03:16 -0500151 def _test_show_interface(self, server, ifs):
152 iface = ifs[0]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300153 _iface = self.interfaces_client.show_interface(
ghanshyama2364f12015-08-24 15:45:37 +0900154 server['id'], iface['port_id'])['interfaceAttachment']
venkata anil45375302014-12-30 10:41:43 +0000155 self._check_interface(iface, port_id=_iface['port_id'],
156 network_id=_iface['net_id'],
157 fixed_ip=_iface['fixed_ips'][0]['ip_address'],
158 mac_addr=_iface['mac_addr'])
Dan Smith8ad1c472013-02-26 13:03:16 -0500159
160 def _test_delete_interface(self, server, ifs):
161 # NOTE(danms): delete not the first or last, but one in the middle
162 iface = ifs[1]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300163 self.interfaces_client.delete_interface(server['id'], iface['port_id'])
164 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900165 ['interfaceAttachments'])
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400166 start = int(time.time())
Dan Smith8ad1c472013-02-26 13:03:16 -0500167
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400168 while len(ifs) == len(_ifs):
169 time.sleep(self.build_interval)
lkuchlan87b5a2d2016-09-27 15:46:16 +0300170 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900171 ['interfaceAttachments'])
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400172 timed_out = int(time.time()) - start >= self.build_timeout
173 if len(ifs) == len(_ifs) and timed_out:
174 message = ('Failed to delete interface within '
175 'the required time: %s sec.' % self.build_timeout)
guo yunxianebb15f22016-11-01 21:03:35 +0800176 raise lib_exc.TimeoutException(message)
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400177
178 self.assertNotIn(iface['port_id'], [i['port_id'] for i in _ifs])
Dan Smith8ad1c472013-02-26 13:03:16 -0500179 return _ifs
180
181 def _compare_iface_list(self, list1, list2):
182 # NOTE(danms): port_state will likely have changed, so just
183 # confirm the port_ids are the same at least
184 list1 = [x['port_id'] for x in list1]
185 list2 = [x['port_id'] for x in list2]
186
187 self.assertEqual(sorted(list1), sorted(list2))
188
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800189 @decorators.idempotent_id('73fe8f02-590d-4bf1-b184-e9ca81065051')
Andrea Frittolicd368412017-08-14 21:37:56 +0100190 @utils.services('network')
zhufl607cfbf2017-12-28 14:55:08 +0800191 def test_create_list_show_delete_interfaces_by_network_port(self):
Dan Smith8ad1c472013-02-26 13:03:16 -0500192 server, ifs = self._create_server_get_interfaces()
193 interface_count = len(ifs)
zhufl080dcfb2016-10-21 17:45:38 +0800194 self.assertGreater(interface_count, 0)
Dan Smith8ad1c472013-02-26 13:03:16 -0500195
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530196 try:
197 iface = self._test_create_interface(server)
198 except lib_exc.BadRequest as e:
199 msg = ('Multiple possible networks found, use a Network ID to be '
200 'more specific.')
junbolibc2ae862017-07-29 15:46:48 +0800201 if not CONF.compute.fixed_network_name and six.text_type(e) == msg:
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530202 raise
203 else:
204 ifs.append(iface)
Dan Smith8ad1c472013-02-26 13:03:16 -0500205
206 iface = self._test_create_interface_by_network_id(server, ifs)
207 ifs.append(iface)
208
Maho Koshiya3fc12462015-12-14 19:03:12 +0900209 iface = self._test_create_interface_by_port_id(server, ifs)
210 ifs.append(iface)
211
zhufl607cfbf2017-12-28 14:55:08 +0800212 _ifs = (self.interfaces_client.list_interfaces(server['id'])
213 ['interfaceAttachments'])
214 self._compare_iface_list(ifs, _ifs)
215
216 self._test_show_interface(server, ifs)
217
218 _ifs = self._test_delete_interface(server, ifs)
219 self.assertEqual(len(ifs) - 1, len(_ifs))
220
221 @decorators.idempotent_id('d290c06c-f5b3-11e7-8ec8-002293781009')
222 @utils.services('network')
223 def test_create_list_show_delete_interfaces_by_fixed_ip(self):
224 # NOTE(zhufl) By default only project that is admin or network owner
225 # or project with role advsvc is authorised to create interfaces with
226 # fixed-ip, so if we don't create network for each project, do not
227 # test _test_create_interface_by_fixed_ips.
228 if not (CONF.auth.use_dynamic_credentials and
229 CONF.auth.create_isolated_networks and
230 not CONF.network.shared_physical_network):
231 raise self.skipException("Only owner network supports "
232 "creating interface by fixed ip.")
233
234 server, ifs = self._create_server_get_interfaces()
235 interface_count = len(ifs)
236 self.assertGreater(interface_count, 0)
237
238 try:
239 iface = self._test_create_interface(server)
240 except lib_exc.BadRequest as e:
241 msg = ('Multiple possible networks found, use a Network ID to be '
242 'more specific.')
243 if not CONF.compute.fixed_network_name and six.text_type(e) == msg:
244 raise
245 else:
246 ifs.append(iface)
247
Maho Koshiya7b629582016-02-22 10:59:01 +0900248 iface = self._test_create_interface_by_fixed_ips(server, ifs)
249 ifs.append(iface)
250
lkuchlan87b5a2d2016-09-27 15:46:16 +0300251 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900252 ['interfaceAttachments'])
Dan Smith8ad1c472013-02-26 13:03:16 -0500253 self._compare_iface_list(ifs, _ifs)
254
255 self._test_show_interface(server, ifs)
256
257 _ifs = self._test_delete_interface(server, ifs)
258 self.assertEqual(len(ifs) - 1, len(_ifs))
259
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800260 @decorators.idempotent_id('2f3a0127-95c7-4977-92d2-bc5aec602fb4')
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400261 def test_reassign_port_between_servers(self):
262 """Tests the following:
263
264 1. Create a port in Neutron.
265 2. Create two servers in Nova.
266 3. Attach the port to the first server.
267 4. Detach the port from the first server.
268 5. Attach the port to the second server.
269 6. Detach the port from the second server.
270 """
271 network = self.get_tenant_network()
272 network_id = network['id']
273 port = self.ports_client.create_port(network_id=network_id)
274 port_id = port['port']['id']
275 self.addCleanup(self.ports_client.delete_port, port_id)
276
277 # create two servers
278 _, servers = compute.create_test_server(
zhufl04190882017-05-23 10:21:48 +0800279 self.os_primary, tenant_network=network,
280 wait_until='ACTIVE', min_count=2)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400281 # add our cleanups for the servers since we bypassed the base class
282 for server in servers:
zhufl1355d982017-01-05 12:06:20 +0800283 self.addCleanup(self.delete_server, server['id'])
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400284
285 for server in servers:
286 # attach the port to the server
lkuchlan87b5a2d2016-09-27 15:46:16 +0300287 iface = self.interfaces_client.create_interface(
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400288 server['id'], port_id=port_id)['interfaceAttachment']
lianghao16353342017-11-28 21:08:12 +0800289 self._check_interface(iface, server_id=server['id'],
290 port_id=port_id)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400291
292 # detach the port from the server; this is a cast in the compute
293 # API so we have to poll the port until the device_id is unset.
lkuchlan87b5a2d2016-09-27 15:46:16 +0300294 self.interfaces_client.delete_interface(server['id'], port_id)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400295 self.wait_for_port_detach(port_id)
zhufl615e63b2018-08-01 17:23:38 +0800296
297
298class AttachInterfacesUnderV243Test(AttachInterfacesTestBase):
299 max_microversion = '2.43'
300
301 @decorators.attr(type='smoke')
302 @decorators.idempotent_id('c7e0e60b-ee45-43d0-abeb-8596fd42a2f9')
303 @utils.services('network')
304 def test_add_remove_fixed_ip(self):
305 # Add and Remove the fixed IP to server.
306 server, ifs = self._create_server_get_interfaces()
307 interface_count = len(ifs)
308 self.assertGreater(interface_count, 0)
309 network_id = ifs[0]['net_id']
310 self.servers_client.add_fixed_ip(server['id'], networkId=network_id)
311 # Remove the fixed IP from server.
312 server_detail = self.os_primary.servers_client.show_server(
313 server['id'])['server']
314 # Get the Fixed IP from server.
315 fixed_ip = None
316 for ip_set in server_detail['addresses']:
317 for ip in server_detail['addresses'][ip_set]:
318 if ip['OS-EXT-IPS:type'] == 'fixed':
319 fixed_ip = ip['addr']
320 break
321 if fixed_ip is not None:
322 break
323 self.servers_client.remove_fixed_ip(server['id'], address=fixed_ip)