blob: bfde847663346694a6d82961c80e6ca8b1362be4 [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
Ryan Tidwell1964a262016-05-04 15:13:23 -070022from tempest.common.utils import net_utils
Matt Riedemanna8c641a2016-07-12 17:07:33 -040023from tempest.common import waiters
Matthew Treinishb0a78fc2014-01-29 16:49:12 +000024from tempest import config
Matt Riedemann3570c1e2016-07-29 12:15:38 -040025from tempest.lib import decorators
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050026from tempest.lib import exceptions as lib_exc
Yuiko Takadae9999d62014-03-06 09:22:54 +000027from tempest import test
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
Dan Smith8ad1c472013-02-26 13:03:16 -050081 def _check_interface(self, iface, port_id=None, network_id=None,
venkata anil45375302014-12-30 10:41:43 +000082 fixed_ip=None, mac_addr=None):
Dan Smith8ad1c472013-02-26 13:03:16 -050083 if port_id:
84 self.assertEqual(iface['port_id'], port_id)
85 if network_id:
86 self.assertEqual(iface['net_id'], network_id)
87 if fixed_ip:
88 self.assertEqual(iface['fixed_ips'][0]['ip_address'], fixed_ip)
venkata anil45375302014-12-30 10:41:43 +000089 if mac_addr:
90 self.assertEqual(iface['mac_addr'], mac_addr)
Dan Smith8ad1c472013-02-26 13:03:16 -050091
92 def _create_server_get_interfaces(self):
David Kranz0fb14292015-02-11 15:55:20 -050093 server = self.create_test_server(wait_until='ACTIVE')
lkuchlan87b5a2d2016-09-27 15:46:16 +030094 ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +090095 ['interfaceAttachments'])
zhufl7b638332016-11-14 10:23:30 +080096 body = waiters.wait_for_interface_status(
97 self.interfaces_client, server['id'], ifs[0]['port_id'], 'ACTIVE')
Leo Toyodaba9e9092013-04-08 09:02:11 +090098 ifs[0]['port_state'] = body['port_state']
Dan Smith8ad1c472013-02-26 13:03:16 -050099 return server, ifs
100
101 def _test_create_interface(self, server):
lkuchlan87b5a2d2016-09-27 15:46:16 +0300102 iface = (self.interfaces_client.create_interface(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900103 ['interfaceAttachment'])
zhufl7b638332016-11-14 10:23:30 +0800104 iface = waiters.wait_for_interface_status(
105 self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
Dan Smith8ad1c472013-02-26 13:03:16 -0500106 self._check_interface(iface)
107 return iface
108
109 def _test_create_interface_by_network_id(self, server, ifs):
110 network_id = ifs[0]['net_id']
lkuchlan87b5a2d2016-09-27 15:46:16 +0300111 iface = self.interfaces_client.create_interface(
ghanshyama2364f12015-08-24 15:45:37 +0900112 server['id'], net_id=network_id)['interfaceAttachment']
zhufl7b638332016-11-14 10:23:30 +0800113 iface = waiters.wait_for_interface_status(
114 self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
Dan Smith8ad1c472013-02-26 13:03:16 -0500115 self._check_interface(iface, network_id=network_id)
116 return iface
117
Maho Koshiya3fc12462015-12-14 19:03:12 +0900118 def _test_create_interface_by_port_id(self, server, ifs):
119 network_id = ifs[0]['net_id']
120 port = self.ports_client.create_port(network_id=network_id)
121 port_id = port['port']['id']
122 self.addCleanup(self.ports_client.delete_port, port_id)
lkuchlan87b5a2d2016-09-27 15:46:16 +0300123 iface = self.interfaces_client.create_interface(
Maho Koshiya3fc12462015-12-14 19:03:12 +0900124 server['id'], port_id=port_id)['interfaceAttachment']
zhufl7b638332016-11-14 10:23:30 +0800125 iface = waiters.wait_for_interface_status(
126 self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
Maho Koshiya3fc12462015-12-14 19:03:12 +0900127 self._check_interface(iface, port_id=port_id)
128 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'])
zhufl7b638332016-11-14 10:23:30 +0800144 iface = waiters.wait_for_interface_status(
145 self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
Ryan Tidwell1964a262016-05-04 15:13:23 -0700146 self._check_interface(iface, fixed_ip=ip_list[0])
Maho Koshiya7b629582016-02-22 10:59:01 +0900147 return iface
148
Dan Smith8ad1c472013-02-26 13:03:16 -0500149 def _test_show_interface(self, server, ifs):
150 iface = ifs[0]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300151 _iface = self.interfaces_client.show_interface(
ghanshyama2364f12015-08-24 15:45:37 +0900152 server['id'], iface['port_id'])['interfaceAttachment']
venkata anil45375302014-12-30 10:41:43 +0000153 self._check_interface(iface, port_id=_iface['port_id'],
154 network_id=_iface['net_id'],
155 fixed_ip=_iface['fixed_ips'][0]['ip_address'],
156 mac_addr=_iface['mac_addr'])
Dan Smith8ad1c472013-02-26 13:03:16 -0500157
158 def _test_delete_interface(self, server, ifs):
159 # NOTE(danms): delete not the first or last, but one in the middle
160 iface = ifs[1]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300161 self.interfaces_client.delete_interface(server['id'], iface['port_id'])
162 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900163 ['interfaceAttachments'])
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400164 start = int(time.time())
Dan Smith8ad1c472013-02-26 13:03:16 -0500165
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400166 while len(ifs) == len(_ifs):
167 time.sleep(self.build_interval)
lkuchlan87b5a2d2016-09-27 15:46:16 +0300168 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900169 ['interfaceAttachments'])
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400170 timed_out = int(time.time()) - start >= self.build_timeout
171 if len(ifs) == len(_ifs) and timed_out:
172 message = ('Failed to delete interface within '
173 'the required time: %s sec.' % self.build_timeout)
guo yunxianebb15f22016-11-01 21:03:35 +0800174 raise lib_exc.TimeoutException(message)
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400175
176 self.assertNotIn(iface['port_id'], [i['port_id'] for i in _ifs])
Dan Smith8ad1c472013-02-26 13:03:16 -0500177 return _ifs
178
179 def _compare_iface_list(self, list1, list2):
180 # NOTE(danms): port_state will likely have changed, so just
181 # confirm the port_ids are the same at least
182 list1 = [x['port_id'] for x in list1]
183 list2 = [x['port_id'] for x in list2]
184
185 self.assertEqual(sorted(list1), sorted(list2))
186
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800187 @decorators.idempotent_id('73fe8f02-590d-4bf1-b184-e9ca81065051')
Matthew Treinish2df97482014-06-13 15:02:26 -0400188 @test.services('network')
Dan Smith8ad1c472013-02-26 13:03:16 -0500189 def test_create_list_show_delete_interfaces(self):
190 server, ifs = self._create_server_get_interfaces()
191 interface_count = len(ifs)
zhufl080dcfb2016-10-21 17:45:38 +0800192 self.assertGreater(interface_count, 0)
Dan Smith8ad1c472013-02-26 13:03:16 -0500193 self._check_interface(ifs[0])
194
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530195 try:
196 iface = self._test_create_interface(server)
197 except lib_exc.BadRequest as e:
198 msg = ('Multiple possible networks found, use a Network ID to be '
199 'more specific.')
junbolibc2ae862017-07-29 15:46:48 +0800200 if not CONF.compute.fixed_network_name and six.text_type(e) == msg:
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530201 raise
202 else:
203 ifs.append(iface)
Dan Smith8ad1c472013-02-26 13:03:16 -0500204
205 iface = self._test_create_interface_by_network_id(server, ifs)
206 ifs.append(iface)
207
Maho Koshiya3fc12462015-12-14 19:03:12 +0900208 iface = self._test_create_interface_by_port_id(server, ifs)
209 ifs.append(iface)
210
Maho Koshiya7b629582016-02-22 10:59:01 +0900211 iface = self._test_create_interface_by_fixed_ips(server, ifs)
212 ifs.append(iface)
213
lkuchlan87b5a2d2016-09-27 15:46:16 +0300214 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900215 ['interfaceAttachments'])
Dan Smith8ad1c472013-02-26 13:03:16 -0500216 self._compare_iface_list(ifs, _ifs)
217
218 self._test_show_interface(server, ifs)
219
220 _ifs = self._test_delete_interface(server, ifs)
221 self.assertEqual(len(ifs) - 1, len(_ifs))
222
Jordan Pittier3b46d272017-04-12 16:17:28 +0200223 @decorators.attr(type='smoke')
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800224 @decorators.idempotent_id('c7e0e60b-ee45-43d0-abeb-8596fd42a2f9')
Matthew Treinish2df97482014-06-13 15:02:26 -0400225 @test.services('network')
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900226 def test_add_remove_fixed_ip(self):
227 # Add and Remove the fixed IP to server.
228 server, ifs = self._create_server_get_interfaces()
229 interface_count = len(ifs)
zhufl080dcfb2016-10-21 17:45:38 +0800230 self.assertGreater(interface_count, 0)
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900231 self._check_interface(ifs[0])
232 network_id = ifs[0]['net_id']
ghanshyam4c7d2a02015-09-14 16:05:13 +0900233 self.servers_client.add_fixed_ip(server['id'], networkId=network_id)
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900234 # Remove the fixed IP from server.
Jordan Pittier8160d312017-04-18 11:52:23 +0200235 server_detail = self.os_primary.servers_client.show_server(
ghanshyam0f825252015-08-25 16:02:50 +0900236 server['id'])['server']
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900237 # Get the Fixed IP from server.
238 fixed_ip = None
239 for ip_set in server_detail['addresses']:
240 for ip in server_detail['addresses'][ip_set]:
241 if ip['OS-EXT-IPS:type'] == 'fixed':
242 fixed_ip = ip['addr']
243 break
244 if fixed_ip is not None:
245 break
ghanshyam4c7d2a02015-09-14 16:05:13 +0900246 self.servers_client.remove_fixed_ip(server['id'], address=fixed_ip)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400247
Matt Riedemann3570c1e2016-07-29 12:15:38 -0400248 @decorators.skip_because(bug='1607714')
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800249 @decorators.idempotent_id('2f3a0127-95c7-4977-92d2-bc5aec602fb4')
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400250 def test_reassign_port_between_servers(self):
251 """Tests the following:
252
253 1. Create a port in Neutron.
254 2. Create two servers in Nova.
255 3. Attach the port to the first server.
256 4. Detach the port from the first server.
257 5. Attach the port to the second server.
258 6. Detach the port from the second server.
259 """
260 network = self.get_tenant_network()
261 network_id = network['id']
262 port = self.ports_client.create_port(network_id=network_id)
263 port_id = port['port']['id']
264 self.addCleanup(self.ports_client.delete_port, port_id)
265
266 # create two servers
267 _, servers = compute.create_test_server(
zhufl04190882017-05-23 10:21:48 +0800268 self.os_primary, tenant_network=network,
269 wait_until='ACTIVE', min_count=2)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400270 # add our cleanups for the servers since we bypassed the base class
271 for server in servers:
zhufl1355d982017-01-05 12:06:20 +0800272 self.addCleanup(self.delete_server, server['id'])
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400273
274 for server in servers:
275 # attach the port to the server
lkuchlan87b5a2d2016-09-27 15:46:16 +0300276 iface = self.interfaces_client.create_interface(
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400277 server['id'], port_id=port_id)['interfaceAttachment']
278 self._check_interface(iface, port_id=port_id)
279
280 # detach the port from the server; this is a cast in the compute
281 # API so we have to poll the port until the device_id is unset.
lkuchlan87b5a2d2016-09-27 15:46:16 +0300282 self.interfaces_client.delete_interface(server['id'], port_id)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400283 self.wait_for_port_detach(port_id)