Statistics
| Branch: | Tag: | Revision:

root / snf-tools / synnefo_tools / burnin / cyclades_common.py @ 5bef1f49

History | View | Annotate | Download (14.9 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 cee3ee9b Ilias Tsitsimpis
import base64
43 d246be88 Ilias Tsitsimpis
import socket
44 d246be88 Ilias Tsitsimpis
import random
45 cee3ee9b Ilias Tsitsimpis
import paramiko
46 cee3ee9b Ilias Tsitsimpis
import tempfile
47 d246be88 Ilias Tsitsimpis
import subprocess
48 d246be88 Ilias Tsitsimpis
49 d246be88 Ilias Tsitsimpis
from synnefo_tools.burnin.common import BurninTests
50 d246be88 Ilias Tsitsimpis
51 d246be88 Ilias Tsitsimpis
52 d246be88 Ilias Tsitsimpis
# Too many public methods. pylint: disable-msg=R0904
53 d246be88 Ilias Tsitsimpis
class CycladesTests(BurninTests):
54 d246be88 Ilias Tsitsimpis
    """Extends the BurninTests class for Cyclades"""
55 3eaf0ec5 Ilias Tsitsimpis
    def _try_until_timeout_expires(self, opmsg, check_fun):
56 d246be88 Ilias Tsitsimpis
        """Try to perform an action until timeout expires"""
57 d246be88 Ilias Tsitsimpis
        assert callable(check_fun), "Not a function"
58 d246be88 Ilias Tsitsimpis
59 d246be88 Ilias Tsitsimpis
        action_timeout = self.action_timeout
60 d246be88 Ilias Tsitsimpis
        action_warning = self.action_warning
61 d246be88 Ilias Tsitsimpis
        if action_warning > action_timeout:
62 d246be88 Ilias Tsitsimpis
            action_warning = action_timeout
63 d246be88 Ilias Tsitsimpis
64 8c67f82e Ilias Tsitsimpis
        start_time = int(time.time())
65 8c67f82e Ilias Tsitsimpis
        end_time = start_time + action_warning
66 8c67f82e Ilias Tsitsimpis
        while end_time > time.time():
67 d246be88 Ilias Tsitsimpis
            try:
68 8c67f82e Ilias Tsitsimpis
                ret_value = check_fun()
69 8c67f82e Ilias Tsitsimpis
                self.info("Operation `%s' finished in %s seconds",
70 8c67f82e Ilias Tsitsimpis
                          opmsg, int(time.time()) - start_time)
71 8c67f82e Ilias Tsitsimpis
                return ret_value
72 d246be88 Ilias Tsitsimpis
            except Retry:
73 d246be88 Ilias Tsitsimpis
                time.sleep(self.query_interval)
74 8c67f82e Ilias Tsitsimpis
        self.warning("Operation `%s' is taking too long after %s seconds",
75 8c67f82e Ilias Tsitsimpis
                     opmsg, int(time.time()) - start_time)
76 8c67f82e Ilias Tsitsimpis
77 8c67f82e Ilias Tsitsimpis
        end_time = start_time + action_timeout
78 8c67f82e Ilias Tsitsimpis
        while end_time > time.time():
79 d246be88 Ilias Tsitsimpis
            try:
80 8c67f82e Ilias Tsitsimpis
                ret_value = check_fun()
81 8c67f82e Ilias Tsitsimpis
                self.info("Operation `%s' finished in %s seconds",
82 8c67f82e Ilias Tsitsimpis
                          opmsg, int(time.time()) - start_time)
83 8c67f82e Ilias Tsitsimpis
                return ret_value
84 d246be88 Ilias Tsitsimpis
            except Retry:
85 d246be88 Ilias Tsitsimpis
                time.sleep(self.query_interval)
86 8c67f82e Ilias Tsitsimpis
        self.error("Operation `%s' timed out after %s seconds",
87 8c67f82e Ilias Tsitsimpis
                   opmsg, int(time.time()) - start_time)
88 d246be88 Ilias Tsitsimpis
        self.fail("time out")
89 d246be88 Ilias Tsitsimpis
90 d246be88 Ilias Tsitsimpis
    def _get_list_of_servers(self, detail=False):
91 d246be88 Ilias Tsitsimpis
        """Get (detailed) list of servers"""
92 d246be88 Ilias Tsitsimpis
        if detail:
93 d246be88 Ilias Tsitsimpis
            self.info("Getting detailed list of servers")
94 d246be88 Ilias Tsitsimpis
        else:
95 d246be88 Ilias Tsitsimpis
            self.info("Getting simple list of servers")
96 d246be88 Ilias Tsitsimpis
        return self.clients.cyclades.list_servers(detail=detail)
97 d246be88 Ilias Tsitsimpis
98 3eaf0ec5 Ilias Tsitsimpis
    def _get_list_of_networks(self, detail=False):
99 3eaf0ec5 Ilias Tsitsimpis
        """Get (detailed) list of networks"""
100 3eaf0ec5 Ilias Tsitsimpis
        if detail:
101 3eaf0ec5 Ilias Tsitsimpis
            self.info("Getting detailed list of networks")
102 3eaf0ec5 Ilias Tsitsimpis
        else:
103 3eaf0ec5 Ilias Tsitsimpis
            self.info("Getting simple list of networks")
104 3eaf0ec5 Ilias Tsitsimpis
        return self.clients.cyclades.list_networks(detail=detail)
105 3eaf0ec5 Ilias Tsitsimpis
106 3eaf0ec5 Ilias Tsitsimpis
    def _get_server_details(self, server, quiet=False):
107 d246be88 Ilias Tsitsimpis
        """Get details for a server"""
108 3eaf0ec5 Ilias Tsitsimpis
        if not quiet:
109 3eaf0ec5 Ilias Tsitsimpis
            self.info("Getting details for server %s with id %s",
110 3eaf0ec5 Ilias Tsitsimpis
                      server['name'], server['id'])
111 d246be88 Ilias Tsitsimpis
        return self.clients.cyclades.get_server_details(server['id'])
112 d246be88 Ilias Tsitsimpis
113 3eaf0ec5 Ilias Tsitsimpis
    def _create_server(self, image, flavor, personality=None):
114 d246be88 Ilias Tsitsimpis
        """Create a new server"""
115 3eaf0ec5 Ilias Tsitsimpis
        servername = "%s for %s" % (self.run_id, image['name'])
116 3eaf0ec5 Ilias Tsitsimpis
        self.info("Creating a server with name %s", servername)
117 d246be88 Ilias Tsitsimpis
        self.info("Using image %s with id %s", image['name'], image['id'])
118 d246be88 Ilias Tsitsimpis
        self.info("Using flavor %s with id %s", flavor['name'], flavor['id'])
119 d246be88 Ilias Tsitsimpis
        server = self.clients.cyclades.create_server(
120 3eaf0ec5 Ilias Tsitsimpis
            servername, flavor['id'], image['id'], personality=personality)
121 d246be88 Ilias Tsitsimpis
122 d246be88 Ilias Tsitsimpis
        self.info("Server id: %s", server['id'])
123 d246be88 Ilias Tsitsimpis
        self.info("Server password: %s", server['adminPass'])
124 d246be88 Ilias Tsitsimpis
125 3eaf0ec5 Ilias Tsitsimpis
        self.assertEqual(server['name'], servername)
126 d246be88 Ilias Tsitsimpis
        self.assertEqual(server['flavor']['id'], flavor['id'])
127 d246be88 Ilias Tsitsimpis
        self.assertEqual(server['image']['id'], image['id'])
128 d246be88 Ilias Tsitsimpis
        self.assertEqual(server['status'], "BUILD")
129 d246be88 Ilias Tsitsimpis
130 d246be88 Ilias Tsitsimpis
        return server
131 d246be88 Ilias Tsitsimpis
132 d246be88 Ilias Tsitsimpis
    def _get_connection_username(self, server):
133 d246be88 Ilias Tsitsimpis
        """Determine the username to use to connect to the server"""
134 d246be88 Ilias Tsitsimpis
        users = server['metadata'].get("users", None)
135 d246be88 Ilias Tsitsimpis
        ret_user = None
136 d246be88 Ilias Tsitsimpis
        if users is not None:
137 d246be88 Ilias Tsitsimpis
            user_list = users.split()
138 d246be88 Ilias Tsitsimpis
            if "root" in user_list:
139 d246be88 Ilias Tsitsimpis
                ret_user = "root"
140 d246be88 Ilias Tsitsimpis
            else:
141 d246be88 Ilias Tsitsimpis
                ret_user = random.choice(user_list)
142 d246be88 Ilias Tsitsimpis
        else:
143 d246be88 Ilias Tsitsimpis
            # Return the login name for connections based on the server OS
144 d246be88 Ilias Tsitsimpis
            self.info("Could not find `users' metadata in server. Let's guess")
145 d246be88 Ilias Tsitsimpis
            os_value = server['metadata'].get("os")
146 d246be88 Ilias Tsitsimpis
            if os_value in ("Ubuntu", "Kubuntu", "Fedora"):
147 d246be88 Ilias Tsitsimpis
                ret_user = "user"
148 d246be88 Ilias Tsitsimpis
            elif os_value in ("windows", "windows_alpha1"):
149 d246be88 Ilias Tsitsimpis
                ret_user = "Administrator"
150 d246be88 Ilias Tsitsimpis
            else:
151 d246be88 Ilias Tsitsimpis
                ret_user = "root"
152 d246be88 Ilias Tsitsimpis
153 d246be88 Ilias Tsitsimpis
        self.assertIsNotNone(ret_user)
154 d246be88 Ilias Tsitsimpis
        self.info("User's login name: %s", ret_user)
155 d246be88 Ilias Tsitsimpis
        return ret_user
156 d246be88 Ilias Tsitsimpis
157 3eaf0ec5 Ilias Tsitsimpis
    def _insist_on_server_transition(self, server, curr_statuses, new_status):
158 3eaf0ec5 Ilias Tsitsimpis
        """Insist on server transiting from curr_statuses to new_status"""
159 d246be88 Ilias Tsitsimpis
        def check_fun():
160 d246be88 Ilias Tsitsimpis
            """Check server status"""
161 3eaf0ec5 Ilias Tsitsimpis
            srv = self._get_server_details(server, quiet=True)
162 3eaf0ec5 Ilias Tsitsimpis
            if srv['status'] in curr_statuses:
163 d246be88 Ilias Tsitsimpis
                raise Retry()
164 d246be88 Ilias Tsitsimpis
            elif srv['status'] == new_status:
165 d246be88 Ilias Tsitsimpis
                return
166 d246be88 Ilias Tsitsimpis
            else:
167 3eaf0ec5 Ilias Tsitsimpis
                msg = "Server \"%s\" with id %s went to unexpected status %s"
168 3eaf0ec5 Ilias Tsitsimpis
                self.error(msg, server['name'], server['id'], srv['status'])
169 3eaf0ec5 Ilias Tsitsimpis
                self.fail(msg % (server['name'], server['id'], srv['status']))
170 5bef1f49 Ilias Tsitsimpis
        opmsg = "Waiting for server \"%s\" with id %s to become %s"
171 5bef1f49 Ilias Tsitsimpis
        self.info(opmsg, server['name'], server['id'], new_status)
172 5bef1f49 Ilias Tsitsimpis
        opmsg = opmsg % (server['name'], server['id'], new_status)
173 3eaf0ec5 Ilias Tsitsimpis
        self._try_until_timeout_expires(opmsg, check_fun)
174 3eaf0ec5 Ilias Tsitsimpis
175 3eaf0ec5 Ilias Tsitsimpis
    def _insist_on_network_transition(self, network,
176 3eaf0ec5 Ilias Tsitsimpis
                                      curr_statuses, new_status):
177 3eaf0ec5 Ilias Tsitsimpis
        """Insist on network transiting from curr_statuses to new_status"""
178 3eaf0ec5 Ilias Tsitsimpis
        def check_fun():
179 3eaf0ec5 Ilias Tsitsimpis
            """Check network status"""
180 3eaf0ec5 Ilias Tsitsimpis
            ntw = self.clients.cyclades.get_network_details(network['id'])
181 3eaf0ec5 Ilias Tsitsimpis
            if ntw['status'] in curr_statuses:
182 3eaf0ec5 Ilias Tsitsimpis
                raise Retry()
183 3eaf0ec5 Ilias Tsitsimpis
            elif ntw['status'] == new_status:
184 3eaf0ec5 Ilias Tsitsimpis
                return
185 3eaf0ec5 Ilias Tsitsimpis
            else:
186 3eaf0ec5 Ilias Tsitsimpis
                msg = "Network %s with id %s went to unexpected status %s"
187 3eaf0ec5 Ilias Tsitsimpis
                self.error(msg, network['name'], network['id'], ntw['status'])
188 3eaf0ec5 Ilias Tsitsimpis
                self.fail(msg %
189 3eaf0ec5 Ilias Tsitsimpis
                          (network['name'], network['id'], ntw['status']))
190 5bef1f49 Ilias Tsitsimpis
        opmsg = "Waiting for network \"%s\" with id %s to become %s"
191 5bef1f49 Ilias Tsitsimpis
        self.info(opmsg, network['name'], network['id'], new_status)
192 5bef1f49 Ilias Tsitsimpis
        opmsg = opmsg % (network['name'], network['id'], new_status)
193 3eaf0ec5 Ilias Tsitsimpis
        self._try_until_timeout_expires(opmsg, check_fun)
194 3eaf0ec5 Ilias Tsitsimpis
195 3eaf0ec5 Ilias Tsitsimpis
    def _insist_on_network_connection(self, server, network, disconnect=False):
196 3eaf0ec5 Ilias Tsitsimpis
        """Insist that the server has connected to the network"""
197 3eaf0ec5 Ilias Tsitsimpis
        def check_fun():
198 3eaf0ec5 Ilias Tsitsimpis
            """Check network connection"""
199 3eaf0ec5 Ilias Tsitsimpis
            dsrv = self._get_server_details(server, quiet=True)
200 3eaf0ec5 Ilias Tsitsimpis
            nets = [s['network_id'] for s in dsrv['attachments']]
201 3eaf0ec5 Ilias Tsitsimpis
            if not disconnect and network['id'] not in nets:
202 3eaf0ec5 Ilias Tsitsimpis
                raise Retry()
203 3eaf0ec5 Ilias Tsitsimpis
            if disconnect and network['id'] in nets:
204 3eaf0ec5 Ilias Tsitsimpis
                raise Retry()
205 3eaf0ec5 Ilias Tsitsimpis
        if disconnect:
206 3eaf0ec5 Ilias Tsitsimpis
            opmsg = \
207 3eaf0ec5 Ilias Tsitsimpis
                "Waiting for server \"%s\" to disconnect from network \"%s\""
208 3eaf0ec5 Ilias Tsitsimpis
        else:
209 3eaf0ec5 Ilias Tsitsimpis
            opmsg = "Waiting for server \"%s\" to connect to network \"%s\""
210 3eaf0ec5 Ilias Tsitsimpis
        self.info(opmsg, server['name'], network['name'])
211 3eaf0ec5 Ilias Tsitsimpis
        opmsg = opmsg % (server['name'], network['name'])
212 d246be88 Ilias Tsitsimpis
        self._try_until_timeout_expires(opmsg, check_fun)
213 d246be88 Ilias Tsitsimpis
214 d246be88 Ilias Tsitsimpis
    def _insist_on_tcp_connection(self, family, host, port):
215 d246be88 Ilias Tsitsimpis
        """Insist on tcp connection"""
216 d246be88 Ilias Tsitsimpis
        def check_fun():
217 d246be88 Ilias Tsitsimpis
            """Get a connected socket from the specified family to host:port"""
218 d246be88 Ilias Tsitsimpis
            sock = None
219 d246be88 Ilias Tsitsimpis
            for res in socket.getaddrinfo(host, port, family,
220 d246be88 Ilias Tsitsimpis
                                          socket.SOCK_STREAM, 0,
221 d246be88 Ilias Tsitsimpis
                                          socket.AI_PASSIVE):
222 d246be88 Ilias Tsitsimpis
                fam, socktype, proto, _, saddr = res
223 d246be88 Ilias Tsitsimpis
                try:
224 d246be88 Ilias Tsitsimpis
                    sock = socket.socket(fam, socktype, proto)
225 d246be88 Ilias Tsitsimpis
                except socket.error:
226 d246be88 Ilias Tsitsimpis
                    sock = None
227 d246be88 Ilias Tsitsimpis
                    continue
228 d246be88 Ilias Tsitsimpis
                try:
229 d246be88 Ilias Tsitsimpis
                    sock.connect(saddr)
230 d246be88 Ilias Tsitsimpis
                except socket.error:
231 d246be88 Ilias Tsitsimpis
                    sock.close()
232 d246be88 Ilias Tsitsimpis
                    sock = None
233 d246be88 Ilias Tsitsimpis
                    continue
234 d246be88 Ilias Tsitsimpis
            if sock is None:
235 d246be88 Ilias Tsitsimpis
                raise Retry
236 d246be88 Ilias Tsitsimpis
            return sock
237 d246be88 Ilias Tsitsimpis
        familystr = {socket.AF_INET: "IPv4", socket.AF_INET6: "IPv6",
238 d246be88 Ilias Tsitsimpis
                     socket.AF_UNSPEC: "Unspecified-IPv4/6"}
239 d246be88 Ilias Tsitsimpis
        opmsg = "Connecting over %s to %s:%s"
240 d246be88 Ilias Tsitsimpis
        self.info(opmsg, familystr.get(family, "Unknown"), host, port)
241 d246be88 Ilias Tsitsimpis
        opmsg = opmsg % (familystr.get(family, "Unknown"), host, port)
242 d246be88 Ilias Tsitsimpis
        return self._try_until_timeout_expires(opmsg, check_fun)
243 d246be88 Ilias Tsitsimpis
244 3eaf0ec5 Ilias Tsitsimpis
    def _get_ip(self, server, version=4, network=None):
245 3eaf0ec5 Ilias Tsitsimpis
        """Get the IP of a server from the detailed server info
246 3eaf0ec5 Ilias Tsitsimpis

247 3eaf0ec5 Ilias Tsitsimpis
        If network not given then get the public IP. Else the ip
248 3eaf0ec5 Ilias Tsitsimpis
        attached to that network
249 3eaf0ec5 Ilias Tsitsimpis

250 3eaf0ec5 Ilias Tsitsimpis
        """
251 d246be88 Ilias Tsitsimpis
        assert version in (4, 6)
252 d246be88 Ilias Tsitsimpis
253 d246be88 Ilias Tsitsimpis
        nics = server['attachments']
254 3eaf0ec5 Ilias Tsitsimpis
        addrs = None
255 d246be88 Ilias Tsitsimpis
        for nic in nics:
256 d246be88 Ilias Tsitsimpis
            net_id = nic['network_id']
257 3eaf0ec5 Ilias Tsitsimpis
            if network is None:
258 3eaf0ec5 Ilias Tsitsimpis
                if self.clients.cyclades.get_network_details(net_id)['public']:
259 ee89df69 Ilias Tsitsimpis
                    if nic['ipv' + str(version)]:
260 ee89df69 Ilias Tsitsimpis
                        addrs = nic['ipv' + str(version)]
261 ee89df69 Ilias Tsitsimpis
                        break
262 3eaf0ec5 Ilias Tsitsimpis
            else:
263 3eaf0ec5 Ilias Tsitsimpis
                if net_id == network['id']:
264 ee89df69 Ilias Tsitsimpis
                    if nic['ipv' + str(version)]:
265 ee89df69 Ilias Tsitsimpis
                        addrs = nic['ipv' + str(version)]
266 ee89df69 Ilias Tsitsimpis
                        break
267 d246be88 Ilias Tsitsimpis
268 3eaf0ec5 Ilias Tsitsimpis
        self.assertIsNotNone(addrs, "Can not get IP from server attachments")
269 3eaf0ec5 Ilias Tsitsimpis
        if network is None:
270 3eaf0ec5 Ilias Tsitsimpis
            msg = "Server's public IPv%s is %s"
271 3eaf0ec5 Ilias Tsitsimpis
            self.info(msg, version, addrs)
272 3eaf0ec5 Ilias Tsitsimpis
        else:
273 3eaf0ec5 Ilias Tsitsimpis
            msg = "Server's IPv%s attached to network \"%s\" is %s"
274 3eaf0ec5 Ilias Tsitsimpis
            self.info(msg, version, network['id'], addrs)
275 3eaf0ec5 Ilias Tsitsimpis
        return addrs
276 d246be88 Ilias Tsitsimpis
277 cee3ee9b Ilias Tsitsimpis
    def _insist_on_ping(self, ip_addr, version=4):
278 d246be88 Ilias Tsitsimpis
        """Test server responds to a single IPv4 of IPv6 ping"""
279 d246be88 Ilias Tsitsimpis
        def check_fun():
280 d246be88 Ilias Tsitsimpis
            """Ping to server"""
281 d246be88 Ilias Tsitsimpis
            cmd = ("ping%s -c 3 -w 20 %s" %
282 d246be88 Ilias Tsitsimpis
                   ("6" if version == 6 else "", ip_addr))
283 d246be88 Ilias Tsitsimpis
            ping = subprocess.Popen(
284 d246be88 Ilias Tsitsimpis
                cmd, shell=True, stdout=subprocess.PIPE,
285 d246be88 Ilias Tsitsimpis
                stderr=subprocess.PIPE)
286 d246be88 Ilias Tsitsimpis
            ping.communicate()
287 d246be88 Ilias Tsitsimpis
            ret = ping.wait()
288 d246be88 Ilias Tsitsimpis
            if ret != 0:
289 d246be88 Ilias Tsitsimpis
                raise Retry
290 cee3ee9b Ilias Tsitsimpis
        assert version in (4, 6)
291 d246be88 Ilias Tsitsimpis
        opmsg = "Sent IPv%s ping requests to %s"
292 d246be88 Ilias Tsitsimpis
        self.info(opmsg, version, ip_addr)
293 d246be88 Ilias Tsitsimpis
        opmsg = opmsg % (version, ip_addr)
294 d246be88 Ilias Tsitsimpis
        self._try_until_timeout_expires(opmsg, check_fun)
295 d246be88 Ilias Tsitsimpis
296 cee3ee9b Ilias Tsitsimpis
    def _image_is(self, image, osfamily):
297 cee3ee9b Ilias Tsitsimpis
        """Return true if the image is of `osfamily'"""
298 cee3ee9b Ilias Tsitsimpis
        d_image = self.clients.cyclades.get_image_details(image['id'])
299 cee3ee9b Ilias Tsitsimpis
        return d_image['metadata']['osfamily'].lower().find(osfamily) >= 0
300 cee3ee9b Ilias Tsitsimpis
301 cee3ee9b Ilias Tsitsimpis
    def _ssh_execute(self, hostip, username, password, command):
302 cee3ee9b Ilias Tsitsimpis
        """Execute a command via ssh"""
303 cee3ee9b Ilias Tsitsimpis
        ssh = paramiko.SSHClient()
304 cee3ee9b Ilias Tsitsimpis
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
305 cee3ee9b Ilias Tsitsimpis
        try:
306 cee3ee9b Ilias Tsitsimpis
            ssh.connect(hostip, username=username, password=password)
307 cee3ee9b Ilias Tsitsimpis
        except socket.error as err:
308 cee3ee9b Ilias Tsitsimpis
            self.fail(err)
309 cee3ee9b Ilias Tsitsimpis
        try:
310 cee3ee9b Ilias Tsitsimpis
            _, stdout, _ = ssh.exec_command(command)
311 cee3ee9b Ilias Tsitsimpis
        except paramiko.SSHException as err:
312 cee3ee9b Ilias Tsitsimpis
            self.fail(err)
313 cee3ee9b Ilias Tsitsimpis
        status = stdout.channel.recv_exit_status()
314 cee3ee9b Ilias Tsitsimpis
        output = stdout.readlines()
315 cee3ee9b Ilias Tsitsimpis
        ssh.close()
316 cee3ee9b Ilias Tsitsimpis
        return output, status
317 cee3ee9b Ilias Tsitsimpis
318 cee3ee9b Ilias Tsitsimpis
    def _insist_get_hostname_over_ssh(self, hostip, username, password):
319 cee3ee9b Ilias Tsitsimpis
        """Connect to server using ssh and get it's hostname"""
320 cee3ee9b Ilias Tsitsimpis
        def check_fun():
321 cee3ee9b Ilias Tsitsimpis
            """Get hostname"""
322 cee3ee9b Ilias Tsitsimpis
            try:
323 cee3ee9b Ilias Tsitsimpis
                lines, status = self._ssh_execute(
324 cee3ee9b Ilias Tsitsimpis
                    hostip, username, password, "hostname")
325 cee3ee9b Ilias Tsitsimpis
                self.assertEqual(status, 0)
326 cee3ee9b Ilias Tsitsimpis
                self.assertEqual(len(lines), 1)
327 cee3ee9b Ilias Tsitsimpis
                # Remove new line
328 cee3ee9b Ilias Tsitsimpis
                return lines[0].strip('\n')
329 cee3ee9b Ilias Tsitsimpis
            except AssertionError:
330 cee3ee9b Ilias Tsitsimpis
                raise Retry()
331 cee3ee9b Ilias Tsitsimpis
        opmsg = "Connecting to server using ssh and get it's hostname"
332 cee3ee9b Ilias Tsitsimpis
        self.info(opmsg)
333 cee3ee9b Ilias Tsitsimpis
        hostname = self._try_until_timeout_expires(opmsg, check_fun)
334 cee3ee9b Ilias Tsitsimpis
        self.info("Server's hostname is %s", hostname)
335 cee3ee9b Ilias Tsitsimpis
        return hostname
336 cee3ee9b Ilias Tsitsimpis
337 cee3ee9b Ilias Tsitsimpis
    # Too many arguments. pylint: disable-msg=R0913
338 cee3ee9b Ilias Tsitsimpis
    def _check_file_through_ssh(self, hostip, username, password,
339 cee3ee9b Ilias Tsitsimpis
                                remotepath, content):
340 cee3ee9b Ilias Tsitsimpis
        """Fetch file from server and compare contents"""
341 cee3ee9b Ilias Tsitsimpis
        self.info("Fetching file %s from remote server", remotepath)
342 cee3ee9b Ilias Tsitsimpis
        transport = paramiko.Transport((hostip, 22))
343 cee3ee9b Ilias Tsitsimpis
        transport.connect(username=username, password=password)
344 cee3ee9b Ilias Tsitsimpis
        with tempfile.NamedTemporaryFile() as ftmp:
345 cee3ee9b Ilias Tsitsimpis
            sftp = paramiko.SFTPClient.from_transport(transport)
346 cee3ee9b Ilias Tsitsimpis
            sftp.get(remotepath, ftmp.name)
347 cee3ee9b Ilias Tsitsimpis
            sftp.close()
348 cee3ee9b Ilias Tsitsimpis
            transport.close()
349 cee3ee9b Ilias Tsitsimpis
            self.info("Comparing file contents")
350 cee3ee9b Ilias Tsitsimpis
            remote_content = base64.b64encode(ftmp.read())
351 cee3ee9b Ilias Tsitsimpis
            self.assertEqual(content, remote_content)
352 cee3ee9b Ilias Tsitsimpis
353 3eaf0ec5 Ilias Tsitsimpis
    def _disconnect_from_network(self, server, network):
354 3eaf0ec5 Ilias Tsitsimpis
        """Disconnect server from network"""
355 3eaf0ec5 Ilias Tsitsimpis
        nid = None
356 3eaf0ec5 Ilias Tsitsimpis
        for nic in server['attachments']:
357 3eaf0ec5 Ilias Tsitsimpis
            if nic['network_id'] == network['id']:
358 3eaf0ec5 Ilias Tsitsimpis
                nid = nic['id']
359 3eaf0ec5 Ilias Tsitsimpis
                break
360 3eaf0ec5 Ilias Tsitsimpis
        self.assertIsNotNone(nid, "Could not find network card")
361 3eaf0ec5 Ilias Tsitsimpis
        self.clients.cyclades.disconnect_server(server['id'], nid)
362 3eaf0ec5 Ilias Tsitsimpis
363 d246be88 Ilias Tsitsimpis
364 d246be88 Ilias Tsitsimpis
class Retry(Exception):
365 d246be88 Ilias Tsitsimpis
    """Retry the action
366 d246be88 Ilias Tsitsimpis

367 d246be88 Ilias Tsitsimpis
    This is used by _try_unit_timeout_expires method.
368 d246be88 Ilias Tsitsimpis

369 d246be88 Ilias Tsitsimpis
    """