blob: 8342a3efa25d357109ac5a517a52b3580c1df9c1 [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
Matt Riedemanna8c641a2016-07-12 17:07:33 -040053 # TODO(mriedem): move this into a common waiters utility module
54 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 self.assertIn('port_state', iface)
84 if port_id:
85 self.assertEqual(iface['port_id'], port_id)
86 if network_id:
87 self.assertEqual(iface['net_id'], network_id)
88 if fixed_ip:
89 self.assertEqual(iface['fixed_ips'][0]['ip_address'], fixed_ip)
venkata anil45375302014-12-30 10:41:43 +000090 if mac_addr:
91 self.assertEqual(iface['mac_addr'], mac_addr)
Dan Smith8ad1c472013-02-26 13:03:16 -050092
93 def _create_server_get_interfaces(self):
David Kranz0fb14292015-02-11 15:55:20 -050094 server = self.create_test_server(wait_until='ACTIVE')
lkuchlan87b5a2d2016-09-27 15:46:16 +030095 ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +090096 ['interfaceAttachments'])
zhufl7b638332016-11-14 10:23:30 +080097 body = waiters.wait_for_interface_status(
98 self.interfaces_client, server['id'], ifs[0]['port_id'], 'ACTIVE')
Leo Toyodaba9e9092013-04-08 09:02:11 +090099 ifs[0]['port_state'] = body['port_state']
Dan Smith8ad1c472013-02-26 13:03:16 -0500100 return server, ifs
101
102 def _test_create_interface(self, server):
lkuchlan87b5a2d2016-09-27 15:46:16 +0300103 iface = (self.interfaces_client.create_interface(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900104 ['interfaceAttachment'])
zhufl7b638332016-11-14 10:23:30 +0800105 iface = waiters.wait_for_interface_status(
106 self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
Dan Smith8ad1c472013-02-26 13:03:16 -0500107 self._check_interface(iface)
108 return iface
109
110 def _test_create_interface_by_network_id(self, server, ifs):
111 network_id = ifs[0]['net_id']
lkuchlan87b5a2d2016-09-27 15:46:16 +0300112 iface = self.interfaces_client.create_interface(
ghanshyama2364f12015-08-24 15:45:37 +0900113 server['id'], net_id=network_id)['interfaceAttachment']
zhufl7b638332016-11-14 10:23:30 +0800114 iface = waiters.wait_for_interface_status(
115 self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
Dan Smith8ad1c472013-02-26 13:03:16 -0500116 self._check_interface(iface, network_id=network_id)
117 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']
zhufl7b638332016-11-14 10:23:30 +0800126 iface = waiters.wait_for_interface_status(
127 self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
Maho Koshiya3fc12462015-12-14 19:03:12 +0900128 self._check_interface(iface, port_id=port_id)
129 return iface
130
Maho Koshiya7b629582016-02-22 10:59:01 +0900131 def _test_create_interface_by_fixed_ips(self, server, ifs):
132 network_id = ifs[0]['net_id']
Ryan Tidwell1964a262016-05-04 15:13:23 -0700133 subnet_id = ifs[0]['fixed_ips'][0]['subnet_id']
134 ip_list = net_utils.get_unused_ip_addresses(self.ports_client,
135 self.subnets_client,
136 network_id,
137 subnet_id,
138 1)
Maho Koshiya7b629582016-02-22 10:59:01 +0900139
Ryan Tidwell1964a262016-05-04 15:13:23 -0700140 fixed_ips = [{'ip_address': ip_list[0]}]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300141 iface = self.interfaces_client.create_interface(
Maho Koshiya7b629582016-02-22 10:59:01 +0900142 server['id'], net_id=network_id,
143 fixed_ips=fixed_ips)['interfaceAttachment']
144 self.addCleanup(self.ports_client.delete_port, iface['port_id'])
zhufl7b638332016-11-14 10:23:30 +0800145 iface = waiters.wait_for_interface_status(
146 self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
Ryan Tidwell1964a262016-05-04 15:13:23 -0700147 self._check_interface(iface, fixed_ip=ip_list[0])
Maho Koshiya7b629582016-02-22 10:59:01 +0900148 return iface
149
Dan Smith8ad1c472013-02-26 13:03:16 -0500150 def _test_show_interface(self, server, ifs):
151 iface = ifs[0]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300152 _iface = self.interfaces_client.show_interface(
ghanshyama2364f12015-08-24 15:45:37 +0900153 server['id'], iface['port_id'])['interfaceAttachment']
venkata anil45375302014-12-30 10:41:43 +0000154 self._check_interface(iface, port_id=_iface['port_id'],
155 network_id=_iface['net_id'],
156 fixed_ip=_iface['fixed_ips'][0]['ip_address'],
157 mac_addr=_iface['mac_addr'])
Dan Smith8ad1c472013-02-26 13:03:16 -0500158
159 def _test_delete_interface(self, server, ifs):
160 # NOTE(danms): delete not the first or last, but one in the middle
161 iface = ifs[1]
lkuchlan87b5a2d2016-09-27 15:46:16 +0300162 self.interfaces_client.delete_interface(server['id'], iface['port_id'])
163 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900164 ['interfaceAttachments'])
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400165 start = int(time.time())
Dan Smith8ad1c472013-02-26 13:03:16 -0500166
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400167 while len(ifs) == len(_ifs):
168 time.sleep(self.build_interval)
lkuchlan87b5a2d2016-09-27 15:46:16 +0300169 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900170 ['interfaceAttachments'])
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400171 timed_out = int(time.time()) - start >= self.build_timeout
172 if len(ifs) == len(_ifs) and timed_out:
173 message = ('Failed to delete interface within '
174 'the required time: %s sec.' % self.build_timeout)
guo yunxianebb15f22016-11-01 21:03:35 +0800175 raise lib_exc.TimeoutException(message)
Oleg Bondarevee50bb12014-01-16 00:01:34 +0400176
177 self.assertNotIn(iface['port_id'], [i['port_id'] for i in _ifs])
Dan Smith8ad1c472013-02-26 13:03:16 -0500178 return _ifs
179
180 def _compare_iface_list(self, list1, list2):
181 # NOTE(danms): port_state will likely have changed, so just
182 # confirm the port_ids are the same at least
183 list1 = [x['port_id'] for x in list1]
184 list2 = [x['port_id'] for x in list2]
185
186 self.assertEqual(sorted(list1), sorted(list2))
187
Chris Hoge7579c1a2015-02-26 14:12:15 -0800188 @test.idempotent_id('73fe8f02-590d-4bf1-b184-e9ca81065051')
Matthew Treinish2df97482014-06-13 15:02:26 -0400189 @test.services('network')
Dan Smith8ad1c472013-02-26 13:03:16 -0500190 def test_create_list_show_delete_interfaces(self):
191 server, ifs = self._create_server_get_interfaces()
192 interface_count = len(ifs)
zhufl080dcfb2016-10-21 17:45:38 +0800193 self.assertGreater(interface_count, 0)
Dan Smith8ad1c472013-02-26 13:03:16 -0500194 self._check_interface(ifs[0])
195
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.')
201 if not CONF.compute.fixed_network_name and e.message == msg:
202 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
Maho Koshiya7b629582016-02-22 10:59:01 +0900212 iface = self._test_create_interface_by_fixed_ips(server, ifs)
213 ifs.append(iface)
214
lkuchlan87b5a2d2016-09-27 15:46:16 +0300215 _ifs = (self.interfaces_client.list_interfaces(server['id'])
ghanshyama2364f12015-08-24 15:45:37 +0900216 ['interfaceAttachments'])
Dan Smith8ad1c472013-02-26 13:03:16 -0500217 self._compare_iface_list(ifs, _ifs)
218
219 self._test_show_interface(server, ifs)
220
221 _ifs = self._test_delete_interface(server, ifs)
222 self.assertEqual(len(ifs) - 1, len(_ifs))
223
Masayuki Igawa750aa922014-03-20 09:46:37 +0900224 @test.attr(type='smoke')
Chris Hoge7579c1a2015-02-26 14:12:15 -0800225 @test.idempotent_id('c7e0e60b-ee45-43d0-abeb-8596fd42a2f9')
Matthew Treinish2df97482014-06-13 15:02:26 -0400226 @test.services('network')
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900227 def test_add_remove_fixed_ip(self):
228 # Add and Remove the fixed IP to server.
229 server, ifs = self._create_server_get_interfaces()
230 interface_count = len(ifs)
zhufl080dcfb2016-10-21 17:45:38 +0800231 self.assertGreater(interface_count, 0)
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900232 self._check_interface(ifs[0])
233 network_id = ifs[0]['net_id']
ghanshyam4c7d2a02015-09-14 16:05:13 +0900234 self.servers_client.add_fixed_ip(server['id'], networkId=network_id)
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900235 # Remove the fixed IP from server.
Ken'ichi Ohmichi76800242015-07-03 05:12:31 +0000236 server_detail = self.os.servers_client.show_server(
ghanshyam0f825252015-08-25 16:02:50 +0900237 server['id'])['server']
Ghanshyam Mann6e855d12014-02-26 13:31:56 +0900238 # Get the Fixed IP from server.
239 fixed_ip = None
240 for ip_set in server_detail['addresses']:
241 for ip in server_detail['addresses'][ip_set]:
242 if ip['OS-EXT-IPS:type'] == 'fixed':
243 fixed_ip = ip['addr']
244 break
245 if fixed_ip is not None:
246 break
ghanshyam4c7d2a02015-09-14 16:05:13 +0900247 self.servers_client.remove_fixed_ip(server['id'], address=fixed_ip)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400248
Matt Riedemann3570c1e2016-07-29 12:15:38 -0400249 @decorators.skip_because(bug='1607714')
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400250 @test.idempotent_id('2f3a0127-95c7-4977-92d2-bc5aec602fb4')
251 def test_reassign_port_between_servers(self):
252 """Tests the following:
253
254 1. Create a port in Neutron.
255 2. Create two servers in Nova.
256 3. Attach the port to the first server.
257 4. Detach the port from the first server.
258 5. Attach the port to the second server.
259 6. Detach the port from the second server.
260 """
261 network = self.get_tenant_network()
262 network_id = network['id']
263 port = self.ports_client.create_port(network_id=network_id)
264 port_id = port['port']['id']
265 self.addCleanup(self.ports_client.delete_port, port_id)
266
267 # create two servers
268 _, servers = compute.create_test_server(
269 self.os, tenant_network=network, wait_until='ACTIVE', min_count=2)
270 # add our cleanups for the servers since we bypassed the base class
271 for server in servers:
272 self.addCleanup(waiters.wait_for_server_termination,
273 self.servers_client, server['id'])
274 self.addCleanup(self.servers_client.delete_server, server['id'])
275
276 for server in servers:
277 # attach the port to the server
lkuchlan87b5a2d2016-09-27 15:46:16 +0300278 iface = self.interfaces_client.create_interface(
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400279 server['id'], port_id=port_id)['interfaceAttachment']
280 self._check_interface(iface, port_id=port_id)
281
282 # detach the port from the server; this is a cast in the compute
283 # API so we have to poll the port until the device_id is unset.
lkuchlan87b5a2d2016-09-27 15:46:16 +0300284 self.interfaces_client.delete_interface(server['id'], port_id)
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400285 self.wait_for_port_detach(port_id)