root / snf-tools / synnefo_tools / burnin / cyclades_common.py @ 16c7f032
History | View | Annotate | Download (23.1 kB)
1 | d246be88 | Ilias Tsitsimpis | # Copyright 2013 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | d246be88 | Ilias Tsitsimpis | #
|
3 | d246be88 | Ilias Tsitsimpis | # Redistribution and use in source and binary forms, with or
|
4 | d246be88 | Ilias Tsitsimpis | # without modification, are permitted provided that the following
|
5 | d246be88 | Ilias Tsitsimpis | # conditions are met:
|
6 | d246be88 | Ilias Tsitsimpis | #
|
7 | d246be88 | Ilias Tsitsimpis | # 1. Redistributions of source code must retain the above
|
8 | d246be88 | Ilias Tsitsimpis | # copyright notice, this list of conditions and the following
|
9 | d246be88 | Ilias Tsitsimpis | # disclaimer.
|
10 | d246be88 | Ilias Tsitsimpis | #
|
11 | d246be88 | Ilias Tsitsimpis | # 2. Redistributions in binary form must reproduce the above
|
12 | d246be88 | Ilias Tsitsimpis | # copyright notice, this list of conditions and the following
|
13 | d246be88 | Ilias Tsitsimpis | # disclaimer in the documentation and/or other materials
|
14 | d246be88 | Ilias Tsitsimpis | # provided with the distribution.
|
15 | d246be88 | Ilias Tsitsimpis | #
|
16 | d246be88 | Ilias Tsitsimpis | # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 | d246be88 | Ilias Tsitsimpis | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 | d246be88 | Ilias Tsitsimpis | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 | d246be88 | Ilias Tsitsimpis | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 | d246be88 | Ilias Tsitsimpis | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 | d246be88 | Ilias Tsitsimpis | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 | d246be88 | Ilias Tsitsimpis | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 | d246be88 | Ilias Tsitsimpis | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 | d246be88 | Ilias Tsitsimpis | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 | d246be88 | Ilias Tsitsimpis | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 | d246be88 | Ilias Tsitsimpis | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 | d246be88 | Ilias Tsitsimpis | # POSSIBILITY OF SUCH DAMAGE.
|
28 | d246be88 | Ilias Tsitsimpis | #
|
29 | d246be88 | Ilias Tsitsimpis | # The views and conclusions contained in the software and
|
30 | d246be88 | Ilias Tsitsimpis | # documentation are those of the authors and should not be
|
31 | d246be88 | Ilias Tsitsimpis | # interpreted as representing official policies, either expressed
|
32 | d246be88 | Ilias Tsitsimpis | # or implied, of GRNET S.A.
|
33 | d246be88 | Ilias Tsitsimpis | |
34 | d246be88 | Ilias Tsitsimpis | """
|
35 | d246be88 | Ilias Tsitsimpis | Utility functions for Cyclades Tests
|
36 | d246be88 | Ilias Tsitsimpis | Cyclades require a lot helper functions and `common'
|
37 | d246be88 | Ilias Tsitsimpis | had grown too much.
|
38 | d246be88 | Ilias Tsitsimpis |
|
39 | d246be88 | Ilias Tsitsimpis | """
|
40 | d246be88 | Ilias Tsitsimpis | |
41 | d246be88 | Ilias Tsitsimpis | import time |
42 | 60a80953 | Ilias Tsitsimpis | import IPy |
43 | cee3ee9b | Ilias Tsitsimpis | import base64 |
44 | d246be88 | Ilias Tsitsimpis | import socket |
45 | d246be88 | Ilias Tsitsimpis | import random |
46 | cee3ee9b | Ilias Tsitsimpis | import paramiko |
47 | cee3ee9b | Ilias Tsitsimpis | import tempfile |
48 | d246be88 | Ilias Tsitsimpis | import subprocess |
49 | d246be88 | Ilias Tsitsimpis | |
50 | 60a80953 | Ilias Tsitsimpis | from kamaki.clients import ClientError |
51 | 60a80953 | Ilias Tsitsimpis | |
52 | 3e5bbd85 | Ilias Tsitsimpis | from synnefo_tools.burnin.common import BurninTests, MB, GB |
53 | d246be88 | Ilias Tsitsimpis | |
54 | d246be88 | Ilias Tsitsimpis | |
55 | d246be88 | Ilias Tsitsimpis | # Too many public methods. pylint: disable-msg=R0904
|
56 | d246be88 | Ilias Tsitsimpis | class CycladesTests(BurninTests): |
57 | d246be88 | Ilias Tsitsimpis | """Extends the BurninTests class for Cyclades"""
|
58 | 3eaf0ec5 | Ilias Tsitsimpis | def _try_until_timeout_expires(self, opmsg, check_fun): |
59 | d246be88 | Ilias Tsitsimpis | """Try to perform an action until timeout expires"""
|
60 | d246be88 | Ilias Tsitsimpis | assert callable(check_fun), "Not a function" |
61 | d246be88 | Ilias Tsitsimpis | |
62 | d246be88 | Ilias Tsitsimpis | action_timeout = self.action_timeout
|
63 | d246be88 | Ilias Tsitsimpis | action_warning = self.action_warning
|
64 | d246be88 | Ilias Tsitsimpis | if action_warning > action_timeout:
|
65 | d246be88 | Ilias Tsitsimpis | action_warning = action_timeout |
66 | d246be88 | Ilias Tsitsimpis | |
67 | 8c67f82e | Ilias Tsitsimpis | start_time = int(time.time())
|
68 | 8c67f82e | Ilias Tsitsimpis | end_time = start_time + action_warning |
69 | 8c67f82e | Ilias Tsitsimpis | while end_time > time.time():
|
70 | d246be88 | Ilias Tsitsimpis | try:
|
71 | 8c67f82e | Ilias Tsitsimpis | ret_value = check_fun() |
72 | 8c67f82e | Ilias Tsitsimpis | self.info("Operation `%s' finished in %s seconds", |
73 | 8c67f82e | Ilias Tsitsimpis | opmsg, int(time.time()) - start_time)
|
74 | 8c67f82e | Ilias Tsitsimpis | return ret_value
|
75 | d246be88 | Ilias Tsitsimpis | except Retry:
|
76 | d246be88 | Ilias Tsitsimpis | time.sleep(self.query_interval)
|
77 | 8c67f82e | Ilias Tsitsimpis | self.warning("Operation `%s' is taking too long after %s seconds", |
78 | 8c67f82e | Ilias Tsitsimpis | opmsg, int(time.time()) - start_time)
|
79 | 8c67f82e | Ilias Tsitsimpis | |
80 | 8c67f82e | Ilias Tsitsimpis | end_time = start_time + action_timeout |
81 | 8c67f82e | Ilias Tsitsimpis | while end_time > time.time():
|
82 | d246be88 | Ilias Tsitsimpis | try:
|
83 | 8c67f82e | Ilias Tsitsimpis | ret_value = check_fun() |
84 | 8c67f82e | Ilias Tsitsimpis | self.info("Operation `%s' finished in %s seconds", |
85 | 8c67f82e | Ilias Tsitsimpis | opmsg, int(time.time()) - start_time)
|
86 | 8c67f82e | Ilias Tsitsimpis | return ret_value
|
87 | d246be88 | Ilias Tsitsimpis | except Retry:
|
88 | d246be88 | Ilias Tsitsimpis | time.sleep(self.query_interval)
|
89 | 8c67f82e | Ilias Tsitsimpis | self.error("Operation `%s' timed out after %s seconds", |
90 | 8c67f82e | Ilias Tsitsimpis | opmsg, int(time.time()) - start_time)
|
91 | d246be88 | Ilias Tsitsimpis | self.fail("time out") |
92 | d246be88 | Ilias Tsitsimpis | |
93 | d246be88 | Ilias Tsitsimpis | def _get_list_of_servers(self, detail=False): |
94 | d246be88 | Ilias Tsitsimpis | """Get (detailed) list of servers"""
|
95 | d246be88 | Ilias Tsitsimpis | if detail:
|
96 | d246be88 | Ilias Tsitsimpis | self.info("Getting detailed list of servers") |
97 | d246be88 | Ilias Tsitsimpis | else:
|
98 | d246be88 | Ilias Tsitsimpis | self.info("Getting simple list of servers") |
99 | d246be88 | Ilias Tsitsimpis | return self.clients.cyclades.list_servers(detail=detail) |
100 | d246be88 | Ilias Tsitsimpis | |
101 | 3eaf0ec5 | Ilias Tsitsimpis | def _get_list_of_networks(self, detail=False): |
102 | 3eaf0ec5 | Ilias Tsitsimpis | """Get (detailed) list of networks"""
|
103 | 3eaf0ec5 | Ilias Tsitsimpis | if detail:
|
104 | 3eaf0ec5 | Ilias Tsitsimpis | self.info("Getting detailed list of networks") |
105 | 3eaf0ec5 | Ilias Tsitsimpis | else:
|
106 | 3eaf0ec5 | Ilias Tsitsimpis | self.info("Getting simple list of networks") |
107 | 60a80953 | Ilias Tsitsimpis | return self.clients.network.list_networks(detail=detail) |
108 | 3eaf0ec5 | Ilias Tsitsimpis | |
109 | 3eaf0ec5 | Ilias Tsitsimpis | def _get_server_details(self, server, quiet=False): |
110 | d246be88 | Ilias Tsitsimpis | """Get details for a server"""
|
111 | 3eaf0ec5 | Ilias Tsitsimpis | if not quiet: |
112 | 3eaf0ec5 | Ilias Tsitsimpis | self.info("Getting details for server %s with id %s", |
113 | 3eaf0ec5 | Ilias Tsitsimpis | server['name'], server['id']) |
114 | d246be88 | Ilias Tsitsimpis | return self.clients.cyclades.get_server_details(server['id']) |
115 | d246be88 | Ilias Tsitsimpis | |
116 | 60a80953 | Ilias Tsitsimpis | def _create_server(self, image, flavor, personality=None, network=False): |
117 | d246be88 | Ilias Tsitsimpis | """Create a new server"""
|
118 | 60a80953 | Ilias Tsitsimpis | if network:
|
119 | 60a80953 | Ilias Tsitsimpis | fip = self._create_floating_ip()
|
120 | 60a80953 | Ilias Tsitsimpis | port = self._create_port(fip['floating_network_id'], |
121 | 60a80953 | Ilias Tsitsimpis | floating_ip=fip) |
122 | 60a80953 | Ilias Tsitsimpis | networks = [{'port': port['id']}] |
123 | 60a80953 | Ilias Tsitsimpis | else:
|
124 | 60a80953 | Ilias Tsitsimpis | networks = None
|
125 | 60a80953 | Ilias Tsitsimpis | |
126 | 3eaf0ec5 | Ilias Tsitsimpis | servername = "%s for %s" % (self.run_id, image['name']) |
127 | 3eaf0ec5 | Ilias Tsitsimpis | self.info("Creating a server with name %s", servername) |
128 | d246be88 | Ilias Tsitsimpis | self.info("Using image %s with id %s", image['name'], image['id']) |
129 | d246be88 | Ilias Tsitsimpis | self.info("Using flavor %s with id %s", flavor['name'], flavor['id']) |
130 | d246be88 | Ilias Tsitsimpis | server = self.clients.cyclades.create_server(
|
131 | 60a80953 | Ilias Tsitsimpis | servername, flavor['id'], image['id'], |
132 | 60a80953 | Ilias Tsitsimpis | personality=personality, networks=networks) |
133 | d246be88 | Ilias Tsitsimpis | |
134 | d246be88 | Ilias Tsitsimpis | self.info("Server id: %s", server['id']) |
135 | d246be88 | Ilias Tsitsimpis | self.info("Server password: %s", server['adminPass']) |
136 | d246be88 | Ilias Tsitsimpis | |
137 | 3eaf0ec5 | Ilias Tsitsimpis | self.assertEqual(server['name'], servername) |
138 | d246be88 | Ilias Tsitsimpis | self.assertEqual(server['flavor']['id'], flavor['id']) |
139 | d246be88 | Ilias Tsitsimpis | self.assertEqual(server['image']['id'], image['id']) |
140 | d246be88 | Ilias Tsitsimpis | self.assertEqual(server['status'], "BUILD") |
141 | d246be88 | Ilias Tsitsimpis | |
142 | 3e5bbd85 | Ilias Tsitsimpis | # Verify quotas
|
143 | 3e5bbd85 | Ilias Tsitsimpis | self._check_quotas(disk=+int(flavor['disk'])*GB, |
144 | 3e5bbd85 | Ilias Tsitsimpis | vm=+1,
|
145 | 3e5bbd85 | Ilias Tsitsimpis | ram=+int(flavor['ram'])*MB, |
146 | 3e5bbd85 | Ilias Tsitsimpis | cpu=+int(flavor['vcpus'])) |
147 | 3e5bbd85 | Ilias Tsitsimpis | |
148 | d246be88 | Ilias Tsitsimpis | return server
|
149 | d246be88 | Ilias Tsitsimpis | |
150 | 60a80953 | Ilias Tsitsimpis | def _delete_servers(self, servers, error=False): |
151 | 60a80953 | Ilias Tsitsimpis | """Deleting a number of servers in parallel"""
|
152 | 60a80953 | Ilias Tsitsimpis | # Disconnect floating IPs
|
153 | 7c37ab19 | Ilias Tsitsimpis | if not error: |
154 | 7c37ab19 | Ilias Tsitsimpis | # If there is the possibility for the machine to be in
|
155 | 7c37ab19 | Ilias Tsitsimpis | # ERROR state we cannot delete its ports.
|
156 | 7c37ab19 | Ilias Tsitsimpis | for srv in servers: |
157 | 7c37ab19 | Ilias Tsitsimpis | self.info(
|
158 | 7c37ab19 | Ilias Tsitsimpis | "Disconnecting all floating IPs from server with id %s",
|
159 | 7c37ab19 | Ilias Tsitsimpis | srv['id'])
|
160 | 7c37ab19 | Ilias Tsitsimpis | self._disconnect_from_network(srv)
|
161 | 60a80953 | Ilias Tsitsimpis | |
162 | 60a80953 | Ilias Tsitsimpis | # Delete servers
|
163 | 60a80953 | Ilias Tsitsimpis | for srv in servers: |
164 | 60a80953 | Ilias Tsitsimpis | self.info("Sending the delete request for server with id %s", |
165 | 60a80953 | Ilias Tsitsimpis | srv['id'])
|
166 | 60a80953 | Ilias Tsitsimpis | self.clients.cyclades.delete_server(srv['id']) |
167 | 60a80953 | Ilias Tsitsimpis | |
168 | 60a80953 | Ilias Tsitsimpis | if error:
|
169 | 60a80953 | Ilias Tsitsimpis | curr_states = ["ACTIVE", "ERROR", "STOPPED", "BUILD"] |
170 | 60a80953 | Ilias Tsitsimpis | else:
|
171 | 60a80953 | Ilias Tsitsimpis | curr_states = ["ACTIVE"]
|
172 | 60a80953 | Ilias Tsitsimpis | for srv in servers: |
173 | 60a80953 | Ilias Tsitsimpis | self._insist_on_server_transition(srv, curr_states, "DELETED") |
174 | 60a80953 | Ilias Tsitsimpis | |
175 | 60a80953 | Ilias Tsitsimpis | # Servers no longer in server list
|
176 | 60a80953 | Ilias Tsitsimpis | new_servers = [s['id'] for s in self._get_list_of_servers()] |
177 | 60a80953 | Ilias Tsitsimpis | for srv in servers: |
178 | 60a80953 | Ilias Tsitsimpis | self.info("Verifying that server with id %s is no longer in " |
179 | 60a80953 | Ilias Tsitsimpis | "server list", srv['id']) |
180 | 60a80953 | Ilias Tsitsimpis | self.assertNotIn(srv['id'], new_servers) |
181 | 60a80953 | Ilias Tsitsimpis | |
182 | 60a80953 | Ilias Tsitsimpis | # Verify quotas
|
183 | 60a80953 | Ilias Tsitsimpis | flavors = \ |
184 | 60a80953 | Ilias Tsitsimpis | [self.clients.compute.get_flavor_details(srv['flavor']['id']) |
185 | 60a80953 | Ilias Tsitsimpis | for srv in servers] |
186 | 60a80953 | Ilias Tsitsimpis | self._verify_quotas_deleted(flavors)
|
187 | 60a80953 | Ilias Tsitsimpis | |
188 | 3e5bbd85 | Ilias Tsitsimpis | def _verify_quotas_deleted(self, flavors): |
189 | 3e5bbd85 | Ilias Tsitsimpis | """Verify quotas for a number of deleted servers"""
|
190 | 3e5bbd85 | Ilias Tsitsimpis | used_disk = 0
|
191 | 3e5bbd85 | Ilias Tsitsimpis | used_vm = 0
|
192 | 3e5bbd85 | Ilias Tsitsimpis | used_ram = 0
|
193 | 3e5bbd85 | Ilias Tsitsimpis | used_cpu = 0
|
194 | 3e5bbd85 | Ilias Tsitsimpis | for flavor in flavors: |
195 | 3e5bbd85 | Ilias Tsitsimpis | used_disk += int(flavor['disk']) * GB |
196 | 3e5bbd85 | Ilias Tsitsimpis | used_vm += 1
|
197 | 3e5bbd85 | Ilias Tsitsimpis | used_ram += int(flavor['ram']) * MB |
198 | 3e5bbd85 | Ilias Tsitsimpis | used_cpu += int(flavor['vcpus']) |
199 | 3e5bbd85 | Ilias Tsitsimpis | self._check_quotas(disk=-used_disk,
|
200 | 3e5bbd85 | Ilias Tsitsimpis | vm=-used_vm, |
201 | 3e5bbd85 | Ilias Tsitsimpis | ram=-used_ram, |
202 | 3e5bbd85 | Ilias Tsitsimpis | cpu=-used_cpu) |
203 | 3e5bbd85 | Ilias Tsitsimpis | |
204 | d246be88 | Ilias Tsitsimpis | def _get_connection_username(self, server): |
205 | d246be88 | Ilias Tsitsimpis | """Determine the username to use to connect to the server"""
|
206 | d246be88 | Ilias Tsitsimpis | users = server['metadata'].get("users", None) |
207 | d246be88 | Ilias Tsitsimpis | ret_user = None
|
208 | d246be88 | Ilias Tsitsimpis | if users is not None: |
209 | d246be88 | Ilias Tsitsimpis | user_list = users.split() |
210 | d246be88 | Ilias Tsitsimpis | if "root" in user_list: |
211 | d246be88 | Ilias Tsitsimpis | ret_user = "root"
|
212 | d246be88 | Ilias Tsitsimpis | else:
|
213 | d246be88 | Ilias Tsitsimpis | ret_user = random.choice(user_list) |
214 | d246be88 | Ilias Tsitsimpis | else:
|
215 | d246be88 | Ilias Tsitsimpis | # Return the login name for connections based on the server OS
|
216 | d246be88 | Ilias Tsitsimpis | self.info("Could not find `users' metadata in server. Let's guess") |
217 | d246be88 | Ilias Tsitsimpis | os_value = server['metadata'].get("os") |
218 | d246be88 | Ilias Tsitsimpis | if os_value in ("Ubuntu", "Kubuntu", "Fedora"): |
219 | d246be88 | Ilias Tsitsimpis | ret_user = "user"
|
220 | d246be88 | Ilias Tsitsimpis | elif os_value in ("windows", "windows_alpha1"): |
221 | d246be88 | Ilias Tsitsimpis | ret_user = "Administrator"
|
222 | d246be88 | Ilias Tsitsimpis | else:
|
223 | d246be88 | Ilias Tsitsimpis | ret_user = "root"
|
224 | d246be88 | Ilias Tsitsimpis | |
225 | d246be88 | Ilias Tsitsimpis | self.assertIsNotNone(ret_user)
|
226 | d246be88 | Ilias Tsitsimpis | self.info("User's login name: %s", ret_user) |
227 | d246be88 | Ilias Tsitsimpis | return ret_user
|
228 | d246be88 | Ilias Tsitsimpis | |
229 | 3eaf0ec5 | Ilias Tsitsimpis | def _insist_on_server_transition(self, server, curr_statuses, new_status): |
230 | 3eaf0ec5 | Ilias Tsitsimpis | """Insist on server transiting from curr_statuses to new_status"""
|
231 | d246be88 | Ilias Tsitsimpis | def check_fun(): |
232 | d246be88 | Ilias Tsitsimpis | """Check server status"""
|
233 | 3eaf0ec5 | Ilias Tsitsimpis | srv = self._get_server_details(server, quiet=True) |
234 | 3eaf0ec5 | Ilias Tsitsimpis | if srv['status'] in curr_statuses: |
235 | d246be88 | Ilias Tsitsimpis | raise Retry()
|
236 | d246be88 | Ilias Tsitsimpis | elif srv['status'] == new_status: |
237 | d246be88 | Ilias Tsitsimpis | return
|
238 | d246be88 | Ilias Tsitsimpis | else:
|
239 | 3eaf0ec5 | Ilias Tsitsimpis | msg = "Server \"%s\" with id %s went to unexpected status %s"
|
240 | 3eaf0ec5 | Ilias Tsitsimpis | self.error(msg, server['name'], server['id'], srv['status']) |
241 | 3eaf0ec5 | Ilias Tsitsimpis | self.fail(msg % (server['name'], server['id'], srv['status'])) |
242 | 5bef1f49 | Ilias Tsitsimpis | opmsg = "Waiting for server \"%s\" with id %s to become %s"
|
243 | 5bef1f49 | Ilias Tsitsimpis | self.info(opmsg, server['name'], server['id'], new_status) |
244 | 5bef1f49 | Ilias Tsitsimpis | opmsg = opmsg % (server['name'], server['id'], new_status) |
245 | 3eaf0ec5 | Ilias Tsitsimpis | self._try_until_timeout_expires(opmsg, check_fun)
|
246 | 3eaf0ec5 | Ilias Tsitsimpis | |
247 | 3eaf0ec5 | Ilias Tsitsimpis | def _insist_on_network_transition(self, network, |
248 | 3eaf0ec5 | Ilias Tsitsimpis | curr_statuses, new_status): |
249 | 3eaf0ec5 | Ilias Tsitsimpis | """Insist on network transiting from curr_statuses to new_status"""
|
250 | 3eaf0ec5 | Ilias Tsitsimpis | def check_fun(): |
251 | 3eaf0ec5 | Ilias Tsitsimpis | """Check network status"""
|
252 | 60a80953 | Ilias Tsitsimpis | ntw = self.clients.network.get_network_details(network['id']) |
253 | 3eaf0ec5 | Ilias Tsitsimpis | if ntw['status'] in curr_statuses: |
254 | 3eaf0ec5 | Ilias Tsitsimpis | raise Retry()
|
255 | 3eaf0ec5 | Ilias Tsitsimpis | elif ntw['status'] == new_status: |
256 | 3eaf0ec5 | Ilias Tsitsimpis | return
|
257 | 3eaf0ec5 | Ilias Tsitsimpis | else:
|
258 | 3eaf0ec5 | Ilias Tsitsimpis | msg = "Network %s with id %s went to unexpected status %s"
|
259 | 3eaf0ec5 | Ilias Tsitsimpis | self.error(msg, network['name'], network['id'], ntw['status']) |
260 | 3eaf0ec5 | Ilias Tsitsimpis | self.fail(msg %
|
261 | 3eaf0ec5 | Ilias Tsitsimpis | (network['name'], network['id'], ntw['status'])) |
262 | 5bef1f49 | Ilias Tsitsimpis | opmsg = "Waiting for network \"%s\" with id %s to become %s"
|
263 | 5bef1f49 | Ilias Tsitsimpis | self.info(opmsg, network['name'], network['id'], new_status) |
264 | 5bef1f49 | Ilias Tsitsimpis | opmsg = opmsg % (network['name'], network['id'], new_status) |
265 | 3eaf0ec5 | Ilias Tsitsimpis | self._try_until_timeout_expires(opmsg, check_fun)
|
266 | 3eaf0ec5 | Ilias Tsitsimpis | |
267 | d246be88 | Ilias Tsitsimpis | def _insist_on_tcp_connection(self, family, host, port): |
268 | d246be88 | Ilias Tsitsimpis | """Insist on tcp connection"""
|
269 | d246be88 | Ilias Tsitsimpis | def check_fun(): |
270 | d246be88 | Ilias Tsitsimpis | """Get a connected socket from the specified family to host:port"""
|
271 | d246be88 | Ilias Tsitsimpis | sock = None
|
272 | d246be88 | Ilias Tsitsimpis | for res in socket.getaddrinfo(host, port, family, |
273 | d246be88 | Ilias Tsitsimpis | socket.SOCK_STREAM, 0,
|
274 | d246be88 | Ilias Tsitsimpis | socket.AI_PASSIVE): |
275 | d246be88 | Ilias Tsitsimpis | fam, socktype, proto, _, saddr = res |
276 | d246be88 | Ilias Tsitsimpis | try:
|
277 | d246be88 | Ilias Tsitsimpis | sock = socket.socket(fam, socktype, proto) |
278 | d246be88 | Ilias Tsitsimpis | except socket.error:
|
279 | d246be88 | Ilias Tsitsimpis | sock = None
|
280 | d246be88 | Ilias Tsitsimpis | continue
|
281 | d246be88 | Ilias Tsitsimpis | try:
|
282 | d246be88 | Ilias Tsitsimpis | sock.connect(saddr) |
283 | d246be88 | Ilias Tsitsimpis | except socket.error:
|
284 | d246be88 | Ilias Tsitsimpis | sock.close() |
285 | d246be88 | Ilias Tsitsimpis | sock = None
|
286 | d246be88 | Ilias Tsitsimpis | continue
|
287 | d246be88 | Ilias Tsitsimpis | if sock is None: |
288 | d246be88 | Ilias Tsitsimpis | raise Retry
|
289 | d246be88 | Ilias Tsitsimpis | return sock
|
290 | d246be88 | Ilias Tsitsimpis | familystr = {socket.AF_INET: "IPv4", socket.AF_INET6: "IPv6", |
291 | d246be88 | Ilias Tsitsimpis | socket.AF_UNSPEC: "Unspecified-IPv4/6"}
|
292 | d246be88 | Ilias Tsitsimpis | opmsg = "Connecting over %s to %s:%s"
|
293 | d246be88 | Ilias Tsitsimpis | self.info(opmsg, familystr.get(family, "Unknown"), host, port) |
294 | d246be88 | Ilias Tsitsimpis | opmsg = opmsg % (familystr.get(family, "Unknown"), host, port)
|
295 | d246be88 | Ilias Tsitsimpis | return self._try_until_timeout_expires(opmsg, check_fun) |
296 | d246be88 | Ilias Tsitsimpis | |
297 | 60a80953 | Ilias Tsitsimpis | def _get_ips(self, server, version=4, network=None): |
298 | 60a80953 | Ilias Tsitsimpis | """Get the IPs of a server from the detailed server info
|
299 | 3eaf0ec5 | Ilias Tsitsimpis |
|
300 | 60a80953 | Ilias Tsitsimpis | If network not given then get the public IPs. Else the IPs
|
301 | 3eaf0ec5 | Ilias Tsitsimpis | attached to that network
|
302 | 3eaf0ec5 | Ilias Tsitsimpis |
|
303 | 3eaf0ec5 | Ilias Tsitsimpis | """
|
304 | d246be88 | Ilias Tsitsimpis | assert version in (4, 6) |
305 | d246be88 | Ilias Tsitsimpis | |
306 | d246be88 | Ilias Tsitsimpis | nics = server['attachments']
|
307 | 60a80953 | Ilias Tsitsimpis | addrs = [] |
308 | d246be88 | Ilias Tsitsimpis | for nic in nics: |
309 | d246be88 | Ilias Tsitsimpis | net_id = nic['network_id']
|
310 | 3eaf0ec5 | Ilias Tsitsimpis | if network is None: |
311 | 60a80953 | Ilias Tsitsimpis | if self.clients.network.get_network_details(net_id)['public']: |
312 | ee89df69 | Ilias Tsitsimpis | if nic['ipv' + str(version)]: |
313 | 60a80953 | Ilias Tsitsimpis | addrs.append(nic['ipv' + str(version)]) |
314 | 3eaf0ec5 | Ilias Tsitsimpis | else:
|
315 | 3eaf0ec5 | Ilias Tsitsimpis | if net_id == network['id']: |
316 | ee89df69 | Ilias Tsitsimpis | if nic['ipv' + str(version)]: |
317 | 60a80953 | Ilias Tsitsimpis | addrs.append(nic['ipv' + str(version)]) |
318 | 60a80953 | Ilias Tsitsimpis | |
319 | 60a80953 | Ilias Tsitsimpis | self.assertGreater(len(addrs), 0, |
320 | 60a80953 | Ilias Tsitsimpis | "Can not get IPs from server attachments")
|
321 | 60a80953 | Ilias Tsitsimpis | |
322 | 60a80953 | Ilias Tsitsimpis | for addr in addrs: |
323 | 60a80953 | Ilias Tsitsimpis | self.assertEquals(IPy.IP(addr).version(), version)
|
324 | d246be88 | Ilias Tsitsimpis | |
325 | 3eaf0ec5 | Ilias Tsitsimpis | if network is None: |
326 | 3eaf0ec5 | Ilias Tsitsimpis | msg = "Server's public IPv%s is %s"
|
327 | 60a80953 | Ilias Tsitsimpis | for addr in addrs: |
328 | 60a80953 | Ilias Tsitsimpis | self.info(msg, version, addr)
|
329 | 3eaf0ec5 | Ilias Tsitsimpis | else:
|
330 | 3eaf0ec5 | Ilias Tsitsimpis | msg = "Server's IPv%s attached to network \"%s\" is %s"
|
331 | 60a80953 | Ilias Tsitsimpis | for addr in addrs: |
332 | 60a80953 | Ilias Tsitsimpis | self.info(msg, version, network['id'], addr) |
333 | 3eaf0ec5 | Ilias Tsitsimpis | return addrs
|
334 | d246be88 | Ilias Tsitsimpis | |
335 | cee3ee9b | Ilias Tsitsimpis | def _insist_on_ping(self, ip_addr, version=4): |
336 | d246be88 | Ilias Tsitsimpis | """Test server responds to a single IPv4 of IPv6 ping"""
|
337 | d246be88 | Ilias Tsitsimpis | def check_fun(): |
338 | d246be88 | Ilias Tsitsimpis | """Ping to server"""
|
339 | d246be88 | Ilias Tsitsimpis | cmd = ("ping%s -c 3 -w 20 %s" %
|
340 | d246be88 | Ilias Tsitsimpis | ("6" if version == 6 else "", ip_addr)) |
341 | d246be88 | Ilias Tsitsimpis | ping = subprocess.Popen( |
342 | d246be88 | Ilias Tsitsimpis | cmd, shell=True, stdout=subprocess.PIPE,
|
343 | d246be88 | Ilias Tsitsimpis | stderr=subprocess.PIPE) |
344 | d246be88 | Ilias Tsitsimpis | ping.communicate() |
345 | d246be88 | Ilias Tsitsimpis | ret = ping.wait() |
346 | d246be88 | Ilias Tsitsimpis | if ret != 0: |
347 | d246be88 | Ilias Tsitsimpis | raise Retry
|
348 | cee3ee9b | Ilias Tsitsimpis | assert version in (4, 6) |
349 | d246be88 | Ilias Tsitsimpis | opmsg = "Sent IPv%s ping requests to %s"
|
350 | d246be88 | Ilias Tsitsimpis | self.info(opmsg, version, ip_addr)
|
351 | d246be88 | Ilias Tsitsimpis | opmsg = opmsg % (version, ip_addr) |
352 | d246be88 | Ilias Tsitsimpis | self._try_until_timeout_expires(opmsg, check_fun)
|
353 | d246be88 | Ilias Tsitsimpis | |
354 | cee3ee9b | Ilias Tsitsimpis | def _image_is(self, image, osfamily): |
355 | cee3ee9b | Ilias Tsitsimpis | """Return true if the image is of `osfamily'"""
|
356 | cee3ee9b | Ilias Tsitsimpis | d_image = self.clients.cyclades.get_image_details(image['id']) |
357 | cee3ee9b | Ilias Tsitsimpis | return d_image['metadata']['osfamily'].lower().find(osfamily) >= 0 |
358 | cee3ee9b | Ilias Tsitsimpis | |
359 | 449a1c40 | Ilias Tsitsimpis | # Method could be a function. pylint: disable-msg=R0201
|
360 | cee3ee9b | Ilias Tsitsimpis | def _ssh_execute(self, hostip, username, password, command): |
361 | cee3ee9b | Ilias Tsitsimpis | """Execute a command via ssh"""
|
362 | cee3ee9b | Ilias Tsitsimpis | ssh = paramiko.SSHClient() |
363 | cee3ee9b | Ilias Tsitsimpis | ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) |
364 | cee3ee9b | Ilias Tsitsimpis | try:
|
365 | cee3ee9b | Ilias Tsitsimpis | ssh.connect(hostip, username=username, password=password) |
366 | 16c7f032 | Ilias Tsitsimpis | except paramiko.SSHException as err: |
367 | 16c7f032 | Ilias Tsitsimpis | if err.args[0] == "Error reading SSH protocol banner": |
368 | 449a1c40 | Ilias Tsitsimpis | raise Retry()
|
369 | 449a1c40 | Ilias Tsitsimpis | else:
|
370 | 449a1c40 | Ilias Tsitsimpis | raise
|
371 | 449a1c40 | Ilias Tsitsimpis | _, stdout, _ = ssh.exec_command(command) |
372 | cee3ee9b | Ilias Tsitsimpis | status = stdout.channel.recv_exit_status() |
373 | cee3ee9b | Ilias Tsitsimpis | output = stdout.readlines() |
374 | cee3ee9b | Ilias Tsitsimpis | ssh.close() |
375 | cee3ee9b | Ilias Tsitsimpis | return output, status
|
376 | cee3ee9b | Ilias Tsitsimpis | |
377 | cee3ee9b | Ilias Tsitsimpis | def _insist_get_hostname_over_ssh(self, hostip, username, password): |
378 | cee3ee9b | Ilias Tsitsimpis | """Connect to server using ssh and get it's hostname"""
|
379 | cee3ee9b | Ilias Tsitsimpis | def check_fun(): |
380 | cee3ee9b | Ilias Tsitsimpis | """Get hostname"""
|
381 | cee3ee9b | Ilias Tsitsimpis | try:
|
382 | cee3ee9b | Ilias Tsitsimpis | lines, status = self._ssh_execute(
|
383 | cee3ee9b | Ilias Tsitsimpis | hostip, username, password, "hostname")
|
384 | cee3ee9b | Ilias Tsitsimpis | self.assertEqual(status, 0) |
385 | cee3ee9b | Ilias Tsitsimpis | self.assertEqual(len(lines), 1) |
386 | cee3ee9b | Ilias Tsitsimpis | # Remove new line
|
387 | cee3ee9b | Ilias Tsitsimpis | return lines[0].strip('\n') |
388 | cee3ee9b | Ilias Tsitsimpis | except AssertionError: |
389 | cee3ee9b | Ilias Tsitsimpis | raise Retry()
|
390 | cee3ee9b | Ilias Tsitsimpis | opmsg = "Connecting to server using ssh and get it's hostname"
|
391 | cee3ee9b | Ilias Tsitsimpis | self.info(opmsg)
|
392 | cee3ee9b | Ilias Tsitsimpis | hostname = self._try_until_timeout_expires(opmsg, check_fun)
|
393 | cee3ee9b | Ilias Tsitsimpis | self.info("Server's hostname is %s", hostname) |
394 | cee3ee9b | Ilias Tsitsimpis | return hostname
|
395 | cee3ee9b | Ilias Tsitsimpis | |
396 | cee3ee9b | Ilias Tsitsimpis | # Too many arguments. pylint: disable-msg=R0913
|
397 | cee3ee9b | Ilias Tsitsimpis | def _check_file_through_ssh(self, hostip, username, password, |
398 | cee3ee9b | Ilias Tsitsimpis | remotepath, content): |
399 | cee3ee9b | Ilias Tsitsimpis | """Fetch file from server and compare contents"""
|
400 | cee3ee9b | Ilias Tsitsimpis | self.info("Fetching file %s from remote server", remotepath) |
401 | cee3ee9b | Ilias Tsitsimpis | transport = paramiko.Transport((hostip, 22))
|
402 | cee3ee9b | Ilias Tsitsimpis | transport.connect(username=username, password=password) |
403 | cee3ee9b | Ilias Tsitsimpis | with tempfile.NamedTemporaryFile() as ftmp: |
404 | cee3ee9b | Ilias Tsitsimpis | sftp = paramiko.SFTPClient.from_transport(transport) |
405 | cee3ee9b | Ilias Tsitsimpis | sftp.get(remotepath, ftmp.name) |
406 | cee3ee9b | Ilias Tsitsimpis | sftp.close() |
407 | cee3ee9b | Ilias Tsitsimpis | transport.close() |
408 | cee3ee9b | Ilias Tsitsimpis | self.info("Comparing file contents") |
409 | cee3ee9b | Ilias Tsitsimpis | remote_content = base64.b64encode(ftmp.read()) |
410 | cee3ee9b | Ilias Tsitsimpis | self.assertEqual(content, remote_content)
|
411 | cee3ee9b | Ilias Tsitsimpis | |
412 | 60a80953 | Ilias Tsitsimpis | # ----------------------------------
|
413 | 60a80953 | Ilias Tsitsimpis | # Networks
|
414 | 60a80953 | Ilias Tsitsimpis | def _create_network(self, cidr="10.0.1.0/28", dhcp=True): |
415 | 3e5bbd85 | Ilias Tsitsimpis | """Create a new private network"""
|
416 | 60a80953 | Ilias Tsitsimpis | name = self.run_id
|
417 | 60a80953 | Ilias Tsitsimpis | network = self.clients.network.create_network(
|
418 | 60a80953 | Ilias Tsitsimpis | "MAC_FILTERED", name=name, shared=False) |
419 | 3e5bbd85 | Ilias Tsitsimpis | self.info("Network with id %s created", network['id']) |
420 | 60a80953 | Ilias Tsitsimpis | subnet = self.clients.network.create_subnet(
|
421 | 60a80953 | Ilias Tsitsimpis | network['id'], cidr=cidr, enable_dhcp=dhcp)
|
422 | 60a80953 | Ilias Tsitsimpis | self.info("Subnet with id %s created", subnet['id']) |
423 | 3e5bbd85 | Ilias Tsitsimpis | |
424 | 3e5bbd85 | Ilias Tsitsimpis | # Verify quotas
|
425 | 3e5bbd85 | Ilias Tsitsimpis | self._check_quotas(network=+1) |
426 | 3e5bbd85 | Ilias Tsitsimpis | |
427 | 3e5bbd85 | Ilias Tsitsimpis | #Test if the right name is assigned
|
428 | 3e5bbd85 | Ilias Tsitsimpis | self.assertEqual(network['name'], name) |
429 | 3e5bbd85 | Ilias Tsitsimpis | |
430 | 3e5bbd85 | Ilias Tsitsimpis | return network
|
431 | 3e5bbd85 | Ilias Tsitsimpis | |
432 | 60a80953 | Ilias Tsitsimpis | def _delete_networks(self, networks, error=False): |
433 | 60a80953 | Ilias Tsitsimpis | """Delete a network"""
|
434 | 60a80953 | Ilias Tsitsimpis | for net in networks: |
435 | 60a80953 | Ilias Tsitsimpis | self.info("Deleting network with id %s", net['id']) |
436 | 60a80953 | Ilias Tsitsimpis | self.clients.network.delete_network(net['id']) |
437 | 60a80953 | Ilias Tsitsimpis | |
438 | 60a80953 | Ilias Tsitsimpis | if error:
|
439 | 60a80953 | Ilias Tsitsimpis | curr_states = ["ACTIVE", "SNF:DRAINED", "ERROR"] |
440 | 60a80953 | Ilias Tsitsimpis | else:
|
441 | 60a80953 | Ilias Tsitsimpis | curr_states = ["ACTIVE", "SNF:DRAINED"] |
442 | 60a80953 | Ilias Tsitsimpis | for net in networks: |
443 | 60a80953 | Ilias Tsitsimpis | self._insist_on_network_transition(net, curr_states, "DELETED") |
444 | 60a80953 | Ilias Tsitsimpis | |
445 | 60a80953 | Ilias Tsitsimpis | # Networks no longer in network list
|
446 | 60a80953 | Ilias Tsitsimpis | new_networks = [n['id'] for n in self._get_list_of_networks()] |
447 | 60a80953 | Ilias Tsitsimpis | for net in networks: |
448 | 60a80953 | Ilias Tsitsimpis | self.info("Verifying that network with id %s is no longer in " |
449 | 60a80953 | Ilias Tsitsimpis | "network list", net['id']) |
450 | 60a80953 | Ilias Tsitsimpis | self.assertNotIn(net['id'], new_networks) |
451 | 60a80953 | Ilias Tsitsimpis | |
452 | 60a80953 | Ilias Tsitsimpis | # Verify quotas
|
453 | 60a80953 | Ilias Tsitsimpis | self._check_quotas(network=-len(networks)) |
454 | 60a80953 | Ilias Tsitsimpis | |
455 | 60a80953 | Ilias Tsitsimpis | def _get_public_network(self, networks=None): |
456 | 60a80953 | Ilias Tsitsimpis | """Get the public network"""
|
457 | 60a80953 | Ilias Tsitsimpis | if networks is None: |
458 | 60a80953 | Ilias Tsitsimpis | networks = self._get_list_of_networks(detail=True) |
459 | 60a80953 | Ilias Tsitsimpis | self.info("Getting the public network") |
460 | 60a80953 | Ilias Tsitsimpis | for net in networks: |
461 | 60a80953 | Ilias Tsitsimpis | if net['SNF:floating_ip_pool'] and net['public']: |
462 | 60a80953 | Ilias Tsitsimpis | return net
|
463 | 60a80953 | Ilias Tsitsimpis | self.fail("Could not find a public network to use") |
464 | 60a80953 | Ilias Tsitsimpis | |
465 | 60a80953 | Ilias Tsitsimpis | def _create_floating_ip(self): |
466 | 60a80953 | Ilias Tsitsimpis | """Create a new floating ip"""
|
467 | 60a80953 | Ilias Tsitsimpis | pub_net = self._get_public_network()
|
468 | 60a80953 | Ilias Tsitsimpis | self.info("Creating a new floating ip for network with id %s", |
469 | 60a80953 | Ilias Tsitsimpis | pub_net['id'])
|
470 | 60a80953 | Ilias Tsitsimpis | fip = self.clients.network.create_floatingip(pub_net['id']) |
471 | 60a80953 | Ilias Tsitsimpis | # Verify that floating ip has been created
|
472 | 60a80953 | Ilias Tsitsimpis | fips = self.clients.network.list_floatingips()
|
473 | 60a80953 | Ilias Tsitsimpis | fips = [f['id'] for f in fips] |
474 | 60a80953 | Ilias Tsitsimpis | self.assertIn(fip['id'], fips) |
475 | 60a80953 | Ilias Tsitsimpis | # Verify quotas
|
476 | 60a80953 | Ilias Tsitsimpis | self._check_quotas(ip=+1) |
477 | 60a80953 | Ilias Tsitsimpis | # Check that IP is IPv4
|
478 | 60a80953 | Ilias Tsitsimpis | self.assertEquals(IPy.IP(fip['floating_ip_address']).version(), 4) |
479 | 60a80953 | Ilias Tsitsimpis | |
480 | 60a80953 | Ilias Tsitsimpis | self.info("Floating IP %s with id %s created", |
481 | 60a80953 | Ilias Tsitsimpis | fip['floating_ip_address'], fip['id']) |
482 | 60a80953 | Ilias Tsitsimpis | return fip
|
483 | 60a80953 | Ilias Tsitsimpis | |
484 | 60a80953 | Ilias Tsitsimpis | def _create_port(self, network_id, device_id=None, floating_ip=None): |
485 | 60a80953 | Ilias Tsitsimpis | """Create a new port attached to the a specific network"""
|
486 | 60a80953 | Ilias Tsitsimpis | self.info("Creating a new port to network with id %s", network_id) |
487 | 60a80953 | Ilias Tsitsimpis | if floating_ip is not None: |
488 | 60a80953 | Ilias Tsitsimpis | fixed_ips = [{'ip_address': floating_ip['floating_ip_address']}] |
489 | 60a80953 | Ilias Tsitsimpis | else:
|
490 | 60a80953 | Ilias Tsitsimpis | fixed_ips = None
|
491 | 60a80953 | Ilias Tsitsimpis | port = self.clients.network.create_port(network_id,
|
492 | 60a80953 | Ilias Tsitsimpis | device_id=device_id, |
493 | 60a80953 | Ilias Tsitsimpis | fixed_ips=fixed_ips) |
494 | 60a80953 | Ilias Tsitsimpis | # Verify that port created
|
495 | 60a80953 | Ilias Tsitsimpis | ports = self.clients.network.list_ports()
|
496 | 60a80953 | Ilias Tsitsimpis | ports = [p['id'] for p in ports] |
497 | 60a80953 | Ilias Tsitsimpis | self.assertIn(port['id'], ports) |
498 | 60a80953 | Ilias Tsitsimpis | # Insist on creation
|
499 | 60a80953 | Ilias Tsitsimpis | if device_id is None: |
500 | 60a80953 | Ilias Tsitsimpis | self._insist_on_port_transition(port, ["BUILD"], "DOWN") |
501 | 60a80953 | Ilias Tsitsimpis | else:
|
502 | 60a80953 | Ilias Tsitsimpis | self._insist_on_port_transition(port, ["BUILD", "DOWN"], "ACTIVE") |
503 | 60a80953 | Ilias Tsitsimpis | |
504 | 60a80953 | Ilias Tsitsimpis | self.info("Port with id %s created", port['id']) |
505 | 60a80953 | Ilias Tsitsimpis | return port
|
506 | 60a80953 | Ilias Tsitsimpis | |
507 | 60a80953 | Ilias Tsitsimpis | def _insist_on_port_transition(self, port, curr_statuses, new_status): |
508 | 60a80953 | Ilias Tsitsimpis | """Insist on port transiting from curr_statuses to new_status"""
|
509 | 60a80953 | Ilias Tsitsimpis | def check_fun(): |
510 | 60a80953 | Ilias Tsitsimpis | """Check port status"""
|
511 | 60a80953 | Ilias Tsitsimpis | portd = self.clients.network.get_port_details(port['id']) |
512 | 60a80953 | Ilias Tsitsimpis | if portd['status'] in curr_statuses: |
513 | 60a80953 | Ilias Tsitsimpis | raise Retry()
|
514 | 60a80953 | Ilias Tsitsimpis | elif portd['status'] == new_status: |
515 | 60a80953 | Ilias Tsitsimpis | return
|
516 | 60a80953 | Ilias Tsitsimpis | else:
|
517 | 60a80953 | Ilias Tsitsimpis | msg = "Port %s went to unexpected status %s"
|
518 | 60a80953 | Ilias Tsitsimpis | self.fail(msg % (portd['id'], portd['status'])) |
519 | 60a80953 | Ilias Tsitsimpis | opmsg = "Waiting for port %s to become %s"
|
520 | 60a80953 | Ilias Tsitsimpis | self.info(opmsg, port['id'], new_status) |
521 | 60a80953 | Ilias Tsitsimpis | opmsg = opmsg % (port['id'], new_status)
|
522 | 60a80953 | Ilias Tsitsimpis | self._try_until_timeout_expires(opmsg, check_fun)
|
523 | 60a80953 | Ilias Tsitsimpis | |
524 | 60a80953 | Ilias Tsitsimpis | def _insist_on_port_deletion(self, portid): |
525 | 60a80953 | Ilias Tsitsimpis | """Insist on port deletion"""
|
526 | 60a80953 | Ilias Tsitsimpis | def check_fun(): |
527 | 60a80953 | Ilias Tsitsimpis | """Check port details"""
|
528 | 60a80953 | Ilias Tsitsimpis | try:
|
529 | 60a80953 | Ilias Tsitsimpis | self.clients.network.get_port_details(portid)
|
530 | 60a80953 | Ilias Tsitsimpis | except ClientError as err: |
531 | 60a80953 | Ilias Tsitsimpis | if err.status != 404: |
532 | 60a80953 | Ilias Tsitsimpis | raise
|
533 | 60a80953 | Ilias Tsitsimpis | else:
|
534 | 60a80953 | Ilias Tsitsimpis | raise Retry()
|
535 | 60a80953 | Ilias Tsitsimpis | opmsg = "Waiting for port %s to be deleted"
|
536 | 60a80953 | Ilias Tsitsimpis | self.info(opmsg, portid)
|
537 | 60a80953 | Ilias Tsitsimpis | opmsg = opmsg % portid |
538 | 60a80953 | Ilias Tsitsimpis | self._try_until_timeout_expires(opmsg, check_fun)
|
539 | 60a80953 | Ilias Tsitsimpis | |
540 | 60a80953 | Ilias Tsitsimpis | def _disconnect_from_network(self, server, network=None): |
541 | 60a80953 | Ilias Tsitsimpis | """Disconnnect server from network"""
|
542 | 60a80953 | Ilias Tsitsimpis | if network is None: |
543 | 60a80953 | Ilias Tsitsimpis | # Disconnect from public network
|
544 | 60a80953 | Ilias Tsitsimpis | network = self._get_public_network()
|
545 | 60a80953 | Ilias Tsitsimpis | |
546 | 60a80953 | Ilias Tsitsimpis | lports = self.clients.network.list_ports()
|
547 | 60a80953 | Ilias Tsitsimpis | ports = [] |
548 | 60a80953 | Ilias Tsitsimpis | for port in lports: |
549 | 60a80953 | Ilias Tsitsimpis | dport = self.clients.network.get_port_details(port['id']) |
550 | 60a80953 | Ilias Tsitsimpis | if str(dport['network_id']) == str(network['id']) \ |
551 | 60a80953 | Ilias Tsitsimpis | and str(dport['device_id']) == str(server['id']): |
552 | 60a80953 | Ilias Tsitsimpis | ports.append(dport) |
553 | 60a80953 | Ilias Tsitsimpis | |
554 | 60a80953 | Ilias Tsitsimpis | # Find floating IPs attached to these ports
|
555 | 60a80953 | Ilias Tsitsimpis | ports_id = [p['id'] for p in ports] |
556 | 60a80953 | Ilias Tsitsimpis | fips = [f for f in self.clients.network.list_floatingips() |
557 | 60a80953 | Ilias Tsitsimpis | if str(f['port_id']) in ports_id] |
558 | 60a80953 | Ilias Tsitsimpis | |
559 | 60a80953 | Ilias Tsitsimpis | # First destroy the ports
|
560 | 60a80953 | Ilias Tsitsimpis | for port in ports: |
561 | 60a80953 | Ilias Tsitsimpis | self.info("Destroying port with id %s", port['id']) |
562 | 60a80953 | Ilias Tsitsimpis | self.clients.network.delete_port(port['id']) |
563 | 60a80953 | Ilias Tsitsimpis | self._insist_on_port_deletion(port['id']) |
564 | 60a80953 | Ilias Tsitsimpis | |
565 | 60a80953 | Ilias Tsitsimpis | # Then delete the floating IPs
|
566 | 17bb60a5 | Ilias Tsitsimpis | self._delete_floating_ips(fips)
|
567 | 17bb60a5 | Ilias Tsitsimpis | |
568 | 17bb60a5 | Ilias Tsitsimpis | def _delete_floating_ips(self, fips): |
569 | 17bb60a5 | Ilias Tsitsimpis | """Delete floating ips"""
|
570 | 60a80953 | Ilias Tsitsimpis | for fip in fips: |
571 | 60a80953 | Ilias Tsitsimpis | self.info("Destroying floating IP %s with id %s", |
572 | 60a80953 | Ilias Tsitsimpis | fip['floating_ip_address'], fip['id']) |
573 | 60a80953 | Ilias Tsitsimpis | self.clients.network.delete_floatingip(fip['id']) |
574 | 60a80953 | Ilias Tsitsimpis | |
575 | 60a80953 | Ilias Tsitsimpis | # Check that floating IPs have been deleted
|
576 | 60a80953 | Ilias Tsitsimpis | list_ips = [f['id'] for f in self.clients.network.list_floatingips()] |
577 | 60a80953 | Ilias Tsitsimpis | for fip in fips: |
578 | 60a80953 | Ilias Tsitsimpis | self.assertNotIn(fip['id'], list_ips) |
579 | 60a80953 | Ilias Tsitsimpis | # Verify quotas
|
580 | 60a80953 | Ilias Tsitsimpis | self._check_quotas(ip=-len(fips)) |
581 | 60a80953 | Ilias Tsitsimpis | |
582 | d246be88 | Ilias Tsitsimpis | |
583 | d246be88 | Ilias Tsitsimpis | class Retry(Exception): |
584 | d246be88 | Ilias Tsitsimpis | """Retry the action
|
585 | d246be88 | Ilias Tsitsimpis |
|
586 | d246be88 | Ilias Tsitsimpis | This is used by _try_unit_timeout_expires method.
|
587 | d246be88 | Ilias Tsitsimpis |
|
588 | d246be88 | Ilias Tsitsimpis | """ |