Statistics
| Branch: | Tag: | Revision:

root / ci / utils.py @ ef761fe4

History | View | Annotate | Download (37.5 kB)

1 09f7ad00 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 329705c8 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 62fcf0e5 Ilias Tsitsimpis
import filelocker
23 c29ac11d Ilias Tsitsimpis
24 7585f464 Ilias Tsitsimpis
DEFAULT_CONFIG_FILE = "ci_wheezy.conf"
25 106659f1 Ilias Tsitsimpis
# Is our terminal a colorful one?
26 106659f1 Ilias Tsitsimpis
USE_COLORS = True
27 62f3f54f Ilias Tsitsimpis
# UUID of owner of system images
28 62f3f54f Ilias Tsitsimpis
DEFAULT_SYSTEM_IMAGES_UUID = [
29 62f3f54f Ilias Tsitsimpis
    "25ecced9-bf53-4145-91ee-cf47377e9fb2",  # production (okeanos.grnet.gr)
30 62f3f54f Ilias Tsitsimpis
    "04cbe33f-29b7-4ef1-94fb-015929e5fc06",  # testing (okeanos.io)
31 905bb10b Christos Stavrakakis
]
32 6ca8f81a Christos Stavrakakis
33 c29ac11d Ilias Tsitsimpis
34 c29ac11d Ilias Tsitsimpis
def _run(cmd, verbose):
35 c29ac11d Ilias Tsitsimpis
    """Run fabric with verbose level"""
36 c29ac11d Ilias Tsitsimpis
    if verbose:
37 c29ac11d Ilias Tsitsimpis
        args = ('running',)
38 c29ac11d Ilias Tsitsimpis
    else:
39 c29ac11d Ilias Tsitsimpis
        args = ('running', 'stdout',)
40 e2a0abb8 Ilias Tsitsimpis
    with fabric.hide(*args):  # Used * or ** magic. pylint: disable-msg=W0142
41 c29ac11d Ilias Tsitsimpis
        return fabric.run(cmd)
42 c29ac11d Ilias Tsitsimpis
43 c29ac11d Ilias Tsitsimpis
44 6868804a Ilias Tsitsimpis
def _put(local, remote):
45 6868804a Ilias Tsitsimpis
    """Run fabric put command without output"""
46 6868804a Ilias Tsitsimpis
    with fabric.quiet():
47 6868804a Ilias Tsitsimpis
        fabric.put(local, remote)
48 6868804a Ilias Tsitsimpis
49 6868804a Ilias Tsitsimpis
50 c29ac11d Ilias Tsitsimpis
def _red(msg):
51 c29ac11d Ilias Tsitsimpis
    """Red color"""
52 106659f1 Ilias Tsitsimpis
    ret = "\x1b[31m" + str(msg) + "\x1b[0m" if USE_COLORS else str(msg)
53 106659f1 Ilias Tsitsimpis
    return ret
54 c29ac11d Ilias Tsitsimpis
55 c29ac11d Ilias Tsitsimpis
56 c29ac11d Ilias Tsitsimpis
def _yellow(msg):
57 c29ac11d Ilias Tsitsimpis
    """Yellow color"""
58 106659f1 Ilias Tsitsimpis
    ret = "\x1b[33m" + str(msg) + "\x1b[0m" if USE_COLORS else str(msg)
59 106659f1 Ilias Tsitsimpis
    return ret
60 c29ac11d Ilias Tsitsimpis
61 c29ac11d Ilias Tsitsimpis
62 c29ac11d Ilias Tsitsimpis
def _green(msg):
63 c29ac11d Ilias Tsitsimpis
    """Green color"""
64 106659f1 Ilias Tsitsimpis
    ret = "\x1b[32m" + str(msg) + "\x1b[0m" if USE_COLORS else str(msg)
65 106659f1 Ilias Tsitsimpis
    return ret
66 c29ac11d Ilias Tsitsimpis
67 c29ac11d Ilias Tsitsimpis
68 c29ac11d Ilias Tsitsimpis
def _check_fabric(fun):
69 c29ac11d Ilias Tsitsimpis
    """Check if fabric env has been set"""
70 43a22402 Christos Stavrakakis
    def wrapper(self, *args, **kwargs):
71 c29ac11d Ilias Tsitsimpis
        """wrapper function"""
72 c29ac11d Ilias Tsitsimpis
        if not self.fabric_installed:
73 c29ac11d Ilias Tsitsimpis
            self.setup_fabric()
74 6c3cc77e Ilias Tsitsimpis
            self.fabric_installed = True
75 43a22402 Christos Stavrakakis
        return fun(self, *args, **kwargs)
76 c29ac11d Ilias Tsitsimpis
    return wrapper
77 c29ac11d Ilias Tsitsimpis
78 c29ac11d Ilias Tsitsimpis
79 c29ac11d Ilias Tsitsimpis
def _check_kamaki(fun):
80 c29ac11d Ilias Tsitsimpis
    """Check if kamaki has been initialized"""
81 43a22402 Christos Stavrakakis
    def wrapper(self, *args, **kwargs):
82 c29ac11d Ilias Tsitsimpis
        """wrapper function"""
83 c29ac11d Ilias Tsitsimpis
        if not self.kamaki_installed:
84 c29ac11d Ilias Tsitsimpis
            self.setup_kamaki()
85 6c3cc77e Ilias Tsitsimpis
            self.kamaki_installed = True
86 43a22402 Christos Stavrakakis
        return fun(self, *args, **kwargs)
87 c29ac11d Ilias Tsitsimpis
    return wrapper
88 c29ac11d Ilias Tsitsimpis
89 c29ac11d Ilias Tsitsimpis
90 c29ac11d Ilias Tsitsimpis
class _MyFormatter(logging.Formatter):
91 c29ac11d Ilias Tsitsimpis
    """Logging Formatter"""
92 c29ac11d Ilias Tsitsimpis
    def format(self, record):
93 c29ac11d Ilias Tsitsimpis
        format_orig = self._fmt
94 c29ac11d Ilias Tsitsimpis
        if record.levelno == logging.DEBUG:
95 c29ac11d Ilias Tsitsimpis
            self._fmt = "  %(msg)s"
96 c29ac11d Ilias Tsitsimpis
        elif record.levelno == logging.INFO:
97 c29ac11d Ilias Tsitsimpis
            self._fmt = "%(msg)s"
98 c29ac11d Ilias Tsitsimpis
        elif record.levelno == logging.WARNING:
99 c29ac11d Ilias Tsitsimpis
            self._fmt = _yellow("[W] %(msg)s")
100 c29ac11d Ilias Tsitsimpis
        elif record.levelno == logging.ERROR:
101 c29ac11d Ilias Tsitsimpis
            self._fmt = _red("[E] %(msg)s")
102 c29ac11d Ilias Tsitsimpis
        result = logging.Formatter.format(self, record)
103 c29ac11d Ilias Tsitsimpis
        self._fmt = format_orig
104 c29ac11d Ilias Tsitsimpis
        return result
105 c29ac11d Ilias Tsitsimpis
106 c29ac11d Ilias Tsitsimpis
107 56ee1bbc Ilias Tsitsimpis
# Too few public methods. pylint: disable-msg=R0903
108 56ee1bbc Ilias Tsitsimpis
class _InfoFilter(logging.Filter):
109 56ee1bbc Ilias Tsitsimpis
    """Logging Filter that allows DEBUG and INFO messages only"""
110 56ee1bbc Ilias Tsitsimpis
    def filter(self, rec):
111 56ee1bbc Ilias Tsitsimpis
        """The filter"""
112 56ee1bbc Ilias Tsitsimpis
        return rec.levelno in (logging.DEBUG, logging.INFO)
113 56ee1bbc Ilias Tsitsimpis
114 56ee1bbc Ilias Tsitsimpis
115 56ee1bbc Ilias Tsitsimpis
# Too many instance attributes. pylint: disable-msg=R0902
116 c29ac11d Ilias Tsitsimpis
class SynnefoCI(object):
117 c29ac11d Ilias Tsitsimpis
    """SynnefoCI python class"""
118 c29ac11d Ilias Tsitsimpis
119 79144a72 Ilias Tsitsimpis
    def __init__(self, config_file=None, build_id=None, cloud=None):
120 c29ac11d Ilias Tsitsimpis
        """ Initialize SynnefoCI python class
121 c29ac11d Ilias Tsitsimpis

122 c29ac11d Ilias Tsitsimpis
        Setup logger, local_dir, config and kamaki
123 c29ac11d Ilias Tsitsimpis
        """
124 c29ac11d Ilias Tsitsimpis
        # Setup logger
125 c29ac11d Ilias Tsitsimpis
        self.logger = logging.getLogger('synnefo-ci')
126 c29ac11d Ilias Tsitsimpis
        self.logger.setLevel(logging.DEBUG)
127 56ee1bbc Ilias Tsitsimpis
128 56ee1bbc Ilias Tsitsimpis
        handler1 = logging.StreamHandler(sys.stdout)
129 56ee1bbc Ilias Tsitsimpis
        handler1.setLevel(logging.DEBUG)
130 56ee1bbc Ilias Tsitsimpis
        handler1.addFilter(_InfoFilter())
131 56ee1bbc Ilias Tsitsimpis
        handler1.setFormatter(_MyFormatter())
132 56ee1bbc Ilias Tsitsimpis
        handler2 = logging.StreamHandler(sys.stderr)
133 56ee1bbc Ilias Tsitsimpis
        handler2.setLevel(logging.WARNING)
134 56ee1bbc Ilias Tsitsimpis
        handler2.setFormatter(_MyFormatter())
135 56ee1bbc Ilias Tsitsimpis
136 56ee1bbc Ilias Tsitsimpis
        self.logger.addHandler(handler1)
137 56ee1bbc Ilias Tsitsimpis
        self.logger.addHandler(handler2)
138 c29ac11d Ilias Tsitsimpis
139 c29ac11d Ilias Tsitsimpis
        # Get our local dir
140 c29ac11d Ilias Tsitsimpis
        self.ci_dir = os.path.dirname(os.path.abspath(__file__))
141 c29ac11d Ilias Tsitsimpis
        self.repo_dir = os.path.dirname(self.ci_dir)
142 c29ac11d Ilias Tsitsimpis
143 c29ac11d Ilias Tsitsimpis
        # Read config file
144 6ca8f81a Christos Stavrakakis
        if config_file is None:
145 2c4a641b Ilias Tsitsimpis
            config_file = os.path.join(self.ci_dir, DEFAULT_CONFIG_FILE)
146 2c4a641b Ilias Tsitsimpis
        config_file = os.path.abspath(config_file)
147 c29ac11d Ilias Tsitsimpis
        self.config = ConfigParser()
148 c29ac11d Ilias Tsitsimpis
        self.config.optionxform = str
149 6ca8f81a Christos Stavrakakis
        self.config.read(config_file)
150 79144a72 Ilias Tsitsimpis
151 79144a72 Ilias Tsitsimpis
        # Read temporary_config file
152 62fcf0e5 Ilias Tsitsimpis
        self.temp_config_file = \
153 62fcf0e5 Ilias Tsitsimpis
            os.path.expanduser(self.config.get('Global', 'temporary_config'))
154 79144a72 Ilias Tsitsimpis
        self.temp_config = ConfigParser()
155 79144a72 Ilias Tsitsimpis
        self.temp_config.optionxform = str
156 62fcf0e5 Ilias Tsitsimpis
        self.temp_config.read(self.temp_config_file)
157 b7496c88 Ilias Tsitsimpis
        self.build_id = build_id
158 99d39120 Ilias Tsitsimpis
        if build_id is not None:
159 99d39120 Ilias Tsitsimpis
            self.logger.info("Will use \"%s\" as build id" %
160 99d39120 Ilias Tsitsimpis
                             _green(self.build_id))
161 c29ac11d Ilias Tsitsimpis
162 c1b1d444 Christos Stavrakakis
        # Set kamaki cloud
163 c1b1d444 Christos Stavrakakis
        if cloud is not None:
164 c1b1d444 Christos Stavrakakis
            self.kamaki_cloud = cloud
165 c1b1d444 Christos Stavrakakis
        elif self.config.has_option("Deployment", "kamaki_cloud"):
166 c1b1d444 Christos Stavrakakis
            kamaki_cloud = self.config.get("Deployment", "kamaki_cloud")
167 c1b1d444 Christos Stavrakakis
            if kamaki_cloud == "":
168 c1b1d444 Christos Stavrakakis
                self.kamaki_cloud = None
169 c1b1d444 Christos Stavrakakis
        else:
170 c1b1d444 Christos Stavrakakis
            self.kamaki_cloud = None
171 c1b1d444 Christos Stavrakakis
172 c29ac11d Ilias Tsitsimpis
        # Initialize variables
173 c29ac11d Ilias Tsitsimpis
        self.fabric_installed = False
174 c29ac11d Ilias Tsitsimpis
        self.kamaki_installed = False
175 c29ac11d Ilias Tsitsimpis
        self.cyclades_client = None
176 ad21ffa9 Ilias Tsitsimpis
        self.compute_client = None
177 c29ac11d Ilias Tsitsimpis
        self.image_client = None
178 694c79bb Ilias Tsitsimpis
        self.astakos_client = None
179 c29ac11d Ilias Tsitsimpis
180 c29ac11d Ilias Tsitsimpis
    def setup_kamaki(self):
181 c29ac11d Ilias Tsitsimpis
        """Initialize kamaki
182 c29ac11d Ilias Tsitsimpis

183 ad21ffa9 Ilias Tsitsimpis
        Setup cyclades_client, image_client and compute_client
184 c29ac11d Ilias Tsitsimpis
        """
185 c1b1d444 Christos Stavrakakis
186 c1b1d444 Christos Stavrakakis
        config = kamaki_config.Config()
187 c1b1d444 Christos Stavrakakis
        if self.kamaki_cloud is None:
188 84d2db4f Ilias Tsitsimpis
            try:
189 84d2db4f Ilias Tsitsimpis
                self.kamaki_cloud = config.get("global", "default_cloud")
190 84d2db4f Ilias Tsitsimpis
            except AttributeError:
191 84d2db4f Ilias Tsitsimpis
                # Compatibility with kamaki version <=0.10
192 84d2db4f Ilias Tsitsimpis
                self.kamaki_cloud = config.get_global("default_cloud")
193 c1b1d444 Christos Stavrakakis
194 c1b1d444 Christos Stavrakakis
        self.logger.info("Setup kamaki client, using cloud '%s'.." %
195 c1b1d444 Christos Stavrakakis
                         self.kamaki_cloud)
196 c1b1d444 Christos Stavrakakis
        auth_url = config.get_cloud(self.kamaki_cloud, "url")
197 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Authentication URL is %s" % _green(auth_url))
198 c1b1d444 Christos Stavrakakis
        token = config.get_cloud(self.kamaki_cloud, "token")
199 c29ac11d Ilias Tsitsimpis
        #self.logger.debug("Token is %s" % _green(token))
200 c29ac11d Ilias Tsitsimpis
201 905bb10b Christos Stavrakakis
        self.astakos_client = AstakosClient(auth_url, token)
202 c29ac11d Ilias Tsitsimpis
203 c29ac11d Ilias Tsitsimpis
        cyclades_url = \
204 905bb10b Christos Stavrakakis
            self.astakos_client.get_service_endpoints('compute')['publicURL']
205 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Cyclades API url is %s" % _green(cyclades_url))
206 c29ac11d Ilias Tsitsimpis
        self.cyclades_client = CycladesClient(cyclades_url, token)
207 c29ac11d Ilias Tsitsimpis
        self.cyclades_client.CONNECTION_RETRY_LIMIT = 2
208 c29ac11d Ilias Tsitsimpis
209 c29ac11d Ilias Tsitsimpis
        image_url = \
210 905bb10b Christos Stavrakakis
            self.astakos_client.get_service_endpoints('image')['publicURL']
211 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Images API url is %s" % _green(image_url))
212 c29ac11d Ilias Tsitsimpis
        self.image_client = ImageClient(cyclades_url, token)
213 c29ac11d Ilias Tsitsimpis
        self.image_client.CONNECTION_RETRY_LIMIT = 2
214 c29ac11d Ilias Tsitsimpis
215 ad21ffa9 Ilias Tsitsimpis
        compute_url = \
216 905bb10b Christos Stavrakakis
            self.astakos_client.get_service_endpoints('compute')['publicURL']
217 ad21ffa9 Ilias Tsitsimpis
        self.logger.debug("Compute API url is %s" % _green(compute_url))
218 ad21ffa9 Ilias Tsitsimpis
        self.compute_client = ComputeClient(compute_url, token)
219 ad21ffa9 Ilias Tsitsimpis
        self.compute_client.CONNECTION_RETRY_LIMIT = 2
220 ad21ffa9 Ilias Tsitsimpis
221 c29ac11d Ilias Tsitsimpis
    def _wait_transition(self, server_id, current_status, new_status):
222 c29ac11d Ilias Tsitsimpis
        """Wait for server to go from current_status to new_status"""
223 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Waiting for server to become %s" % new_status)
224 c29ac11d Ilias Tsitsimpis
        timeout = self.config.getint('Global', 'build_timeout')
225 c29ac11d Ilias Tsitsimpis
        sleep_time = 5
226 c29ac11d Ilias Tsitsimpis
        while True:
227 c29ac11d Ilias Tsitsimpis
            server = self.cyclades_client.get_server_details(server_id)
228 c29ac11d Ilias Tsitsimpis
            if server['status'] == new_status:
229 c29ac11d Ilias Tsitsimpis
                return server
230 c29ac11d Ilias Tsitsimpis
            elif timeout < 0:
231 c29ac11d Ilias Tsitsimpis
                self.logger.error(
232 c29ac11d Ilias Tsitsimpis
                    "Waiting for server to become %s timed out" % new_status)
233 c29ac11d Ilias Tsitsimpis
                self.destroy_server(False)
234 99d39120 Ilias Tsitsimpis
                sys.exit(1)
235 c29ac11d Ilias Tsitsimpis
            elif server['status'] == current_status:
236 c29ac11d Ilias Tsitsimpis
                # Sleep for #n secs and continue
237 c29ac11d Ilias Tsitsimpis
                timeout = timeout - sleep_time
238 c29ac11d Ilias Tsitsimpis
                time.sleep(sleep_time)
239 c29ac11d Ilias Tsitsimpis
            else:
240 c29ac11d Ilias Tsitsimpis
                self.logger.error(
241 c29ac11d Ilias Tsitsimpis
                    "Server failed with status %s" % server['status'])
242 c29ac11d Ilias Tsitsimpis
                self.destroy_server(False)
243 99d39120 Ilias Tsitsimpis
                sys.exit(1)
244 c29ac11d Ilias Tsitsimpis
245 c29ac11d Ilias Tsitsimpis
    @_check_kamaki
246 c29ac11d Ilias Tsitsimpis
    def destroy_server(self, wait=True):
247 c29ac11d Ilias Tsitsimpis
        """Destroy slave server"""
248 b7496c88 Ilias Tsitsimpis
        server_id = int(self.read_temp_config('server_id'))
249 c29ac11d Ilias Tsitsimpis
        self.logger.info("Destoying server with id %s " % server_id)
250 c29ac11d Ilias Tsitsimpis
        self.cyclades_client.delete_server(server_id)
251 c29ac11d Ilias Tsitsimpis
        if wait:
252 c29ac11d Ilias Tsitsimpis
            self._wait_transition(server_id, "ACTIVE", "DELETED")
253 c29ac11d Ilias Tsitsimpis
254 c29ac11d Ilias Tsitsimpis
    @_check_kamaki
255 2945e7ed Christos Stavrakakis
    def create_server(self, image=None, flavor=None, ssh_keys=None,
256 2945e7ed Christos Stavrakakis
                      server_name=None):
257 c29ac11d Ilias Tsitsimpis
        """Create slave server"""
258 c29ac11d Ilias Tsitsimpis
        self.logger.info("Create a new server..")
259 b7496c88 Ilias Tsitsimpis
260 b7496c88 Ilias Tsitsimpis
        # Find a build_id to use
261 c7828946 Ilias Tsitsimpis
        self._create_new_build_id()
262 b7496c88 Ilias Tsitsimpis
263 b7496c88 Ilias Tsitsimpis
        # Find an image to use
264 358a19bc Ilias Tsitsimpis
        image_id = self._find_image(image)
265 b7496c88 Ilias Tsitsimpis
        # Find a flavor to use
266 358a19bc Ilias Tsitsimpis
        flavor_id = self._find_flavor(flavor)
267 358a19bc Ilias Tsitsimpis
268 358a19bc Ilias Tsitsimpis
        # Create Server
269 2945e7ed Christos Stavrakakis
        if server_name is None:
270 2945e7ed Christos Stavrakakis
            server_name = self.config.get("Deployment", "server_name")
271 2945e7ed Christos Stavrakakis
            server_name = "%s(BID: %s)" % (server_name, self.build_id)
272 2945e7ed Christos Stavrakakis
        server = self.cyclades_client.create_server(server_name, flavor_id,
273 2945e7ed Christos Stavrakakis
                                                    image_id)
274 c29ac11d Ilias Tsitsimpis
        server_id = server['id']
275 b7496c88 Ilias Tsitsimpis
        self.write_temp_config('server_id', server_id)
276 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Server got id %s" % _green(server_id))
277 c29ac11d Ilias Tsitsimpis
        server_user = server['metadata']['users']
278 b7496c88 Ilias Tsitsimpis
        self.write_temp_config('server_user', server_user)
279 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Server's admin user is %s" % _green(server_user))
280 c29ac11d Ilias Tsitsimpis
        server_passwd = server['adminPass']
281 b7496c88 Ilias Tsitsimpis
        self.write_temp_config('server_passwd', server_passwd)
282 c29ac11d Ilias Tsitsimpis
283 c29ac11d Ilias Tsitsimpis
        server = self._wait_transition(server_id, "BUILD", "ACTIVE")
284 c29ac11d Ilias Tsitsimpis
        self._get_server_ip_and_port(server)
285 6868804a Ilias Tsitsimpis
        self._copy_ssh_keys(ssh_keys)
286 c29ac11d Ilias Tsitsimpis
287 6c3cc77e Ilias Tsitsimpis
        # Setup Firewall
288 c29ac11d Ilias Tsitsimpis
        self.setup_fabric()
289 c29ac11d Ilias Tsitsimpis
        self.logger.info("Setup firewall")
290 6868804a Ilias Tsitsimpis
        accept_ssh_from = self.config.get('Global', 'accept_ssh_from')
291 1c75c4dd Christos Stavrakakis
        if accept_ssh_from != "":
292 1c75c4dd Christos Stavrakakis
            self.logger.debug("Block ssh except from %s" % accept_ssh_from)
293 1c75c4dd Christos Stavrakakis
            cmd = """
294 1c75c4dd Christos Stavrakakis
            local_ip=$(/sbin/ifconfig eth0 | grep 'inet addr:' | \
295 1c75c4dd Christos Stavrakakis
                cut -d':' -f2 | cut -d' ' -f1)
296 1c75c4dd Christos Stavrakakis
            iptables -A INPUT -s localhost -j ACCEPT
297 1c75c4dd Christos Stavrakakis
            iptables -A INPUT -s $local_ip -j ACCEPT
298 1c75c4dd Christos Stavrakakis
            iptables -A INPUT -s {0} -p tcp --dport 22 -j ACCEPT
299 1c75c4dd Christos Stavrakakis
            iptables -A INPUT -p tcp --dport 22 -j DROP
300 1c75c4dd Christos Stavrakakis
            """.format(accept_ssh_from)
301 1c75c4dd Christos Stavrakakis
            _run(cmd, False)
302 c29ac11d Ilias Tsitsimpis
303 6c3cc77e Ilias Tsitsimpis
        # Setup apt, download packages
304 6c3cc77e Ilias Tsitsimpis
        self.logger.debug("Setup apt. Install x2goserver and firefox")
305 6c3cc77e Ilias Tsitsimpis
        cmd = """
306 6c3cc77e Ilias Tsitsimpis
        echo 'APT::Install-Suggests "false";' >> /etc/apt/apt.conf
307 a7d32e21 Ilias Tsitsimpis
        echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf
308 6c3cc77e Ilias Tsitsimpis
        apt-get update
309 71f2649f Ilias Tsitsimpis
        apt-get install curl --yes --force-yes
310 6c3cc77e Ilias Tsitsimpis
        echo -e "\n\n{0}" >> /etc/apt/sources.list
311 6c3cc77e Ilias Tsitsimpis
        # Synnefo repo's key
312 6c3cc77e Ilias Tsitsimpis
        curl https://dev.grnet.gr/files/apt-grnetdev.pub | apt-key add -
313 8ddb541b Ilias Tsitsimpis

314 6c3cc77e Ilias Tsitsimpis
        # X2GO Key
315 6c3cc77e Ilias Tsitsimpis
        apt-key adv --recv-keys --keyserver keys.gnupg.net E1F958385BFE2B6E
316 71f2649f Ilias Tsitsimpis
        apt-get install x2go-keyring --yes --force-yes
317 6c3cc77e Ilias Tsitsimpis
        apt-get update
318 71f2649f Ilias Tsitsimpis
        apt-get install x2goserver x2goserver-xsession \
319 71f2649f Ilias Tsitsimpis
                iceweasel --yes --force-yes
320 8ddb541b Ilias Tsitsimpis

321 8ddb541b Ilias Tsitsimpis
        # xterm published application
322 8ddb541b Ilias Tsitsimpis
        echo '[Desktop Entry]' > /usr/share/applications/xterm.desktop
323 8ddb541b Ilias Tsitsimpis
        echo 'Name=XTerm' >> /usr/share/applications/xterm.desktop
324 8ddb541b Ilias Tsitsimpis
        echo 'Comment=standard terminal emulator for the X window system' >> \
325 8ddb541b Ilias Tsitsimpis
            /usr/share/applications/xterm.desktop
326 8ddb541b Ilias Tsitsimpis
        echo 'Exec=xterm' >> /usr/share/applications/xterm.desktop
327 8ddb541b Ilias Tsitsimpis
        echo 'Terminal=false' >> /usr/share/applications/xterm.desktop
328 8ddb541b Ilias Tsitsimpis
        echo 'Type=Application' >> /usr/share/applications/xterm.desktop
329 8ddb541b Ilias Tsitsimpis
        echo 'Encoding=UTF-8' >> /usr/share/applications/xterm.desktop
330 8ddb541b Ilias Tsitsimpis
        echo 'Icon=xterm-color_48x48' >> /usr/share/applications/xterm.desktop
331 8ddb541b Ilias Tsitsimpis
        echo 'Categories=System;TerminalEmulator;' >> \
332 8ddb541b Ilias Tsitsimpis
                /usr/share/applications/xterm.desktop
333 6c3cc77e Ilias Tsitsimpis
        """.format(self.config.get('Global', 'apt_repo'))
334 6c3cc77e Ilias Tsitsimpis
        _run(cmd, False)
335 6c3cc77e Ilias Tsitsimpis
336 358a19bc Ilias Tsitsimpis
    def _find_flavor(self, flavor=None):
337 358a19bc Ilias Tsitsimpis
        """Find a suitable flavor to use
338 358a19bc Ilias Tsitsimpis

339 358a19bc Ilias Tsitsimpis
        Search by name (reg expression) or by id
340 358a19bc Ilias Tsitsimpis
        """
341 358a19bc Ilias Tsitsimpis
        # Get a list of flavors from config file
342 358a19bc Ilias Tsitsimpis
        flavors = self.config.get('Deployment', 'flavors').split(",")
343 358a19bc Ilias Tsitsimpis
        if flavor is not None:
344 a8bfeffc Ilias Tsitsimpis
            # If we have a flavor_name to use, add it to our list
345 358a19bc Ilias Tsitsimpis
            flavors.insert(0, flavor)
346 358a19bc Ilias Tsitsimpis
347 358a19bc Ilias Tsitsimpis
        list_flavors = self.compute_client.list_flavors()
348 358a19bc Ilias Tsitsimpis
        for flv in flavors:
349 905bb10b Christos Stavrakakis
            flv_type, flv_value = parse_typed_option(option="flavor",
350 905bb10b Christos Stavrakakis
                                                     value=flv)
351 358a19bc Ilias Tsitsimpis
            if flv_type == "name":
352 358a19bc Ilias Tsitsimpis
                # Filter flavors by name
353 358a19bc Ilias Tsitsimpis
                self.logger.debug(
354 358a19bc Ilias Tsitsimpis
                    "Trying to find a flavor with name \"%s\"" % flv_value)
355 358a19bc Ilias Tsitsimpis
                list_flvs = \
356 358a19bc Ilias Tsitsimpis
                    [f for f in list_flavors
357 905bb10b Christos Stavrakakis
                     if re.search(flv_value, f['name'], flags=re.I)
358 905bb10b Christos Stavrakakis
                     is not None]
359 358a19bc Ilias Tsitsimpis
            elif flv_type == "id":
360 358a19bc Ilias Tsitsimpis
                # Filter flavors by id
361 358a19bc Ilias Tsitsimpis
                self.logger.debug(
362 358a19bc Ilias Tsitsimpis
                    "Trying to find a flavor with id \"%s\"" % flv_value)
363 358a19bc Ilias Tsitsimpis
                list_flvs = \
364 358a19bc Ilias Tsitsimpis
                    [f for f in list_flavors
365 694c79bb Ilias Tsitsimpis
                     if str(f['id']) == flv_value]
366 358a19bc Ilias Tsitsimpis
            else:
367 358a19bc Ilias Tsitsimpis
                self.logger.error("Unrecognized flavor type %s" % flv_type)
368 358a19bc Ilias Tsitsimpis
369 358a19bc Ilias Tsitsimpis
            # Check if we found one
370 358a19bc Ilias Tsitsimpis
            if list_flvs:
371 358a19bc Ilias Tsitsimpis
                self.logger.debug("Will use \"%s\" with id \"%s\""
372 106659f1 Ilias Tsitsimpis
                                  % (_green(list_flvs[0]['name']),
373 106659f1 Ilias Tsitsimpis
                                     _green(list_flvs[0]['id'])))
374 358a19bc Ilias Tsitsimpis
                return list_flvs[0]['id']
375 a8bfeffc Ilias Tsitsimpis
376 a8bfeffc Ilias Tsitsimpis
        self.logger.error("No matching flavor found.. aborting")
377 a8bfeffc Ilias Tsitsimpis
        sys.exit(1)
378 ad21ffa9 Ilias Tsitsimpis
379 358a19bc Ilias Tsitsimpis
    def _find_image(self, image=None):
380 c29ac11d Ilias Tsitsimpis
        """Find a suitable image to use
381 c29ac11d Ilias Tsitsimpis

382 358a19bc Ilias Tsitsimpis
        In case of search by name, the image has to belong to one
383 358a19bc Ilias Tsitsimpis
        of the `DEFAULT_SYSTEM_IMAGES_UUID' users.
384 358a19bc Ilias Tsitsimpis
        In case of search by id it only has to exist.
385 c29ac11d Ilias Tsitsimpis
        """
386 358a19bc Ilias Tsitsimpis
        # Get a list of images from config file
387 358a19bc Ilias Tsitsimpis
        images = self.config.get('Deployment', 'images').split(",")
388 358a19bc Ilias Tsitsimpis
        if image is not None:
389 358a19bc Ilias Tsitsimpis
            # If we have an image from command line, add it to our list
390 358a19bc Ilias Tsitsimpis
            images.insert(0, image)
391 358a19bc Ilias Tsitsimpis
392 905bb10b Christos Stavrakakis
        auth = self.astakos_client.authenticate()
393 905bb10b Christos Stavrakakis
        user_uuid = auth["access"]["token"]["tenant"]["id"]
394 358a19bc Ilias Tsitsimpis
        list_images = self.image_client.list_public(detail=True)['images']
395 358a19bc Ilias Tsitsimpis
        for img in images:
396 6958ffc6 Christos Stavrakakis
            img_type, img_value = parse_typed_option(option="image", value=img)
397 358a19bc Ilias Tsitsimpis
            if img_type == "name":
398 358a19bc Ilias Tsitsimpis
                # Filter images by name
399 358a19bc Ilias Tsitsimpis
                self.logger.debug(
400 358a19bc Ilias Tsitsimpis
                    "Trying to find an image with name \"%s\"" % img_value)
401 905bb10b Christos Stavrakakis
                accepted_uuids = DEFAULT_SYSTEM_IMAGES_UUID + [user_uuid]
402 358a19bc Ilias Tsitsimpis
                list_imgs = \
403 905bb10b Christos Stavrakakis
                    [i for i in list_images if i['user_id'] in accepted_uuids
404 905bb10b Christos Stavrakakis
                     and
405 905bb10b Christos Stavrakakis
                     re.search(img_value, i['name'], flags=re.I) is not None]
406 358a19bc Ilias Tsitsimpis
            elif img_type == "id":
407 358a19bc Ilias Tsitsimpis
                # Filter images by id
408 358a19bc Ilias Tsitsimpis
                self.logger.debug(
409 358a19bc Ilias Tsitsimpis
                    "Trying to find an image with id \"%s\"" % img_value)
410 358a19bc Ilias Tsitsimpis
                list_imgs = \
411 358a19bc Ilias Tsitsimpis
                    [i for i in list_images
412 358a19bc Ilias Tsitsimpis
                     if i['id'].lower() == img_value.lower()]
413 358a19bc Ilias Tsitsimpis
            else:
414 358a19bc Ilias Tsitsimpis
                self.logger.error("Unrecognized image type %s" % img_type)
415 358a19bc Ilias Tsitsimpis
                sys.exit(1)
416 358a19bc Ilias Tsitsimpis
417 358a19bc Ilias Tsitsimpis
            # Check if we found one
418 358a19bc Ilias Tsitsimpis
            if list_imgs:
419 358a19bc Ilias Tsitsimpis
                self.logger.debug("Will use \"%s\" with id \"%s\""
420 106659f1 Ilias Tsitsimpis
                                  % (_green(list_imgs[0]['name']),
421 106659f1 Ilias Tsitsimpis
                                     _green(list_imgs[0]['id'])))
422 358a19bc Ilias Tsitsimpis
                return list_imgs[0]['id']
423 358a19bc Ilias Tsitsimpis
424 358a19bc Ilias Tsitsimpis
        # We didn't found one
425 358a19bc Ilias Tsitsimpis
        self.logger.error("No matching image found.. aborting")
426 358a19bc Ilias Tsitsimpis
        sys.exit(1)
427 c29ac11d Ilias Tsitsimpis
428 c29ac11d Ilias Tsitsimpis
    def _get_server_ip_and_port(self, server):
429 c29ac11d Ilias Tsitsimpis
        """Compute server's IPv4 and ssh port number"""
430 c29ac11d Ilias Tsitsimpis
        self.logger.info("Get server connection details..")
431 c29ac11d Ilias Tsitsimpis
        server_ip = server['attachments'][0]['ipv4']
432 705f70a9 Christos Stavrakakis
        if (".okeanos.io" in self.cyclades_client.base_url or
433 705f70a9 Christos Stavrakakis
           ".demo.synnefo.org" in self.cyclades_client.base_url):
434 c29ac11d Ilias Tsitsimpis
            tmp1 = int(server_ip.split(".")[2])
435 c29ac11d Ilias Tsitsimpis
            tmp2 = int(server_ip.split(".")[3])
436 c29ac11d Ilias Tsitsimpis
            server_ip = "gate.okeanos.io"
437 c29ac11d Ilias Tsitsimpis
            server_port = 10000 + tmp1 * 256 + tmp2
438 c29ac11d Ilias Tsitsimpis
        else:
439 c29ac11d Ilias Tsitsimpis
            server_port = 22
440 b7496c88 Ilias Tsitsimpis
        self.write_temp_config('server_ip', server_ip)
441 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Server's IPv4 is %s" % _green(server_ip))
442 b7496c88 Ilias Tsitsimpis
        self.write_temp_config('server_port', server_port)
443 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Server's ssh port is %s" % _green(server_port))
444 106659f1 Ilias Tsitsimpis
        ssh_command = "ssh -p %s %s@%s" \
445 106659f1 Ilias Tsitsimpis
            % (server_port, server['metadata']['users'], server_ip)
446 106659f1 Ilias Tsitsimpis
        self.logger.debug("Access server using \"%s\"" %
447 106659f1 Ilias Tsitsimpis
                          (_green(ssh_command)))
448 c29ac11d Ilias Tsitsimpis
449 e480f0ce Christos Stavrakakis
    @_check_fabric
450 6868804a Ilias Tsitsimpis
    def _copy_ssh_keys(self, ssh_keys):
451 e2a0abb8 Ilias Tsitsimpis
        """Upload/Install ssh keys to server"""
452 4b743650 Ilias Tsitsimpis
        self.logger.debug("Check for authentication keys to use")
453 6868804a Ilias Tsitsimpis
        if ssh_keys is None:
454 6868804a Ilias Tsitsimpis
            ssh_keys = self.config.get("Deployment", "ssh_keys")
455 6868804a Ilias Tsitsimpis
456 4b743650 Ilias Tsitsimpis
        if ssh_keys != "":
457 6058ae72 Ilias Tsitsimpis
            ssh_keys = os.path.expanduser(ssh_keys)
458 106659f1 Ilias Tsitsimpis
            self.logger.debug("Will use \"%s\" authentication keys file" %
459 106659f1 Ilias Tsitsimpis
                              _green(ssh_keys))
460 e480f0ce Christos Stavrakakis
            keyfile = '/tmp/%s.pub' % fabric.env.user
461 e480f0ce Christos Stavrakakis
            _run('mkdir -p ~/.ssh && chmod 700 ~/.ssh', False)
462 4b743650 Ilias Tsitsimpis
            if ssh_keys.startswith("http://") or \
463 4b743650 Ilias Tsitsimpis
                    ssh_keys.startswith("https://") or \
464 4b743650 Ilias Tsitsimpis
                    ssh_keys.startswith("ftp://"):
465 4b743650 Ilias Tsitsimpis
                cmd = """
466 4b743650 Ilias Tsitsimpis
                apt-get update
467 71f2649f Ilias Tsitsimpis
                apt-get install wget --yes --force-yes
468 4b743650 Ilias Tsitsimpis
                wget {0} -O {1} --no-check-certificate
469 4b743650 Ilias Tsitsimpis
                """.format(ssh_keys, keyfile)
470 4b743650 Ilias Tsitsimpis
                _run(cmd, False)
471 4b743650 Ilias Tsitsimpis
            elif os.path.exists(ssh_keys):
472 4b743650 Ilias Tsitsimpis
                _put(ssh_keys, keyfile)
473 4b743650 Ilias Tsitsimpis
            else:
474 4b743650 Ilias Tsitsimpis
                self.logger.debug("No ssh keys found")
475 6058ae72 Ilias Tsitsimpis
                return
476 e480f0ce Christos Stavrakakis
            _run('cat %s >> ~/.ssh/authorized_keys' % keyfile, False)
477 e480f0ce Christos Stavrakakis
            _run('rm %s' % keyfile, False)
478 e480f0ce Christos Stavrakakis
            self.logger.debug("Uploaded ssh authorized keys")
479 e480f0ce Christos Stavrakakis
        else:
480 e480f0ce Christos Stavrakakis
            self.logger.debug("No ssh keys found")
481 e480f0ce Christos Stavrakakis
482 2cbdb63f Ilias Tsitsimpis
    def _create_new_build_id(self):
483 2cbdb63f Ilias Tsitsimpis
        """Find a uniq build_id to use"""
484 2cbdb63f Ilias Tsitsimpis
        with filelocker.lock("%s.lock" % self.temp_config_file,
485 2cbdb63f Ilias Tsitsimpis
                             filelocker.LOCK_EX):
486 2cbdb63f Ilias Tsitsimpis
            # Read temp_config again to get any new entries
487 2cbdb63f Ilias Tsitsimpis
            self.temp_config.read(self.temp_config_file)
488 2cbdb63f Ilias Tsitsimpis
489 2cbdb63f Ilias Tsitsimpis
            # Find a uniq build_id to use
490 c7828946 Ilias Tsitsimpis
            if self.build_id is None:
491 c7828946 Ilias Tsitsimpis
                ids = self.temp_config.sections()
492 c7828946 Ilias Tsitsimpis
                if ids:
493 c7828946 Ilias Tsitsimpis
                    max_id = int(max(self.temp_config.sections(), key=int))
494 c7828946 Ilias Tsitsimpis
                    self.build_id = max_id + 1
495 c7828946 Ilias Tsitsimpis
                else:
496 c7828946 Ilias Tsitsimpis
                    self.build_id = 1
497 c7828946 Ilias Tsitsimpis
            self.logger.debug("Will use \"%s\" as build id"
498 2cbdb63f Ilias Tsitsimpis
                              % _green(self.build_id))
499 2cbdb63f Ilias Tsitsimpis
500 2cbdb63f Ilias Tsitsimpis
            # Create a new section
501 329705c8 Ilias Tsitsimpis
            try:
502 329705c8 Ilias Tsitsimpis
                self.temp_config.add_section(str(self.build_id))
503 329705c8 Ilias Tsitsimpis
            except DuplicateSectionError:
504 329705c8 Ilias Tsitsimpis
                msg = ("Build id \"%s\" already in use. " +
505 329705c8 Ilias Tsitsimpis
                       "Please use a uniq one or cleanup \"%s\" file.\n") \
506 329705c8 Ilias Tsitsimpis
                    % (self.build_id, self.temp_config_file)
507 329705c8 Ilias Tsitsimpis
                self.logger.error(msg)
508 329705c8 Ilias Tsitsimpis
                sys.exit(1)
509 2cbdb63f Ilias Tsitsimpis
            creation_time = \
510 2cbdb63f Ilias Tsitsimpis
                time.strftime("%a, %d %b %Y %X", time.localtime())
511 2cbdb63f Ilias Tsitsimpis
            self.temp_config.set(str(self.build_id),
512 2cbdb63f Ilias Tsitsimpis
                                 "created", str(creation_time))
513 2cbdb63f Ilias Tsitsimpis
514 2cbdb63f Ilias Tsitsimpis
            # Write changes back to temp config file
515 2cbdb63f Ilias Tsitsimpis
            with open(self.temp_config_file, 'wb') as tcf:
516 2cbdb63f Ilias Tsitsimpis
                self.temp_config.write(tcf)
517 2cbdb63f Ilias Tsitsimpis
518 b7496c88 Ilias Tsitsimpis
    def write_temp_config(self, option, value):
519 c29ac11d Ilias Tsitsimpis
        """Write changes back to config file"""
520 62fcf0e5 Ilias Tsitsimpis
        # Acquire the lock to write to temp_config_file
521 62fcf0e5 Ilias Tsitsimpis
        with filelocker.lock("%s.lock" % self.temp_config_file,
522 62fcf0e5 Ilias Tsitsimpis
                             filelocker.LOCK_EX):
523 62fcf0e5 Ilias Tsitsimpis
524 62fcf0e5 Ilias Tsitsimpis
            # Read temp_config again to get any new entries
525 62fcf0e5 Ilias Tsitsimpis
            self.temp_config.read(self.temp_config_file)
526 62fcf0e5 Ilias Tsitsimpis
527 62fcf0e5 Ilias Tsitsimpis
            self.temp_config.set(str(self.build_id), option, str(value))
528 62fcf0e5 Ilias Tsitsimpis
            curr_time = time.strftime("%a, %d %b %Y %X", time.localtime())
529 62fcf0e5 Ilias Tsitsimpis
            self.temp_config.set(str(self.build_id), "modified", curr_time)
530 2cbdb63f Ilias Tsitsimpis
531 2cbdb63f Ilias Tsitsimpis
            # Write changes back to temp config file
532 62fcf0e5 Ilias Tsitsimpis
            with open(self.temp_config_file, 'wb') as tcf:
533 62fcf0e5 Ilias Tsitsimpis
                self.temp_config.write(tcf)
534 c29ac11d Ilias Tsitsimpis
535 b7496c88 Ilias Tsitsimpis
    def read_temp_config(self, option):
536 b7496c88 Ilias Tsitsimpis
        """Read from temporary_config file"""
537 b7496c88 Ilias Tsitsimpis
        # If build_id is None use the latest one
538 b7496c88 Ilias Tsitsimpis
        if self.build_id is None:
539 b7496c88 Ilias Tsitsimpis
            ids = self.temp_config.sections()
540 b7496c88 Ilias Tsitsimpis
            if ids:
541 b7496c88 Ilias Tsitsimpis
                self.build_id = int(ids[-1])
542 b7496c88 Ilias Tsitsimpis
            else:
543 b7496c88 Ilias Tsitsimpis
                self.logger.error("No sections in temporary config file")
544 b7496c88 Ilias Tsitsimpis
                sys.exit(1)
545 b7496c88 Ilias Tsitsimpis
            self.logger.debug("Will use \"%s\" as build id"
546 b7496c88 Ilias Tsitsimpis
                              % _green(self.build_id))
547 b7496c88 Ilias Tsitsimpis
        # Read specified option
548 b7496c88 Ilias Tsitsimpis
        return self.temp_config.get(str(self.build_id), option)
549 b7496c88 Ilias Tsitsimpis
550 c29ac11d Ilias Tsitsimpis
    def setup_fabric(self):
551 c29ac11d Ilias Tsitsimpis
        """Setup fabric environment"""
552 c29ac11d Ilias Tsitsimpis
        self.logger.info("Setup fabric parameters..")
553 b7496c88 Ilias Tsitsimpis
        fabric.env.user = self.read_temp_config('server_user')
554 b7496c88 Ilias Tsitsimpis
        fabric.env.host_string = self.read_temp_config('server_ip')
555 b7496c88 Ilias Tsitsimpis
        fabric.env.port = int(self.read_temp_config('server_port'))
556 b7496c88 Ilias Tsitsimpis
        fabric.env.password = self.read_temp_config('server_passwd')
557 c29ac11d Ilias Tsitsimpis
        fabric.env.connection_attempts = 10
558 c29ac11d Ilias Tsitsimpis
        fabric.env.shell = "/bin/bash -c"
559 c29ac11d Ilias Tsitsimpis
        fabric.env.disable_known_hosts = True
560 c29ac11d Ilias Tsitsimpis
        fabric.env.output_prefix = None
561 c29ac11d Ilias Tsitsimpis
562 c29ac11d Ilias Tsitsimpis
    def _check_hash_sum(self, localfile, remotefile):
563 c29ac11d Ilias Tsitsimpis
        """Check hash sums of two files"""
564 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Check hash sum for local file %s" % localfile)
565 c29ac11d Ilias Tsitsimpis
        hash1 = os.popen("sha256sum %s" % localfile).read().split(' ')[0]
566 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Local file has sha256 hash %s" % hash1)
567 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Check hash sum for remote file %s" % remotefile)
568 c29ac11d Ilias Tsitsimpis
        hash2 = _run("sha256sum %s" % remotefile, False)
569 c29ac11d Ilias Tsitsimpis
        hash2 = hash2.split(' ')[0]
570 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Remote file has sha256 hash %s" % hash2)
571 c29ac11d Ilias Tsitsimpis
        if hash1 != hash2:
572 c29ac11d Ilias Tsitsimpis
            self.logger.error("Hashes differ.. aborting")
573 99d39120 Ilias Tsitsimpis
            sys.exit(1)
574 c29ac11d Ilias Tsitsimpis
575 c29ac11d Ilias Tsitsimpis
    @_check_fabric
576 5323404f Ilias Tsitsimpis
    def clone_repo(self, local_repo=False):
577 c29ac11d Ilias Tsitsimpis
        """Clone Synnefo repo from slave server"""
578 c29ac11d Ilias Tsitsimpis
        self.logger.info("Configure repositories on remote server..")
579 6c3cc77e Ilias Tsitsimpis
        self.logger.debug("Install/Setup git")
580 c29ac11d Ilias Tsitsimpis
        cmd = """
581 71f2649f Ilias Tsitsimpis
        apt-get install git --yes --force-yes
582 6c3cc77e Ilias Tsitsimpis
        git config --global user.name {0}
583 6c3cc77e Ilias Tsitsimpis
        git config --global user.email {1}
584 6c3cc77e Ilias Tsitsimpis
        """.format(self.config.get('Global', 'git_config_name'),
585 c29ac11d Ilias Tsitsimpis
                   self.config.get('Global', 'git_config_mail'))
586 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
587 c29ac11d Ilias Tsitsimpis
588 99d39120 Ilias Tsitsimpis
        # Clone synnefo_repo
589 99d39120 Ilias Tsitsimpis
        synnefo_branch = self.clone_synnefo_repo(local_repo=local_repo)
590 99d39120 Ilias Tsitsimpis
        # Clone pithos-web-client
591 99d39120 Ilias Tsitsimpis
        self.clone_pithos_webclient_repo(synnefo_branch)
592 99d39120 Ilias Tsitsimpis
593 99d39120 Ilias Tsitsimpis
    @_check_fabric
594 99d39120 Ilias Tsitsimpis
    def clone_synnefo_repo(self, local_repo=False):
595 99d39120 Ilias Tsitsimpis
        """Clone Synnefo repo to remote server"""
596 5323404f Ilias Tsitsimpis
        # Find synnefo_repo and synnefo_branch to use
597 c29ac11d Ilias Tsitsimpis
        synnefo_repo = self.config.get('Global', 'synnefo_repo')
598 b69b55ca Christos Stavrakakis
        synnefo_branch = self.config.get("Global", "synnefo_branch")
599 b69b55ca Christos Stavrakakis
        if synnefo_branch == "":
600 e2a0abb8 Ilias Tsitsimpis
            synnefo_branch = \
601 e2a0abb8 Ilias Tsitsimpis
                subprocess.Popen(
602 e2a0abb8 Ilias Tsitsimpis
                    ["git", "rev-parse", "--abbrev-ref", "HEAD"],
603 b69b55ca Christos Stavrakakis
                    stdout=subprocess.PIPE).communicate()[0].strip()
604 b69b55ca Christos Stavrakakis
            if synnefo_branch == "HEAD":
605 b69b55ca Christos Stavrakakis
                synnefo_branch = \
606 e2a0abb8 Ilias Tsitsimpis
                    subprocess.Popen(
607 e2a0abb8 Ilias Tsitsimpis
                        ["git", "rev-parse", "--short", "HEAD"],
608 b69b55ca Christos Stavrakakis
                        stdout=subprocess.PIPE).communicate()[0].strip()
609 99d39120 Ilias Tsitsimpis
        self.logger.debug("Will use branch \"%s\"" % _green(synnefo_branch))
610 5323404f Ilias Tsitsimpis
611 99d39120 Ilias Tsitsimpis
        if local_repo or synnefo_repo == "":
612 5323404f Ilias Tsitsimpis
            # Use local_repo
613 5323404f Ilias Tsitsimpis
            self.logger.debug("Push local repo to server")
614 5323404f Ilias Tsitsimpis
            # Firstly create the remote repo
615 5323404f Ilias Tsitsimpis
            _run("git init synnefo", False)
616 5323404f Ilias Tsitsimpis
            # Then push our local repo over ssh
617 5323404f Ilias Tsitsimpis
            # We have to pass some arguments to ssh command
618 5323404f Ilias Tsitsimpis
            # namely to disable host checking.
619 5323404f Ilias Tsitsimpis
            (temp_ssh_file_handle, temp_ssh_file) = tempfile.mkstemp()
620 5323404f Ilias Tsitsimpis
            os.close(temp_ssh_file_handle)
621 62fcf0e5 Ilias Tsitsimpis
            # XXX: git push doesn't read the password
622 5323404f Ilias Tsitsimpis
            cmd = """
623 5323404f Ilias Tsitsimpis
            echo 'exec ssh -o "StrictHostKeyChecking no" \
624 5323404f Ilias Tsitsimpis
                           -o "UserKnownHostsFile /dev/null" \
625 5323404f Ilias Tsitsimpis
                           -q "$@"' > {4}
626 5323404f Ilias Tsitsimpis
            chmod u+x {4}
627 5323404f Ilias Tsitsimpis
            export GIT_SSH="{4}"
628 99d39120 Ilias Tsitsimpis
            echo "{0}" | git push --quiet --mirror ssh://{1}@{2}:{3}/~/synnefo
629 5323404f Ilias Tsitsimpis
            rm -f {4}
630 5323404f Ilias Tsitsimpis
            """.format(fabric.env.password,
631 5323404f Ilias Tsitsimpis
                       fabric.env.user,
632 5323404f Ilias Tsitsimpis
                       fabric.env.host_string,
633 5323404f Ilias Tsitsimpis
                       fabric.env.port,
634 5323404f Ilias Tsitsimpis
                       temp_ssh_file)
635 5323404f Ilias Tsitsimpis
            os.system(cmd)
636 5323404f Ilias Tsitsimpis
        else:
637 5323404f Ilias Tsitsimpis
            # Clone Synnefo from remote repo
638 99d39120 Ilias Tsitsimpis
            self.logger.debug("Clone synnefo from %s" % synnefo_repo)
639 99d39120 Ilias Tsitsimpis
            self._git_clone(synnefo_repo)
640 5323404f Ilias Tsitsimpis
641 5323404f Ilias Tsitsimpis
        # Checkout the desired synnefo_branch
642 07710fc3 Ilias Tsitsimpis
        self.logger.debug("Checkout \"%s\" branch/commit" % synnefo_branch)
643 e2a0abb8 Ilias Tsitsimpis
        cmd = """
644 b69b55ca Christos Stavrakakis
        cd synnefo
645 99d39120 Ilias Tsitsimpis
        for branch in `git branch -a | grep remotes | grep -v HEAD`; do
646 b69b55ca Christos Stavrakakis
            git branch --track ${branch##*/} $branch
647 b69b55ca Christos Stavrakakis
        done
648 b69b55ca Christos Stavrakakis
        git checkout %s
649 b69b55ca Christos Stavrakakis
        """ % (synnefo_branch)
650 b69b55ca Christos Stavrakakis
        _run(cmd, False)
651 b69b55ca Christos Stavrakakis
652 99d39120 Ilias Tsitsimpis
        return synnefo_branch
653 99d39120 Ilias Tsitsimpis
654 c29ac11d Ilias Tsitsimpis
    @_check_fabric
655 99d39120 Ilias Tsitsimpis
    def clone_pithos_webclient_repo(self, synnefo_branch):
656 99d39120 Ilias Tsitsimpis
        """Clone Pithos WebClient repo to remote server"""
657 99d39120 Ilias Tsitsimpis
        # Find pithos_webclient_repo and pithos_webclient_branch to use
658 99d39120 Ilias Tsitsimpis
        pithos_webclient_repo = \
659 99d39120 Ilias Tsitsimpis
            self.config.get('Global', 'pithos_webclient_repo')
660 99d39120 Ilias Tsitsimpis
        pithos_webclient_branch = \
661 99d39120 Ilias Tsitsimpis
            self.config.get('Global', 'pithos_webclient_branch')
662 99d39120 Ilias Tsitsimpis
663 99d39120 Ilias Tsitsimpis
        # Clone pithos-webclient from remote repo
664 99d39120 Ilias Tsitsimpis
        self.logger.debug("Clone pithos-webclient from %s" %
665 99d39120 Ilias Tsitsimpis
                          pithos_webclient_repo)
666 99d39120 Ilias Tsitsimpis
        self._git_clone(pithos_webclient_repo)
667 99d39120 Ilias Tsitsimpis
668 99d39120 Ilias Tsitsimpis
        # Track all pithos-webclient branches
669 99d39120 Ilias Tsitsimpis
        cmd = """
670 99d39120 Ilias Tsitsimpis
        cd pithos-web-client
671 99d39120 Ilias Tsitsimpis
        for branch in `git branch -a | grep remotes | grep -v HEAD`; do
672 99d39120 Ilias Tsitsimpis
            git branch --track ${branch##*/} $branch > /dev/null 2>&1
673 99d39120 Ilias Tsitsimpis
        done
674 99d39120 Ilias Tsitsimpis
        git branch
675 99d39120 Ilias Tsitsimpis
        """
676 99d39120 Ilias Tsitsimpis
        webclient_branches = _run(cmd, False)
677 99d39120 Ilias Tsitsimpis
        webclient_branches = webclient_branches.split()
678 99d39120 Ilias Tsitsimpis
679 99d39120 Ilias Tsitsimpis
        # If we have pithos_webclient_branch in config file use this one
680 99d39120 Ilias Tsitsimpis
        # else try to use the same branch as synnefo_branch
681 99d39120 Ilias Tsitsimpis
        # else use an appropriate one.
682 99d39120 Ilias Tsitsimpis
        if pithos_webclient_branch == "":
683 99d39120 Ilias Tsitsimpis
            if synnefo_branch in webclient_branches:
684 99d39120 Ilias Tsitsimpis
                pithos_webclient_branch = synnefo_branch
685 99d39120 Ilias Tsitsimpis
            else:
686 99d39120 Ilias Tsitsimpis
                # If synnefo_branch starts with one of
687 99d39120 Ilias Tsitsimpis
                # 'master', 'hotfix'; use the master branch
688 99d39120 Ilias Tsitsimpis
                if synnefo_branch.startswith('master') or \
689 99d39120 Ilias Tsitsimpis
                        synnefo_branch.startswith('hotfix'):
690 99d39120 Ilias Tsitsimpis
                    pithos_webclient_branch = "master"
691 99d39120 Ilias Tsitsimpis
                # If synnefo_branch starts with one of
692 99d39120 Ilias Tsitsimpis
                # 'develop', 'feature'; use the develop branch
693 99d39120 Ilias Tsitsimpis
                elif synnefo_branch.startswith('develop') or \
694 99d39120 Ilias Tsitsimpis
                        synnefo_branch.startswith('feature'):
695 99d39120 Ilias Tsitsimpis
                    pithos_webclient_branch = "develop"
696 99d39120 Ilias Tsitsimpis
                else:
697 7a8e156f Ilias Tsitsimpis
                    self.logger.warning(
698 99d39120 Ilias Tsitsimpis
                        "Cannot determine which pithos-web-client branch to "
699 99d39120 Ilias Tsitsimpis
                        "use based on \"%s\" synnefo branch. "
700 99d39120 Ilias Tsitsimpis
                        "Will use develop." % synnefo_branch)
701 99d39120 Ilias Tsitsimpis
                    pithos_webclient_branch = "develop"
702 99d39120 Ilias Tsitsimpis
        # Checkout branch
703 99d39120 Ilias Tsitsimpis
        self.logger.debug("Checkout \"%s\" branch" %
704 99d39120 Ilias Tsitsimpis
                          _green(pithos_webclient_branch))
705 99d39120 Ilias Tsitsimpis
        cmd = """
706 99d39120 Ilias Tsitsimpis
        cd pithos-web-client
707 99d39120 Ilias Tsitsimpis
        git checkout {0}
708 99d39120 Ilias Tsitsimpis
        """.format(pithos_webclient_branch)
709 99d39120 Ilias Tsitsimpis
        _run(cmd, False)
710 99d39120 Ilias Tsitsimpis
711 99d39120 Ilias Tsitsimpis
    def _git_clone(self, repo):
712 99d39120 Ilias Tsitsimpis
        """Clone repo to remote server
713 99d39120 Ilias Tsitsimpis

714 99d39120 Ilias Tsitsimpis
        Currently clonning from code.grnet.gr can fail unexpectedly.
715 99d39120 Ilias Tsitsimpis
        So retry!!
716 99d39120 Ilias Tsitsimpis

717 99d39120 Ilias Tsitsimpis
        """
718 99d39120 Ilias Tsitsimpis
        cloned = False
719 99d39120 Ilias Tsitsimpis
        for i in range(1, 11):
720 99d39120 Ilias Tsitsimpis
            try:
721 99d39120 Ilias Tsitsimpis
                _run("git clone %s" % repo, False)
722 99d39120 Ilias Tsitsimpis
                cloned = True
723 99d39120 Ilias Tsitsimpis
                break
724 99d39120 Ilias Tsitsimpis
            except BaseException:
725 99d39120 Ilias Tsitsimpis
                self.logger.warning("Clonning failed.. retrying %s/10" % i)
726 99d39120 Ilias Tsitsimpis
        if not cloned:
727 99d39120 Ilias Tsitsimpis
            self.logger.error("Can not clone repo.")
728 99d39120 Ilias Tsitsimpis
            sys.exit(1)
729 99d39120 Ilias Tsitsimpis
730 99d39120 Ilias Tsitsimpis
    @_check_fabric
731 99d39120 Ilias Tsitsimpis
    def build_packages(self):
732 99d39120 Ilias Tsitsimpis
        """Build packages needed by Synnefo software"""
733 99d39120 Ilias Tsitsimpis
        self.logger.info("Install development packages")
734 c29ac11d Ilias Tsitsimpis
        cmd = """
735 c29ac11d Ilias Tsitsimpis
        apt-get update
736 c29ac11d Ilias Tsitsimpis
        apt-get install zlib1g-dev dpkg-dev debhelper git-buildpackage \
737 99d39120 Ilias Tsitsimpis
                python-dev python-all python-pip ant --yes --force-yes
738 8d2c08e4 Christos Stavrakakis
        pip install -U devflow
739 c29ac11d Ilias Tsitsimpis
        """
740 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
741 c29ac11d Ilias Tsitsimpis
742 99d39120 Ilias Tsitsimpis
        # Patch pydist bug
743 e908a902 Christos Stavrakakis
        if self.config.get('Global', 'patch_pydist') == "True":
744 c29ac11d Ilias Tsitsimpis
            self.logger.debug("Patch pydist.py module")
745 c29ac11d Ilias Tsitsimpis
            cmd = r"""
746 c29ac11d Ilias Tsitsimpis
            sed -r -i 's/(\(\?P<name>\[A-Za-z\]\[A-Za-z0-9_\.)/\1\\\-/' \
747 c29ac11d Ilias Tsitsimpis
                /usr/share/python/debpython/pydist.py
748 c29ac11d Ilias Tsitsimpis
            """
749 c29ac11d Ilias Tsitsimpis
            _run(cmd, False)
750 c29ac11d Ilias Tsitsimpis

751 1c230fd8 Ilias Tsitsimpis
        # Build synnefo packages
752 99d39120 Ilias Tsitsimpis
        self.build_synnefo()
753 99d39120 Ilias Tsitsimpis
        # Build pithos-web-client packages
754 99d39120 Ilias Tsitsimpis
        self.build_pithos_webclient()
755 99d39120 Ilias Tsitsimpis

756 99d39120 Ilias Tsitsimpis
    @_check_fabric
757 99d39120 Ilias Tsitsimpis
    def build_synnefo(self):
758 99d39120 Ilias Tsitsimpis
        """Build Synnefo packages"""
759 99d39120 Ilias Tsitsimpis
        self.logger.info("Build Synnefo packages..")
760 99d39120 Ilias Tsitsimpis

761 c29ac11d Ilias Tsitsimpis
        cmd = """
762 1c230fd8 Ilias Tsitsimpis
        devflow-autopkg snapshot -b ~/synnefo_build-area --no-sign
763 c29ac11d Ilias Tsitsimpis
        """
764 1c230fd8 Ilias Tsitsimpis
        with fabric.cd("synnefo"):
765 c29ac11d Ilias Tsitsimpis
            _run(cmd, True)
766 c29ac11d Ilias Tsitsimpis

767 1c230fd8 Ilias Tsitsimpis
        # Install snf-deploy package
768 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Install snf-deploy package")
769 c29ac11d Ilias Tsitsimpis
        cmd = """
770 c29ac11d Ilias Tsitsimpis
        dpkg -i snf-deploy*.deb
771 71f2649f Ilias Tsitsimpis
        apt-get -f install --yes --force-yes
772 c29ac11d Ilias Tsitsimpis
        """
773 1c230fd8 Ilias Tsitsimpis
        with fabric.cd("synnefo_build-area"):
774 c29ac11d Ilias Tsitsimpis
            with fabric.settings(warn_only=True):
775 c29ac11d Ilias Tsitsimpis
                _run(cmd, True)
776 c29ac11d Ilias Tsitsimpis

777 1c230fd8 Ilias Tsitsimpis
        # Setup synnefo packages for snf-deploy
778 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Copy synnefo debs to snf-deploy packages dir")
779 c29ac11d Ilias Tsitsimpis
        cmd = """
780 c29ac11d Ilias Tsitsimpis
        cp ~/synnefo_build-area/*.deb /var/lib/snf-deploy/packages/
781 c29ac11d Ilias Tsitsimpis
        """
782 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
783 c29ac11d Ilias Tsitsimpis

784 88e6558b Christos Stavrakakis
    @_check_fabric
785 99d39120 Ilias Tsitsimpis
    def build_pithos_webclient(self):
786 99d39120 Ilias Tsitsimpis
        """Build pithos-web-client packages"""
787 99d39120 Ilias Tsitsimpis
        self.logger.info("Build pithos-web-client packages..")
788 99d39120 Ilias Tsitsimpis

789 99d39120 Ilias Tsitsimpis
        cmd = """
790 99d39120 Ilias Tsitsimpis
        devflow-autopkg snapshot -b ~/webclient_build-area --no-sign
791 99d39120 Ilias Tsitsimpis
        """
792 99d39120 Ilias Tsitsimpis
        with fabric.cd("pithos-web-client"):
793 99d39120 Ilias Tsitsimpis
            _run(cmd, True)
794 99d39120 Ilias Tsitsimpis

795 99d39120 Ilias Tsitsimpis
        # Setup pithos-web-client packages for snf-deploy
796 99d39120 Ilias Tsitsimpis
        self.logger.debug("Copy webclient debs to snf-deploy packages dir")
797 99d39120 Ilias Tsitsimpis
        cmd = """
798 99d39120 Ilias Tsitsimpis
        cp ~/webclient_build-area/*.deb /var/lib/snf-deploy/packages/
799 99d39120 Ilias Tsitsimpis
        """
800 99d39120 Ilias Tsitsimpis
        _run(cmd, False)
801 99d39120 Ilias Tsitsimpis

802 99d39120 Ilias Tsitsimpis
    @_check_fabric
803 88e6558b Christos Stavrakakis
    def build_documentation(self):
804 e2a0abb8 Ilias Tsitsimpis
        """Build Synnefo documentation"""
805 88e6558b Christos Stavrakakis
        self.logger.info("Build Synnefo documentation..")
806 88e6558b Christos Stavrakakis
        _run("pip install -U Sphinx", False)
807 88e6558b Christos Stavrakakis
        with fabric.cd("synnefo"):
808 e2a0abb8 Ilias Tsitsimpis
            _run("devflow-update-version; "
809 e2a0abb8 Ilias Tsitsimpis
                 "./ci/make_docs.sh synnefo_documentation", False)
810 88e6558b Christos Stavrakakis

811 88e6558b Christos Stavrakakis
    def fetch_documentation(self, dest=None):
812 e2a0abb8 Ilias Tsitsimpis
        """Fetch Synnefo documentation"""
813 e2a0abb8 Ilias Tsitsimpis
        self.logger.info("Fetch Synnefo documentation..")
814 88e6558b Christos Stavrakakis
        if dest is None:
815 88e6558b Christos Stavrakakis
            dest = "synnefo_documentation"
816 88e6558b Christos Stavrakakis
        dest = os.path.abspath(dest)
817 88e6558b Christos Stavrakakis
        if not os.path.exists(dest):
818 88e6558b Christos Stavrakakis
            os.makedirs(dest)
819 88e6558b Christos Stavrakakis
        self.fetch_compressed("synnefo/synnefo_documentation", dest)
820 88e6558b Christos Stavrakakis
        self.logger.info("Downloaded documentation to %s" %
821 88e6558b Christos Stavrakakis
                         _green(dest))
822 88e6558b Christos Stavrakakis

823 c29ac11d Ilias Tsitsimpis
    @_check_fabric
824 ec8bc030 Christos Stavrakakis
    def deploy_synnefo(self, schema=None):
825 c29ac11d Ilias Tsitsimpis
        """Deploy Synnefo using snf-deploy"""
826 c29ac11d Ilias Tsitsimpis
        self.logger.info("Deploy Synnefo..")
827 ec8bc030 Christos Stavrakakis
        if schema is None:
828 ec8bc030 Christos Stavrakakis
            schema = self.config.get('Global', 'schema')
829 106659f1 Ilias Tsitsimpis
        self.logger.debug("Will use \"%s\" schema" % _green(schema))
830 c29ac11d Ilias Tsitsimpis

831 ec8bc030 Christos Stavrakakis
        schema_dir = os.path.join(self.ci_dir, "schemas/%s" % schema)
832 ec8bc030 Christos Stavrakakis
        if not (os.path.exists(schema_dir) and os.path.isdir(schema_dir)):
833 ec8bc030 Christos Stavrakakis
            raise ValueError("Unknown schema: %s" % schema)
834 ec8bc030 Christos Stavrakakis

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

838 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Change password in nodes.conf file")
839 c29ac11d Ilias Tsitsimpis
        cmd = """
840 c29ac11d Ilias Tsitsimpis
        sed -i 's/^password =.*/password = {0}/' /etc/snf-deploy/nodes.conf
841 c29ac11d Ilias Tsitsimpis
        """.format(fabric.env.password)
842 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
843 c29ac11d Ilias Tsitsimpis

844 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Run snf-deploy")
845 c29ac11d Ilias Tsitsimpis
        cmd = """
846 985442f5 Ilias Tsitsimpis
        snf-deploy keygen --force
847 f82ce32a Christos Stavrakakis
        snf-deploy --disable-colors --autoconf all
848 c29ac11d Ilias Tsitsimpis
        """
849 c29ac11d Ilias Tsitsimpis
        _run(cmd, True)
850 c29ac11d Ilias Tsitsimpis

851 c29ac11d Ilias Tsitsimpis
    @_check_fabric
852 c29ac11d Ilias Tsitsimpis
    def unit_test(self):
853 c29ac11d Ilias Tsitsimpis
        """Run Synnefo unit test suite"""
854 c29ac11d Ilias Tsitsimpis
        self.logger.info("Run Synnefo unit test suite")
855 c29ac11d Ilias Tsitsimpis
        component = self.config.get('Unit Tests', 'component')
856 c29ac11d Ilias Tsitsimpis

857 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Install needed packages")
858 c29ac11d Ilias Tsitsimpis
        cmd = """
859 8d2c08e4 Christos Stavrakakis
        pip install -U mock
860 8d2c08e4 Christos Stavrakakis
        pip install -U factory_boy
861 cb1060f2 Ilias Tsitsimpis
        pip install -U nose
862 c29ac11d Ilias Tsitsimpis
        """
863 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
864 c29ac11d Ilias Tsitsimpis

865 861b437e Ilias Tsitsimpis
        self.logger.debug("Upload tests.sh file")
866 861b437e Ilias Tsitsimpis
        unit_tests_file = os.path.join(self.ci_dir, "tests.sh")
867 6868804a Ilias Tsitsimpis
        _put(unit_tests_file, ".")
868 c29ac11d Ilias Tsitsimpis

869 c29ac11d Ilias Tsitsimpis
        self.logger.debug("Run unit tests")
870 c29ac11d Ilias Tsitsimpis
        cmd = """
871 861b437e Ilias Tsitsimpis
        bash tests.sh {0}
872 c29ac11d Ilias Tsitsimpis
        """.format(component)
873 c29ac11d Ilias Tsitsimpis
        _run(cmd, True)
874 c29ac11d Ilias Tsitsimpis

875 c29ac11d Ilias Tsitsimpis
    @_check_fabric
876 c29ac11d Ilias Tsitsimpis
    def run_burnin(self):
877 c29ac11d Ilias Tsitsimpis
        """Run burnin functional test suite"""
878 c29ac11d Ilias Tsitsimpis
        self.logger.info("Run Burnin functional test suite")
879 c29ac11d Ilias Tsitsimpis
        cmd = """
880 c29ac11d Ilias Tsitsimpis
        auth_url=$(grep -e '^url =' .kamakirc | cut -d' ' -f3)
881 c29ac11d Ilias Tsitsimpis
        token=$(grep -e '^token =' .kamakirc | cut -d' ' -f3)
882 c29ac11d Ilias Tsitsimpis
        images_user=$(kamaki image list -l | grep owner | \
883 c29ac11d Ilias Tsitsimpis
                      cut -d':' -f2 | tr -d ' ')
884 c29ac11d Ilias Tsitsimpis
        snf-burnin --auth-url=$auth_url --token=$token \
885 c29ac11d Ilias Tsitsimpis
            --force-flavor=2 --image-id=all \
886 c29ac11d Ilias Tsitsimpis
            --system-images-user=$images_user \
887 c29ac11d Ilias Tsitsimpis
            {0}
888 281c7634 Ilias Tsitsimpis
        BurninExitStatus=$?
889 c29ac11d Ilias Tsitsimpis
        log_folder=$(ls -1d /var/log/burnin/* | tail -n1)
890 c29ac11d Ilias Tsitsimpis
        for i in $(ls $log_folder/*/details*); do
891 c29ac11d Ilias Tsitsimpis
            echo -e "\\n\\n"
892 c29ac11d Ilias Tsitsimpis
            echo -e "***** $i\\n"
893 c29ac11d Ilias Tsitsimpis
            cat $i
894 c29ac11d Ilias Tsitsimpis
        done
895 281c7634 Ilias Tsitsimpis
        exit $BurninExitStatus
896 c29ac11d Ilias Tsitsimpis
        """.format(self.config.get('Burnin', 'cmd_options'))
897 c29ac11d Ilias Tsitsimpis
        _run(cmd, True)
898 c29ac11d Ilias Tsitsimpis

899 c29ac11d Ilias Tsitsimpis
    @_check_fabric
900 88e6558b Christos Stavrakakis
    def fetch_compressed(self, src, dest=None):
901 e2a0abb8 Ilias Tsitsimpis
        """Create a tarball and fetch it locally"""
902 88e6558b Christos Stavrakakis
        self.logger.debug("Creating tarball of %s" % src)
903 88e6558b Christos Stavrakakis
        basename = os.path.basename(src)
904 88e6558b Christos Stavrakakis
        tar_file = basename + ".tgz"
905 88e6558b Christos Stavrakakis
        cmd = "tar czf %s %s" % (tar_file, src)
906 c29ac11d Ilias Tsitsimpis
        _run(cmd, False)
907 88e6558b Christos Stavrakakis
        if not os.path.exists(dest):
908 88e6558b Christos Stavrakakis
            os.makedirs(dest)
909 c29ac11d Ilias Tsitsimpis

910 88e6558b Christos Stavrakakis
        tmp_dir = tempfile.mkdtemp()
911 88e6558b Christos Stavrakakis
        fabric.get(tar_file, tmp_dir)
912 c29ac11d Ilias Tsitsimpis

913 88e6558b Christos Stavrakakis
        dest_file = os.path.join(tmp_dir, tar_file)
914 88e6558b Christos Stavrakakis
        self._check_hash_sum(dest_file, tar_file)
915 88e6558b Christos Stavrakakis
        self.logger.debug("Untar packages file %s" % dest_file)
916 e2dc37b2 Christos Stavrakakis
        cmd = """
917 e2dc37b2 Christos Stavrakakis
        cd %s
918 88e6558b Christos Stavrakakis
        tar xzf %s
919 88e6558b Christos Stavrakakis
        cp -r %s/* %s
920 88e6558b Christos Stavrakakis
        rm -r %s
921 88e6558b Christos Stavrakakis
        """ % (tmp_dir, tar_file, src, dest, tmp_dir)
922 e2dc37b2 Christos Stavrakakis
        os.system(cmd)
923 88e6558b Christos Stavrakakis
        self.logger.info("Downloaded %s to %s" %
924 88e6558b Christos Stavrakakis
                         (src, _green(dest)))
925 88e6558b Christos Stavrakakis

926 88e6558b Christos Stavrakakis
    @_check_fabric
927 88e6558b Christos Stavrakakis
    def fetch_packages(self, dest=None):
928 e2a0abb8 Ilias Tsitsimpis
        """Fetch Synnefo packages"""
929 88e6558b Christos Stavrakakis
        if dest is None:
930 88e6558b Christos Stavrakakis
            dest = self.config.get('Global', 'pkgs_dir')
931 6058ae72 Ilias Tsitsimpis
        dest = os.path.abspath(os.path.expanduser(dest))
932 88e6558b Christos Stavrakakis
        if not os.path.exists(dest):
933 88e6558b Christos Stavrakakis
            os.makedirs(dest)
934 88e6558b Christos Stavrakakis
        self.fetch_compressed("synnefo_build-area", dest)
935 99d39120 Ilias Tsitsimpis
        self.fetch_compressed("webclient_build-area", dest)
936 464e58e9 Christos Stavrakakis
        self.logger.info("Downloaded debian packages to %s" %
937 88e6558b Christos Stavrakakis
                         _green(dest))
938 6958ffc6 Christos Stavrakakis

939 cf99ca80 Ilias Tsitsimpis
    def x2go_plugin(self, dest=None):
940 cf99ca80 Ilias Tsitsimpis
        """Produce an html page which will use the x2goplugin
941 cf99ca80 Ilias Tsitsimpis
942 cf99ca80 Ilias Tsitsimpis
        Arguments:
943 cf99ca80 Ilias Tsitsimpis
          dest  -- The file where to save the page (String)
944 cf99ca80 Ilias Tsitsimpis
945 cf99ca80 Ilias Tsitsimpis
        """
946 cf99ca80 Ilias Tsitsimpis
        output_str = """
947 cf99ca80 Ilias Tsitsimpis
        <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
948 cf99ca80 Ilias Tsitsimpis
        <html>
949 cf99ca80 Ilias Tsitsimpis
        <head>
950 cf99ca80 Ilias Tsitsimpis
        <title>X2Go SynnefoCI Service</title>
951 cf99ca80 Ilias Tsitsimpis
        </head>
952 cf99ca80 Ilias Tsitsimpis
        <body onload="checkPlugin()">
953 cf99ca80 Ilias Tsitsimpis
        <div id="x2goplugin">
954 cf99ca80 Ilias Tsitsimpis
            <object
955 cf99ca80 Ilias Tsitsimpis
                src="location"
956 cf99ca80 Ilias Tsitsimpis
                type="application/x2go"
957 cf99ca80 Ilias Tsitsimpis
                name="x2goplugin"
958 cf99ca80 Ilias Tsitsimpis
                palette="background"
959 cf99ca80 Ilias Tsitsimpis
                height="100%"
960 cf99ca80 Ilias Tsitsimpis
                hspace="0"
961 cf99ca80 Ilias Tsitsimpis
                vspace="0"
962 cf99ca80 Ilias Tsitsimpis
                width="100%"
963 cf99ca80 Ilias Tsitsimpis
                x2goconfig="
964 cf99ca80 Ilias Tsitsimpis
                    session=X2Go-SynnefoCI-Session
965 cf99ca80 Ilias Tsitsimpis
                    server={0}
966 cf99ca80 Ilias Tsitsimpis
                    user={1}
967 cf99ca80 Ilias Tsitsimpis
                    sshport={2}
968 cf99ca80 Ilias Tsitsimpis
                    published=true
969 cf99ca80 Ilias Tsitsimpis
                    autologin=true
970 cf99ca80 Ilias Tsitsimpis
                ">
971 cf99ca80 Ilias Tsitsimpis
            </object>
972 cf99ca80 Ilias Tsitsimpis
        </div>
973 cf99ca80 Ilias Tsitsimpis
        </body>
974 cf99ca80 Ilias Tsitsimpis
        </html>
975 cf99ca80 Ilias Tsitsimpis
        """.format(self.read_temp_config('server_ip'),
976 cf99ca80 Ilias Tsitsimpis
                   self.read_temp_config('server_user'),
977 cf99ca80 Ilias Tsitsimpis
                   self.read_temp_config('server_port'))
978 cf99ca80 Ilias Tsitsimpis
        if dest is None:
979 cf99ca80 Ilias Tsitsimpis
            dest = self.config.get('Global', 'x2go_plugin_file')
980 cf99ca80 Ilias Tsitsimpis

981 cf99ca80 Ilias Tsitsimpis
        self.logger.info("Writting x2go plugin html file to %s" % dest)
982 cf99ca80 Ilias Tsitsimpis
        fid = open(dest, 'w')
983 cf99ca80 Ilias Tsitsimpis
        fid.write(output_str)
984 cf99ca80 Ilias Tsitsimpis
        fid.close()
985 cf99ca80 Ilias Tsitsimpis

986 6958ffc6 Christos Stavrakakis

987 6958ffc6 Christos Stavrakakis
def parse_typed_option(option, value):
988 694c79bb Ilias Tsitsimpis
    """Parsed typed options (flavors and images)"""
989 6958ffc6 Christos Stavrakakis
    try:
990 6958ffc6 Christos Stavrakakis
        [type_, val] = value.strip().split(':')
991 6958ffc6 Christos Stavrakakis
        if type_ not in ["id", "name"]:
992 6958ffc6 Christos Stavrakakis
            raise ValueError
993 6958ffc6 Christos Stavrakakis
        return type_, val
994 6958ffc6 Christos Stavrakakis
    except ValueError:
995 6958ffc6 Christos Stavrakakis
        msg = "Invalid %s format. Must be [id|name]:.+" % option
996 6958ffc6 Christos Stavrakakis
        raise ValueError(msg)