Statistics
| Branch: | Tag: | Revision:

root / ci / utils.py @ 07710fc3

History | View | Annotate | Download (26.5 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 79144a72 Ilias Tsitsimpis
    def __init__(self, config_file=None, build_id=None, 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 c29ac11d Ilias Tsitsimpis
        self.config = ConfigParser()
144 c29ac11d Ilias Tsitsimpis
        self.config.optionxform = str
145 6ca8f81a Christos Stavrakakis
        self.config.read(config_file)
146 79144a72 Ilias Tsitsimpis
147 79144a72 Ilias Tsitsimpis
        # Read temporary_config file
148 c29ac11d Ilias Tsitsimpis
        temp_config = self.config.get('Global', 'temporary_config')
149 79144a72 Ilias Tsitsimpis
        self.temp_config = ConfigParser()
150 79144a72 Ilias Tsitsimpis
        self.temp_config.optionxform = str
151 79144a72 Ilias Tsitsimpis
        self.temp_config.read(temp_config)
152 b7496c88 Ilias Tsitsimpis
        self.build_id = build_id
153 b7496c88 Ilias Tsitsimpis
        self.logger.info("Will use \"%s\" as build id" % _green(self.build_id))
154 c29ac11d Ilias Tsitsimpis
155 c1b1d444 Christos Stavrakakis
        # Set kamaki cloud
156 c1b1d444 Christos Stavrakakis
        if cloud is not None:
157 c1b1d444 Christos Stavrakakis
            self.kamaki_cloud = cloud
158 c1b1d444 Christos Stavrakakis
        elif self.config.has_option("Deployment", "kamaki_cloud"):
159 c1b1d444 Christos Stavrakakis
            kamaki_cloud = self.config.get("Deployment", "kamaki_cloud")
160 c1b1d444 Christos Stavrakakis
            if kamaki_cloud == "":
161 c1b1d444 Christos Stavrakakis
                self.kamaki_cloud = None
162 c1b1d444 Christos Stavrakakis
        else:
163 c1b1d444 Christos Stavrakakis
            self.kamaki_cloud = None
164 c1b1d444 Christos Stavrakakis
165 c29ac11d Ilias Tsitsimpis
        # Initialize variables
166 c29ac11d Ilias Tsitsimpis
        self.fabric_installed = False
167 c29ac11d Ilias Tsitsimpis
        self.kamaki_installed = False
168 c29ac11d Ilias Tsitsimpis
        self.cyclades_client = None
169 ad21ffa9 Ilias Tsitsimpis
        self.compute_client = None
170 c29ac11d Ilias Tsitsimpis
        self.image_client = None
171 c29ac11d Ilias Tsitsimpis
172 c29ac11d Ilias Tsitsimpis
    def setup_kamaki(self):
173 c29ac11d Ilias Tsitsimpis
        """Initialize kamaki
174 c29ac11d Ilias Tsitsimpis

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

325 62f3f54f Ilias Tsitsimpis
        It has to belong to one of the `DEFAULT_SYSTEM_IMAGES_UUID'
326 62f3f54f Ilias Tsitsimpis
        users and contain the word given by `image_name' option.
327 c29ac11d Ilias Tsitsimpis
        """
328 c29ac11d Ilias Tsitsimpis
        image_name = self.config.get('Deployment', 'image_name').lower()
329 c29ac11d Ilias Tsitsimpis
        images = self.image_client.list_public(detail=True)['images']
330 c29ac11d Ilias Tsitsimpis
        # Select images by `system_uuid' user
331 62f3f54f Ilias Tsitsimpis
        images = [x for x in images
332 62f3f54f Ilias Tsitsimpis
                  if x['user_id'] in DEFAULT_SYSTEM_IMAGES_UUID]
333 c29ac11d Ilias Tsitsimpis
        # Select images with `image_name' in their names
334 62f3f54f Ilias Tsitsimpis
        images = [x for x in images
335 62f3f54f Ilias Tsitsimpis
                  if x['name'].lower().find(image_name) != -1]
336 c29ac11d Ilias Tsitsimpis
        # Let's select the first one
337 c29ac11d Ilias Tsitsimpis
        return images[0]
338 c29ac11d Ilias Tsitsimpis
339 c29ac11d Ilias Tsitsimpis
    def _get_server_ip_and_port(self, server):
340 c29ac11d Ilias Tsitsimpis
        """Compute server's IPv4 and ssh port number"""
341 c29ac11d Ilias Tsitsimpis
        self.logger.info("Get server connection details..")
342 c29ac11d Ilias Tsitsimpis
        server_ip = server['attachments'][0]['ipv4']
343 3b26ae00 Christos Stavrakakis
        if ".okeanos.io" in self.cyclades_client.base_url:
344 c29ac11d Ilias Tsitsimpis
            tmp1 = int(server_ip.split(".")[2])
345 c29ac11d Ilias Tsitsimpis
            tmp2 = int(server_ip.split(".")[3])
346 c29ac11d Ilias Tsitsimpis
            server_ip = "gate.okeanos.io"
347 c29ac11d Ilias Tsitsimpis
            server_port = 10000 + tmp1 * 256 + tmp2
348 c29ac11d Ilias Tsitsimpis
        else:
349 c29ac11d Ilias Tsitsimpis
            server_port = 22
350 b7496c88 Ilias Tsitsimpis
        self.write_temp_config('server_ip', server_ip)
351 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Server's IPv4 is %s" % _green(server_ip))
352 b7496c88 Ilias Tsitsimpis
        self.write_temp_config('server_port', server_port)
353 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Server's ssh port is %s" % _green(server_port))
354 07710fc3 Ilias Tsitsimpis
        self.logger.debug("Access server using \"ssh -X -p %s %s@%s\"" %
355 4b743650 Ilias Tsitsimpis
                          (server_port, server['metadata']['users'], server_ip))
356 c29ac11d Ilias Tsitsimpis
357 e480f0ce Christos Stavrakakis
    @_check_fabric
358 6868804a Ilias Tsitsimpis
    def _copy_ssh_keys(self, ssh_keys):
359 e2a0abb8 Ilias Tsitsimpis
        """Upload/Install ssh keys to server"""
360 4b743650 Ilias Tsitsimpis
        self.logger.debug("Check for authentication keys to use")
361 6868804a Ilias Tsitsimpis
        if ssh_keys is None:
362 6868804a Ilias Tsitsimpis
            ssh_keys = self.config.get("Deployment", "ssh_keys")
363 6868804a Ilias Tsitsimpis
364 4b743650 Ilias Tsitsimpis
        if ssh_keys != "":
365 4b743650 Ilias Tsitsimpis
            self.logger.debug("Will use %s authentication keys file" % ssh_keys)
366 e480f0ce Christos Stavrakakis
            keyfile = '/tmp/%s.pub' % fabric.env.user
367 e480f0ce Christos Stavrakakis
            _run('mkdir -p ~/.ssh && chmod 700 ~/.ssh', False)
368 4b743650 Ilias Tsitsimpis
            if ssh_keys.startswith("http://") or \
369 4b743650 Ilias Tsitsimpis
                    ssh_keys.startswith("https://") or \
370 4b743650 Ilias Tsitsimpis
                    ssh_keys.startswith("ftp://"):
371 4b743650 Ilias Tsitsimpis
                cmd = """
372 4b743650 Ilias Tsitsimpis
                apt-get update
373 4b743650 Ilias Tsitsimpis
                apt-get install wget --yes
374 4b743650 Ilias Tsitsimpis
                wget {0} -O {1} --no-check-certificate
375 4b743650 Ilias Tsitsimpis
                """.format(ssh_keys, keyfile)
376 4b743650 Ilias Tsitsimpis
                _run(cmd, False)
377 4b743650 Ilias Tsitsimpis
            elif os.path.exists(ssh_keys):
378 4b743650 Ilias Tsitsimpis
                _put(ssh_keys, keyfile)
379 4b743650 Ilias Tsitsimpis
            else:
380 4b743650 Ilias Tsitsimpis
                self.logger.debug("No ssh keys found")
381 e480f0ce Christos Stavrakakis
            _run('cat %s >> ~/.ssh/authorized_keys' % keyfile, False)
382 e480f0ce Christos Stavrakakis
            _run('rm %s' % keyfile, False)
383 e480f0ce Christos Stavrakakis
            self.logger.debug("Uploaded ssh authorized keys")
384 e480f0ce Christos Stavrakakis
        else:
385 e480f0ce Christos Stavrakakis
            self.logger.debug("No ssh keys found")
386 e480f0ce Christos Stavrakakis
387 b7496c88 Ilias Tsitsimpis
    def write_temp_config(self, option, value):
388 c29ac11d Ilias Tsitsimpis
        """Write changes back to config file"""
389 b7496c88 Ilias Tsitsimpis
        # If build_id section doesn't exist create a new one
390 b7496c88 Ilias Tsitsimpis
        try:
391 b7496c88 Ilias Tsitsimpis
            self.temp_config.add_section(str(self.build_id))
392 b7496c88 Ilias Tsitsimpis
            creation_time = time.strftime("%a, %d %b %Y %X", time.localtime())
393 b7496c88 Ilias Tsitsimpis
            self.write_temp_config("created", creation_time)
394 b7496c88 Ilias Tsitsimpis
        except DuplicateSectionError:
395 b7496c88 Ilias Tsitsimpis
            pass
396 79144a72 Ilias Tsitsimpis
        self.temp_config.set(str(self.build_id), option, str(value))
397 79144a72 Ilias Tsitsimpis
        curr_time = time.strftime("%a, %d %b %Y %X", time.localtime())
398 79144a72 Ilias Tsitsimpis
        self.temp_config.set(str(self.build_id), "modified", curr_time)
399 c29ac11d Ilias Tsitsimpis
        temp_conf_file = self.config.get('Global', 'temporary_config')
400 c29ac11d Ilias Tsitsimpis
        with open(temp_conf_file, 'wb') as tcf:
401 79144a72 Ilias Tsitsimpis
            self.temp_config.write(tcf)
402 c29ac11d Ilias Tsitsimpis
403 b7496c88 Ilias Tsitsimpis
    def read_temp_config(self, option):
404 b7496c88 Ilias Tsitsimpis
        """Read from temporary_config file"""
405 b7496c88 Ilias Tsitsimpis
        # If build_id is None use the latest one
406 b7496c88 Ilias Tsitsimpis
        if self.build_id is None:
407 b7496c88 Ilias Tsitsimpis
            ids = self.temp_config.sections()
408 b7496c88 Ilias Tsitsimpis
            if ids:
409 b7496c88 Ilias Tsitsimpis
                self.build_id = int(ids[-1])
410 b7496c88 Ilias Tsitsimpis
            else:
411 b7496c88 Ilias Tsitsimpis
                self.logger.error("No sections in temporary config file")
412 b7496c88 Ilias Tsitsimpis
                sys.exit(1)
413 b7496c88 Ilias Tsitsimpis
            self.logger.debug("Will use \"%s\" as build id"
414 b7496c88 Ilias Tsitsimpis
                              % _green(self.build_id))
415 b7496c88 Ilias Tsitsimpis
        # Read specified option
416 b7496c88 Ilias Tsitsimpis
        return self.temp_config.get(str(self.build_id), option)
417 b7496c88 Ilias Tsitsimpis
418 c29ac11d Ilias Tsitsimpis
    def setup_fabric(self):
419 c29ac11d Ilias Tsitsimpis
        """Setup fabric environment"""
420 c29ac11d Ilias Tsitsimpis
        self.logger.info("Setup fabric parameters..")
421 b7496c88 Ilias Tsitsimpis
        fabric.env.user = self.read_temp_config('server_user')
422 b7496c88 Ilias Tsitsimpis
        fabric.env.host_string = self.read_temp_config('server_ip')
423 b7496c88 Ilias Tsitsimpis
        fabric.env.port = int(self.read_temp_config('server_port'))
424 b7496c88 Ilias Tsitsimpis
        fabric.env.password = self.read_temp_config('server_passwd')
425 c29ac11d Ilias Tsitsimpis
        fabric.env.connection_attempts = 10
426 c29ac11d Ilias Tsitsimpis
        fabric.env.shell = "/bin/bash -c"
427 c29ac11d Ilias Tsitsimpis
        fabric.env.disable_known_hosts = True
428 c29ac11d Ilias Tsitsimpis
        fabric.env.output_prefix = None
429 c29ac11d Ilias Tsitsimpis
430 c29ac11d Ilias Tsitsimpis
    def _check_hash_sum(self, localfile, remotefile):
431 c29ac11d Ilias Tsitsimpis
        """Check hash sums of two files"""
432 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Check hash sum for local file %s" % localfile)
433 c29ac11d Ilias Tsitsimpis
        hash1 = os.popen("sha256sum %s" % localfile).read().split(' ')[0]
434 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Local file has sha256 hash %s" % hash1)
435 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Check hash sum for remote file %s" % remotefile)
436 c29ac11d Ilias Tsitsimpis
        hash2 = _run("sha256sum %s" % remotefile, False)
437 c29ac11d Ilias Tsitsimpis
        hash2 = hash2.split(' ')[0]
438 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Remote file has sha256 hash %s" % hash2)
439 c29ac11d Ilias Tsitsimpis
        if hash1 != hash2:
440 c29ac11d Ilias Tsitsimpis
            self.logger.error("Hashes differ.. aborting")
441 c29ac11d Ilias Tsitsimpis
            sys.exit(-1)
442 c29ac11d Ilias Tsitsimpis
443 c29ac11d Ilias Tsitsimpis
    @_check_fabric
444 5323404f Ilias Tsitsimpis
    def clone_repo(self, local_repo=False):
445 c29ac11d Ilias Tsitsimpis
        """Clone Synnefo repo from slave server"""
446 c29ac11d Ilias Tsitsimpis
        self.logger.info("Configure repositories on remote server..")
447 07710fc3 Ilias Tsitsimpis
        self.logger.debug("Setup apt. Install curl, git and firefox")
448 c29ac11d Ilias Tsitsimpis
        cmd = """
449 c29ac11d Ilias Tsitsimpis
        echo 'APT::Install-Suggests "false";' >> /etc/apt/apt.conf
450 c29ac11d Ilias Tsitsimpis
        apt-get update
451 07710fc3 Ilias Tsitsimpis
        apt-get install curl git iceweasel --yes
452 c29ac11d Ilias Tsitsimpis
        echo -e "\n\ndeb {0}" >> /etc/apt/sources.list
453 c29ac11d Ilias Tsitsimpis
        curl https://dev.grnet.gr/files/apt-grnetdev.pub | apt-key add -
454 c29ac11d Ilias Tsitsimpis
        apt-get update
455 c29ac11d Ilias Tsitsimpis
        git config --global user.name {1}
456 b52c7bb0 Christos Stavrakakis
        git config --global user.email {2}
457 c29ac11d Ilias Tsitsimpis
        """.format(self.config.get('Global', 'apt_repo'),
458 c29ac11d Ilias Tsitsimpis
                   self.config.get('Global', 'git_config_name'),
459 c29ac11d Ilias Tsitsimpis
                   self.config.get('Global', 'git_config_mail'))
460 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
461 c29ac11d Ilias Tsitsimpis
462 5323404f Ilias Tsitsimpis
        # Find synnefo_repo and synnefo_branch to use
463 c29ac11d Ilias Tsitsimpis
        synnefo_repo = self.config.get('Global', 'synnefo_repo')
464 b69b55ca Christos Stavrakakis
        synnefo_branch = self.config.get("Global", "synnefo_branch")
465 b69b55ca Christos Stavrakakis
        if synnefo_branch == "":
466 e2a0abb8 Ilias Tsitsimpis
            synnefo_branch = \
467 e2a0abb8 Ilias Tsitsimpis
                subprocess.Popen(
468 e2a0abb8 Ilias Tsitsimpis
                    ["git", "rev-parse", "--abbrev-ref", "HEAD"],
469 b69b55ca Christos Stavrakakis
                    stdout=subprocess.PIPE).communicate()[0].strip()
470 b69b55ca Christos Stavrakakis
            if synnefo_branch == "HEAD":
471 b69b55ca Christos Stavrakakis
                synnefo_branch = \
472 e2a0abb8 Ilias Tsitsimpis
                    subprocess.Popen(
473 e2a0abb8 Ilias Tsitsimpis
                        ["git", "rev-parse", "--short", "HEAD"],
474 b69b55ca Christos Stavrakakis
                        stdout=subprocess.PIPE).communicate()[0].strip()
475 b69b55ca Christos Stavrakakis
        self.logger.info("Will use branch %s" % synnefo_branch)
476 5323404f Ilias Tsitsimpis
477 5323404f Ilias Tsitsimpis
        if local_repo or synnefo_branch == "":
478 5323404f Ilias Tsitsimpis
            # Use local_repo
479 5323404f Ilias Tsitsimpis
            self.logger.debug("Push local repo to server")
480 5323404f Ilias Tsitsimpis
            # Firstly create the remote repo
481 5323404f Ilias Tsitsimpis
            _run("git init synnefo", False)
482 5323404f Ilias Tsitsimpis
            # Then push our local repo over ssh
483 5323404f Ilias Tsitsimpis
            # We have to pass some arguments to ssh command
484 5323404f Ilias Tsitsimpis
            # namely to disable host checking.
485 5323404f Ilias Tsitsimpis
            (temp_ssh_file_handle, temp_ssh_file) = tempfile.mkstemp()
486 5323404f Ilias Tsitsimpis
            os.close(temp_ssh_file_handle)
487 5323404f Ilias Tsitsimpis
            cmd = """
488 5323404f Ilias Tsitsimpis
            echo 'exec ssh -o "StrictHostKeyChecking no" \
489 5323404f Ilias Tsitsimpis
                           -o "UserKnownHostsFile /dev/null" \
490 5323404f Ilias Tsitsimpis
                           -q "$@"' > {4}
491 5323404f Ilias Tsitsimpis
            chmod u+x {4}
492 5323404f Ilias Tsitsimpis
            export GIT_SSH="{4}"
493 5323404f Ilias Tsitsimpis
            echo "{0}" | git push --mirror ssh://{1}@{2}:{3}/~/synnefo
494 5323404f Ilias Tsitsimpis
            rm -f {4}
495 5323404f Ilias Tsitsimpis
            """.format(fabric.env.password,
496 5323404f Ilias Tsitsimpis
                       fabric.env.user,
497 5323404f Ilias Tsitsimpis
                       fabric.env.host_string,
498 5323404f Ilias Tsitsimpis
                       fabric.env.port,
499 5323404f Ilias Tsitsimpis
                       temp_ssh_file)
500 5323404f Ilias Tsitsimpis
            os.system(cmd)
501 5323404f Ilias Tsitsimpis
        else:
502 5323404f Ilias Tsitsimpis
            # Clone Synnefo from remote repo
503 5323404f Ilias Tsitsimpis
            # Currently clonning synnefo can fail unexpectedly
504 5323404f Ilias Tsitsimpis
            cloned = False
505 5323404f Ilias Tsitsimpis
            for i in range(10):
506 5323404f Ilias Tsitsimpis
                self.logger.debug("Clone synnefo from %s" % synnefo_repo)
507 5323404f Ilias Tsitsimpis
                try:
508 5323404f Ilias Tsitsimpis
                    _run("git clone %s synnefo" % synnefo_repo, False)
509 5323404f Ilias Tsitsimpis
                    cloned = True
510 5323404f Ilias Tsitsimpis
                    break
511 5323404f Ilias Tsitsimpis
                except BaseException:
512 5323404f Ilias Tsitsimpis
                    self.logger.warning(
513 5323404f Ilias Tsitsimpis
                        "Clonning synnefo failed.. retrying %s" % i)
514 5323404f Ilias Tsitsimpis
            if not cloned:
515 5323404f Ilias Tsitsimpis
                self.logger.error("Can not clone Synnefo repo.")
516 5323404f Ilias Tsitsimpis
                sys.exit(-1)
517 5323404f Ilias Tsitsimpis
518 5323404f Ilias Tsitsimpis
        # Checkout the desired synnefo_branch
519 07710fc3 Ilias Tsitsimpis
        self.logger.debug("Checkout \"%s\" branch/commit" % synnefo_branch)
520 e2a0abb8 Ilias Tsitsimpis
        cmd = """
521 b69b55ca Christos Stavrakakis
        cd synnefo
522 e2a0abb8 Ilias Tsitsimpis
        for branch in `git branch -a | grep remotes | \
523 e2a0abb8 Ilias Tsitsimpis
                       grep -v HEAD | grep -v master`; do
524 b69b55ca Christos Stavrakakis
            git branch --track ${branch##*/} $branch
525 b69b55ca Christos Stavrakakis
        done
526 b69b55ca Christos Stavrakakis
        git checkout %s
527 b69b55ca Christos Stavrakakis
        """ % (synnefo_branch)
528 b69b55ca Christos Stavrakakis
        _run(cmd, False)
529 b69b55ca Christos Stavrakakis
530 c29ac11d Ilias Tsitsimpis
    @_check_fabric
531 c29ac11d Ilias Tsitsimpis
    def build_synnefo(self):
532 c29ac11d Ilias Tsitsimpis
        """Build Synnefo packages"""
533 c29ac11d Ilias Tsitsimpis
        self.logger.info("Build Synnefo packages..")
534 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Install development packages")
535 c29ac11d Ilias Tsitsimpis
        cmd = """
536 c29ac11d Ilias Tsitsimpis
        apt-get update
537 c29ac11d Ilias Tsitsimpis
        apt-get install zlib1g-dev dpkg-dev debhelper git-buildpackage \
538 c29ac11d Ilias Tsitsimpis
                python-dev python-all python-pip --yes
539 c29ac11d Ilias Tsitsimpis
        pip install devflow
540 c29ac11d Ilias Tsitsimpis
        """
541 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
542 c29ac11d Ilias Tsitsimpis
543 e908a902 Christos Stavrakakis
        if self.config.get('Global', 'patch_pydist') == "True":
544 c29ac11d Ilias Tsitsimpis
            self.logger.debug("Patch pydist.py module")
545 c29ac11d Ilias Tsitsimpis
            cmd = r"""
546 c29ac11d Ilias Tsitsimpis
            sed -r -i 's/(\(\?P<name>\[A-Za-z\]\[A-Za-z0-9_\.)/\1\\\-/' \
547 c29ac11d Ilias Tsitsimpis
                /usr/share/python/debpython/pydist.py
548 c29ac11d Ilias Tsitsimpis
            """
549 c29ac11d Ilias Tsitsimpis
            _run(cmd, False)
550 c29ac11d Ilias Tsitsimpis

551 1c230fd8 Ilias Tsitsimpis
        # Build synnefo packages
552 1c230fd8 Ilias Tsitsimpis
        self.logger.debug("Build synnefo packages")
553 c29ac11d Ilias Tsitsimpis
        cmd = """
554 1c230fd8 Ilias Tsitsimpis
        devflow-autopkg snapshot -b ~/synnefo_build-area --no-sign
555 c29ac11d Ilias Tsitsimpis
        """
556 1c230fd8 Ilias Tsitsimpis
        with fabric.cd("synnefo"):
557 c29ac11d Ilias Tsitsimpis
            _run(cmd, True)
558 c29ac11d Ilias Tsitsimpis

559 1c230fd8 Ilias Tsitsimpis
        # Install snf-deploy package
560 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Install snf-deploy package")
561 c29ac11d Ilias Tsitsimpis
        cmd = """
562 c29ac11d Ilias Tsitsimpis
        dpkg -i snf-deploy*.deb
563 c29ac11d Ilias Tsitsimpis
        apt-get -f install --yes
564 c29ac11d Ilias Tsitsimpis
        """
565 1c230fd8 Ilias Tsitsimpis
        with fabric.cd("synnefo_build-area"):
566 c29ac11d Ilias Tsitsimpis
            with fabric.settings(warn_only=True):
567 c29ac11d Ilias Tsitsimpis
                _run(cmd, True)
568 c29ac11d Ilias Tsitsimpis

569 1c230fd8 Ilias Tsitsimpis
        # Setup synnefo packages for snf-deploy
570 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Copy synnefo debs to snf-deploy packages dir")
571 c29ac11d Ilias Tsitsimpis
        cmd = """
572 c29ac11d Ilias Tsitsimpis
        cp ~/synnefo_build-area/*.deb /var/lib/snf-deploy/packages/
573 c29ac11d Ilias Tsitsimpis
        """
574 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
575 c29ac11d Ilias Tsitsimpis

576 88e6558b Christos Stavrakakis
    @_check_fabric
577 88e6558b Christos Stavrakakis
    def build_documentation(self):
578 e2a0abb8 Ilias Tsitsimpis
        """Build Synnefo documentation"""
579 88e6558b Christos Stavrakakis
        self.logger.info("Build Synnefo documentation..")
580 88e6558b Christos Stavrakakis
        _run("pip install -U Sphinx", False)
581 88e6558b Christos Stavrakakis
        with fabric.cd("synnefo"):
582 e2a0abb8 Ilias Tsitsimpis
            _run("devflow-update-version; "
583 e2a0abb8 Ilias Tsitsimpis
                 "./ci/make_docs.sh synnefo_documentation", False)
584 88e6558b Christos Stavrakakis

585 88e6558b Christos Stavrakakis
    def fetch_documentation(self, dest=None):
586 e2a0abb8 Ilias Tsitsimpis
        """Fetch Synnefo documentation"""
587 e2a0abb8 Ilias Tsitsimpis
        self.logger.info("Fetch Synnefo documentation..")
588 88e6558b Christos Stavrakakis
        if dest is None:
589 88e6558b Christos Stavrakakis
            dest = "synnefo_documentation"
590 88e6558b Christos Stavrakakis
        dest = os.path.abspath(dest)
591 88e6558b Christos Stavrakakis
        if not os.path.exists(dest):
592 88e6558b Christos Stavrakakis
            os.makedirs(dest)
593 88e6558b Christos Stavrakakis
        self.fetch_compressed("synnefo/synnefo_documentation", dest)
594 88e6558b Christos Stavrakakis
        self.logger.info("Downloaded documentation to %s" %
595 88e6558b Christos Stavrakakis
                         _green(dest))
596 88e6558b Christos Stavrakakis

597 c29ac11d Ilias Tsitsimpis
    @_check_fabric
598 ec8bc030 Christos Stavrakakis
    def deploy_synnefo(self, schema=None):
599 c29ac11d Ilias Tsitsimpis
        """Deploy Synnefo using snf-deploy"""
600 c29ac11d Ilias Tsitsimpis
        self.logger.info("Deploy Synnefo..")
601 ec8bc030 Christos Stavrakakis
        if schema is None:
602 ec8bc030 Christos Stavrakakis
            schema = self.config.get('Global', 'schema')
603 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Will use %s schema" % schema)
604 c29ac11d Ilias Tsitsimpis

605 ec8bc030 Christos Stavrakakis
        schema_dir = os.path.join(self.ci_dir, "schemas/%s" % schema)
606 ec8bc030 Christos Stavrakakis
        if not (os.path.exists(schema_dir) and os.path.isdir(schema_dir)):
607 ec8bc030 Christos Stavrakakis
            raise ValueError("Unknown schema: %s" % schema)
608 ec8bc030 Christos Stavrakakis

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

612 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Change password in nodes.conf file")
613 c29ac11d Ilias Tsitsimpis
        cmd = """
614 c29ac11d Ilias Tsitsimpis
        sed -i 's/^password =.*/password = {0}/' /etc/snf-deploy/nodes.conf
615 c29ac11d Ilias Tsitsimpis
        """.format(fabric.env.password)
616 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
617 c29ac11d Ilias Tsitsimpis

618 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Run snf-deploy")
619 c29ac11d Ilias Tsitsimpis
        cmd = """
620 f82ce32a Christos Stavrakakis
        snf-deploy --disable-colors --autoconf all
621 c29ac11d Ilias Tsitsimpis
        """
622 c29ac11d Ilias Tsitsimpis
        _run(cmd, True)
623 c29ac11d Ilias Tsitsimpis

624 c29ac11d Ilias Tsitsimpis
    @_check_fabric
625 c29ac11d Ilias Tsitsimpis
    def unit_test(self):
626 c29ac11d Ilias Tsitsimpis
        """Run Synnefo unit test suite"""
627 c29ac11d Ilias Tsitsimpis
        self.logger.info("Run Synnefo unit test suite")
628 c29ac11d Ilias Tsitsimpis
        component = self.config.get('Unit Tests', 'component')
629 c29ac11d Ilias Tsitsimpis

630 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Install needed packages")
631 c29ac11d Ilias Tsitsimpis
        cmd = """
632 c29ac11d Ilias Tsitsimpis
        pip install mock
633 c29ac11d Ilias Tsitsimpis
        pip install factory_boy
634 c29ac11d Ilias Tsitsimpis
        """
635 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
636 c29ac11d Ilias Tsitsimpis

637 861b437e Ilias Tsitsimpis
        self.logger.debug("Upload tests.sh file")
638 861b437e Ilias Tsitsimpis
        unit_tests_file = os.path.join(self.ci_dir, "tests.sh")
639 6868804a Ilias Tsitsimpis
        _put(unit_tests_file, ".")
640 c29ac11d Ilias Tsitsimpis

641 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Run unit tests")
642 c29ac11d Ilias Tsitsimpis
        cmd = """
643 861b437e Ilias Tsitsimpis
        bash tests.sh {0}
644 c29ac11d Ilias Tsitsimpis
        """.format(component)
645 c29ac11d Ilias Tsitsimpis
        _run(cmd, True)
646 c29ac11d Ilias Tsitsimpis

647 c29ac11d Ilias Tsitsimpis
    @_check_fabric
648 c29ac11d Ilias Tsitsimpis
    def run_burnin(self):
649 c29ac11d Ilias Tsitsimpis
        """Run burnin functional test suite"""
650 c29ac11d Ilias Tsitsimpis
        self.logger.info("Run Burnin functional test suite")
651 c29ac11d Ilias Tsitsimpis
        cmd = """
652 c29ac11d Ilias Tsitsimpis
        auth_url=$(grep -e '^url =' .kamakirc | cut -d' ' -f3)
653 c29ac11d Ilias Tsitsimpis
        token=$(grep -e '^token =' .kamakirc | cut -d' ' -f3)
654 c29ac11d Ilias Tsitsimpis
        images_user=$(kamaki image list -l | grep owner | \
655 c29ac11d Ilias Tsitsimpis
                      cut -d':' -f2 | tr -d ' ')
656 c29ac11d Ilias Tsitsimpis
        snf-burnin --auth-url=$auth_url --token=$token \
657 c29ac11d Ilias Tsitsimpis
            --force-flavor=2 --image-id=all \
658 c29ac11d Ilias Tsitsimpis
            --system-images-user=$images_user \
659 c29ac11d Ilias Tsitsimpis
            {0}
660 c29ac11d Ilias Tsitsimpis
        log_folder=$(ls -1d /var/log/burnin/* | tail -n1)
661 c29ac11d Ilias Tsitsimpis
        for i in $(ls $log_folder/*/details*); do
662 c29ac11d Ilias Tsitsimpis
            echo -e "\\n\\n"
663 c29ac11d Ilias Tsitsimpis
            echo -e "***** $i\\n"
664 c29ac11d Ilias Tsitsimpis
            cat $i
665 c29ac11d Ilias Tsitsimpis
        done
666 c29ac11d Ilias Tsitsimpis
        """.format(self.config.get('Burnin', 'cmd_options'))
667 c29ac11d Ilias Tsitsimpis
        _run(cmd, True)
668 c29ac11d Ilias Tsitsimpis

669 c29ac11d Ilias Tsitsimpis
    @_check_fabric
670 88e6558b Christos Stavrakakis
    def fetch_compressed(self, src, dest=None):
671 e2a0abb8 Ilias Tsitsimpis
        """Create a tarball and fetch it locally"""
672 88e6558b Christos Stavrakakis
        self.logger.debug("Creating tarball of %s" % src)
673 88e6558b Christos Stavrakakis
        basename = os.path.basename(src)
674 88e6558b Christos Stavrakakis
        tar_file = basename + ".tgz"
675 88e6558b Christos Stavrakakis
        cmd = "tar czf %s %s" % (tar_file, src)
676 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
677 88e6558b Christos Stavrakakis
        if not os.path.exists(dest):
678 88e6558b Christos Stavrakakis
            os.makedirs(dest)
679 c29ac11d Ilias Tsitsimpis

680 88e6558b Christos Stavrakakis
        tmp_dir = tempfile.mkdtemp()
681 88e6558b Christos Stavrakakis
        fabric.get(tar_file, tmp_dir)
682 c29ac11d Ilias Tsitsimpis

683 88e6558b Christos Stavrakakis
        dest_file = os.path.join(tmp_dir, tar_file)
684 88e6558b Christos Stavrakakis
        self._check_hash_sum(dest_file, tar_file)
685 88e6558b Christos Stavrakakis
        self.logger.debug("Untar packages file %s" % dest_file)
686 e2dc37b2 Christos Stavrakakis
        cmd = """
687 e2dc37b2 Christos Stavrakakis
        cd %s
688 88e6558b Christos Stavrakakis
        tar xzf %s
689 88e6558b Christos Stavrakakis
        cp -r %s/* %s
690 88e6558b Christos Stavrakakis
        rm -r %s
691 88e6558b Christos Stavrakakis
        """ % (tmp_dir, tar_file, src, dest, tmp_dir)
692 e2dc37b2 Christos Stavrakakis
        os.system(cmd)
693 88e6558b Christos Stavrakakis
        self.logger.info("Downloaded %s to %s" %
694 88e6558b Christos Stavrakakis
                         (src, _green(dest)))
695 88e6558b Christos Stavrakakis

696 88e6558b Christos Stavrakakis
    @_check_fabric
697 88e6558b Christos Stavrakakis
    def fetch_packages(self, dest=None):
698 e2a0abb8 Ilias Tsitsimpis
        """Fetch Synnefo packages"""
699 88e6558b Christos Stavrakakis
        if dest is None:
700 88e6558b Christos Stavrakakis
            dest = self.config.get('Global', 'pkgs_dir')
701 88e6558b Christos Stavrakakis
        dest = os.path.abspath(dest)
702 88e6558b Christos Stavrakakis
        if not os.path.exists(dest):
703 88e6558b Christos Stavrakakis
            os.makedirs(dest)
704 88e6558b Christos Stavrakakis
        self.fetch_compressed("synnefo_build-area", dest)
705 464e58e9 Christos Stavrakakis
        self.logger.info("Downloaded debian packages to %s" %
706 88e6558b Christos Stavrakakis
                         _green(dest))