blob: d02f86f13ebf4547b95ee7d02cb1f994abdc0262 [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
Oleg Bondarevee50bb12014-01-16 00:01:34 +040023from tempest import exceptions
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()
David Kranzb9017e72013-05-07 11:16:29 -040049 cls.client = cls.os.interfaces_client
Maho Koshiya7b629582016-02-22 10:59:01 +090050 cls.networks_client = cls.os.networks_client
51 cls.subnets_client = cls.os.subnets_client
Maho Koshiya3fc12462015-12-14 19:03:12 +090052 cls.ports_client = cls.os.ports_client
Matt Riedemanna8c641a2016-07-12 17:07:33 -040053 cls.servers_client = cls.servers_client
Dan Smith8ad1c472013-02-26 13:03:16 -050054
Ken'ichi Ohmichi84e99682015-07-08 05:28:57 +000055 def wait_for_interface_status(self, server, port_id, status):
Maho Koshiya3fc12462015-12-14 19:03:12 +090056 """Waits for an interface to reach a given status."""
ghanshyama2364f12015-08-24 15:45:37 +090057 body = (self.client.show_interface(server, port_id)
58 ['interfaceAttachment'])
Ken'ichi Ohmichi84e99682015-07-08 05:28:57 +000059 interface_status = body['port_state']
60 start = int(time.time())
61
62 while(interface_status != status):
63 time.sleep(self.build_interval)
ghanshyama2364f12015-08-24 15:45:37 +090064 body = (self.client.show_interface(server, port_id)
65 ['interfaceAttachment'])
Ken'ichi Ohmichi84e99682015-07-08 05:28:57 +000066 interface_status = body['port_state']
67
68 timed_out = int(time.time()) - start >= self.build_timeout
69
70 if interface_status != status and timed_out:
71 message = ('Interface %s failed to reach %s status '
72 '(current %s) within the required time (%s s).' %
73 (port_id, status, interface_status,
74 self.build_timeout))
75 raise exceptions.TimeoutException(message)
76
77 return body
78
Matt Riedemanna8c641a2016-07-12 17:07:33 -040079 # TODO(mriedem): move this into a common waiters utility module
80 def wait_for_port_detach(self, port_id):
81 """Waits for the port's device_id to be unset.
82
83 :param port_id: The id of the port being detached.
84 :returns: The final port dict from the show_port response.
85 """
86 port = self.ports_client.show_port(port_id)['port']
87 device_id = port['device_id']
88 start = int(time.time())
89
90 # NOTE(mriedem): Nova updates the port's device_id to '' rather than
91 # None, but it's not contractual so handle Falsey either way.
92 while device_id:
93 time.sleep(self.build_interval)
94 port = self.ports_client.show_port(port_id)['port']
95 device_id = port['device_id']
96
97 timed_out = int(time.time()) - start >= self.build_timeout
98
99 if device_id and timed_out:
100 message = ('Port %s failed to detach (device_id %s) within '
101 'the required time (%s s).' %
102 (port_id, device_id, self.build_timeout))
103 raise exceptions.TimeoutException(message)
104
105 return port
106
Dan Smith8ad1c472013-02-26 13:03:16 -0500107 def _check_interface(self, iface, port_id=None, network_id=None,
venkata anil45375302014-12-30 10:41:43 +0000108 fixed_ip=None, mac_addr=None):
Dan Smith8ad1c472013-02-26 13:03:16 -0500109 self.assertIn('port_state', iface)
110 if port_id:
111 self.assertEqual(iface['port_id'], port_id)
112 if network_id:
113 self.assertEqual(iface['net_id'], network_id)
114 if fixed_ip:
115 self.assertEqual(iface['fixed_ips'][0]['ip_address'], fixed_ip)
venkata anil45375302014-12-30 10:41:43 +0000116 if mac_addr:
117 self.assertEqual(iface['mac_addr'], mac_addr)
Dan Smith8ad1c472013-02-26 13:03:16 -0500118
119 def _create_server_get_interfaces(self):
David Kranz0fb14292015-02-11 15:55:20 -0500120 server = self.create_test_server(wait_until='ACTIVE')
ghanshyama2364f12015-08-24 15:45:37 +0900121 ifs = (self.client.list_interfaces(server['id'])
122 ['interfaceAttachments'])
Ken'ichi Ohmichi84e99682015-07-08 05:28:57 +0000123 body = self.wait_for_interface_status(
Leo Toyodaba9e9092013-04-08 09:02:11 +0900124 server['id'], ifs[0]['port_id'], 'ACTIVE')
125 ifs[0]['port_state'] = body['port_state']
Dan Smith8ad1c472013-02-26 13:03:16 -0500126 return server, ifs
127
128 def _test_create_interface(self, server):
ghanshyama2364f12015-08-24 15:45:37 +0900129 iface = (self.client.create_interface(server['id'])
130 ['interfaceAttachment'])
Ken'ichi Ohmichi84e99682015-07-08 05:28:57 +0000131 iface = self.wait_for_interface_status(
Leo Toyodaba9e9092013-04-08 09:02:11 +0900132 server['id'], iface['port_id'], 'ACTIVE')
Dan Smith8ad1c472013-02-26 13:03:16 -0500133 self._check_interface(iface)
134 return iface
135
136 def _test_create_interface_by_network_id(self, server, ifs):
137 network_id = ifs[0]['net_id']
ghanshyama2364f12015-08-24 15:45:37 +0900138 iface = self.client.create_interface(
139 server['id'], net_id=network_id)['interfaceAttachment']
Ken'ichi Ohmichi84e99682015-07-08 05:28:57 +0000140 iface = self.wait_for_interface_status(
Leo Toyodaba9e9092013-04-08 09:02:11 +0900141 server['id'], iface['port_id'], 'ACTIVE')
Dan Smith8ad1c472013-02-26 13:03:16 -0500142 self._check_interface(iface, network_id=network_id)
143 return iface
144
Maho Koshiya3fc12462015-12-14 19:03:12 +0900145 def _test_create_interface_by_port_id(self, server, ifs):
146 network_id = ifs[0]['net_id']
147 port = self.ports_client.create_port(network_id=network_id)
148 port_id = port['port']['id']
149 self.addCleanup(self.ports_client.delete_port, port_id)
150 iface = self.client.create_interface(
151 server['id'], port_id=port_id)['interfaceAttachment']
152 iface = self.wait_for_interface_status(
153 server['id'], iface['port_id'], 'ACTIVE')
154 self._check_interface(iface, port_id=port_id)
155 return iface
156
Maho Koshiya7b629582016-02-22 10:59:01 +0900157 def _test_create_interface_by_fixed_ips(self, server, ifs):
158 network_id = ifs[0]['net_id']
Ryan Tidwell1964a262016-05-04 15:13:23 -0700159 subnet_id = ifs[0]['fixed_ips'][0]['subnet_id']
160 ip_list = net_utils.get_unused_ip_addresses(self.ports_client,
161 self.subnets_client,
162 network_id,
163 subnet_id,
164 1)
Maho Koshiya7b629582016-02-22 10:59:01 +0900165
Ryan Tidwell1964a262016-05-04 15:13:23 -0700166 fixed_ips = [{'ip_address': ip_list[0]}]
Maho Koshiya7b629582016-02-22 10:59:01 +0900167 iface = self.client.create_interface(
168 server['id'], net_id=network_id,
169 fixed_ips=fixed_ips)['interfaceAttachment']
170 self.addCleanup(self.ports_client.delete_port, iface['port_id'])
171 iface = self.wait_for_interface_status(
172 server['id'], iface['port_id'], 'ACTIVE')
Ryan Tidwell1964a262016-05-04 15:13:23 -0700173 self._check_interface(iface, fixed_ip=ip_list[0])
Maho Koshiya7b629582016-02-22 10:59:01 +0900174 return iface
175
Dan Smith8ad1c472013-02-26 13:03:16 -0500176 def _test_show_interface(self, server, ifs):
177 iface = ifs[0]
ghanshyama2364f12015-08-24 15:45:37 +0900178 _iface = self.client.show_interface(
179 server['id'], iface['port_id'])['interfaceAttachment']
venkata anil45375302014-12-30 10:41:43 +0000180 self._check_interface(iface, port_id=_iface['port_id'],
181 network_id=_iface['net_id'],
182 fixed_ip=_iface['fixed_ips'][0]['ip_address'],
183 mac_addr=_iface['mac_addr'])
Dan Smith8ad1c472013-02-26 13:03:16 -0500184
185 def _test_delete_interface(self, server, ifs):
186 # NOTE(danms): delete not the first or last, but one in the middle
187 iface = ifs[1]
David Kranzb2b0c182015-02-18 13:28:19 -0500188 self.client.delete_interface(server['id'], iface['port_id'])
ghanshyama2364f12015-08-24 15:45:37 +0900189 _ifs = (self.client.list_interfaces(server['id'])
190 ['interfaceAttachments'])
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400191 start = int(time.time())
Dan Smith8ad1c472013-02-26 13:03:16 -0500192
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400193 while len(ifs) == len(_ifs):
194 time.sleep(self.build_interval)
ghanshyama2364f12015-08-24 15:45:37 +0900195 _ifs = (self.client.list_interfaces(server['id'])
196 ['interfaceAttachments'])
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400197 timed_out = int(time.time()) - start >= self.build_timeout
198 if len(ifs) == len(_ifs) and timed_out:
199 message = ('Failed to delete interface within '
200 'the required time: %s sec.' % self.build_timeout)
201 raise exceptions.TimeoutException(message)
202
203 self.assertNotIn(iface['port_id'], [i['port_id'] for i in _ifs])
Dan Smith8ad1c472013-02-26 13:03:16 -0500204 return _ifs
205
206 def _compare_iface_list(self, list1, list2):
207 # NOTE(danms): port_state will likely have changed, so just
208 # confirm the port_ids are the same at least
209 list1 = [x['port_id'] for x in list1]
210 list2 = [x['port_id'] for x in list2]
211
212 self.assertEqual(sorted(list1), sorted(list2))
213
Chris Hoge7579c1a2015-02-26 14:12:15 -0800214 @test.idempotent_id('73fe8f02-590d-4bf1-b184-e9ca81065051')
Matthew Treinish2df97482014-06-13 15:02:26 -0400215 @test.services('network')
Dan Smith8ad1c472013-02-26 13:03:16 -0500216 def test_create_list_show_delete_interfaces(self):
217 server, ifs = self._create_server_get_interfaces()
218 interface_count = len(ifs)
219 self.assertTrue(interface_count > 0)
220 self._check_interface(ifs[0])
221
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530222 try:
223 iface = self._test_create_interface(server)
224 except lib_exc.BadRequest as e:
225 msg = ('Multiple possible networks found, use a Network ID to be '
226 'more specific.')
227 if not CONF.compute.fixed_network_name and e.message == msg:
228 raise
229 else:
230 ifs.append(iface)
Dan Smith8ad1c472013-02-26 13:03:16 -0500231
232 iface = self._test_create_interface_by_network_id(server, ifs)
233 ifs.append(iface)
234
Maho Koshiya3fc12462015-12-14 19:03:12 +0900235 iface = self._test_create_interface_by_port_id(server, ifs)
236 ifs.append(iface)
237
Maho Koshiya7b629582016-02-22 10:59:01 +0900238 iface = self._test_create_interface_by_fixed_ips(server, ifs)
239 ifs.append(iface)
240
ghanshyama2364f12015-08-24 15:45:37 +0900241 _ifs = (self.client.list_interfaces(server['id'])
242 ['interfaceAttachments'])
Dan Smith8ad1c472013-02-26 13:03:16 -0500243 self._compare_iface_list(ifs, _ifs)
244
245 self._test_show_interface(server, ifs)
246
247 _ifs = self._test_delete_interface(server, ifs)
248 self.assertEqual(len(ifs) - 1, len(_ifs))
249
Masayuki Igawa750aa922014-03-20 09:46:37 +0900250 @test.attr(type='smoke')
Chris Hoge7579c1a2015-02-26 14:12:15 -0800251 @test.idempotent_id('c7e0e60b-ee45-43d0-abeb-8596fd42a2f9')
Matthew Treinish2df97482014-06-13 15:02:26 -0400252 @test.services('network')
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900253 def test_add_remove_fixed_ip(self):
254 # Add and Remove the fixed IP to server.
255 server, ifs = self._create_server_get_interfaces()
256 interface_count = len(ifs)
257 self.assertTrue(interface_count > 0)
258 self._check_interface(ifs[0])
259 network_id = ifs[0]['net_id']
ghanshyam4c7d2a02015-09-14 16:05:13 +0900260 self.servers_client.add_fixed_ip(server['id'], networkId=network_id)
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900261 # Remove the fixed IP from server.
Ken'ichi Ohmichi76800242015-07-03 05:12:31 +0000262 server_detail = self.os.servers_client.show_server(
ghanshyam0f825252015-08-25 16:02:50 +0900263 server['id'])['server']
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900264 # Get the Fixed IP from server.
265 fixed_ip = None
266 for ip_set in server_detail['addresses']:
267 for ip in server_detail['addresses'][ip_set]:
268 if ip['OS-EXT-IPS:type'] == 'fixed':
269 fixed_ip = ip['addr']
270 break
271 if fixed_ip is not None:
272 break
ghanshyam4c7d2a02015-09-14 16:05:13 +0900273 self.servers_client.remove_fixed_ip(server['id'], address=fixed_ip)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400274
275 @test.idempotent_id('2f3a0127-95c7-4977-92d2-bc5aec602fb4')
276 def test_reassign_port_between_servers(self):
277 """Tests the following:
278
279 1. Create a port in Neutron.
280 2. Create two servers in Nova.
281 3. Attach the port to the first server.
282 4. Detach the port from the first server.
283 5. Attach the port to the second server.
284 6. Detach the port from the second server.
285 """
286 network = self.get_tenant_network()
287 network_id = network['id']
288 port = self.ports_client.create_port(network_id=network_id)
289 port_id = port['port']['id']
290 self.addCleanup(self.ports_client.delete_port, port_id)
291
292 # create two servers
293 _, servers = compute.create_test_server(
294 self.os, tenant_network=network, wait_until='ACTIVE', min_count=2)
295 # add our cleanups for the servers since we bypassed the base class
296 for server in servers:
297 self.addCleanup(waiters.wait_for_server_termination,
298 self.servers_client, server['id'])
299 self.addCleanup(self.servers_client.delete_server, server['id'])
300
301 for server in servers:
302 # attach the port to the server
303 iface = self.client.create_interface(
304 server['id'], port_id=port_id)['interfaceAttachment']
305 self._check_interface(iface, port_id=port_id)
306
307 # detach the port from the server; this is a cast in the compute
308 # API so we have to poll the port until the device_id is unset.
309 self.client.delete_interface(server['id'], port_id)
310 self.wait_for_port_detach(port_id)