root / snf-tools / synnefo_tools / burnin / cyclades_common.py @ 60a80953
History | View | Annotate | Download (22.8 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 | 60a80953 | Ilias Tsitsimpis | for srv in servers: |
154 | 60a80953 | Ilias Tsitsimpis | self.info("Disconnecting all floating IPs from server with id %s", |
155 | 60a80953 | Ilias Tsitsimpis | srv['id'])
|
156 | 60a80953 | Ilias Tsitsimpis | self._disconnect_from_network(srv)
|
157 | 60a80953 | Ilias Tsitsimpis | |
158 | 60a80953 | Ilias Tsitsimpis | # Delete servers
|
159 | 60a80953 | Ilias Tsitsimpis | for srv in servers: |
160 | 60a80953 | Ilias Tsitsimpis | self.info("Sending the delete request for server with id %s", |
161 | 60a80953 | Ilias Tsitsimpis | srv['id'])
|
162 | 60a80953 | Ilias Tsitsimpis | self.clients.cyclades.delete_server(srv['id']) |
163 | 60a80953 | Ilias Tsitsimpis | |
164 | 60a80953 | Ilias Tsitsimpis | if error:
|
165 | 60a80953 | Ilias Tsitsimpis | curr_states = ["ACTIVE", "ERROR", "STOPPED", "BUILD"] |
166 | 60a80953 | Ilias Tsitsimpis | else:
|
167 | 60a80953 | Ilias Tsitsimpis | curr_states = ["ACTIVE"]
|
168 | 60a80953 | Ilias Tsitsimpis | for srv in servers: |
169 | 60a80953 | Ilias Tsitsimpis | self._insist_on_server_transition(srv, curr_states, "DELETED") |
170 | 60a80953 | Ilias Tsitsimpis | |
171 | 60a80953 | Ilias Tsitsimpis | # Servers no longer in server list
|
172 | 60a80953 | Ilias Tsitsimpis | new_servers = [s['id'] for s in self._get_list_of_servers()] |
173 | 60a80953 | Ilias Tsitsimpis | for srv in servers: |
174 | 60a80953 | Ilias Tsitsimpis | self.info("Verifying that server with id %s is no longer in " |
175 | 60a80953 | Ilias Tsitsimpis | "server list", srv['id']) |
176 | 60a80953 | Ilias Tsitsimpis | self.assertNotIn(srv['id'], new_servers) |
177 | 60a80953 | Ilias Tsitsimpis | |
178 | 60a80953 | Ilias Tsitsimpis | # Verify quotas
|
179 | 60a80953 | Ilias Tsitsimpis | flavors = \ |
180 | 60a80953 | Ilias Tsitsimpis | [self.clients.compute.get_flavor_details(srv['flavor']['id']) |
181 | 60a80953 | Ilias Tsitsimpis | for srv in servers] |
182 | 60a80953 | Ilias Tsitsimpis | self._verify_quotas_deleted(flavors)
|
183 | 60a80953 | Ilias Tsitsimpis | |
184 | 3e5bbd85 | Ilias Tsitsimpis | def _verify_quotas_deleted(self, flavors): |
185 | 3e5bbd85 | Ilias Tsitsimpis | """Verify quotas for a number of deleted servers"""
|
186 | 3e5bbd85 | Ilias Tsitsimpis | used_disk = 0
|
187 | 3e5bbd85 | Ilias Tsitsimpis | used_vm = 0
|
188 | 3e5bbd85 | Ilias Tsitsimpis | used_ram = 0
|
189 | 3e5bbd85 | Ilias Tsitsimpis | used_cpu = 0
|
190 | 3e5bbd85 | Ilias Tsitsimpis | for flavor in flavors: |
191 | 3e5bbd85 | Ilias Tsitsimpis | used_disk += int(flavor['disk']) * GB |
192 | 3e5bbd85 | Ilias Tsitsimpis | used_vm += 1
|
193 | 3e5bbd85 | Ilias Tsitsimpis | used_ram += int(flavor['ram']) * MB |
194 | 3e5bbd85 | Ilias Tsitsimpis | used_cpu += int(flavor['vcpus']) |
195 | 3e5bbd85 | Ilias Tsitsimpis | self._check_quotas(disk=-used_disk,
|
196 | 3e5bbd85 | Ilias Tsitsimpis | vm=-used_vm, |
197 | 3e5bbd85 | Ilias Tsitsimpis | ram=-used_ram, |
198 | 3e5bbd85 | Ilias Tsitsimpis | cpu=-used_cpu) |
199 | 3e5bbd85 | Ilias Tsitsimpis | |
200 | d246be88 | Ilias Tsitsimpis | def _get_connection_username(self, server): |
201 | d246be88 | Ilias Tsitsimpis | """Determine the username to use to connect to the server"""
|
202 | d246be88 | Ilias Tsitsimpis | users = server['metadata'].get("users", None) |
203 | d246be88 | Ilias Tsitsimpis | ret_user = None
|
204 | d246be88 | Ilias Tsitsimpis | if users is not None: |
205 | d246be88 | Ilias Tsitsimpis | user_list = users.split() |
206 | d246be88 | Ilias Tsitsimpis | if "root" in user_list: |
207 | d246be88 | Ilias Tsitsimpis | ret_user = "root"
|
208 | d246be88 | Ilias Tsitsimpis | else:
|
209 | d246be88 | Ilias Tsitsimpis | ret_user = random.choice(user_list) |
210 | d246be88 | Ilias Tsitsimpis | else:
|
211 | d246be88 | Ilias Tsitsimpis | # Return the login name for connections based on the server OS
|
212 | d246be88 | Ilias Tsitsimpis | self.info("Could not find `users' metadata in server. Let's guess") |
213 | d246be88 | Ilias Tsitsimpis | os_value = server['metadata'].get("os") |
214 | d246be88 | Ilias Tsitsimpis | if os_value in ("Ubuntu", "Kubuntu", "Fedora"): |
215 | d246be88 | Ilias Tsitsimpis | ret_user = "user"
|
216 | d246be88 | Ilias Tsitsimpis | elif os_value in ("windows", "windows_alpha1"): |
217 | d246be88 | Ilias Tsitsimpis | ret_user = "Administrator"
|
218 | d246be88 | Ilias Tsitsimpis | else:
|
219 | d246be88 | Ilias Tsitsimpis | ret_user = "root"
|
220 | d246be88 | Ilias Tsitsimpis | |
221 | d246be88 | Ilias Tsitsimpis | self.assertIsNotNone(ret_user)
|
222 | d246be88 | Ilias Tsitsimpis | self.info("User's login name: %s", ret_user) |
223 | d246be88 | Ilias Tsitsimpis | return ret_user
|
224 | d246be88 | Ilias Tsitsimpis | |
225 | 3eaf0ec5 | Ilias Tsitsimpis | def _insist_on_server_transition(self, server, curr_statuses, new_status): |
226 | 3eaf0ec5 | Ilias Tsitsimpis | """Insist on server transiting from curr_statuses to new_status"""
|
227 | d246be88 | Ilias Tsitsimpis | def check_fun(): |
228 | d246be88 | Ilias Tsitsimpis | """Check server status"""
|
229 | 3eaf0ec5 | Ilias Tsitsimpis | srv = self._get_server_details(server, quiet=True) |
230 | 3eaf0ec5 | Ilias Tsitsimpis | if srv['status'] in curr_statuses: |
231 | d246be88 | Ilias Tsitsimpis | raise Retry()
|
232 | d246be88 | Ilias Tsitsimpis | elif srv['status'] == new_status: |
233 | d246be88 | Ilias Tsitsimpis | return
|
234 | d246be88 | Ilias Tsitsimpis | else:
|
235 | 3eaf0ec5 | Ilias Tsitsimpis | msg = "Server \"%s\" with id %s went to unexpected status %s"
|
236 | 3eaf0ec5 | Ilias Tsitsimpis | self.error(msg, server['name'], server['id'], srv['status']) |
237 | 3eaf0ec5 | Ilias Tsitsimpis | self.fail(msg % (server['name'], server['id'], srv['status'])) |
238 | 5bef1f49 | Ilias Tsitsimpis | opmsg = "Waiting for server \"%s\" with id %s to become %s"
|
239 | 5bef1f49 | Ilias Tsitsimpis | self.info(opmsg, server['name'], server['id'], new_status) |
240 | 5bef1f49 | Ilias Tsitsimpis | opmsg = opmsg % (server['name'], server['id'], new_status) |
241 | 3eaf0ec5 | Ilias Tsitsimpis | self._try_until_timeout_expires(opmsg, check_fun)
|
242 | 3eaf0ec5 | Ilias Tsitsimpis | |
243 | 3eaf0ec5 | Ilias Tsitsimpis | def _insist_on_network_transition(self, network, |
244 | 3eaf0ec5 | Ilias Tsitsimpis | curr_statuses, new_status): |
245 | 3eaf0ec5 | Ilias Tsitsimpis | """Insist on network transiting from curr_statuses to new_status"""
|
246 | 3eaf0ec5 | Ilias Tsitsimpis | def check_fun(): |
247 | 3eaf0ec5 | Ilias Tsitsimpis | """Check network status"""
|
248 | 60a80953 | Ilias Tsitsimpis | ntw = self.clients.network.get_network_details(network['id']) |
249 | 3eaf0ec5 | Ilias Tsitsimpis | if ntw['status'] in curr_statuses: |
250 | 3eaf0ec5 | Ilias Tsitsimpis | raise Retry()
|
251 | 3eaf0ec5 | Ilias Tsitsimpis | elif ntw['status'] == new_status: |
252 | 3eaf0ec5 | Ilias Tsitsimpis | return
|
253 | 3eaf0ec5 | Ilias Tsitsimpis | else:
|
254 | 3eaf0ec5 | Ilias Tsitsimpis | msg = "Network %s with id %s went to unexpected status %s"
|
255 | 3eaf0ec5 | Ilias Tsitsimpis | self.error(msg, network['name'], network['id'], ntw['status']) |
256 | 3eaf0ec5 | Ilias Tsitsimpis | self.fail(msg %
|
257 | 3eaf0ec5 | Ilias Tsitsimpis | (network['name'], network['id'], ntw['status'])) |
258 | 5bef1f49 | Ilias Tsitsimpis | opmsg = "Waiting for network \"%s\" with id %s to become %s"
|
259 | 5bef1f49 | Ilias Tsitsimpis | self.info(opmsg, network['name'], network['id'], new_status) |
260 | 5bef1f49 | Ilias Tsitsimpis | opmsg = opmsg % (network['name'], network['id'], new_status) |
261 | 3eaf0ec5 | Ilias Tsitsimpis | self._try_until_timeout_expires(opmsg, check_fun)
|
262 | 3eaf0ec5 | Ilias Tsitsimpis | |
263 | d246be88 | Ilias Tsitsimpis | def _insist_on_tcp_connection(self, family, host, port): |
264 | d246be88 | Ilias Tsitsimpis | """Insist on tcp connection"""
|
265 | d246be88 | Ilias Tsitsimpis | def check_fun(): |
266 | d246be88 | Ilias Tsitsimpis | """Get a connected socket from the specified family to host:port"""
|
267 | d246be88 | Ilias Tsitsimpis | sock = None
|
268 | d246be88 | Ilias Tsitsimpis | for res in socket.getaddrinfo(host, port, family, |
269 | d246be88 | Ilias Tsitsimpis | socket.SOCK_STREAM, 0,
|
270 | d246be88 | Ilias Tsitsimpis | socket.AI_PASSIVE): |
271 | d246be88 | Ilias Tsitsimpis | fam, socktype, proto, _, saddr = res |
272 | d246be88 | Ilias Tsitsimpis | try:
|
273 | d246be88 | Ilias Tsitsimpis | sock = socket.socket(fam, socktype, proto) |
274 | d246be88 | Ilias Tsitsimpis | except socket.error:
|
275 | d246be88 | Ilias Tsitsimpis | sock = None
|
276 | d246be88 | Ilias Tsitsimpis | continue
|
277 | d246be88 | Ilias Tsitsimpis | try:
|
278 | d246be88 | Ilias Tsitsimpis | sock.connect(saddr) |
279 | d246be88 | Ilias Tsitsimpis | except socket.error:
|
280 | d246be88 | Ilias Tsitsimpis | sock.close() |
281 | d246be88 | Ilias Tsitsimpis | sock = None
|
282 | d246be88 | Ilias Tsitsimpis | continue
|
283 | d246be88 | Ilias Tsitsimpis | if sock is None: |
284 | d246be88 | Ilias Tsitsimpis | raise Retry
|
285 | d246be88 | Ilias Tsitsimpis | return sock
|
286 | d246be88 | Ilias Tsitsimpis | familystr = {socket.AF_INET: "IPv4", socket.AF_INET6: "IPv6", |
287 | d246be88 | Ilias Tsitsimpis | socket.AF_UNSPEC: "Unspecified-IPv4/6"}
|
288 | d246be88 | Ilias Tsitsimpis | opmsg = "Connecting over %s to %s:%s"
|
289 | d246be88 | Ilias Tsitsimpis | self.info(opmsg, familystr.get(family, "Unknown"), host, port) |
290 | d246be88 | Ilias Tsitsimpis | opmsg = opmsg % (familystr.get(family, "Unknown"), host, port)
|
291 | d246be88 | Ilias Tsitsimpis | return self._try_until_timeout_expires(opmsg, check_fun) |
292 | d246be88 | Ilias Tsitsimpis | |
293 | 60a80953 | Ilias Tsitsimpis | def _get_ips(self, server, version=4, network=None): |
294 | 60a80953 | Ilias Tsitsimpis | """Get the IPs of a server from the detailed server info
|
295 | 3eaf0ec5 | Ilias Tsitsimpis |
|
296 | 60a80953 | Ilias Tsitsimpis | If network not given then get the public IPs. Else the IPs
|
297 | 3eaf0ec5 | Ilias Tsitsimpis | attached to that network
|
298 | 3eaf0ec5 | Ilias Tsitsimpis |
|
299 | 3eaf0ec5 | Ilias Tsitsimpis | """
|
300 | d246be88 | Ilias Tsitsimpis | assert version in (4, 6) |
301 | d246be88 | Ilias Tsitsimpis | |
302 | d246be88 | Ilias Tsitsimpis | nics = server['attachments']
|
303 | 60a80953 | Ilias Tsitsimpis | addrs = [] |
304 | d246be88 | Ilias Tsitsimpis | for nic in nics: |
305 | d246be88 | Ilias Tsitsimpis | net_id = nic['network_id']
|
306 | 3eaf0ec5 | Ilias Tsitsimpis | if network is None: |
307 | 60a80953 | Ilias Tsitsimpis | if self.clients.network.get_network_details(net_id)['public']: |
308 | ee89df69 | Ilias Tsitsimpis | if nic['ipv' + str(version)]: |
309 | 60a80953 | Ilias Tsitsimpis | addrs.append(nic['ipv' + str(version)]) |
310 | 3eaf0ec5 | Ilias Tsitsimpis | else:
|
311 | 3eaf0ec5 | Ilias Tsitsimpis | if net_id == network['id']: |
312 | ee89df69 | Ilias Tsitsimpis | if nic['ipv' + str(version)]: |
313 | 60a80953 | Ilias Tsitsimpis | addrs.append(nic['ipv' + str(version)]) |
314 | 60a80953 | Ilias Tsitsimpis | |
315 | 60a80953 | Ilias Tsitsimpis | self.assertGreater(len(addrs), 0, |
316 | 60a80953 | Ilias Tsitsimpis | "Can not get IPs from server attachments")
|
317 | 60a80953 | Ilias Tsitsimpis | |
318 | 60a80953 | Ilias Tsitsimpis | for addr in addrs: |
319 | 60a80953 | Ilias Tsitsimpis | self.assertEquals(IPy.IP(addr).version(), version)
|
320 | d246be88 | Ilias Tsitsimpis | |
321 | 3eaf0ec5 | Ilias Tsitsimpis | if network is None: |
322 | 3eaf0ec5 | Ilias Tsitsimpis | msg = "Server's public IPv%s is %s"
|
323 | 60a80953 | Ilias Tsitsimpis | for addr in addrs: |
324 | 60a80953 | Ilias Tsitsimpis | self.info(msg, version, addr)
|
325 | 3eaf0ec5 | Ilias Tsitsimpis | else:
|
326 | 3eaf0ec5 | Ilias Tsitsimpis | msg = "Server's IPv%s attached to network \"%s\" is %s"
|
327 | 60a80953 | Ilias Tsitsimpis | for addr in addrs: |
328 | 60a80953 | Ilias Tsitsimpis | self.info(msg, version, network['id'], addr) |
329 | 3eaf0ec5 | Ilias Tsitsimpis | return addrs
|
330 | d246be88 | Ilias Tsitsimpis | |
331 | cee3ee9b | Ilias Tsitsimpis | def _insist_on_ping(self, ip_addr, version=4): |
332 | d246be88 | Ilias Tsitsimpis | """Test server responds to a single IPv4 of IPv6 ping"""
|
333 | d246be88 | Ilias Tsitsimpis | def check_fun(): |
334 | d246be88 | Ilias Tsitsimpis | """Ping to server"""
|
335 | d246be88 | Ilias Tsitsimpis | cmd = ("ping%s -c 3 -w 20 %s" %
|
336 | d246be88 | Ilias Tsitsimpis | ("6" if version == 6 else "", ip_addr)) |
337 | d246be88 | Ilias Tsitsimpis | ping = subprocess.Popen( |
338 | d246be88 | Ilias Tsitsimpis | cmd, shell=True, stdout=subprocess.PIPE,
|
339 | d246be88 | Ilias Tsitsimpis | stderr=subprocess.PIPE) |
340 | d246be88 | Ilias Tsitsimpis | ping.communicate() |
341 | d246be88 | Ilias Tsitsimpis | ret = ping.wait() |
342 | d246be88 | Ilias Tsitsimpis | if ret != 0: |
343 | d246be88 | Ilias Tsitsimpis | raise Retry
|
344 | cee3ee9b | Ilias Tsitsimpis | assert version in (4, 6) |
345 | d246be88 | Ilias Tsitsimpis | opmsg = "Sent IPv%s ping requests to %s"
|
346 | d246be88 | Ilias Tsitsimpis | self.info(opmsg, version, ip_addr)
|
347 | d246be88 | Ilias Tsitsimpis | opmsg = opmsg % (version, ip_addr) |
348 | d246be88 | Ilias Tsitsimpis | self._try_until_timeout_expires(opmsg, check_fun)
|
349 | d246be88 | Ilias Tsitsimpis | |
350 | cee3ee9b | Ilias Tsitsimpis | def _image_is(self, image, osfamily): |
351 | cee3ee9b | Ilias Tsitsimpis | """Return true if the image is of `osfamily'"""
|
352 | cee3ee9b | Ilias Tsitsimpis | d_image = self.clients.cyclades.get_image_details(image['id']) |
353 | cee3ee9b | Ilias Tsitsimpis | return d_image['metadata']['osfamily'].lower().find(osfamily) >= 0 |
354 | cee3ee9b | Ilias Tsitsimpis | |
355 | cee3ee9b | Ilias Tsitsimpis | def _ssh_execute(self, hostip, username, password, command): |
356 | cee3ee9b | Ilias Tsitsimpis | """Execute a command via ssh"""
|
357 | cee3ee9b | Ilias Tsitsimpis | ssh = paramiko.SSHClient() |
358 | cee3ee9b | Ilias Tsitsimpis | ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) |
359 | cee3ee9b | Ilias Tsitsimpis | try:
|
360 | cee3ee9b | Ilias Tsitsimpis | ssh.connect(hostip, username=username, password=password) |
361 | cee3ee9b | Ilias Tsitsimpis | except socket.error as err: |
362 | cee3ee9b | Ilias Tsitsimpis | self.fail(err)
|
363 | cee3ee9b | Ilias Tsitsimpis | try:
|
364 | cee3ee9b | Ilias Tsitsimpis | _, stdout, _ = ssh.exec_command(command) |
365 | cee3ee9b | Ilias Tsitsimpis | except paramiko.SSHException as err: |
366 | cee3ee9b | Ilias Tsitsimpis | self.fail(err)
|
367 | cee3ee9b | Ilias Tsitsimpis | status = stdout.channel.recv_exit_status() |
368 | cee3ee9b | Ilias Tsitsimpis | output = stdout.readlines() |
369 | cee3ee9b | Ilias Tsitsimpis | ssh.close() |
370 | cee3ee9b | Ilias Tsitsimpis | return output, status
|
371 | cee3ee9b | Ilias Tsitsimpis | |
372 | cee3ee9b | Ilias Tsitsimpis | def _insist_get_hostname_over_ssh(self, hostip, username, password): |
373 | cee3ee9b | Ilias Tsitsimpis | """Connect to server using ssh and get it's hostname"""
|
374 | cee3ee9b | Ilias Tsitsimpis | def check_fun(): |
375 | cee3ee9b | Ilias Tsitsimpis | """Get hostname"""
|
376 | cee3ee9b | Ilias Tsitsimpis | try:
|
377 | cee3ee9b | Ilias Tsitsimpis | lines, status = self._ssh_execute(
|
378 | cee3ee9b | Ilias Tsitsimpis | hostip, username, password, "hostname")
|
379 | cee3ee9b | Ilias Tsitsimpis | self.assertEqual(status, 0) |
380 | cee3ee9b | Ilias Tsitsimpis | self.assertEqual(len(lines), 1) |
381 | cee3ee9b | Ilias Tsitsimpis | # Remove new line
|
382 | cee3ee9b | Ilias Tsitsimpis | return lines[0].strip('\n') |
383 | cee3ee9b | Ilias Tsitsimpis | except AssertionError: |
384 | cee3ee9b | Ilias Tsitsimpis | raise Retry()
|
385 | cee3ee9b | Ilias Tsitsimpis | opmsg = "Connecting to server using ssh and get it's hostname"
|
386 | cee3ee9b | Ilias Tsitsimpis | self.info(opmsg)
|
387 | cee3ee9b | Ilias Tsitsimpis | hostname = self._try_until_timeout_expires(opmsg, check_fun)
|
388 | cee3ee9b | Ilias Tsitsimpis | self.info("Server's hostname is %s", hostname) |
389 | cee3ee9b | Ilias Tsitsimpis | return hostname
|
390 | cee3ee9b | Ilias Tsitsimpis | |
391 | cee3ee9b | Ilias Tsitsimpis | # Too many arguments. pylint: disable-msg=R0913
|
392 | cee3ee9b | Ilias Tsitsimpis | def _check_file_through_ssh(self, hostip, username, password, |
393 | cee3ee9b | Ilias Tsitsimpis | remotepath, content): |
394 | cee3ee9b | Ilias Tsitsimpis | """Fetch file from server and compare contents"""
|
395 | cee3ee9b | Ilias Tsitsimpis | self.info("Fetching file %s from remote server", remotepath) |
396 | cee3ee9b | Ilias Tsitsimpis | transport = paramiko.Transport((hostip, 22))
|
397 | cee3ee9b | Ilias Tsitsimpis | transport.connect(username=username, password=password) |
398 | cee3ee9b | Ilias Tsitsimpis | with tempfile.NamedTemporaryFile() as ftmp: |
399 | cee3ee9b | Ilias Tsitsimpis | sftp = paramiko.SFTPClient.from_transport(transport) |
400 | cee3ee9b | Ilias Tsitsimpis | sftp.get(remotepath, ftmp.name) |
401 | cee3ee9b | Ilias Tsitsimpis | sftp.close() |
402 | cee3ee9b | Ilias Tsitsimpis | transport.close() |
403 | cee3ee9b | Ilias Tsitsimpis | self.info("Comparing file contents") |
404 | cee3ee9b | Ilias Tsitsimpis | remote_content = base64.b64encode(ftmp.read()) |
405 | cee3ee9b | Ilias Tsitsimpis | self.assertEqual(content, remote_content)
|
406 | cee3ee9b | Ilias Tsitsimpis | |
407 | 60a80953 | Ilias Tsitsimpis | # ----------------------------------
|
408 | 60a80953 | Ilias Tsitsimpis | # Networks
|
409 | 60a80953 | Ilias Tsitsimpis | def _create_network(self, cidr="10.0.1.0/28", dhcp=True): |
410 | 3e5bbd85 | Ilias Tsitsimpis | """Create a new private network"""
|
411 | 60a80953 | Ilias Tsitsimpis | name = self.run_id
|
412 | 60a80953 | Ilias Tsitsimpis | network = self.clients.network.create_network(
|
413 | 60a80953 | Ilias Tsitsimpis | "MAC_FILTERED", name=name, shared=False) |
414 | 3e5bbd85 | Ilias Tsitsimpis | self.info("Network with id %s created", network['id']) |
415 | 60a80953 | Ilias Tsitsimpis | subnet = self.clients.network.create_subnet(
|
416 | 60a80953 | Ilias Tsitsimpis | network['id'], cidr=cidr, enable_dhcp=dhcp)
|
417 | 60a80953 | Ilias Tsitsimpis | self.info("Subnet with id %s created", subnet['id']) |
418 | 3e5bbd85 | Ilias Tsitsimpis | |
419 | 3e5bbd85 | Ilias Tsitsimpis | # Verify quotas
|
420 | 3e5bbd85 | Ilias Tsitsimpis | self._check_quotas(network=+1) |
421 | 3e5bbd85 | Ilias Tsitsimpis | |
422 | 3e5bbd85 | Ilias Tsitsimpis | #Test if the right name is assigned
|
423 | 3e5bbd85 | Ilias Tsitsimpis | self.assertEqual(network['name'], name) |
424 | 3e5bbd85 | Ilias Tsitsimpis | |
425 | 3e5bbd85 | Ilias Tsitsimpis | return network
|
426 | 3e5bbd85 | Ilias Tsitsimpis | |
427 | 60a80953 | Ilias Tsitsimpis | def _delete_networks(self, networks, error=False): |
428 | 60a80953 | Ilias Tsitsimpis | """Delete a network"""
|
429 | 60a80953 | Ilias Tsitsimpis | for net in networks: |
430 | 60a80953 | Ilias Tsitsimpis | self.info("Deleting network with id %s", net['id']) |
431 | 60a80953 | Ilias Tsitsimpis | self.clients.network.delete_network(net['id']) |
432 | 60a80953 | Ilias Tsitsimpis | |
433 | 60a80953 | Ilias Tsitsimpis | if error:
|
434 | 60a80953 | Ilias Tsitsimpis | curr_states = ["ACTIVE", "SNF:DRAINED", "ERROR"] |
435 | 60a80953 | Ilias Tsitsimpis | else:
|
436 | 60a80953 | Ilias Tsitsimpis | curr_states = ["ACTIVE", "SNF:DRAINED"] |
437 | 60a80953 | Ilias Tsitsimpis | for net in networks: |
438 | 60a80953 | Ilias Tsitsimpis | self._insist_on_network_transition(net, curr_states, "DELETED") |
439 | 60a80953 | Ilias Tsitsimpis | |
440 | 60a80953 | Ilias Tsitsimpis | # Networks no longer in network list
|
441 | 60a80953 | Ilias Tsitsimpis | new_networks = [n['id'] for n in self._get_list_of_networks()] |
442 | 60a80953 | Ilias Tsitsimpis | for net in networks: |
443 | 60a80953 | Ilias Tsitsimpis | self.info("Verifying that network with id %s is no longer in " |
444 | 60a80953 | Ilias Tsitsimpis | "network list", net['id']) |
445 | 60a80953 | Ilias Tsitsimpis | self.assertNotIn(net['id'], new_networks) |
446 | 60a80953 | Ilias Tsitsimpis | |
447 | 60a80953 | Ilias Tsitsimpis | # Verify quotas
|
448 | 60a80953 | Ilias Tsitsimpis | self._check_quotas(network=-len(networks)) |
449 | 60a80953 | Ilias Tsitsimpis | |
450 | 60a80953 | Ilias Tsitsimpis | def _get_public_network(self, networks=None): |
451 | 60a80953 | Ilias Tsitsimpis | """Get the public network"""
|
452 | 60a80953 | Ilias Tsitsimpis | if networks is None: |
453 | 60a80953 | Ilias Tsitsimpis | networks = self._get_list_of_networks(detail=True) |
454 | 60a80953 | Ilias Tsitsimpis | self.info("Getting the public network") |
455 | 60a80953 | Ilias Tsitsimpis | for net in networks: |
456 | 60a80953 | Ilias Tsitsimpis | if net['SNF:floating_ip_pool'] and net['public']: |
457 | 60a80953 | Ilias Tsitsimpis | return net
|
458 | 60a80953 | Ilias Tsitsimpis | self.fail("Could not find a public network to use") |
459 | 60a80953 | Ilias Tsitsimpis | |
460 | 60a80953 | Ilias Tsitsimpis | def _create_floating_ip(self): |
461 | 60a80953 | Ilias Tsitsimpis | """Create a new floating ip"""
|
462 | 60a80953 | Ilias Tsitsimpis | pub_net = self._get_public_network()
|
463 | 60a80953 | Ilias Tsitsimpis | self.info("Creating a new floating ip for network with id %s", |
464 | 60a80953 | Ilias Tsitsimpis | pub_net['id'])
|
465 | 60a80953 | Ilias Tsitsimpis | fip = self.clients.network.create_floatingip(pub_net['id']) |
466 | 60a80953 | Ilias Tsitsimpis | # Verify that floating ip has been created
|
467 | 60a80953 | Ilias Tsitsimpis | fips = self.clients.network.list_floatingips()
|
468 | 60a80953 | Ilias Tsitsimpis | fips = [f['id'] for f in fips] |
469 | 60a80953 | Ilias Tsitsimpis | self.assertIn(fip['id'], fips) |
470 | 60a80953 | Ilias Tsitsimpis | # Verify quotas
|
471 | 60a80953 | Ilias Tsitsimpis | self._check_quotas(ip=+1) |
472 | 60a80953 | Ilias Tsitsimpis | # Check that IP is IPv4
|
473 | 60a80953 | Ilias Tsitsimpis | self.assertEquals(IPy.IP(fip['floating_ip_address']).version(), 4) |
474 | 60a80953 | Ilias Tsitsimpis | |
475 | 60a80953 | Ilias Tsitsimpis | self.info("Floating IP %s with id %s created", |
476 | 60a80953 | Ilias Tsitsimpis | fip['floating_ip_address'], fip['id']) |
477 | 60a80953 | Ilias Tsitsimpis | return fip
|
478 | 60a80953 | Ilias Tsitsimpis | |
479 | 60a80953 | Ilias Tsitsimpis | def _create_port(self, network_id, device_id=None, floating_ip=None): |
480 | 60a80953 | Ilias Tsitsimpis | """Create a new port attached to the a specific network"""
|
481 | 60a80953 | Ilias Tsitsimpis | self.info("Creating a new port to network with id %s", network_id) |
482 | 60a80953 | Ilias Tsitsimpis | if floating_ip is not None: |
483 | 60a80953 | Ilias Tsitsimpis | fixed_ips = [{'ip_address': floating_ip['floating_ip_address']}] |
484 | 60a80953 | Ilias Tsitsimpis | else:
|
485 | 60a80953 | Ilias Tsitsimpis | fixed_ips = None
|
486 | 60a80953 | Ilias Tsitsimpis | port = self.clients.network.create_port(network_id,
|
487 | 60a80953 | Ilias Tsitsimpis | device_id=device_id, |
488 | 60a80953 | Ilias Tsitsimpis | fixed_ips=fixed_ips) |
489 | 60a80953 | Ilias Tsitsimpis | # Verify that port created
|
490 | 60a80953 | Ilias Tsitsimpis | ports = self.clients.network.list_ports()
|
491 | 60a80953 | Ilias Tsitsimpis | ports = [p['id'] for p in ports] |
492 | 60a80953 | Ilias Tsitsimpis | self.assertIn(port['id'], ports) |
493 | 60a80953 | Ilias Tsitsimpis | # Insist on creation
|
494 | 60a80953 | Ilias Tsitsimpis | if device_id is None: |
495 | 60a80953 | Ilias Tsitsimpis | self._insist_on_port_transition(port, ["BUILD"], "DOWN") |
496 | 60a80953 | Ilias Tsitsimpis | else:
|
497 | 60a80953 | Ilias Tsitsimpis | self._insist_on_port_transition(port, ["BUILD", "DOWN"], "ACTIVE") |
498 | 60a80953 | Ilias Tsitsimpis | |
499 | 60a80953 | Ilias Tsitsimpis | self.info("Port with id %s created", port['id']) |
500 | 60a80953 | Ilias Tsitsimpis | return port
|
501 | 60a80953 | Ilias Tsitsimpis | |
502 | 60a80953 | Ilias Tsitsimpis | def _insist_on_port_transition(self, port, curr_statuses, new_status): |
503 | 60a80953 | Ilias Tsitsimpis | """Insist on port transiting from curr_statuses to new_status"""
|
504 | 60a80953 | Ilias Tsitsimpis | def check_fun(): |
505 | 60a80953 | Ilias Tsitsimpis | """Check port status"""
|
506 | 60a80953 | Ilias Tsitsimpis | portd = self.clients.network.get_port_details(port['id']) |
507 | 60a80953 | Ilias Tsitsimpis | if portd['status'] in curr_statuses: |
508 | 60a80953 | Ilias Tsitsimpis | raise Retry()
|
509 | 60a80953 | Ilias Tsitsimpis | elif portd['status'] == new_status: |
510 | 60a80953 | Ilias Tsitsimpis | return
|
511 | 60a80953 | Ilias Tsitsimpis | else:
|
512 | 60a80953 | Ilias Tsitsimpis | msg = "Port %s went to unexpected status %s"
|
513 | 60a80953 | Ilias Tsitsimpis | self.fail(msg % (portd['id'], portd['status'])) |
514 | 60a80953 | Ilias Tsitsimpis | opmsg = "Waiting for port %s to become %s"
|
515 | 60a80953 | Ilias Tsitsimpis | self.info(opmsg, port['id'], new_status) |
516 | 60a80953 | Ilias Tsitsimpis | opmsg = opmsg % (port['id'], new_status)
|
517 | 60a80953 | Ilias Tsitsimpis | self._try_until_timeout_expires(opmsg, check_fun)
|
518 | 60a80953 | Ilias Tsitsimpis | |
519 | 60a80953 | Ilias Tsitsimpis | def _insist_on_port_deletion(self, portid): |
520 | 60a80953 | Ilias Tsitsimpis | """Insist on port deletion"""
|
521 | 60a80953 | Ilias Tsitsimpis | def check_fun(): |
522 | 60a80953 | Ilias Tsitsimpis | """Check port details"""
|
523 | 60a80953 | Ilias Tsitsimpis | try:
|
524 | 60a80953 | Ilias Tsitsimpis | self.clients.network.get_port_details(portid)
|
525 | 60a80953 | Ilias Tsitsimpis | except ClientError as err: |
526 | 60a80953 | Ilias Tsitsimpis | if err.status != 404: |
527 | 60a80953 | Ilias Tsitsimpis | raise
|
528 | 60a80953 | Ilias Tsitsimpis | else:
|
529 | 60a80953 | Ilias Tsitsimpis | raise Retry()
|
530 | 60a80953 | Ilias Tsitsimpis | opmsg = "Waiting for port %s to be deleted"
|
531 | 60a80953 | Ilias Tsitsimpis | self.info(opmsg, portid)
|
532 | 60a80953 | Ilias Tsitsimpis | opmsg = opmsg % portid |
533 | 60a80953 | Ilias Tsitsimpis | self._try_until_timeout_expires(opmsg, check_fun)
|
534 | 60a80953 | Ilias Tsitsimpis | |
535 | 60a80953 | Ilias Tsitsimpis | def _disconnect_from_network(self, server, network=None): |
536 | 60a80953 | Ilias Tsitsimpis | """Disconnnect server from network"""
|
537 | 60a80953 | Ilias Tsitsimpis | if network is None: |
538 | 60a80953 | Ilias Tsitsimpis | # Disconnect from public network
|
539 | 60a80953 | Ilias Tsitsimpis | network = self._get_public_network()
|
540 | 60a80953 | Ilias Tsitsimpis | |
541 | 60a80953 | Ilias Tsitsimpis | lports = self.clients.network.list_ports()
|
542 | 60a80953 | Ilias Tsitsimpis | ports = [] |
543 | 60a80953 | Ilias Tsitsimpis | for port in lports: |
544 | 60a80953 | Ilias Tsitsimpis | dport = self.clients.network.get_port_details(port['id']) |
545 | 60a80953 | Ilias Tsitsimpis | if str(dport['network_id']) == str(network['id']) \ |
546 | 60a80953 | Ilias Tsitsimpis | and str(dport['device_id']) == str(server['id']): |
547 | 60a80953 | Ilias Tsitsimpis | ports.append(dport) |
548 | 60a80953 | Ilias Tsitsimpis | |
549 | 60a80953 | Ilias Tsitsimpis | # Find floating IPs attached to these ports
|
550 | 60a80953 | Ilias Tsitsimpis | ports_id = [p['id'] for p in ports] |
551 | 60a80953 | Ilias Tsitsimpis | fips = [f for f in self.clients.network.list_floatingips() |
552 | 60a80953 | Ilias Tsitsimpis | if str(f['port_id']) in ports_id] |
553 | 60a80953 | Ilias Tsitsimpis | |
554 | 60a80953 | Ilias Tsitsimpis | # First destroy the ports
|
555 | 60a80953 | Ilias Tsitsimpis | for port in ports: |
556 | 60a80953 | Ilias Tsitsimpis | self.info("Destroying port with id %s", port['id']) |
557 | 60a80953 | Ilias Tsitsimpis | self.clients.network.delete_port(port['id']) |
558 | 60a80953 | Ilias Tsitsimpis | self._insist_on_port_deletion(port['id']) |
559 | 60a80953 | Ilias Tsitsimpis | |
560 | 60a80953 | Ilias Tsitsimpis | # Then delete the floating IPs
|
561 | 60a80953 | Ilias Tsitsimpis | for fip in fips: |
562 | 60a80953 | Ilias Tsitsimpis | self.info("Destroying floating IP %s with id %s", |
563 | 60a80953 | Ilias Tsitsimpis | fip['floating_ip_address'], fip['id']) |
564 | 60a80953 | Ilias Tsitsimpis | self.clients.network.delete_floatingip(fip['id']) |
565 | 60a80953 | Ilias Tsitsimpis | |
566 | 60a80953 | Ilias Tsitsimpis | # Check that floating IPs have been deleted
|
567 | 60a80953 | Ilias Tsitsimpis | list_ips = [f['id'] for f in self.clients.network.list_floatingips()] |
568 | 60a80953 | Ilias Tsitsimpis | for fip in fips: |
569 | 60a80953 | Ilias Tsitsimpis | self.assertNotIn(fip['id'], list_ips) |
570 | 60a80953 | Ilias Tsitsimpis | # Verify quotas
|
571 | 60a80953 | Ilias Tsitsimpis | self._check_quotas(ip=-len(fips)) |
572 | 60a80953 | Ilias Tsitsimpis | |
573 | d246be88 | Ilias Tsitsimpis | |
574 | d246be88 | Ilias Tsitsimpis | class Retry(Exception): |
575 | d246be88 | Ilias Tsitsimpis | """Retry the action
|
576 | d246be88 | Ilias Tsitsimpis |
|
577 | d246be88 | Ilias Tsitsimpis | This is used by _try_unit_timeout_expires method.
|
578 | d246be88 | Ilias Tsitsimpis |
|
579 | d246be88 | Ilias Tsitsimpis | """ |