blob: fc6a20f3795720024682b390645bf67938ca8ce8 [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
Sean Dague1937d092013-05-17 16:36:38 -040018from tempest.api.compute import base
Matt Riedemanna8c641a2016-07-12 17:07:33 -040019from tempest.common import compute
Ryan Tidwell1964a262016-05-04 15:13:23 -070020from tempest.common.utils import net_utils
Matt Riedemanna8c641a2016-07-12 17:07:33 -040021from tempest.common import waiters
Matthew Treinishb0a78fc2014-01-29 16:49:12 +000022from tempest import config
Matt Riedemann3570c1e2016-07-29 12:15:38 -040023from tempest.lib import decorators
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050024from tempest.lib import exceptions as lib_exc
Yuiko Takadae9999d62014-03-06 09:22:54 +000025from tempest import test
Dan Smith8ad1c472013-02-26 13:03:16 -050026
Matthew Treinishb0a78fc2014-01-29 16:49:12 +000027CONF = config.CONF
28
Dan Smith8ad1c472013-02-26 13:03:16 -050029
ivan-zhuf2b00502013-10-18 10:06:52 +080030class AttachInterfacesTestJSON(base.BaseV2ComputeTest):
Dan Smith8ad1c472013-02-26 13:03:16 -050031
32 @classmethod
Emily Hugenbruche7991d92014-12-12 16:53:36 +000033 def skip_checks(cls):
34 super(AttachInterfacesTestJSON, cls).skip_checks()
Matthew Treinishb0a78fc2014-01-29 16:49:12 +000035 if not CONF.service_available.neutron:
Mark McClainf2982e82013-07-06 17:48:03 -040036 raise cls.skipException("Neutron is required")
Adam Gandelman7186f7a2014-07-23 09:28:56 -040037 if not CONF.compute_feature_enabled.interface_attach:
38 raise cls.skipException("Interface attachment is not available.")
Emily Hugenbruche7991d92014-12-12 16:53:36 +000039
40 @classmethod
41 def setup_credentials(cls):
Salvatore Orlando5a337242014-01-15 22:49:22 +000042 # This test class requires network and subnet
43 cls.set_network_resources(network=True, subnet=True)
Emily Hugenbruche7991d92014-12-12 16:53:36 +000044 super(AttachInterfacesTestJSON, cls).setup_credentials()
45
46 @classmethod
47 def setup_clients(cls):
48 super(AttachInterfacesTestJSON, cls).setup_clients()
Maho Koshiya7b629582016-02-22 10:59:01 +090049 cls.networks_client = cls.os.networks_client
50 cls.subnets_client = cls.os.subnets_client
Maho Koshiya3fc12462015-12-14 19:03:12 +090051 cls.ports_client = cls.os.ports_client
Dan Smith8ad1c472013-02-26 13:03:16 -050052
Ken'ichi Ohmichi84e99682015-07-08 05:28:57 +000053 def wait_for_interface_status(self, server, port_id, status):
Maho Koshiya3fc12462015-12-14 19:03:12 +090054 """Waits for an interface to reach a given status."""
lkuchlan87b5a2d2016-09-27 15:46:16 +030055 body = (self.interfaces_client.show_interface(server, port_id)
ghanshyama2364f12015-08-24 15:45:37 +090056 ['interfaceAttachment'])
Ken'ichi Ohmichi84e99682015-07-08 05:28:57 +000057 interface_status = body['port_state']
58 start = int(time.time())
59
60 while(interface_status != status):
61 time.sleep(self.build_interval)
lkuchlan87b5a2d2016-09-27 15:46:16 +030062 body = (self.interfaces_client.show_interface(server, port_id)
ghanshyama2364f12015-08-24 15:45:37 +090063 ['interfaceAttachment'])
Ken'ichi Ohmichi84e99682015-07-08 05:28:57 +000064 interface_status = body['port_state']
65
66 timed_out = int(time.time()) - start >= self.build_timeout
67
68 if interface_status != status and timed_out:
69 message = ('Interface %s failed to reach %s status '
70 '(current %s) within the required time (%s s).' %
71 (port_id, status, interface_status,
72 self.build_timeout))
guo yunxianebb15f22016-11-01 21:03:35 +080073 raise lib_exc.TimeoutException(message)
Ken'ichi Ohmichi84e99682015-07-08 05:28:57 +000074
75 return body
76
Matt Riedemanna8c641a2016-07-12 17:07:33 -040077 # TODO(mriedem): move this into a common waiters utility module
78 def wait_for_port_detach(self, port_id):
79 """Waits for the port's device_id to be unset.
80
81 :param port_id: The id of the port being detached.
82 :returns: The final port dict from the show_port response.
83 """
84 port = self.ports_client.show_port(port_id)['port']
85 device_id = port['device_id']
86 start = int(time.time())
87
88 # NOTE(mriedem): Nova updates the port's device_id to '' rather than
89 # None, but it's not contractual so handle Falsey either way.
90 while device_id:
91 time.sleep(self.build_interval)
92 port = self.ports_client.show_port(port_id)['port']
93 device_id = port['device_id']
94
95 timed_out = int(time.time()) - start >= self.build_timeout
96
97 if device_id and timed_out:
98 message = ('Port %s failed to detach (device_id %s) within '
99 'the required time (%s s).' %
100 (port_id, device_id, self.build_timeout))
guo yunxianebb15f22016-11-01 21:03:35 +0800101 raise lib_exc.TimeoutException(message)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400102
103 return port
104
Dan Smith8ad1c472013-02-26 13:03:16 -0500105 def _check_interface(self, iface, port_id=None, network_id=None,
venkata anil45375302014-12-30 10:41:43 +0000106 fixed_ip=None, mac_addr=None):
Dan Smith8ad1c472013-02-26 13:03:16 -0500107 self.assertIn('port_state', iface)
108 if port_id:
109 self.assertEqual(iface['port_id'], port_id)
110 if network_id:
111 self.assertEqual(iface['net_id'], network_id)
112 if fixed_ip:
113 self.assertEqual(iface['fixed_ips'][0]['ip_address'], fixed_ip)
venkata anil45375302014-12-30 10:41:43 +0000114 if mac_addr:
115 self.assertEqual(iface['mac_addr'], mac_addr)
Dan Smith8ad1c472013-02-26 13:03:16 -0500116
117 def _create_server_get_interfaces(self):
David Kranz0fb14292015-02-11 15:55:20 -0500118 server = self.create_test_server(wait_until='ACTIVE')
lkuchlan87b5a2d2016-09-27 15:46:16 +0300119 ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900120 ['interfaceAttachments'])
Ken'ichi Ohmichi84e99682015-07-08 05:28:57 +0000121 body = self.wait_for_interface_status(
Leo Toyodaba9e9092013-04-08 09:02:11 +0900122 server['id'], ifs[0]['port_id'], 'ACTIVE')
123 ifs[0]['port_state'] = body['port_state']
Dan Smith8ad1c472013-02-26 13:03:16 -0500124 return server, ifs
125
126 def _test_create_interface(self, server):
lkuchlan87b5a2d2016-09-27 15:46:16 +0300127 iface = (self.interfaces_client.create_interface(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900128 ['interfaceAttachment'])
Ken'ichi Ohmichi84e99682015-07-08 05:28:57 +0000129 iface = self.wait_for_interface_status(
Leo Toyodaba9e9092013-04-08 09:02:11 +0900130 server['id'], iface['port_id'], 'ACTIVE')
Dan Smith8ad1c472013-02-26 13:03:16 -0500131 self._check_interface(iface)
132 return iface
133
134 def _test_create_interface_by_network_id(self, server, ifs):
135 network_id = ifs[0]['net_id']
lkuchlan87b5a2d2016-09-27 15:46:16 +0300136 iface = self.interfaces_client.create_interface(
ghanshyama2364f12015-08-24 15:45:37 +0900137 server['id'], net_id=network_id)['interfaceAttachment']
Ken'ichi Ohmichi84e99682015-07-08 05:28:57 +0000138 iface = self.wait_for_interface_status(
Leo Toyodaba9e9092013-04-08 09:02:11 +0900139 server['id'], iface['port_id'], 'ACTIVE')
Dan Smith8ad1c472013-02-26 13:03:16 -0500140 self._check_interface(iface, network_id=network_id)
141 return iface
142
Maho Koshiya3fc12462015-12-14 19:03:12 +0900143 def _test_create_interface_by_port_id(self, server, ifs):
144 network_id = ifs[0]['net_id']
145 port = self.ports_client.create_port(network_id=network_id)
146 port_id = port['port']['id']
147 self.addCleanup(self.ports_client.delete_port, port_id)
lkuchlan87b5a2d2016-09-27 15:46:16 +0300148 iface = self.interfaces_client.create_interface(
Maho Koshiya3fc12462015-12-14 19:03:12 +0900149 server['id'], port_id=port_id)['interfaceAttachment']
150 iface = self.wait_for_interface_status(
151 server['id'], iface['port_id'], 'ACTIVE')
152 self._check_interface(iface, port_id=port_id)
153 return iface
154
Maho Koshiya7b629582016-02-22 10:59:01 +0900155 def _test_create_interface_by_fixed_ips(self, server, ifs):
156 network_id = ifs[0]['net_id']
Ryan Tidwell1964a262016-05-04 15:13:23 -0700157 subnet_id = ifs[0]['fixed_ips'][0]['subnet_id']
158 ip_list = net_utils.get_unused_ip_addresses(self.ports_client,
159 self.subnets_client,
160 network_id,
161 subnet_id,
162 1)
Maho Koshiya7b629582016-02-22 10:59:01 +0900163
Ryan Tidwell1964a262016-05-04 15:13:23 -0700164 fixed_ips = [{'ip_address': ip_list[0]}]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300165 iface = self.interfaces_client.create_interface(
Maho Koshiya7b629582016-02-22 10:59:01 +0900166 server['id'], net_id=network_id,
167 fixed_ips=fixed_ips)['interfaceAttachment']
168 self.addCleanup(self.ports_client.delete_port, iface['port_id'])
169 iface = self.wait_for_interface_status(
170 server['id'], iface['port_id'], 'ACTIVE')
Ryan Tidwell1964a262016-05-04 15:13:23 -0700171 self._check_interface(iface, fixed_ip=ip_list[0])
Maho Koshiya7b629582016-02-22 10:59:01 +0900172 return iface
173
Dan Smith8ad1c472013-02-26 13:03:16 -0500174 def _test_show_interface(self, server, ifs):
175 iface = ifs[0]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300176 _iface = self.interfaces_client.show_interface(
ghanshyama2364f12015-08-24 15:45:37 +0900177 server['id'], iface['port_id'])['interfaceAttachment']
venkata anil45375302014-12-30 10:41:43 +0000178 self._check_interface(iface, port_id=_iface['port_id'],
179 network_id=_iface['net_id'],
180 fixed_ip=_iface['fixed_ips'][0]['ip_address'],
181 mac_addr=_iface['mac_addr'])
Dan Smith8ad1c472013-02-26 13:03:16 -0500182
183 def _test_delete_interface(self, server, ifs):
184 # NOTE(danms): delete not the first or last, but one in the middle
185 iface = ifs[1]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300186 self.interfaces_client.delete_interface(server['id'], iface['port_id'])
187 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900188 ['interfaceAttachments'])
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400189 start = int(time.time())
Dan Smith8ad1c472013-02-26 13:03:16 -0500190
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400191 while len(ifs) == len(_ifs):
192 time.sleep(self.build_interval)
lkuchlan87b5a2d2016-09-27 15:46:16 +0300193 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900194 ['interfaceAttachments'])
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400195 timed_out = int(time.time()) - start >= self.build_timeout
196 if len(ifs) == len(_ifs) and timed_out:
197 message = ('Failed to delete interface within '
198 'the required time: %s sec.' % self.build_timeout)
guo yunxianebb15f22016-11-01 21:03:35 +0800199 raise lib_exc.TimeoutException(message)
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400200
201 self.assertNotIn(iface['port_id'], [i['port_id'] for i in _ifs])
Dan Smith8ad1c472013-02-26 13:03:16 -0500202 return _ifs
203
204 def _compare_iface_list(self, list1, list2):
205 # NOTE(danms): port_state will likely have changed, so just
206 # confirm the port_ids are the same at least
207 list1 = [x['port_id'] for x in list1]
208 list2 = [x['port_id'] for x in list2]
209
210 self.assertEqual(sorted(list1), sorted(list2))
211
Chris Hoge7579c1a2015-02-26 14:12:15 -0800212 @test.idempotent_id('73fe8f02-590d-4bf1-b184-e9ca81065051')
Matthew Treinish2df97482014-06-13 15:02:26 -0400213 @test.services('network')
Dan Smith8ad1c472013-02-26 13:03:16 -0500214 def test_create_list_show_delete_interfaces(self):
215 server, ifs = self._create_server_get_interfaces()
216 interface_count = len(ifs)
zhufl080dcfb2016-10-21 17:45:38 +0800217 self.assertGreater(interface_count, 0)
Dan Smith8ad1c472013-02-26 13:03:16 -0500218 self._check_interface(ifs[0])
219
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530220 try:
221 iface = self._test_create_interface(server)
222 except lib_exc.BadRequest as e:
223 msg = ('Multiple possible networks found, use a Network ID to be '
224 'more specific.')
225 if not CONF.compute.fixed_network_name and e.message == msg:
226 raise
227 else:
228 ifs.append(iface)
Dan Smith8ad1c472013-02-26 13:03:16 -0500229
230 iface = self._test_create_interface_by_network_id(server, ifs)
231 ifs.append(iface)
232
Maho Koshiya3fc12462015-12-14 19:03:12 +0900233 iface = self._test_create_interface_by_port_id(server, ifs)
234 ifs.append(iface)
235
Maho Koshiya7b629582016-02-22 10:59:01 +0900236 iface = self._test_create_interface_by_fixed_ips(server, ifs)
237 ifs.append(iface)
238
lkuchlan87b5a2d2016-09-27 15:46:16 +0300239 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900240 ['interfaceAttachments'])
Dan Smith8ad1c472013-02-26 13:03:16 -0500241 self._compare_iface_list(ifs, _ifs)
242
243 self._test_show_interface(server, ifs)
244
245 _ifs = self._test_delete_interface(server, ifs)
246 self.assertEqual(len(ifs) - 1, len(_ifs))
247
Masayuki Igawa750aa922014-03-20 09:46:37 +0900248 @test.attr(type='smoke')
Chris Hoge7579c1a2015-02-26 14:12:15 -0800249 @test.idempotent_id('c7e0e60b-ee45-43d0-abeb-8596fd42a2f9')
Matthew Treinish2df97482014-06-13 15:02:26 -0400250 @test.services('network')
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900251 def test_add_remove_fixed_ip(self):
252 # Add and Remove the fixed IP to server.
253 server, ifs = self._create_server_get_interfaces()
254 interface_count = len(ifs)
zhufl080dcfb2016-10-21 17:45:38 +0800255 self.assertGreater(interface_count, 0)
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900256 self._check_interface(ifs[0])
257 network_id = ifs[0]['net_id']
ghanshyam4c7d2a02015-09-14 16:05:13 +0900258 self.servers_client.add_fixed_ip(server['id'], networkId=network_id)
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900259 # Remove the fixed IP from server.
Ken'ichi Ohmichi76800242015-07-03 05:12:31 +0000260 server_detail = self.os.servers_client.show_server(
ghanshyam0f825252015-08-25 16:02:50 +0900261 server['id'])['server']
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900262 # Get the Fixed IP from server.
263 fixed_ip = None
264 for ip_set in server_detail['addresses']:
265 for ip in server_detail['addresses'][ip_set]:
266 if ip['OS-EXT-IPS:type'] == 'fixed':
267 fixed_ip = ip['addr']
268 break
269 if fixed_ip is not None:
270 break
ghanshyam4c7d2a02015-09-14 16:05:13 +0900271 self.servers_client.remove_fixed_ip(server['id'], address=fixed_ip)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400272
Matt Riedemann3570c1e2016-07-29 12:15:38 -0400273 @decorators.skip_because(bug='1607714')
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400274 @test.idempotent_id('2f3a0127-95c7-4977-92d2-bc5aec602fb4')
275 def test_reassign_port_between_servers(self):
276 """Tests the following:
277
278 1. Create a port in Neutron.
279 2. Create two servers in Nova.
280 3. Attach the port to the first server.
281 4. Detach the port from the first server.
282 5. Attach the port to the second server.
283 6. Detach the port from the second server.
284 """
285 network = self.get_tenant_network()
286 network_id = network['id']
287 port = self.ports_client.create_port(network_id=network_id)
288 port_id = port['port']['id']
289 self.addCleanup(self.ports_client.delete_port, port_id)
290
291 # create two servers
292 _, servers = compute.create_test_server(
293 self.os, tenant_network=network, wait_until='ACTIVE', min_count=2)
294 # add our cleanups for the servers since we bypassed the base class
295 for server in servers:
296 self.addCleanup(waiters.wait_for_server_termination,
297 self.servers_client, server['id'])
298 self.addCleanup(self.servers_client.delete_server, server['id'])
299
300 for server in servers:
301 # attach the port to the server
lkuchlan87b5a2d2016-09-27 15:46:16 +0300302 iface = self.interfaces_client.create_interface(
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400303 server['id'], port_id=port_id)['interfaceAttachment']
304 self._check_interface(iface, port_id=port_id)
305
306 # detach the port from the server; this is a cast in the compute
307 # API so we have to poll the port until the device_id is unset.
lkuchlan87b5a2d2016-09-27 15:46:16 +0300308 self.interfaces_client.delete_interface(server['id'], port_id)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400309 self.wait_for_port_detach(port_id)