| Dan Smith | 8ad1c47 | 2013-02-26 13:03:16 -0500 | [diff] [blame] | 1 | # 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 |  | 
| Sean Dague | 1937d09 | 2013-05-17 16:36:38 -0400 | [diff] [blame] | 16 | from tempest.api.compute import base | 
| Matthew Treinish | b0a78fc | 2014-01-29 16:49:12 +0000 | [diff] [blame] | 17 | from tempest import config | 
| Oleg Bondarev | ee50bb1 | 2014-01-16 00:01:34 +0400 | [diff] [blame] | 18 | from tempest import exceptions | 
| Yuiko Takada | e9999d6 | 2014-03-06 09:22:54 +0000 | [diff] [blame] | 19 | from tempest import test | 
| Dan Smith | 8ad1c47 | 2013-02-26 13:03:16 -0500 | [diff] [blame] | 20 |  | 
|  | 21 | import time | 
|  | 22 |  | 
| Matthew Treinish | b0a78fc | 2014-01-29 16:49:12 +0000 | [diff] [blame] | 23 | CONF = config.CONF | 
|  | 24 |  | 
| Dan Smith | 8ad1c47 | 2013-02-26 13:03:16 -0500 | [diff] [blame] | 25 |  | 
| ivan-zhu | f2b0050 | 2013-10-18 10:06:52 +0800 | [diff] [blame] | 26 | class AttachInterfacesTestJSON(base.BaseV2ComputeTest): | 
| Dan Smith | 8ad1c47 | 2013-02-26 13:03:16 -0500 | [diff] [blame] | 27 |  | 
|  | 28 | @classmethod | 
|  | 29 | def setUpClass(cls): | 
| Matthew Treinish | b0a78fc | 2014-01-29 16:49:12 +0000 | [diff] [blame] | 30 | if not CONF.service_available.neutron: | 
| Mark McClain | f2982e8 | 2013-07-06 17:48:03 -0400 | [diff] [blame] | 31 | raise cls.skipException("Neutron is required") | 
| Adam Gandelman | 7186f7a | 2014-07-23 09:28:56 -0400 | [diff] [blame^] | 32 | if not CONF.compute_feature_enabled.interface_attach: | 
|  | 33 | raise cls.skipException("Interface attachment is not available.") | 
| Salvatore Orlando | 5a33724 | 2014-01-15 22:49:22 +0000 | [diff] [blame] | 34 | # This test class requires network and subnet | 
|  | 35 | cls.set_network_resources(network=True, subnet=True) | 
| David Kranz | b9017e7 | 2013-05-07 11:16:29 -0400 | [diff] [blame] | 36 | super(AttachInterfacesTestJSON, cls).setUpClass() | 
|  | 37 | cls.client = cls.os.interfaces_client | 
| Dan Smith | 8ad1c47 | 2013-02-26 13:03:16 -0500 | [diff] [blame] | 38 |  | 
|  | 39 | def _check_interface(self, iface, port_id=None, network_id=None, | 
|  | 40 | fixed_ip=None): | 
|  | 41 | self.assertIn('port_state', iface) | 
|  | 42 | if port_id: | 
|  | 43 | self.assertEqual(iface['port_id'], port_id) | 
|  | 44 | if network_id: | 
|  | 45 | self.assertEqual(iface['net_id'], network_id) | 
|  | 46 | if fixed_ip: | 
|  | 47 | self.assertEqual(iface['fixed_ips'][0]['ip_address'], fixed_ip) | 
|  | 48 |  | 
|  | 49 | def _create_server_get_interfaces(self): | 
| Ken'ichi Ohmichi | cfc052e | 2013-10-23 11:50:04 +0900 | [diff] [blame] | 50 | resp, server = self.create_test_server(wait_until='ACTIVE') | 
| Dan Smith | 8ad1c47 | 2013-02-26 13:03:16 -0500 | [diff] [blame] | 51 | resp, ifs = self.client.list_interfaces(server['id']) | 
| Ken'ichi Ohmichi | 5eb89e0 | 2014-03-04 23:45:43 +0900 | [diff] [blame] | 52 | self.assertEqual(200, resp.status) | 
| Leo Toyoda | ba9e909 | 2013-04-08 09:02:11 +0900 | [diff] [blame] | 53 | resp, body = self.client.wait_for_interface_status( | 
|  | 54 | server['id'], ifs[0]['port_id'], 'ACTIVE') | 
|  | 55 | ifs[0]['port_state'] = body['port_state'] | 
| Dan Smith | 8ad1c47 | 2013-02-26 13:03:16 -0500 | [diff] [blame] | 56 | return server, ifs | 
|  | 57 |  | 
|  | 58 | def _test_create_interface(self, server): | 
|  | 59 | resp, iface = self.client.create_interface(server['id']) | 
| Ken'ichi Ohmichi | 5eb89e0 | 2014-03-04 23:45:43 +0900 | [diff] [blame] | 60 | self.assertEqual(200, resp.status) | 
| Leo Toyoda | ba9e909 | 2013-04-08 09:02:11 +0900 | [diff] [blame] | 61 | resp, iface = self.client.wait_for_interface_status( | 
|  | 62 | server['id'], iface['port_id'], 'ACTIVE') | 
| Dan Smith | 8ad1c47 | 2013-02-26 13:03:16 -0500 | [diff] [blame] | 63 | self._check_interface(iface) | 
|  | 64 | return iface | 
|  | 65 |  | 
|  | 66 | def _test_create_interface_by_network_id(self, server, ifs): | 
|  | 67 | network_id = ifs[0]['net_id'] | 
|  | 68 | resp, iface = self.client.create_interface(server['id'], | 
|  | 69 | network_id=network_id) | 
| Ken'ichi Ohmichi | 5eb89e0 | 2014-03-04 23:45:43 +0900 | [diff] [blame] | 70 | self.assertEqual(200, resp.status) | 
| Leo Toyoda | ba9e909 | 2013-04-08 09:02:11 +0900 | [diff] [blame] | 71 | resp, iface = self.client.wait_for_interface_status( | 
|  | 72 | server['id'], iface['port_id'], 'ACTIVE') | 
| Dan Smith | 8ad1c47 | 2013-02-26 13:03:16 -0500 | [diff] [blame] | 73 | self._check_interface(iface, network_id=network_id) | 
|  | 74 | return iface | 
|  | 75 |  | 
|  | 76 | def _test_show_interface(self, server, ifs): | 
|  | 77 | iface = ifs[0] | 
|  | 78 | resp, _iface = self.client.show_interface(server['id'], | 
|  | 79 | iface['port_id']) | 
| Ken'ichi Ohmichi | 5eb89e0 | 2014-03-04 23:45:43 +0900 | [diff] [blame] | 80 | self.assertEqual(200, resp.status) | 
| Dan Smith | 8ad1c47 | 2013-02-26 13:03:16 -0500 | [diff] [blame] | 81 | self.assertEqual(iface, _iface) | 
|  | 82 |  | 
|  | 83 | def _test_delete_interface(self, server, ifs): | 
|  | 84 | # NOTE(danms): delete not the first or last, but one in the middle | 
|  | 85 | iface = ifs[1] | 
| Ken'ichi Ohmichi | 5eb89e0 | 2014-03-04 23:45:43 +0900 | [diff] [blame] | 86 | resp, _ = self.client.delete_interface(server['id'], iface['port_id']) | 
|  | 87 | self.assertEqual(202, resp.status) | 
| Oleg Bondarev | ee50bb1 | 2014-01-16 00:01:34 +0400 | [diff] [blame] | 88 | _ifs = self.client.list_interfaces(server['id'])[1] | 
|  | 89 | start = int(time.time()) | 
| Dan Smith | 8ad1c47 | 2013-02-26 13:03:16 -0500 | [diff] [blame] | 90 |  | 
| Oleg Bondarev | ee50bb1 | 2014-01-16 00:01:34 +0400 | [diff] [blame] | 91 | while len(ifs) == len(_ifs): | 
|  | 92 | time.sleep(self.build_interval) | 
|  | 93 | _ifs = self.client.list_interfaces(server['id'])[1] | 
|  | 94 | timed_out = int(time.time()) - start >= self.build_timeout | 
|  | 95 | if len(ifs) == len(_ifs) and timed_out: | 
|  | 96 | message = ('Failed to delete interface within ' | 
|  | 97 | 'the required time: %s sec.' % self.build_timeout) | 
|  | 98 | raise exceptions.TimeoutException(message) | 
|  | 99 |  | 
|  | 100 | self.assertNotIn(iface['port_id'], [i['port_id'] for i in _ifs]) | 
| Dan Smith | 8ad1c47 | 2013-02-26 13:03:16 -0500 | [diff] [blame] | 101 | return _ifs | 
|  | 102 |  | 
|  | 103 | def _compare_iface_list(self, list1, list2): | 
|  | 104 | # NOTE(danms): port_state will likely have changed, so just | 
|  | 105 | # confirm the port_ids are the same at least | 
|  | 106 | list1 = [x['port_id'] for x in list1] | 
|  | 107 | list2 = [x['port_id'] for x in list2] | 
|  | 108 |  | 
|  | 109 | self.assertEqual(sorted(list1), sorted(list2)) | 
|  | 110 |  | 
| Yuiko Takada | e9999d6 | 2014-03-06 09:22:54 +0000 | [diff] [blame] | 111 | @test.attr(type='smoke') | 
| Matthew Treinish | 2df9748 | 2014-06-13 15:02:26 -0400 | [diff] [blame] | 112 | @test.services('network') | 
| Dan Smith | 8ad1c47 | 2013-02-26 13:03:16 -0500 | [diff] [blame] | 113 | def test_create_list_show_delete_interfaces(self): | 
|  | 114 | server, ifs = self._create_server_get_interfaces() | 
|  | 115 | interface_count = len(ifs) | 
|  | 116 | self.assertTrue(interface_count > 0) | 
|  | 117 | self._check_interface(ifs[0]) | 
|  | 118 |  | 
|  | 119 | iface = self._test_create_interface(server) | 
|  | 120 | ifs.append(iface) | 
|  | 121 |  | 
|  | 122 | iface = self._test_create_interface_by_network_id(server, ifs) | 
|  | 123 | ifs.append(iface) | 
|  | 124 |  | 
|  | 125 | resp, _ifs = self.client.list_interfaces(server['id']) | 
|  | 126 | self._compare_iface_list(ifs, _ifs) | 
|  | 127 |  | 
|  | 128 | self._test_show_interface(server, ifs) | 
|  | 129 |  | 
|  | 130 | _ifs = self._test_delete_interface(server, ifs) | 
|  | 131 | self.assertEqual(len(ifs) - 1, len(_ifs)) | 
|  | 132 |  | 
| Masayuki Igawa | 750aa92 | 2014-03-20 09:46:37 +0900 | [diff] [blame] | 133 | @test.attr(type='smoke') | 
| Matthew Treinish | 2df9748 | 2014-06-13 15:02:26 -0400 | [diff] [blame] | 134 | @test.services('network') | 
| Ghanshyam Mann | 6e855d1 | 2014-02-26 13:31:56 +0900 | [diff] [blame] | 135 | def test_add_remove_fixed_ip(self): | 
|  | 136 | # Add and Remove the fixed IP to server. | 
|  | 137 | server, ifs = self._create_server_get_interfaces() | 
|  | 138 | interface_count = len(ifs) | 
|  | 139 | self.assertTrue(interface_count > 0) | 
|  | 140 | self._check_interface(ifs[0]) | 
|  | 141 | network_id = ifs[0]['net_id'] | 
|  | 142 | resp, body = self.client.add_fixed_ip(server['id'], | 
|  | 143 | network_id) | 
|  | 144 | self.assertEqual(202, resp.status) | 
|  | 145 | # Remove the fixed IP from server. | 
|  | 146 | server_resp, server_detail = self.os.servers_client.get_server( | 
|  | 147 | server['id']) | 
|  | 148 | # Get the Fixed IP from server. | 
|  | 149 | fixed_ip = None | 
|  | 150 | for ip_set in server_detail['addresses']: | 
|  | 151 | for ip in server_detail['addresses'][ip_set]: | 
|  | 152 | if ip['OS-EXT-IPS:type'] == 'fixed': | 
|  | 153 | fixed_ip = ip['addr'] | 
|  | 154 | break | 
|  | 155 | if fixed_ip is not None: | 
|  | 156 | break | 
|  | 157 | resp, body = self.client.remove_fixed_ip(server['id'], | 
|  | 158 | fixed_ip) | 
|  | 159 | self.assertEqual(202, resp.status) | 
|  | 160 |  | 
| Dan Smith | 8ad1c47 | 2013-02-26 13:03:16 -0500 | [diff] [blame] | 161 |  | 
|  | 162 | class AttachInterfacesTestXML(AttachInterfacesTestJSON): | 
|  | 163 | _interface = 'xml' |