blob: 7509ac6dbf7f24d3ec783c7d0ce9f5ea4c6fea57 [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
ivan-zhuf2b00502013-10-18 10:06:52 +080032class AttachInterfacesTestJSON(base.BaseV2ComputeTest):
Dan Smith8ad1c472013-02-26 13:03:16 -050033
34 @classmethod
Emily Hugenbruche7991d92014-12-12 16:53:36 +000035 def skip_checks(cls):
36 super(AttachInterfacesTestJSON, 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)
Emily Hugenbruche7991d92014-12-12 16:53:36 +000046 super(AttachInterfacesTestJSON, cls).setup_credentials()
47
48 @classmethod
49 def setup_clients(cls):
50 super(AttachInterfacesTestJSON, 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
Matt Riedemanna8c641a2016-07-12 17:07:33 -040054 def wait_for_port_detach(self, port_id):
55 """Waits for the port's device_id to be unset.
56
57 :param port_id: The id of the port being detached.
58 :returns: The final port dict from the show_port response.
59 """
60 port = self.ports_client.show_port(port_id)['port']
61 device_id = port['device_id']
62 start = int(time.time())
63
64 # NOTE(mriedem): Nova updates the port's device_id to '' rather than
65 # None, but it's not contractual so handle Falsey either way.
66 while device_id:
67 time.sleep(self.build_interval)
68 port = self.ports_client.show_port(port_id)['port']
69 device_id = port['device_id']
70
71 timed_out = int(time.time()) - start >= self.build_timeout
72
73 if device_id and timed_out:
74 message = ('Port %s failed to detach (device_id %s) within '
75 'the required time (%s s).' %
76 (port_id, device_id, self.build_timeout))
guo yunxianebb15f22016-11-01 21:03:35 +080077 raise lib_exc.TimeoutException(message)
Matt Riedemanna8c641a2016-07-12 17:07:33 -040078
79 return port
80
lianghao16353342017-11-28 21:08:12 +080081 def _check_interface(self, iface, server_id=None, port_id=None,
82 network_id=None, fixed_ip=None, mac_addr=None):
83 if server_id:
84 iface = waiters.wait_for_interface_status(
85 self.interfaces_client, server_id, iface['port_id'], 'ACTIVE')
Dan Smith8ad1c472013-02-26 13:03:16 -050086 if port_id:
87 self.assertEqual(iface['port_id'], port_id)
88 if network_id:
89 self.assertEqual(iface['net_id'], network_id)
90 if fixed_ip:
91 self.assertEqual(iface['fixed_ips'][0]['ip_address'], fixed_ip)
venkata anil45375302014-12-30 10:41:43 +000092 if mac_addr:
93 self.assertEqual(iface['mac_addr'], mac_addr)
Dan Smith8ad1c472013-02-26 13:03:16 -050094
95 def _create_server_get_interfaces(self):
David Kranz0fb14292015-02-11 15:55:20 -050096 server = self.create_test_server(wait_until='ACTIVE')
lkuchlan87b5a2d2016-09-27 15:46:16 +030097 ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +090098 ['interfaceAttachments'])
zhufl7b638332016-11-14 10:23:30 +080099 body = waiters.wait_for_interface_status(
100 self.interfaces_client, server['id'], ifs[0]['port_id'], 'ACTIVE')
Leo Toyodaba9e9092013-04-08 09:02:11 +0900101 ifs[0]['port_state'] = body['port_state']
Dan Smith8ad1c472013-02-26 13:03:16 -0500102 return server, ifs
103
104 def _test_create_interface(self, server):
lkuchlan87b5a2d2016-09-27 15:46:16 +0300105 iface = (self.interfaces_client.create_interface(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900106 ['interfaceAttachment'])
zhufl7b638332016-11-14 10:23:30 +0800107 iface = waiters.wait_for_interface_status(
108 self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
Dan Smith8ad1c472013-02-26 13:03:16 -0500109 return iface
110
111 def _test_create_interface_by_network_id(self, server, ifs):
112 network_id = ifs[0]['net_id']
lkuchlan87b5a2d2016-09-27 15:46:16 +0300113 iface = self.interfaces_client.create_interface(
ghanshyama2364f12015-08-24 15:45:37 +0900114 server['id'], net_id=network_id)['interfaceAttachment']
lianghao16353342017-11-28 21:08:12 +0800115 self._check_interface(iface, server_id=server['id'],
116 network_id=network_id)
Dan Smith8ad1c472013-02-26 13:03:16 -0500117 return iface
118
Maho Koshiya3fc12462015-12-14 19:03:12 +0900119 def _test_create_interface_by_port_id(self, server, ifs):
120 network_id = ifs[0]['net_id']
121 port = self.ports_client.create_port(network_id=network_id)
122 port_id = port['port']['id']
123 self.addCleanup(self.ports_client.delete_port, port_id)
lkuchlan87b5a2d2016-09-27 15:46:16 +0300124 iface = self.interfaces_client.create_interface(
Maho Koshiya3fc12462015-12-14 19:03:12 +0900125 server['id'], port_id=port_id)['interfaceAttachment']
lianghao16353342017-11-28 21:08:12 +0800126 self._check_interface(iface, server_id=server['id'], port_id=port_id,
127 network_id=network_id)
Maho Koshiya3fc12462015-12-14 19:03:12 +0900128 return iface
129
Maho Koshiya7b629582016-02-22 10:59:01 +0900130 def _test_create_interface_by_fixed_ips(self, server, ifs):
131 network_id = ifs[0]['net_id']
Ryan Tidwell1964a262016-05-04 15:13:23 -0700132 subnet_id = ifs[0]['fixed_ips'][0]['subnet_id']
133 ip_list = net_utils.get_unused_ip_addresses(self.ports_client,
134 self.subnets_client,
135 network_id,
136 subnet_id,
137 1)
Maho Koshiya7b629582016-02-22 10:59:01 +0900138
Ryan Tidwell1964a262016-05-04 15:13:23 -0700139 fixed_ips = [{'ip_address': ip_list[0]}]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300140 iface = self.interfaces_client.create_interface(
Maho Koshiya7b629582016-02-22 10:59:01 +0900141 server['id'], net_id=network_id,
142 fixed_ips=fixed_ips)['interfaceAttachment']
143 self.addCleanup(self.ports_client.delete_port, iface['port_id'])
lianghao16353342017-11-28 21:08:12 +0800144 self._check_interface(iface, server_id=server['id'],
145 fixed_ip=ip_list[0])
Maho Koshiya7b629582016-02-22 10:59:01 +0900146 return iface
147
Dan Smith8ad1c472013-02-26 13:03:16 -0500148 def _test_show_interface(self, server, ifs):
149 iface = ifs[0]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300150 _iface = self.interfaces_client.show_interface(
ghanshyama2364f12015-08-24 15:45:37 +0900151 server['id'], iface['port_id'])['interfaceAttachment']
venkata anil45375302014-12-30 10:41:43 +0000152 self._check_interface(iface, port_id=_iface['port_id'],
153 network_id=_iface['net_id'],
154 fixed_ip=_iface['fixed_ips'][0]['ip_address'],
155 mac_addr=_iface['mac_addr'])
Dan Smith8ad1c472013-02-26 13:03:16 -0500156
157 def _test_delete_interface(self, server, ifs):
158 # NOTE(danms): delete not the first or last, but one in the middle
159 iface = ifs[1]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300160 self.interfaces_client.delete_interface(server['id'], iface['port_id'])
161 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900162 ['interfaceAttachments'])
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400163 start = int(time.time())
Dan Smith8ad1c472013-02-26 13:03:16 -0500164
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400165 while len(ifs) == len(_ifs):
166 time.sleep(self.build_interval)
lkuchlan87b5a2d2016-09-27 15:46:16 +0300167 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900168 ['interfaceAttachments'])
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400169 timed_out = int(time.time()) - start >= self.build_timeout
170 if len(ifs) == len(_ifs) and timed_out:
171 message = ('Failed to delete interface within '
172 'the required time: %s sec.' % self.build_timeout)
guo yunxianebb15f22016-11-01 21:03:35 +0800173 raise lib_exc.TimeoutException(message)
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400174
175 self.assertNotIn(iface['port_id'], [i['port_id'] for i in _ifs])
Dan Smith8ad1c472013-02-26 13:03:16 -0500176 return _ifs
177
178 def _compare_iface_list(self, list1, list2):
179 # NOTE(danms): port_state will likely have changed, so just
180 # confirm the port_ids are the same at least
181 list1 = [x['port_id'] for x in list1]
182 list2 = [x['port_id'] for x in list2]
183
184 self.assertEqual(sorted(list1), sorted(list2))
185
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800186 @decorators.idempotent_id('73fe8f02-590d-4bf1-b184-e9ca81065051')
Andrea Frittolicd368412017-08-14 21:37:56 +0100187 @utils.services('network')
zhufl607cfbf2017-12-28 14:55:08 +0800188 def test_create_list_show_delete_interfaces_by_network_port(self):
Dan Smith8ad1c472013-02-26 13:03:16 -0500189 server, ifs = self._create_server_get_interfaces()
190 interface_count = len(ifs)
zhufl080dcfb2016-10-21 17:45:38 +0800191 self.assertGreater(interface_count, 0)
Dan Smith8ad1c472013-02-26 13:03:16 -0500192
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530193 try:
194 iface = self._test_create_interface(server)
195 except lib_exc.BadRequest as e:
196 msg = ('Multiple possible networks found, use a Network ID to be '
197 'more specific.')
junbolibc2ae862017-07-29 15:46:48 +0800198 if not CONF.compute.fixed_network_name and six.text_type(e) == msg:
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530199 raise
200 else:
201 ifs.append(iface)
Dan Smith8ad1c472013-02-26 13:03:16 -0500202
203 iface = self._test_create_interface_by_network_id(server, ifs)
204 ifs.append(iface)
205
Maho Koshiya3fc12462015-12-14 19:03:12 +0900206 iface = self._test_create_interface_by_port_id(server, ifs)
207 ifs.append(iface)
208
zhufl607cfbf2017-12-28 14:55:08 +0800209 _ifs = (self.interfaces_client.list_interfaces(server['id'])
210 ['interfaceAttachments'])
211 self._compare_iface_list(ifs, _ifs)
212
213 self._test_show_interface(server, ifs)
214
215 _ifs = self._test_delete_interface(server, ifs)
216 self.assertEqual(len(ifs) - 1, len(_ifs))
217
218 @decorators.idempotent_id('d290c06c-f5b3-11e7-8ec8-002293781009')
219 @utils.services('network')
220 def test_create_list_show_delete_interfaces_by_fixed_ip(self):
221 # NOTE(zhufl) By default only project that is admin or network owner
222 # or project with role advsvc is authorised to create interfaces with
223 # fixed-ip, so if we don't create network for each project, do not
224 # test _test_create_interface_by_fixed_ips.
225 if not (CONF.auth.use_dynamic_credentials and
226 CONF.auth.create_isolated_networks and
227 not CONF.network.shared_physical_network):
228 raise self.skipException("Only owner network supports "
229 "creating interface by fixed ip.")
230
231 server, ifs = self._create_server_get_interfaces()
232 interface_count = len(ifs)
233 self.assertGreater(interface_count, 0)
234
235 try:
236 iface = self._test_create_interface(server)
237 except lib_exc.BadRequest as e:
238 msg = ('Multiple possible networks found, use a Network ID to be '
239 'more specific.')
240 if not CONF.compute.fixed_network_name and six.text_type(e) == msg:
241 raise
242 else:
243 ifs.append(iface)
244
Maho Koshiya7b629582016-02-22 10:59:01 +0900245 iface = self._test_create_interface_by_fixed_ips(server, ifs)
246 ifs.append(iface)
247
lkuchlan87b5a2d2016-09-27 15:46:16 +0300248 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900249 ['interfaceAttachments'])
Dan Smith8ad1c472013-02-26 13:03:16 -0500250 self._compare_iface_list(ifs, _ifs)
251
252 self._test_show_interface(server, ifs)
253
254 _ifs = self._test_delete_interface(server, ifs)
255 self.assertEqual(len(ifs) - 1, len(_ifs))
256
Jordan Pittier3b46d272017-04-12 16:17:28 +0200257 @decorators.attr(type='smoke')
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800258 @decorators.idempotent_id('c7e0e60b-ee45-43d0-abeb-8596fd42a2f9')
Andrea Frittolicd368412017-08-14 21:37:56 +0100259 @utils.services('network')
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900260 def test_add_remove_fixed_ip(self):
261 # Add and Remove the fixed IP to server.
262 server, ifs = self._create_server_get_interfaces()
263 interface_count = len(ifs)
zhufl080dcfb2016-10-21 17:45:38 +0800264 self.assertGreater(interface_count, 0)
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900265 network_id = ifs[0]['net_id']
ghanshyam4c7d2a02015-09-14 16:05:13 +0900266 self.servers_client.add_fixed_ip(server['id'], networkId=network_id)
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900267 # Remove the fixed IP from server.
Jordan Pittier8160d312017-04-18 11:52:23 +0200268 server_detail = self.os_primary.servers_client.show_server(
ghanshyam0f825252015-08-25 16:02:50 +0900269 server['id'])['server']
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900270 # Get the Fixed IP from server.
271 fixed_ip = None
272 for ip_set in server_detail['addresses']:
273 for ip in server_detail['addresses'][ip_set]:
274 if ip['OS-EXT-IPS:type'] == 'fixed':
275 fixed_ip = ip['addr']
276 break
277 if fixed_ip is not None:
278 break
ghanshyam4c7d2a02015-09-14 16:05:13 +0900279 self.servers_client.remove_fixed_ip(server['id'], address=fixed_ip)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400280
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800281 @decorators.idempotent_id('2f3a0127-95c7-4977-92d2-bc5aec602fb4')
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400282 def test_reassign_port_between_servers(self):
283 """Tests the following:
284
285 1. Create a port in Neutron.
286 2. Create two servers in Nova.
287 3. Attach the port to the first server.
288 4. Detach the port from the first server.
289 5. Attach the port to the second server.
290 6. Detach the port from the second server.
291 """
292 network = self.get_tenant_network()
293 network_id = network['id']
294 port = self.ports_client.create_port(network_id=network_id)
295 port_id = port['port']['id']
296 self.addCleanup(self.ports_client.delete_port, port_id)
297
298 # create two servers
299 _, servers = compute.create_test_server(
zhufl04190882017-05-23 10:21:48 +0800300 self.os_primary, tenant_network=network,
301 wait_until='ACTIVE', min_count=2)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400302 # add our cleanups for the servers since we bypassed the base class
303 for server in servers:
zhufl1355d982017-01-05 12:06:20 +0800304 self.addCleanup(self.delete_server, server['id'])
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400305
306 for server in servers:
307 # attach the port to the server
lkuchlan87b5a2d2016-09-27 15:46:16 +0300308 iface = self.interfaces_client.create_interface(
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400309 server['id'], port_id=port_id)['interfaceAttachment']
lianghao16353342017-11-28 21:08:12 +0800310 self._check_interface(iface, server_id=server['id'],
311 port_id=port_id)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400312
313 # detach the port from the server; this is a cast in the compute
314 # API so we have to poll the port until the device_id is unset.
lkuchlan87b5a2d2016-09-27 15:46:16 +0300315 self.interfaces_client.delete_interface(server['id'], port_id)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400316 self.wait_for_port_detach(port_id)