Statistics
| Branch: | Tag: | Revision:

root / ci / utils.py @ f82ce32a

History | View | Annotate | Download (24 kB)

1 c29ac11d Ilias Tsitsimpis
#!/usr/bin/env python
2 c29ac11d Ilias Tsitsimpis
3 c29ac11d Ilias Tsitsimpis
"""
4 c29ac11d Ilias Tsitsimpis
Synnefo ci utils module
5 c29ac11d Ilias Tsitsimpis
"""
6 c29ac11d Ilias Tsitsimpis
7 c29ac11d Ilias Tsitsimpis
import os
8 ad21ffa9 Ilias Tsitsimpis
import re
9 c29ac11d Ilias Tsitsimpis
import sys
10 c29ac11d Ilias Tsitsimpis
import time
11 c29ac11d Ilias Tsitsimpis
import logging
12 c29ac11d Ilias Tsitsimpis
import fabric.api as fabric
13 b69b55ca Christos Stavrakakis
import subprocess
14 88e6558b Christos Stavrakakis
import tempfile
15 c29ac11d Ilias Tsitsimpis
from ConfigParser import ConfigParser, DuplicateSectionError
16 c29ac11d Ilias Tsitsimpis
17 c1b1d444 Christos Stavrakakis
from kamaki.cli import config as kamaki_config
18 c29ac11d Ilias Tsitsimpis
from kamaki.clients.astakos import AstakosClient
19 c29ac11d Ilias Tsitsimpis
from kamaki.clients.cyclades import CycladesClient
20 c29ac11d Ilias Tsitsimpis
from kamaki.clients.image import ImageClient
21 ad21ffa9 Ilias Tsitsimpis
from kamaki.clients.compute import ComputeClient
22 c29ac11d Ilias Tsitsimpis
23 6ca8f81a Christos Stavrakakis
DEFAULT_CONFIG_FILE = "new_config"
24 62f3f54f Ilias Tsitsimpis
# UUID of owner of system images
25 62f3f54f Ilias Tsitsimpis
DEFAULT_SYSTEM_IMAGES_UUID = [
26 62f3f54f Ilias Tsitsimpis
    "25ecced9-bf53-4145-91ee-cf47377e9fb2",  # production (okeanos.grnet.gr)
27 62f3f54f Ilias Tsitsimpis
    "04cbe33f-29b7-4ef1-94fb-015929e5fc06",  # testing (okeanos.io)
28 62f3f54f Ilias Tsitsimpis
    ]
29 6ca8f81a Christos Stavrakakis
30 c29ac11d Ilias Tsitsimpis
31 c29ac11d Ilias Tsitsimpis
def _run(cmd, verbose):
32 c29ac11d Ilias Tsitsimpis
    """Run fabric with verbose level"""
33 c29ac11d Ilias Tsitsimpis
    if verbose:
34 c29ac11d Ilias Tsitsimpis
        args = ('running',)
35 c29ac11d Ilias Tsitsimpis
    else:
36 c29ac11d Ilias Tsitsimpis
        args = ('running', 'stdout',)
37 e2a0abb8 Ilias Tsitsimpis
    with fabric.hide(*args):  # Used * or ** magic. pylint: disable-msg=W0142
38 c29ac11d Ilias Tsitsimpis
        return fabric.run(cmd)
39 c29ac11d Ilias Tsitsimpis
40 c29ac11d Ilias Tsitsimpis
41 6868804a Ilias Tsitsimpis
def _put(local, remote):
42 6868804a Ilias Tsitsimpis
    """Run fabric put command without output"""
43 6868804a Ilias Tsitsimpis
    with fabric.quiet():
44 6868804a Ilias Tsitsimpis
        fabric.put(local, remote)
45 6868804a Ilias Tsitsimpis
46 6868804a Ilias Tsitsimpis
47 c29ac11d Ilias Tsitsimpis
def _red(msg):
48 c29ac11d Ilias Tsitsimpis
    """Red color"""
49 c29ac11d Ilias Tsitsimpis
    #return "\x1b[31m" + str(msg) + "\x1b[0m"
50 c29ac11d Ilias Tsitsimpis
    return str(msg)
51 c29ac11d Ilias Tsitsimpis
52 c29ac11d Ilias Tsitsimpis
53 c29ac11d Ilias Tsitsimpis
def _yellow(msg):
54 c29ac11d Ilias Tsitsimpis
    """Yellow color"""
55 c29ac11d Ilias Tsitsimpis
    #return "\x1b[33m" + str(msg) + "\x1b[0m"
56 c29ac11d Ilias Tsitsimpis
    return str(msg)
57 c29ac11d Ilias Tsitsimpis
58 c29ac11d Ilias Tsitsimpis
59 c29ac11d Ilias Tsitsimpis
def _green(msg):
60 c29ac11d Ilias Tsitsimpis
    """Green color"""
61 c29ac11d Ilias Tsitsimpis
    #return "\x1b[32m" + str(msg) + "\x1b[0m"
62 c29ac11d Ilias Tsitsimpis
    return str(msg)
63 c29ac11d Ilias Tsitsimpis
64 c29ac11d Ilias Tsitsimpis
65 c29ac11d Ilias Tsitsimpis
def _check_fabric(fun):
66 c29ac11d Ilias Tsitsimpis
    """Check if fabric env has been set"""
67 43a22402 Christos Stavrakakis
    def wrapper(self, *args, **kwargs):
68 c29ac11d Ilias Tsitsimpis
        """wrapper function"""
69 c29ac11d Ilias Tsitsimpis
        if not self.fabric_installed:
70 c29ac11d Ilias Tsitsimpis
            self.setup_fabric()
71 43a22402 Christos Stavrakakis
        return fun(self, *args, **kwargs)
72 c29ac11d Ilias Tsitsimpis
    return wrapper
73 c29ac11d Ilias Tsitsimpis
74 c29ac11d Ilias Tsitsimpis
75 c29ac11d Ilias Tsitsimpis
def _check_kamaki(fun):
76 c29ac11d Ilias Tsitsimpis
    """Check if kamaki has been initialized"""
77 43a22402 Christos Stavrakakis
    def wrapper(self, *args, **kwargs):
78 c29ac11d Ilias Tsitsimpis
        """wrapper function"""
79 c29ac11d Ilias Tsitsimpis
        if not self.kamaki_installed:
80 c29ac11d Ilias Tsitsimpis
            self.setup_kamaki()
81 43a22402 Christos Stavrakakis
        return fun(self, *args, **kwargs)
82 c29ac11d Ilias Tsitsimpis
    return wrapper
83 c29ac11d Ilias Tsitsimpis
84 c29ac11d Ilias Tsitsimpis
85 c29ac11d Ilias Tsitsimpis
class _MyFormatter(logging.Formatter):
86 c29ac11d Ilias Tsitsimpis
    """Logging Formatter"""
87 c29ac11d Ilias Tsitsimpis
    def format(self, record):
88 c29ac11d Ilias Tsitsimpis
        format_orig = self._fmt
89 c29ac11d Ilias Tsitsimpis
        if record.levelno == logging.DEBUG:
90 c29ac11d Ilias Tsitsimpis
            self._fmt = "  %(msg)s"
91 c29ac11d Ilias Tsitsimpis
        elif record.levelno == logging.INFO:
92 c29ac11d Ilias Tsitsimpis
            self._fmt = "%(msg)s"
93 c29ac11d Ilias Tsitsimpis
        elif record.levelno == logging.WARNING:
94 c29ac11d Ilias Tsitsimpis
            self._fmt = _yellow("[W] %(msg)s")
95 c29ac11d Ilias Tsitsimpis
        elif record.levelno == logging.ERROR:
96 c29ac11d Ilias Tsitsimpis
            self._fmt = _red("[E] %(msg)s")
97 c29ac11d Ilias Tsitsimpis
        result = logging.Formatter.format(self, record)
98 c29ac11d Ilias Tsitsimpis
        self._fmt = format_orig
99 c29ac11d Ilias Tsitsimpis
        return result
100 c29ac11d Ilias Tsitsimpis
101 c29ac11d Ilias Tsitsimpis
102 56ee1bbc Ilias Tsitsimpis
# Too few public methods. pylint: disable-msg=R0903
103 56ee1bbc Ilias Tsitsimpis
class _InfoFilter(logging.Filter):
104 56ee1bbc Ilias Tsitsimpis
    """Logging Filter that allows DEBUG and INFO messages only"""
105 56ee1bbc Ilias Tsitsimpis
    def filter(self, rec):
106 56ee1bbc Ilias Tsitsimpis
        """The filter"""
107 56ee1bbc Ilias Tsitsimpis
        return rec.levelno in (logging.DEBUG, logging.INFO)
108 56ee1bbc Ilias Tsitsimpis
109 56ee1bbc Ilias Tsitsimpis
110 56ee1bbc Ilias Tsitsimpis
# Too many instance attributes. pylint: disable-msg=R0902
111 c29ac11d Ilias Tsitsimpis
class SynnefoCI(object):
112 c29ac11d Ilias Tsitsimpis
    """SynnefoCI python class"""
113 c29ac11d Ilias Tsitsimpis
114 6ca8f81a Christos Stavrakakis
    def __init__(self, config_file=None, cleanup_config=False, cloud=None):
115 c29ac11d Ilias Tsitsimpis
        """ Initialize SynnefoCI python class
116 c29ac11d Ilias Tsitsimpis

117 c29ac11d Ilias Tsitsimpis
        Setup logger, local_dir, config and kamaki
118 c29ac11d Ilias Tsitsimpis
        """
119 c29ac11d Ilias Tsitsimpis
        # Setup logger
120 c29ac11d Ilias Tsitsimpis
        self.logger = logging.getLogger('synnefo-ci')
121 c29ac11d Ilias Tsitsimpis
        self.logger.setLevel(logging.DEBUG)
122 56ee1bbc Ilias Tsitsimpis
123 56ee1bbc Ilias Tsitsimpis
        handler1 = logging.StreamHandler(sys.stdout)
124 56ee1bbc Ilias Tsitsimpis
        handler1.setLevel(logging.DEBUG)
125 56ee1bbc Ilias Tsitsimpis
        handler1.addFilter(_InfoFilter())
126 56ee1bbc Ilias Tsitsimpis
        handler1.setFormatter(_MyFormatter())
127 56ee1bbc Ilias Tsitsimpis
        handler2 = logging.StreamHandler(sys.stderr)
128 56ee1bbc Ilias Tsitsimpis
        handler2.setLevel(logging.WARNING)
129 56ee1bbc Ilias Tsitsimpis
        handler2.setFormatter(_MyFormatter())
130 56ee1bbc Ilias Tsitsimpis
131 56ee1bbc Ilias Tsitsimpis
        self.logger.addHandler(handler1)
132 56ee1bbc Ilias Tsitsimpis
        self.logger.addHandler(handler2)
133 c29ac11d Ilias Tsitsimpis
134 c29ac11d Ilias Tsitsimpis
        # Get our local dir
135 c29ac11d Ilias Tsitsimpis
        self.ci_dir = os.path.dirname(os.path.abspath(__file__))
136 c29ac11d Ilias Tsitsimpis
        self.repo_dir = os.path.dirname(self.ci_dir)
137 c29ac11d Ilias Tsitsimpis
138 c29ac11d Ilias Tsitsimpis
        # Read config file
139 6ca8f81a Christos Stavrakakis
        if config_file is None:
140 6ca8f81a Christos Stavrakakis
            config_file = DEFAULT_CONFIG_FILE
141 6ca8f81a Christos Stavrakakis
        if not os.path.isabs(config_file):
142 6ca8f81a Christos Stavrakakis
            config_file = os.path.join(self.ci_dir, config_file)
143 e908a902 Christos Stavrakakis
144 c29ac11d Ilias Tsitsimpis
        self.config = ConfigParser()
145 c29ac11d Ilias Tsitsimpis
        self.config.optionxform = str
146 6ca8f81a Christos Stavrakakis
        self.config.read(config_file)
147 c29ac11d Ilias Tsitsimpis
        temp_config = self.config.get('Global', 'temporary_config')
148 c29ac11d Ilias Tsitsimpis
        if cleanup_config:
149 c29ac11d Ilias Tsitsimpis
            try:
150 c29ac11d Ilias Tsitsimpis
                os.remove(temp_config)
151 e2a0abb8 Ilias Tsitsimpis
            except OSError:
152 c29ac11d Ilias Tsitsimpis
                pass
153 c29ac11d Ilias Tsitsimpis
        else:
154 c29ac11d Ilias Tsitsimpis
            self.config.read(self.config.get('Global', 'temporary_config'))
155 c29ac11d Ilias Tsitsimpis
156 c1b1d444 Christos Stavrakakis
        # Set kamaki cloud
157 c1b1d444 Christos Stavrakakis
        if cloud is not None:
158 c1b1d444 Christos Stavrakakis
            self.kamaki_cloud = cloud
159 c1b1d444 Christos Stavrakakis
        elif self.config.has_option("Deployment", "kamaki_cloud"):
160 c1b1d444 Christos Stavrakakis
            kamaki_cloud = self.config.get("Deployment", "kamaki_cloud")
161 c1b1d444 Christos Stavrakakis
            if kamaki_cloud == "":
162 c1b1d444 Christos Stavrakakis
                self.kamaki_cloud = None
163 c1b1d444 Christos Stavrakakis
        else:
164 c1b1d444 Christos Stavrakakis
            self.kamaki_cloud = None
165 c1b1d444 Christos Stavrakakis
166 c29ac11d Ilias Tsitsimpis
        # Initialize variables
167 c29ac11d Ilias Tsitsimpis
        self.fabric_installed = False
168 c29ac11d Ilias Tsitsimpis
        self.kamaki_installed = False
169 c29ac11d Ilias Tsitsimpis
        self.cyclades_client = None
170 ad21ffa9 Ilias Tsitsimpis
        self.compute_client = None
171 c29ac11d Ilias Tsitsimpis
        self.image_client = None
172 c29ac11d Ilias Tsitsimpis
173 c29ac11d Ilias Tsitsimpis
    def setup_kamaki(self):
174 c29ac11d Ilias Tsitsimpis
        """Initialize kamaki
175 c29ac11d Ilias Tsitsimpis

176 ad21ffa9 Ilias Tsitsimpis
        Setup cyclades_client, image_client and compute_client
177 c29ac11d Ilias Tsitsimpis
        """
178 c1b1d444 Christos Stavrakakis
179 c1b1d444 Christos Stavrakakis
        config = kamaki_config.Config()
180 c1b1d444 Christos Stavrakakis
        if self.kamaki_cloud is None:
181 c1b1d444 Christos Stavrakakis
            self.kamaki_cloud = config.get_global("default_cloud")
182 c1b1d444 Christos Stavrakakis
183 c1b1d444 Christos Stavrakakis
        self.logger.info("Setup kamaki client, using cloud '%s'.." %
184 c1b1d444 Christos Stavrakakis
                         self.kamaki_cloud)
185 c1b1d444 Christos Stavrakakis
        auth_url = config.get_cloud(self.kamaki_cloud, "url")
186 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Authentication URL is %s" % _green(auth_url))
187 c1b1d444 Christos Stavrakakis
        token = config.get_cloud(self.kamaki_cloud, "token")
188 c29ac11d Ilias Tsitsimpis
        #self.logger.debug("Token is %s" % _green(token))
189 c29ac11d Ilias Tsitsimpis
190 c29ac11d Ilias Tsitsimpis
        astakos_client = AstakosClient(auth_url, token)
191 c29ac11d Ilias Tsitsimpis
192 c29ac11d Ilias Tsitsimpis
        cyclades_url = \
193 c29ac11d Ilias Tsitsimpis
            astakos_client.get_service_endpoints('compute')['publicURL']
194 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Cyclades API url is %s" % _green(cyclades_url))
195 c29ac11d Ilias Tsitsimpis
        self.cyclades_client = CycladesClient(cyclades_url, token)
196 c29ac11d Ilias Tsitsimpis
        self.cyclades_client.CONNECTION_RETRY_LIMIT = 2
197 c29ac11d Ilias Tsitsimpis
198 c29ac11d Ilias Tsitsimpis
        image_url = \
199 c29ac11d Ilias Tsitsimpis
            astakos_client.get_service_endpoints('image')['publicURL']
200 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Images API url is %s" % _green(image_url))
201 c29ac11d Ilias Tsitsimpis
        self.image_client = ImageClient(cyclades_url, token)
202 c29ac11d Ilias Tsitsimpis
        self.image_client.CONNECTION_RETRY_LIMIT = 2
203 c29ac11d Ilias Tsitsimpis
204 ad21ffa9 Ilias Tsitsimpis
        compute_url = \
205 ad21ffa9 Ilias Tsitsimpis
            astakos_client.get_service_endpoints('compute')['publicURL']
206 ad21ffa9 Ilias Tsitsimpis
        self.logger.debug("Compute API url is %s" % _green(compute_url))
207 ad21ffa9 Ilias Tsitsimpis
        self.compute_client = ComputeClient(compute_url, token)
208 ad21ffa9 Ilias Tsitsimpis
        self.compute_client.CONNECTION_RETRY_LIMIT = 2
209 ad21ffa9 Ilias Tsitsimpis
210 c29ac11d Ilias Tsitsimpis
    def _wait_transition(self, server_id, current_status, new_status):
211 c29ac11d Ilias Tsitsimpis
        """Wait for server to go from current_status to new_status"""
212 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Waiting for server to become %s" % new_status)
213 c29ac11d Ilias Tsitsimpis
        timeout = self.config.getint('Global', 'build_timeout')
214 c29ac11d Ilias Tsitsimpis
        sleep_time = 5
215 c29ac11d Ilias Tsitsimpis
        while True:
216 c29ac11d Ilias Tsitsimpis
            server = self.cyclades_client.get_server_details(server_id)
217 c29ac11d Ilias Tsitsimpis
            if server['status'] == new_status:
218 c29ac11d Ilias Tsitsimpis
                return server
219 c29ac11d Ilias Tsitsimpis
            elif timeout < 0:
220 c29ac11d Ilias Tsitsimpis
                self.logger.error(
221 c29ac11d Ilias Tsitsimpis
                    "Waiting for server to become %s timed out" % new_status)
222 c29ac11d Ilias Tsitsimpis
                self.destroy_server(False)
223 c29ac11d Ilias Tsitsimpis
                sys.exit(-1)
224 c29ac11d Ilias Tsitsimpis
            elif server['status'] == current_status:
225 c29ac11d Ilias Tsitsimpis
                # Sleep for #n secs and continue
226 c29ac11d Ilias Tsitsimpis
                timeout = timeout - sleep_time
227 c29ac11d Ilias Tsitsimpis
                time.sleep(sleep_time)
228 c29ac11d Ilias Tsitsimpis
            else:
229 c29ac11d Ilias Tsitsimpis
                self.logger.error(
230 c29ac11d Ilias Tsitsimpis
                    "Server failed with status %s" % server['status'])
231 c29ac11d Ilias Tsitsimpis
                self.destroy_server(False)
232 c29ac11d Ilias Tsitsimpis
                sys.exit(-1)
233 c29ac11d Ilias Tsitsimpis
234 c29ac11d Ilias Tsitsimpis
    @_check_kamaki
235 c29ac11d Ilias Tsitsimpis
    def destroy_server(self, wait=True):
236 c29ac11d Ilias Tsitsimpis
        """Destroy slave server"""
237 c29ac11d Ilias Tsitsimpis
        server_id = self.config.getint('Temporary Options', 'server_id')
238 c29ac11d Ilias Tsitsimpis
        self.logger.info("Destoying server with id %s " % server_id)
239 c29ac11d Ilias Tsitsimpis
        self.cyclades_client.delete_server(server_id)
240 c29ac11d Ilias Tsitsimpis
        if wait:
241 c29ac11d Ilias Tsitsimpis
            self._wait_transition(server_id, "ACTIVE", "DELETED")
242 c29ac11d Ilias Tsitsimpis
243 c29ac11d Ilias Tsitsimpis
    @_check_kamaki
244 ad21ffa9 Ilias Tsitsimpis
    def create_server(self, image_id=None, flavor_name=None, ssh_keys=None):
245 c29ac11d Ilias Tsitsimpis
        """Create slave server"""
246 c29ac11d Ilias Tsitsimpis
        self.logger.info("Create a new server..")
247 43a22402 Christos Stavrakakis
        if image_id is None:
248 43a22402 Christos Stavrakakis
            image = self._find_image()
249 43a22402 Christos Stavrakakis
            self.logger.debug("Will use image \"%s\"" % _green(image['name']))
250 43a22402 Christos Stavrakakis
            image_id = image["id"]
251 43a22402 Christos Stavrakakis
        self.logger.debug("Image has id %s" % _green(image_id))
252 ad21ffa9 Ilias Tsitsimpis
        flavor_id = self._find_flavor(flavor_name)
253 c29ac11d Ilias Tsitsimpis
        server = self.cyclades_client.create_server(
254 c29ac11d Ilias Tsitsimpis
            self.config.get('Deployment', 'server_name'),
255 43a22402 Christos Stavrakakis
            flavor_id,
256 43a22402 Christos Stavrakakis
            image_id)
257 c29ac11d Ilias Tsitsimpis
        server_id = server['id']
258 c29ac11d Ilias Tsitsimpis
        self.write_config('server_id', server_id)
259 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Server got id %s" % _green(server_id))
260 c29ac11d Ilias Tsitsimpis
        server_user = server['metadata']['users']
261 c29ac11d Ilias Tsitsimpis
        self.write_config('server_user', server_user)
262 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Server's admin user is %s" % _green(server_user))
263 c29ac11d Ilias Tsitsimpis
        server_passwd = server['adminPass']
264 c29ac11d Ilias Tsitsimpis
        self.write_config('server_passwd', server_passwd)
265 c29ac11d Ilias Tsitsimpis
266 c29ac11d Ilias Tsitsimpis
        server = self._wait_transition(server_id, "BUILD", "ACTIVE")
267 c29ac11d Ilias Tsitsimpis
        self._get_server_ip_and_port(server)
268 6868804a Ilias Tsitsimpis
        self._copy_ssh_keys(ssh_keys)
269 c29ac11d Ilias Tsitsimpis
270 c29ac11d Ilias Tsitsimpis
        self.setup_fabric()
271 c29ac11d Ilias Tsitsimpis
        self.logger.info("Setup firewall")
272 6868804a Ilias Tsitsimpis
        accept_ssh_from = self.config.get('Global', 'accept_ssh_from')
273 1c75c4dd Christos Stavrakakis
        if accept_ssh_from != "":
274 1c75c4dd Christos Stavrakakis
            self.logger.debug("Block ssh except from %s" % accept_ssh_from)
275 1c75c4dd Christos Stavrakakis
            cmd = """
276 1c75c4dd Christos Stavrakakis
            local_ip=$(/sbin/ifconfig eth0 | grep 'inet addr:' | \
277 1c75c4dd Christos Stavrakakis
                cut -d':' -f2 | cut -d' ' -f1)
278 1c75c4dd Christos Stavrakakis
            iptables -A INPUT -s localhost -j ACCEPT
279 1c75c4dd Christos Stavrakakis
            iptables -A INPUT -s $local_ip -j ACCEPT
280 1c75c4dd Christos Stavrakakis
            iptables -A INPUT -s {0} -p tcp --dport 22 -j ACCEPT
281 1c75c4dd Christos Stavrakakis
            iptables -A INPUT -p tcp --dport 22 -j DROP
282 1c75c4dd Christos Stavrakakis
            """.format(accept_ssh_from)
283 1c75c4dd Christos Stavrakakis
            _run(cmd, False)
284 c29ac11d Ilias Tsitsimpis
285 ad21ffa9 Ilias Tsitsimpis
    def _find_flavor(self, flavor_name):
286 ad21ffa9 Ilias Tsitsimpis
        """Given a flavor_name (reg expression) find a flavor id to use"""
287 ad21ffa9 Ilias Tsitsimpis
        if flavor_name is None:
288 ad21ffa9 Ilias Tsitsimpis
            flavor_name = self.config.get('Deployment', 'flavor_name')
289 ad21ffa9 Ilias Tsitsimpis
        self.logger.debug("Try to find a flavor with name \"%s\"" % flavor_name)
290 ad21ffa9 Ilias Tsitsimpis
291 ad21ffa9 Ilias Tsitsimpis
        flavors = self.compute_client.list_flavors()
292 ad21ffa9 Ilias Tsitsimpis
        flavors = [f for f in flavors
293 ad21ffa9 Ilias Tsitsimpis
                   if re.search(flavor_name, f['name']) is not None]
294 ad21ffa9 Ilias Tsitsimpis
295 ad21ffa9 Ilias Tsitsimpis
        if flavors:
296 ad21ffa9 Ilias Tsitsimpis
            self.logger.debug("Will use %s with id %s"
297 ad21ffa9 Ilias Tsitsimpis
                              % (flavors[0]['name'], flavors[0]['id']))
298 ad21ffa9 Ilias Tsitsimpis
            return flavors[0]['id']
299 ad21ffa9 Ilias Tsitsimpis
        else:
300 ad21ffa9 Ilias Tsitsimpis
            self.logger.error("No matching flavor found.. aborting")
301 ad21ffa9 Ilias Tsitsimpis
            sys.exit(1)
302 ad21ffa9 Ilias Tsitsimpis
303 c29ac11d Ilias Tsitsimpis
    def _find_image(self):
304 c29ac11d Ilias Tsitsimpis
        """Find a suitable image to use
305 c29ac11d Ilias Tsitsimpis

306 62f3f54f Ilias Tsitsimpis
        It has to belong to one of the `DEFAULT_SYSTEM_IMAGES_UUID'
307 62f3f54f Ilias Tsitsimpis
        users and contain the word given by `image_name' option.
308 c29ac11d Ilias Tsitsimpis
        """
309 c29ac11d Ilias Tsitsimpis
        image_name = self.config.get('Deployment', 'image_name').lower()
310 c29ac11d Ilias Tsitsimpis
        images = self.image_client.list_public(detail=True)['images']
311 c29ac11d Ilias Tsitsimpis
        # Select images by `system_uuid' user
312 62f3f54f Ilias Tsitsimpis
        images = [x for x in images
313 62f3f54f Ilias Tsitsimpis
                  if x['user_id'] in DEFAULT_SYSTEM_IMAGES_UUID]
314 c29ac11d Ilias Tsitsimpis
        # Select images with `image_name' in their names
315 62f3f54f Ilias Tsitsimpis
        images = [x for x in images
316 62f3f54f Ilias Tsitsimpis
                  if x['name'].lower().find(image_name) != -1]
317 c29ac11d Ilias Tsitsimpis
        # Let's select the first one
318 c29ac11d Ilias Tsitsimpis
        return images[0]
319 c29ac11d Ilias Tsitsimpis
320 c29ac11d Ilias Tsitsimpis
    def _get_server_ip_and_port(self, server):
321 c29ac11d Ilias Tsitsimpis
        """Compute server's IPv4 and ssh port number"""
322 c29ac11d Ilias Tsitsimpis
        self.logger.info("Get server connection details..")
323 c29ac11d Ilias Tsitsimpis
        server_ip = server['attachments'][0]['ipv4']
324 3b26ae00 Christos Stavrakakis
        if ".okeanos.io" in self.cyclades_client.base_url:
325 c29ac11d Ilias Tsitsimpis
            tmp1 = int(server_ip.split(".")[2])
326 c29ac11d Ilias Tsitsimpis
            tmp2 = int(server_ip.split(".")[3])
327 c29ac11d Ilias Tsitsimpis
            server_ip = "gate.okeanos.io"
328 c29ac11d Ilias Tsitsimpis
            server_port = 10000 + tmp1 * 256 + tmp2
329 c29ac11d Ilias Tsitsimpis
        else:
330 c29ac11d Ilias Tsitsimpis
            server_port = 22
331 c29ac11d Ilias Tsitsimpis
        self.write_config('server_ip', server_ip)
332 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Server's IPv4 is %s" % _green(server_ip))
333 c29ac11d Ilias Tsitsimpis
        self.write_config('server_port', server_port)
334 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Server's ssh port is %s" % _green(server_port))
335 6868804a Ilias Tsitsimpis
        self.logger.debug("Access server using \"ssh -p %s %s@%s\"" %
336 4b743650 Ilias Tsitsimpis
                          (server_port, server['metadata']['users'], server_ip))
337 c29ac11d Ilias Tsitsimpis
338 e480f0ce Christos Stavrakakis
    @_check_fabric
339 6868804a Ilias Tsitsimpis
    def _copy_ssh_keys(self, ssh_keys):
340 e2a0abb8 Ilias Tsitsimpis
        """Upload/Install ssh keys to server"""
341 4b743650 Ilias Tsitsimpis
        self.logger.debug("Check for authentication keys to use")
342 6868804a Ilias Tsitsimpis
        if ssh_keys is None:
343 6868804a Ilias Tsitsimpis
            ssh_keys = self.config.get("Deployment", "ssh_keys")
344 6868804a Ilias Tsitsimpis
345 4b743650 Ilias Tsitsimpis
        if ssh_keys != "":
346 4b743650 Ilias Tsitsimpis
            self.logger.debug("Will use %s authentication keys file" % ssh_keys)
347 e480f0ce Christos Stavrakakis
            keyfile = '/tmp/%s.pub' % fabric.env.user
348 e480f0ce Christos Stavrakakis
            _run('mkdir -p ~/.ssh && chmod 700 ~/.ssh', False)
349 4b743650 Ilias Tsitsimpis
            if ssh_keys.startswith("http://") or \
350 4b743650 Ilias Tsitsimpis
                    ssh_keys.startswith("https://") or \
351 4b743650 Ilias Tsitsimpis
                    ssh_keys.startswith("ftp://"):
352 4b743650 Ilias Tsitsimpis
                cmd = """
353 4b743650 Ilias Tsitsimpis
                apt-get update
354 4b743650 Ilias Tsitsimpis
                apt-get install wget --yes
355 4b743650 Ilias Tsitsimpis
                wget {0} -O {1} --no-check-certificate
356 4b743650 Ilias Tsitsimpis
                """.format(ssh_keys, keyfile)
357 4b743650 Ilias Tsitsimpis
                _run(cmd, False)
358 4b743650 Ilias Tsitsimpis
            elif os.path.exists(ssh_keys):
359 4b743650 Ilias Tsitsimpis
                _put(ssh_keys, keyfile)
360 4b743650 Ilias Tsitsimpis
            else:
361 4b743650 Ilias Tsitsimpis
                self.logger.debug("No ssh keys found")
362 e480f0ce Christos Stavrakakis
            _run('cat %s >> ~/.ssh/authorized_keys' % keyfile, False)
363 e480f0ce Christos Stavrakakis
            _run('rm %s' % keyfile, False)
364 e480f0ce Christos Stavrakakis
            self.logger.debug("Uploaded ssh authorized keys")
365 e480f0ce Christos Stavrakakis
        else:
366 e480f0ce Christos Stavrakakis
            self.logger.debug("No ssh keys found")
367 e480f0ce Christos Stavrakakis
368 c29ac11d Ilias Tsitsimpis
    def write_config(self, option, value, section="Temporary Options"):
369 c29ac11d Ilias Tsitsimpis
        """Write changes back to config file"""
370 c29ac11d Ilias Tsitsimpis
        try:
371 c29ac11d Ilias Tsitsimpis
            self.config.add_section(section)
372 c29ac11d Ilias Tsitsimpis
        except DuplicateSectionError:
373 c29ac11d Ilias Tsitsimpis
            pass
374 c29ac11d Ilias Tsitsimpis
        self.config.set(section, option, str(value))
375 c29ac11d Ilias Tsitsimpis
        temp_conf_file = self.config.get('Global', 'temporary_config')
376 c29ac11d Ilias Tsitsimpis
        with open(temp_conf_file, 'wb') as tcf:
377 c29ac11d Ilias Tsitsimpis
            self.config.write(tcf)
378 c29ac11d Ilias Tsitsimpis
379 c29ac11d Ilias Tsitsimpis
    def setup_fabric(self):
380 c29ac11d Ilias Tsitsimpis
        """Setup fabric environment"""
381 c29ac11d Ilias Tsitsimpis
        self.logger.info("Setup fabric parameters..")
382 c29ac11d Ilias Tsitsimpis
        fabric.env.user = self.config.get('Temporary Options', 'server_user')
383 c29ac11d Ilias Tsitsimpis
        fabric.env.host_string = \
384 c29ac11d Ilias Tsitsimpis
            self.config.get('Temporary Options', 'server_ip')
385 e908a902 Christos Stavrakakis
        fabric.env.port = self.config.getint('Temporary Options',
386 e908a902 Christos Stavrakakis
                                             'server_port')
387 e908a902 Christos Stavrakakis
        fabric.env.password = self.config.get('Temporary Options',
388 e908a902 Christos Stavrakakis
                                              'server_passwd')
389 c29ac11d Ilias Tsitsimpis
        fabric.env.connection_attempts = 10
390 c29ac11d Ilias Tsitsimpis
        fabric.env.shell = "/bin/bash -c"
391 c29ac11d Ilias Tsitsimpis
        fabric.env.disable_known_hosts = True
392 c29ac11d Ilias Tsitsimpis
        fabric.env.output_prefix = None
393 c29ac11d Ilias Tsitsimpis
394 c29ac11d Ilias Tsitsimpis
    def _check_hash_sum(self, localfile, remotefile):
395 c29ac11d Ilias Tsitsimpis
        """Check hash sums of two files"""
396 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Check hash sum for local file %s" % localfile)
397 c29ac11d Ilias Tsitsimpis
        hash1 = os.popen("sha256sum %s" % localfile).read().split(' ')[0]
398 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Local file has sha256 hash %s" % hash1)
399 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Check hash sum for remote file %s" % remotefile)
400 c29ac11d Ilias Tsitsimpis
        hash2 = _run("sha256sum %s" % remotefile, False)
401 c29ac11d Ilias Tsitsimpis
        hash2 = hash2.split(' ')[0]
402 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Remote file has sha256 hash %s" % hash2)
403 c29ac11d Ilias Tsitsimpis
        if hash1 != hash2:
404 c29ac11d Ilias Tsitsimpis
            self.logger.error("Hashes differ.. aborting")
405 c29ac11d Ilias Tsitsimpis
            sys.exit(-1)
406 c29ac11d Ilias Tsitsimpis
407 c29ac11d Ilias Tsitsimpis
    @_check_fabric
408 c29ac11d Ilias Tsitsimpis
    def clone_repo(self):
409 c29ac11d Ilias Tsitsimpis
        """Clone Synnefo repo from slave server"""
410 c29ac11d Ilias Tsitsimpis
        self.logger.info("Configure repositories on remote server..")
411 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Setup apt, install curl and git")
412 c29ac11d Ilias Tsitsimpis
        cmd = """
413 c29ac11d Ilias Tsitsimpis
        echo 'APT::Install-Suggests "false";' >> /etc/apt/apt.conf
414 c29ac11d Ilias Tsitsimpis
        apt-get update
415 c29ac11d Ilias Tsitsimpis
        apt-get install curl git --yes
416 c29ac11d Ilias Tsitsimpis
        echo -e "\n\ndeb {0}" >> /etc/apt/sources.list
417 c29ac11d Ilias Tsitsimpis
        curl https://dev.grnet.gr/files/apt-grnetdev.pub | apt-key add -
418 c29ac11d Ilias Tsitsimpis
        apt-get update
419 c29ac11d Ilias Tsitsimpis
        git config --global user.name {1}
420 b52c7bb0 Christos Stavrakakis
        git config --global user.email {2}
421 c29ac11d Ilias Tsitsimpis
        """.format(self.config.get('Global', 'apt_repo'),
422 c29ac11d Ilias Tsitsimpis
                   self.config.get('Global', 'git_config_name'),
423 c29ac11d Ilias Tsitsimpis
                   self.config.get('Global', 'git_config_mail'))
424 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
425 c29ac11d Ilias Tsitsimpis
426 c29ac11d Ilias Tsitsimpis
        synnefo_repo = self.config.get('Global', 'synnefo_repo')
427 b69b55ca Christos Stavrakakis
        synnefo_branch = self.config.get("Global", "synnefo_branch")
428 b69b55ca Christos Stavrakakis
        if synnefo_branch == "":
429 e2a0abb8 Ilias Tsitsimpis
            synnefo_branch = \
430 e2a0abb8 Ilias Tsitsimpis
                subprocess.Popen(
431 e2a0abb8 Ilias Tsitsimpis
                    ["git", "rev-parse", "--abbrev-ref", "HEAD"],
432 b69b55ca Christos Stavrakakis
                    stdout=subprocess.PIPE).communicate()[0].strip()
433 b69b55ca Christos Stavrakakis
            if synnefo_branch == "HEAD":
434 b69b55ca Christos Stavrakakis
                synnefo_branch = \
435 e2a0abb8 Ilias Tsitsimpis
                    subprocess.Popen(
436 e2a0abb8 Ilias Tsitsimpis
                        ["git", "rev-parse", "--short", "HEAD"],
437 b69b55ca Christos Stavrakakis
                        stdout=subprocess.PIPE).communicate()[0].strip()
438 b69b55ca Christos Stavrakakis
        self.logger.info("Will use branch %s" % synnefo_branch)
439 c29ac11d Ilias Tsitsimpis
        # Currently clonning synnefo can fail unexpectedly
440 e908a902 Christos Stavrakakis
        cloned = False
441 b69b55ca Christos Stavrakakis
        for i in range(10):
442 c29ac11d Ilias Tsitsimpis
            self.logger.debug("Clone synnefo from %s" % synnefo_repo)
443 c29ac11d Ilias Tsitsimpis
            try:
444 b69b55ca Christos Stavrakakis
                _run("git clone %s synnefo" % synnefo_repo, False)
445 e908a902 Christos Stavrakakis
                cloned = True
446 c29ac11d Ilias Tsitsimpis
                break
447 e2a0abb8 Ilias Tsitsimpis
            except BaseException:
448 e908a902 Christos Stavrakakis
                self.logger.warning("Clonning synnefo failed.. retrying %s"
449 e908a902 Christos Stavrakakis
                                    % i)
450 e2a0abb8 Ilias Tsitsimpis
        cmd = """
451 b69b55ca Christos Stavrakakis
        cd synnefo
452 e2a0abb8 Ilias Tsitsimpis
        for branch in `git branch -a | grep remotes | \
453 e2a0abb8 Ilias Tsitsimpis
                       grep -v HEAD | grep -v master`; do
454 b69b55ca Christos Stavrakakis
            git branch --track ${branch##*/} $branch
455 b69b55ca Christos Stavrakakis
        done
456 b69b55ca Christos Stavrakakis
        git checkout %s
457 b69b55ca Christos Stavrakakis
        """ % (synnefo_branch)
458 b69b55ca Christos Stavrakakis
        _run(cmd, False)
459 b69b55ca Christos Stavrakakis
460 e908a902 Christos Stavrakakis
        if not cloned:
461 e908a902 Christos Stavrakakis
            self.logger.error("Can not clone Synnefo repo.")
462 e908a902 Christos Stavrakakis
            sys.exit(-1)
463 c29ac11d Ilias Tsitsimpis
464 c29ac11d Ilias Tsitsimpis
        deploy_repo = self.config.get('Global', 'deploy_repo')
465 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Clone snf-deploy from %s" % deploy_repo)
466 e908a902 Christos Stavrakakis
        _run("git clone --depth 1 %s" % deploy_repo, False)
467 c29ac11d Ilias Tsitsimpis
468 c29ac11d Ilias Tsitsimpis
    @_check_fabric
469 c29ac11d Ilias Tsitsimpis
    def build_synnefo(self):
470 c29ac11d Ilias Tsitsimpis
        """Build Synnefo packages"""
471 c29ac11d Ilias Tsitsimpis
        self.logger.info("Build Synnefo packages..")
472 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Install development packages")
473 c29ac11d Ilias Tsitsimpis
        cmd = """
474 c29ac11d Ilias Tsitsimpis
        apt-get update
475 c29ac11d Ilias Tsitsimpis
        apt-get install zlib1g-dev dpkg-dev debhelper git-buildpackage \
476 c29ac11d Ilias Tsitsimpis
                python-dev python-all python-pip --yes
477 c29ac11d Ilias Tsitsimpis
        pip install devflow
478 c29ac11d Ilias Tsitsimpis
        """
479 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
480 c29ac11d Ilias Tsitsimpis
481 e908a902 Christos Stavrakakis
        if self.config.get('Global', 'patch_pydist') == "True":
482 c29ac11d Ilias Tsitsimpis
            self.logger.debug("Patch pydist.py module")
483 c29ac11d Ilias Tsitsimpis
            cmd = r"""
484 c29ac11d Ilias Tsitsimpis
            sed -r -i 's/(\(\?P<name>\[A-Za-z\]\[A-Za-z0-9_\.)/\1\\\-/' \
485 c29ac11d Ilias Tsitsimpis
                /usr/share/python/debpython/pydist.py
486 c29ac11d Ilias Tsitsimpis
            """
487 c29ac11d Ilias Tsitsimpis
            _run(cmd, False)
488 c29ac11d Ilias Tsitsimpis

489 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Build snf-deploy package")
490 c29ac11d Ilias Tsitsimpis
        cmd = """
491 c29ac11d Ilias Tsitsimpis
        git checkout -t origin/debian
492 c29ac11d Ilias Tsitsimpis
        git-buildpackage --git-upstream-branch=master \
493 c29ac11d Ilias Tsitsimpis
                --git-debian-branch=debian \
494 c29ac11d Ilias Tsitsimpis
                --git-export-dir=../snf-deploy_build-area \
495 c29ac11d Ilias Tsitsimpis
                -uc -us
496 c29ac11d Ilias Tsitsimpis
        """
497 c29ac11d Ilias Tsitsimpis
        with fabric.cd("snf-deploy"):
498 c29ac11d Ilias Tsitsimpis
            _run(cmd, True)
499 c29ac11d Ilias Tsitsimpis

500 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Install snf-deploy package")
501 c29ac11d Ilias Tsitsimpis
        cmd = """
502 c29ac11d Ilias Tsitsimpis
        dpkg -i snf-deploy*.deb
503 c29ac11d Ilias Tsitsimpis
        apt-get -f install --yes
504 c29ac11d Ilias Tsitsimpis
        """
505 c29ac11d Ilias Tsitsimpis
        with fabric.cd("snf-deploy_build-area"):
506 c29ac11d Ilias Tsitsimpis
            with fabric.settings(warn_only=True):
507 c29ac11d Ilias Tsitsimpis
                _run(cmd, True)
508 c29ac11d Ilias Tsitsimpis

509 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Build synnefo packages")
510 c29ac11d Ilias Tsitsimpis
        cmd = """
511 c29ac11d Ilias Tsitsimpis
        devflow-autopkg snapshot -b ~/synnefo_build-area --no-sign
512 c29ac11d Ilias Tsitsimpis
        """
513 c29ac11d Ilias Tsitsimpis
        with fabric.cd("synnefo"):
514 c29ac11d Ilias Tsitsimpis
            _run(cmd, True)
515 c29ac11d Ilias Tsitsimpis

516 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Copy synnefo debs to snf-deploy packages dir")
517 c29ac11d Ilias Tsitsimpis
        cmd = """
518 c29ac11d Ilias Tsitsimpis
        cp ~/synnefo_build-area/*.deb /var/lib/snf-deploy/packages/
519 c29ac11d Ilias Tsitsimpis
        """
520 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
521 c29ac11d Ilias Tsitsimpis

522 88e6558b Christos Stavrakakis
    @_check_fabric
523 88e6558b Christos Stavrakakis
    def build_documentation(self):
524 e2a0abb8 Ilias Tsitsimpis
        """Build Synnefo documentation"""
525 88e6558b Christos Stavrakakis
        self.logger.info("Build Synnefo documentation..")
526 88e6558b Christos Stavrakakis
        _run("pip install -U Sphinx", False)
527 88e6558b Christos Stavrakakis
        with fabric.cd("synnefo"):
528 e2a0abb8 Ilias Tsitsimpis
            _run("devflow-update-version; "
529 e2a0abb8 Ilias Tsitsimpis
                 "./ci/make_docs.sh synnefo_documentation", False)
530 88e6558b Christos Stavrakakis

531 88e6558b Christos Stavrakakis
    def fetch_documentation(self, dest=None):
532 e2a0abb8 Ilias Tsitsimpis
        """Fetch Synnefo documentation"""
533 e2a0abb8 Ilias Tsitsimpis
        self.logger.info("Fetch Synnefo documentation..")
534 88e6558b Christos Stavrakakis
        if dest is None:
535 88e6558b Christos Stavrakakis
            dest = "synnefo_documentation"
536 88e6558b Christos Stavrakakis
        dest = os.path.abspath(dest)
537 88e6558b Christos Stavrakakis
        if not os.path.exists(dest):
538 88e6558b Christos Stavrakakis
            os.makedirs(dest)
539 88e6558b Christos Stavrakakis
        self.fetch_compressed("synnefo/synnefo_documentation", dest)
540 88e6558b Christos Stavrakakis
        self.logger.info("Downloaded documentation to %s" %
541 88e6558b Christos Stavrakakis
                         _green(dest))
542 88e6558b Christos Stavrakakis

543 c29ac11d Ilias Tsitsimpis
    @_check_fabric
544 ec8bc030 Christos Stavrakakis
    def deploy_synnefo(self, schema=None):
545 c29ac11d Ilias Tsitsimpis
        """Deploy Synnefo using snf-deploy"""
546 c29ac11d Ilias Tsitsimpis
        self.logger.info("Deploy Synnefo..")
547 ec8bc030 Christos Stavrakakis
        if schema is None:
548 ec8bc030 Christos Stavrakakis
            schema = self.config.get('Global', 'schema')
549 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Will use %s schema" % schema)
550 c29ac11d Ilias Tsitsimpis

551 ec8bc030 Christos Stavrakakis
        schema_dir = os.path.join(self.ci_dir, "schemas/%s" % schema)
552 ec8bc030 Christos Stavrakakis
        if not (os.path.exists(schema_dir) and os.path.isdir(schema_dir)):
553 ec8bc030 Christos Stavrakakis
            raise ValueError("Unknown schema: %s" % schema)
554 ec8bc030 Christos Stavrakakis

555 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Upload schema files to server")
556 6868804a Ilias Tsitsimpis
        _put(os.path.join(schema_dir, "*"), "/etc/snf-deploy/")
557 c29ac11d Ilias Tsitsimpis

558 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Change password in nodes.conf file")
559 c29ac11d Ilias Tsitsimpis
        cmd = """
560 c29ac11d Ilias Tsitsimpis
        sed -i 's/^password =.*/password = {0}/' /etc/snf-deploy/nodes.conf
561 c29ac11d Ilias Tsitsimpis
        """.format(fabric.env.password)
562 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
563 c29ac11d Ilias Tsitsimpis

564 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Run snf-deploy")
565 c29ac11d Ilias Tsitsimpis
        cmd = """
566 f82ce32a Christos Stavrakakis
        snf-deploy --disable-colors --autoconf all
567 c29ac11d Ilias Tsitsimpis
        """
568 c29ac11d Ilias Tsitsimpis
        _run(cmd, True)
569 c29ac11d Ilias Tsitsimpis

570 c29ac11d Ilias Tsitsimpis
    @_check_fabric
571 c29ac11d Ilias Tsitsimpis
    def unit_test(self):
572 c29ac11d Ilias Tsitsimpis
        """Run Synnefo unit test suite"""
573 c29ac11d Ilias Tsitsimpis
        self.logger.info("Run Synnefo unit test suite")
574 c29ac11d Ilias Tsitsimpis
        component = self.config.get('Unit Tests', 'component')
575 c29ac11d Ilias Tsitsimpis

576 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Install needed packages")
577 c29ac11d Ilias Tsitsimpis
        cmd = """
578 c29ac11d Ilias Tsitsimpis
        pip install mock
579 c29ac11d Ilias Tsitsimpis
        pip install factory_boy
580 c29ac11d Ilias Tsitsimpis
        """
581 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
582 c29ac11d Ilias Tsitsimpis

583 861b437e Ilias Tsitsimpis
        self.logger.debug("Upload tests.sh file")
584 861b437e Ilias Tsitsimpis
        unit_tests_file = os.path.join(self.ci_dir, "tests.sh")
585 6868804a Ilias Tsitsimpis
        _put(unit_tests_file, ".")
586 c29ac11d Ilias Tsitsimpis

587 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Run unit tests")
588 c29ac11d Ilias Tsitsimpis
        cmd = """
589 861b437e Ilias Tsitsimpis
        bash tests.sh {0}
590 c29ac11d Ilias Tsitsimpis
        """.format(component)
591 c29ac11d Ilias Tsitsimpis
        _run(cmd, True)
592 c29ac11d Ilias Tsitsimpis

593 c29ac11d Ilias Tsitsimpis
    @_check_fabric
594 c29ac11d Ilias Tsitsimpis
    def run_burnin(self):
595 c29ac11d Ilias Tsitsimpis
        """Run burnin functional test suite"""
596 c29ac11d Ilias Tsitsimpis
        self.logger.info("Run Burnin functional test suite")
597 c29ac11d Ilias Tsitsimpis
        cmd = """
598 c29ac11d Ilias Tsitsimpis
        auth_url=$(grep -e '^url =' .kamakirc | cut -d' ' -f3)
599 c29ac11d Ilias Tsitsimpis
        token=$(grep -e '^token =' .kamakirc | cut -d' ' -f3)
600 c29ac11d Ilias Tsitsimpis
        images_user=$(kamaki image list -l | grep owner | \
601 c29ac11d Ilias Tsitsimpis
                      cut -d':' -f2 | tr -d ' ')
602 c29ac11d Ilias Tsitsimpis
        snf-burnin --auth-url=$auth_url --token=$token \
603 c29ac11d Ilias Tsitsimpis
            --force-flavor=2 --image-id=all \
604 c29ac11d Ilias Tsitsimpis
            --system-images-user=$images_user \
605 c29ac11d Ilias Tsitsimpis
            {0}
606 c29ac11d Ilias Tsitsimpis
        log_folder=$(ls -1d /var/log/burnin/* | tail -n1)
607 c29ac11d Ilias Tsitsimpis
        for i in $(ls $log_folder/*/details*); do
608 c29ac11d Ilias Tsitsimpis
            echo -e "\\n\\n"
609 c29ac11d Ilias Tsitsimpis
            echo -e "***** $i\\n"
610 c29ac11d Ilias Tsitsimpis
            cat $i
611 c29ac11d Ilias Tsitsimpis
        done
612 c29ac11d Ilias Tsitsimpis
        """.format(self.config.get('Burnin', 'cmd_options'))
613 c29ac11d Ilias Tsitsimpis
        _run(cmd, True)
614 c29ac11d Ilias Tsitsimpis

615 c29ac11d Ilias Tsitsimpis
    @_check_fabric
616 88e6558b Christos Stavrakakis
    def fetch_compressed(self, src, dest=None):
617 e2a0abb8 Ilias Tsitsimpis
        """Create a tarball and fetch it locally"""
618 88e6558b Christos Stavrakakis
        self.logger.debug("Creating tarball of %s" % src)
619 88e6558b Christos Stavrakakis
        basename = os.path.basename(src)
620 88e6558b Christos Stavrakakis
        tar_file = basename + ".tgz"
621 88e6558b Christos Stavrakakis
        cmd = "tar czf %s %s" % (tar_file, src)
622 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
623 88e6558b Christos Stavrakakis
        if not os.path.exists(dest):
624 88e6558b Christos Stavrakakis
            os.makedirs(dest)
625 c29ac11d Ilias Tsitsimpis

626 88e6558b Christos Stavrakakis
        tmp_dir = tempfile.mkdtemp()
627 88e6558b Christos Stavrakakis
        fabric.get(tar_file, tmp_dir)
628 c29ac11d Ilias Tsitsimpis

629 88e6558b Christos Stavrakakis
        dest_file = os.path.join(tmp_dir, tar_file)
630 88e6558b Christos Stavrakakis
        self._check_hash_sum(dest_file, tar_file)
631 88e6558b Christos Stavrakakis
        self.logger.debug("Untar packages file %s" % dest_file)
632 e2dc37b2 Christos Stavrakakis
        cmd = """
633 e2dc37b2 Christos Stavrakakis
        cd %s
634 88e6558b Christos Stavrakakis
        tar xzf %s
635 88e6558b Christos Stavrakakis
        cp -r %s/* %s
636 88e6558b Christos Stavrakakis
        rm -r %s
637 88e6558b Christos Stavrakakis
        """ % (tmp_dir, tar_file, src, dest, tmp_dir)
638 e2dc37b2 Christos Stavrakakis
        os.system(cmd)
639 88e6558b Christos Stavrakakis
        self.logger.info("Downloaded %s to %s" %
640 88e6558b Christos Stavrakakis
                         (src, _green(dest)))
641 88e6558b Christos Stavrakakis

642 88e6558b Christos Stavrakakis
    @_check_fabric
643 88e6558b Christos Stavrakakis
    def fetch_packages(self, dest=None):
644 e2a0abb8 Ilias Tsitsimpis
        """Fetch Synnefo packages"""
645 88e6558b Christos Stavrakakis
        if dest is None:
646 88e6558b Christos Stavrakakis
            dest = self.config.get('Global', 'pkgs_dir')
647 88e6558b Christos Stavrakakis
        dest = os.path.abspath(dest)
648 88e6558b Christos Stavrakakis
        if not os.path.exists(dest):
649 88e6558b Christos Stavrakakis
            os.makedirs(dest)
650 88e6558b Christos Stavrakakis
        self.fetch_compressed("synnefo_build-area", dest)
651 464e58e9 Christos Stavrakakis
        self.logger.info("Downloaded debian packages to %s" %
652 88e6558b Christos Stavrakakis
                         _green(dest))