Statistics
| Branch: | Tag: | Revision:

root / ci / utils.py @ 525f2979

History | View | Annotate | Download (17.6 kB)

1 525f2979 Ilias Tsitsimpis
#!/usr/bin/env python
2 525f2979 Ilias Tsitsimpis
3 525f2979 Ilias Tsitsimpis
"""
4 525f2979 Ilias Tsitsimpis
Synnefo ci utils module
5 525f2979 Ilias Tsitsimpis
"""
6 525f2979 Ilias Tsitsimpis
7 525f2979 Ilias Tsitsimpis
import os
8 525f2979 Ilias Tsitsimpis
import sys
9 525f2979 Ilias Tsitsimpis
import time
10 525f2979 Ilias Tsitsimpis
import logging
11 525f2979 Ilias Tsitsimpis
import fabric.api as fabric
12 525f2979 Ilias Tsitsimpis
from ConfigParser import ConfigParser, DuplicateSectionError
13 525f2979 Ilias Tsitsimpis
14 525f2979 Ilias Tsitsimpis
from kamaki.clients.astakos import AstakosClient
15 525f2979 Ilias Tsitsimpis
from kamaki.clients.cyclades import CycladesClient
16 525f2979 Ilias Tsitsimpis
from kamaki.clients.image import ImageClient
17 525f2979 Ilias Tsitsimpis
18 525f2979 Ilias Tsitsimpis
19 525f2979 Ilias Tsitsimpis
def _run(cmd, verbose):
20 525f2979 Ilias Tsitsimpis
    """Run fabric with verbose level"""
21 525f2979 Ilias Tsitsimpis
    if verbose:
22 525f2979 Ilias Tsitsimpis
        args = ('running',)
23 525f2979 Ilias Tsitsimpis
    else:
24 525f2979 Ilias Tsitsimpis
        args = ('running', 'stdout',)
25 525f2979 Ilias Tsitsimpis
    with fabric.hide(*args):
26 525f2979 Ilias Tsitsimpis
        return fabric.run(cmd)
27 525f2979 Ilias Tsitsimpis
28 525f2979 Ilias Tsitsimpis
29 525f2979 Ilias Tsitsimpis
def _red(msg):
30 525f2979 Ilias Tsitsimpis
    """Red color"""
31 525f2979 Ilias Tsitsimpis
    #return "\x1b[31m" + str(msg) + "\x1b[0m"
32 525f2979 Ilias Tsitsimpis
    return str(msg)
33 525f2979 Ilias Tsitsimpis
34 525f2979 Ilias Tsitsimpis
35 525f2979 Ilias Tsitsimpis
def _yellow(msg):
36 525f2979 Ilias Tsitsimpis
    """Yellow color"""
37 525f2979 Ilias Tsitsimpis
    #return "\x1b[33m" + str(msg) + "\x1b[0m"
38 525f2979 Ilias Tsitsimpis
    return str(msg)
39 525f2979 Ilias Tsitsimpis
40 525f2979 Ilias Tsitsimpis
41 525f2979 Ilias Tsitsimpis
def _green(msg):
42 525f2979 Ilias Tsitsimpis
    """Green color"""
43 525f2979 Ilias Tsitsimpis
    #return "\x1b[32m" + str(msg) + "\x1b[0m"
44 525f2979 Ilias Tsitsimpis
    return str(msg)
45 525f2979 Ilias Tsitsimpis
46 525f2979 Ilias Tsitsimpis
47 525f2979 Ilias Tsitsimpis
def _check_fabric(fun):
48 525f2979 Ilias Tsitsimpis
    """Check if fabric env has been set"""
49 525f2979 Ilias Tsitsimpis
    def wrapper(self, *args):
50 525f2979 Ilias Tsitsimpis
        """wrapper function"""
51 525f2979 Ilias Tsitsimpis
        if not self.fabric_installed:
52 525f2979 Ilias Tsitsimpis
            self.setup_fabric()
53 525f2979 Ilias Tsitsimpis
        return fun(self, *args)
54 525f2979 Ilias Tsitsimpis
    return wrapper
55 525f2979 Ilias Tsitsimpis
56 525f2979 Ilias Tsitsimpis
57 525f2979 Ilias Tsitsimpis
def _check_kamaki(fun):
58 525f2979 Ilias Tsitsimpis
    """Check if kamaki has been initialized"""
59 525f2979 Ilias Tsitsimpis
    def wrapper(self, *args):
60 525f2979 Ilias Tsitsimpis
        """wrapper function"""
61 525f2979 Ilias Tsitsimpis
        if not self.kamaki_installed:
62 525f2979 Ilias Tsitsimpis
            self.setup_kamaki()
63 525f2979 Ilias Tsitsimpis
        return fun(self, *args)
64 525f2979 Ilias Tsitsimpis
    return wrapper
65 525f2979 Ilias Tsitsimpis
66 525f2979 Ilias Tsitsimpis
67 525f2979 Ilias Tsitsimpis
class _MyFormatter(logging.Formatter):
68 525f2979 Ilias Tsitsimpis
    """Logging Formatter"""
69 525f2979 Ilias Tsitsimpis
    def format(self, record):
70 525f2979 Ilias Tsitsimpis
        format_orig = self._fmt
71 525f2979 Ilias Tsitsimpis
        if record.levelno == logging.DEBUG:
72 525f2979 Ilias Tsitsimpis
            self._fmt = "  %(msg)s"
73 525f2979 Ilias Tsitsimpis
        elif record.levelno == logging.INFO:
74 525f2979 Ilias Tsitsimpis
            self._fmt = "%(msg)s"
75 525f2979 Ilias Tsitsimpis
        elif record.levelno == logging.WARNING:
76 525f2979 Ilias Tsitsimpis
            self._fmt = _yellow("[W] %(msg)s")
77 525f2979 Ilias Tsitsimpis
        elif record.levelno == logging.ERROR:
78 525f2979 Ilias Tsitsimpis
            self._fmt = _red("[E] %(msg)s")
79 525f2979 Ilias Tsitsimpis
        result = logging.Formatter.format(self, record)
80 525f2979 Ilias Tsitsimpis
        self._fmt = format_orig
81 525f2979 Ilias Tsitsimpis
        return result
82 525f2979 Ilias Tsitsimpis
83 525f2979 Ilias Tsitsimpis
84 525f2979 Ilias Tsitsimpis
class SynnefoCI(object):
85 525f2979 Ilias Tsitsimpis
    """SynnefoCI python class"""
86 525f2979 Ilias Tsitsimpis
87 525f2979 Ilias Tsitsimpis
    def __init__(self, cleanup_config=False):
88 525f2979 Ilias Tsitsimpis
        """ Initialize SynnefoCI python class
89 525f2979 Ilias Tsitsimpis

90 525f2979 Ilias Tsitsimpis
        Setup logger, local_dir, config and kamaki
91 525f2979 Ilias Tsitsimpis
        """
92 525f2979 Ilias Tsitsimpis
        # Setup logger
93 525f2979 Ilias Tsitsimpis
        self.logger = logging.getLogger('synnefo-ci')
94 525f2979 Ilias Tsitsimpis
        self.logger.setLevel(logging.DEBUG)
95 525f2979 Ilias Tsitsimpis
        handler = logging.StreamHandler()
96 525f2979 Ilias Tsitsimpis
        handler.setFormatter(_MyFormatter())
97 525f2979 Ilias Tsitsimpis
        self.logger.addHandler(handler)
98 525f2979 Ilias Tsitsimpis
99 525f2979 Ilias Tsitsimpis
        # Get our local dir
100 525f2979 Ilias Tsitsimpis
        self.ci_dir = os.path.dirname(os.path.abspath(__file__))
101 525f2979 Ilias Tsitsimpis
        self.repo_dir = os.path.dirname(self.ci_dir)
102 525f2979 Ilias Tsitsimpis
103 525f2979 Ilias Tsitsimpis
        # Read config file
104 525f2979 Ilias Tsitsimpis
        self.conffile = os.path.join(self.ci_dir, "new_config")
105 525f2979 Ilias Tsitsimpis
        self.config = ConfigParser()
106 525f2979 Ilias Tsitsimpis
        self.config.optionxform = str
107 525f2979 Ilias Tsitsimpis
        self.config.read(self.conffile)
108 525f2979 Ilias Tsitsimpis
        temp_config = self.config.get('Global', 'temporary_config')
109 525f2979 Ilias Tsitsimpis
        if cleanup_config:
110 525f2979 Ilias Tsitsimpis
            try:
111 525f2979 Ilias Tsitsimpis
                os.remove(temp_config)
112 525f2979 Ilias Tsitsimpis
            except:
113 525f2979 Ilias Tsitsimpis
                pass
114 525f2979 Ilias Tsitsimpis
        else:
115 525f2979 Ilias Tsitsimpis
            self.config.read(self.config.get('Global', 'temporary_config'))
116 525f2979 Ilias Tsitsimpis
117 525f2979 Ilias Tsitsimpis
        # Initialize variables
118 525f2979 Ilias Tsitsimpis
        self.fabric_installed = False
119 525f2979 Ilias Tsitsimpis
        self.kamaki_installed = False
120 525f2979 Ilias Tsitsimpis
        self.cyclades_client = None
121 525f2979 Ilias Tsitsimpis
        self.image_client = None
122 525f2979 Ilias Tsitsimpis
123 525f2979 Ilias Tsitsimpis
    def setup_kamaki(self):
124 525f2979 Ilias Tsitsimpis
        """Initialize kamaki
125 525f2979 Ilias Tsitsimpis

126 525f2979 Ilias Tsitsimpis
        Setup cyclades_client and image_client
127 525f2979 Ilias Tsitsimpis
        """
128 525f2979 Ilias Tsitsimpis
        self.logger.info("Setup kamaki client..")
129 525f2979 Ilias Tsitsimpis
        auth_url = self.config.get('Deployment', 'auth_url')
130 525f2979 Ilias Tsitsimpis
        self.logger.debug("Authentication URL is %s" % _green(auth_url))
131 525f2979 Ilias Tsitsimpis
        token = self.config.get('Deployment', 'token')
132 525f2979 Ilias Tsitsimpis
        #self.logger.debug("Token is %s" % _green(token))
133 525f2979 Ilias Tsitsimpis
134 525f2979 Ilias Tsitsimpis
        astakos_client = AstakosClient(auth_url, token)
135 525f2979 Ilias Tsitsimpis
136 525f2979 Ilias Tsitsimpis
        cyclades_url = \
137 525f2979 Ilias Tsitsimpis
            astakos_client.get_service_endpoints('compute')['publicURL']
138 525f2979 Ilias Tsitsimpis
        self.logger.debug("Cyclades API url is %s" % _green(cyclades_url))
139 525f2979 Ilias Tsitsimpis
        self.cyclades_client = CycladesClient(cyclades_url, token)
140 525f2979 Ilias Tsitsimpis
        self.cyclades_client.CONNECTION_RETRY_LIMIT = 2
141 525f2979 Ilias Tsitsimpis
142 525f2979 Ilias Tsitsimpis
        image_url = \
143 525f2979 Ilias Tsitsimpis
            astakos_client.get_service_endpoints('image')['publicURL']
144 525f2979 Ilias Tsitsimpis
        self.logger.debug("Images API url is %s" % _green(image_url))
145 525f2979 Ilias Tsitsimpis
        self.image_client = ImageClient(cyclades_url, token)
146 525f2979 Ilias Tsitsimpis
        self.image_client.CONNECTION_RETRY_LIMIT = 2
147 525f2979 Ilias Tsitsimpis
148 525f2979 Ilias Tsitsimpis
    def _wait_transition(self, server_id, current_status, new_status):
149 525f2979 Ilias Tsitsimpis
        """Wait for server to go from current_status to new_status"""
150 525f2979 Ilias Tsitsimpis
        self.logger.debug("Waiting for server to become %s" % new_status)
151 525f2979 Ilias Tsitsimpis
        timeout = self.config.getint('Global', 'build_timeout')
152 525f2979 Ilias Tsitsimpis
        sleep_time = 5
153 525f2979 Ilias Tsitsimpis
        while True:
154 525f2979 Ilias Tsitsimpis
            server = self.cyclades_client.get_server_details(server_id)
155 525f2979 Ilias Tsitsimpis
            if server['status'] == new_status:
156 525f2979 Ilias Tsitsimpis
                return server
157 525f2979 Ilias Tsitsimpis
            elif timeout < 0:
158 525f2979 Ilias Tsitsimpis
                self.logger.error(
159 525f2979 Ilias Tsitsimpis
                    "Waiting for server to become %s timed out" % new_status)
160 525f2979 Ilias Tsitsimpis
                self.destroy_server(False)
161 525f2979 Ilias Tsitsimpis
                sys.exit(-1)
162 525f2979 Ilias Tsitsimpis
            elif server['status'] == current_status:
163 525f2979 Ilias Tsitsimpis
                # Sleep for #n secs and continue
164 525f2979 Ilias Tsitsimpis
                timeout = timeout - sleep_time
165 525f2979 Ilias Tsitsimpis
                time.sleep(sleep_time)
166 525f2979 Ilias Tsitsimpis
            else:
167 525f2979 Ilias Tsitsimpis
                self.logger.error(
168 525f2979 Ilias Tsitsimpis
                    "Server failed with status %s" % server['status'])
169 525f2979 Ilias Tsitsimpis
                self.destroy_server(False)
170 525f2979 Ilias Tsitsimpis
                sys.exit(-1)
171 525f2979 Ilias Tsitsimpis
172 525f2979 Ilias Tsitsimpis
    @_check_kamaki
173 525f2979 Ilias Tsitsimpis
    def destroy_server(self, wait=True):
174 525f2979 Ilias Tsitsimpis
        """Destroy slave server"""
175 525f2979 Ilias Tsitsimpis
        server_id = self.config.getint('Temporary Options', 'server_id')
176 525f2979 Ilias Tsitsimpis
        self.logger.info("Destoying server with id %s " % server_id)
177 525f2979 Ilias Tsitsimpis
        self.cyclades_client.delete_server(server_id)
178 525f2979 Ilias Tsitsimpis
        if wait:
179 525f2979 Ilias Tsitsimpis
            self._wait_transition(server_id, "ACTIVE", "DELETED")
180 525f2979 Ilias Tsitsimpis
181 525f2979 Ilias Tsitsimpis
    @_check_kamaki
182 525f2979 Ilias Tsitsimpis
    def create_server(self):
183 525f2979 Ilias Tsitsimpis
        """Create slave server"""
184 525f2979 Ilias Tsitsimpis
        self.logger.info("Create a new server..")
185 525f2979 Ilias Tsitsimpis
        image = self._find_image()
186 525f2979 Ilias Tsitsimpis
        self.logger.debug("Will use image \"%s\"" % _green(image['name']))
187 525f2979 Ilias Tsitsimpis
        self.logger.debug("Image has id %s" % _green(image['id']))
188 525f2979 Ilias Tsitsimpis
        server = self.cyclades_client.create_server(
189 525f2979 Ilias Tsitsimpis
            self.config.get('Deployment', 'server_name'),
190 525f2979 Ilias Tsitsimpis
            self.config.getint('Deployment', 'flavor_id'),
191 525f2979 Ilias Tsitsimpis
            image['id'])
192 525f2979 Ilias Tsitsimpis
        server_id = server['id']
193 525f2979 Ilias Tsitsimpis
        self.write_config('server_id', server_id)
194 525f2979 Ilias Tsitsimpis
        self.logger.debug("Server got id %s" % _green(server_id))
195 525f2979 Ilias Tsitsimpis
        server_user = server['metadata']['users']
196 525f2979 Ilias Tsitsimpis
        self.write_config('server_user', server_user)
197 525f2979 Ilias Tsitsimpis
        self.logger.debug("Server's admin user is %s" % _green(server_user))
198 525f2979 Ilias Tsitsimpis
        server_passwd = server['adminPass']
199 525f2979 Ilias Tsitsimpis
        self.write_config('server_passwd', server_passwd)
200 525f2979 Ilias Tsitsimpis
        self.logger.debug(
201 525f2979 Ilias Tsitsimpis
            "Server's admin password is %s" % _green(server_passwd))
202 525f2979 Ilias Tsitsimpis
203 525f2979 Ilias Tsitsimpis
        server = self._wait_transition(server_id, "BUILD", "ACTIVE")
204 525f2979 Ilias Tsitsimpis
        self._get_server_ip_and_port(server)
205 525f2979 Ilias Tsitsimpis
206 525f2979 Ilias Tsitsimpis
        self.setup_fabric()
207 525f2979 Ilias Tsitsimpis
        self.logger.info("Setup firewall")
208 525f2979 Ilias Tsitsimpis
        accept_ssh_from = self.config.get('Global', 'filter_access_network')
209 525f2979 Ilias Tsitsimpis
        self.logger.debug("Block ssh except from %s" % accept_ssh_from)
210 525f2979 Ilias Tsitsimpis
        cmd = """
211 525f2979 Ilias Tsitsimpis
        iptables -A INPUT -s localhost -j ACCEPT
212 525f2979 Ilias Tsitsimpis
        iptables -A INPUT -s {0} -p tcp --dport 22 -j ACCEPT
213 525f2979 Ilias Tsitsimpis
        iptables -A INPUT -p tcp --dport 22 -j DROP
214 525f2979 Ilias Tsitsimpis
        """.format(accept_ssh_from)
215 525f2979 Ilias Tsitsimpis
        _run(cmd, False)
216 525f2979 Ilias Tsitsimpis
217 525f2979 Ilias Tsitsimpis
    def _find_image(self):
218 525f2979 Ilias Tsitsimpis
        """Find a suitable image to use
219 525f2979 Ilias Tsitsimpis

220 525f2979 Ilias Tsitsimpis
        It has to belong to the `system_uuid' user and
221 525f2979 Ilias Tsitsimpis
        contain the word `image_name'
222 525f2979 Ilias Tsitsimpis
        """
223 525f2979 Ilias Tsitsimpis
        system_uuid = self.config.get('Deployment', 'system_uuid')
224 525f2979 Ilias Tsitsimpis
        image_name = self.config.get('Deployment', 'image_name').lower()
225 525f2979 Ilias Tsitsimpis
        images = self.image_client.list_public(detail=True)['images']
226 525f2979 Ilias Tsitsimpis
        # Select images by `system_uuid' user
227 525f2979 Ilias Tsitsimpis
        images = [x for x in images if x['user_id'] == system_uuid]
228 525f2979 Ilias Tsitsimpis
        # Select images with `image_name' in their names
229 525f2979 Ilias Tsitsimpis
        images = \
230 525f2979 Ilias Tsitsimpis
            [x for x in images if x['name'].lower().find(image_name) != -1]
231 525f2979 Ilias Tsitsimpis
        # Let's select the first one
232 525f2979 Ilias Tsitsimpis
        return images[0]
233 525f2979 Ilias Tsitsimpis
234 525f2979 Ilias Tsitsimpis
    def _get_server_ip_and_port(self, server):
235 525f2979 Ilias Tsitsimpis
        """Compute server's IPv4 and ssh port number"""
236 525f2979 Ilias Tsitsimpis
        self.logger.info("Get server connection details..")
237 525f2979 Ilias Tsitsimpis
        # XXX: check if this IP is from public network
238 525f2979 Ilias Tsitsimpis
        server_ip = server['attachments'][0]['ipv4']
239 525f2979 Ilias Tsitsimpis
        if eval(self.config.get('Deployment', 'deploy_on_io')):
240 525f2979 Ilias Tsitsimpis
            tmp1 = int(server_ip.split(".")[2])
241 525f2979 Ilias Tsitsimpis
            tmp2 = int(server_ip.split(".")[3])
242 525f2979 Ilias Tsitsimpis
            server_ip = "gate.okeanos.io"
243 525f2979 Ilias Tsitsimpis
            server_port = 10000 + tmp1 * 256 + tmp2
244 525f2979 Ilias Tsitsimpis
        else:
245 525f2979 Ilias Tsitsimpis
            server_port = 22
246 525f2979 Ilias Tsitsimpis
        self.write_config('server_ip', server_ip)
247 525f2979 Ilias Tsitsimpis
        self.logger.debug("Server's IPv4 is %s" % _green(server_ip))
248 525f2979 Ilias Tsitsimpis
        self.write_config('server_port', server_port)
249 525f2979 Ilias Tsitsimpis
        self.logger.debug("Server's ssh port is %s" % _green(server_port))
250 525f2979 Ilias Tsitsimpis
251 525f2979 Ilias Tsitsimpis
    def write_config(self, option, value, section="Temporary Options"):
252 525f2979 Ilias Tsitsimpis
        """Write changes back to config file"""
253 525f2979 Ilias Tsitsimpis
        try:
254 525f2979 Ilias Tsitsimpis
            self.config.add_section(section)
255 525f2979 Ilias Tsitsimpis
        except DuplicateSectionError:
256 525f2979 Ilias Tsitsimpis
            pass
257 525f2979 Ilias Tsitsimpis
        self.config.set(section, option, str(value))
258 525f2979 Ilias Tsitsimpis
        temp_conf_file = self.config.get('Global', 'temporary_config')
259 525f2979 Ilias Tsitsimpis
        with open(temp_conf_file, 'wb') as tcf:
260 525f2979 Ilias Tsitsimpis
            self.config.write(tcf)
261 525f2979 Ilias Tsitsimpis
262 525f2979 Ilias Tsitsimpis
    def setup_fabric(self):
263 525f2979 Ilias Tsitsimpis
        """Setup fabric environment"""
264 525f2979 Ilias Tsitsimpis
        self.logger.info("Setup fabric parameters..")
265 525f2979 Ilias Tsitsimpis
        fabric.env.user = self.config.get('Temporary Options', 'server_user')
266 525f2979 Ilias Tsitsimpis
        fabric.env.host_string = \
267 525f2979 Ilias Tsitsimpis
            self.config.get('Temporary Options', 'server_ip')
268 525f2979 Ilias Tsitsimpis
        fabric.env.port = self.config.getint('Temporary Options', 'server_port')
269 525f2979 Ilias Tsitsimpis
        fabric.env.password = \
270 525f2979 Ilias Tsitsimpis
            self.config.get('Temporary Options', 'server_passwd')
271 525f2979 Ilias Tsitsimpis
        fabric.env.connection_attempts = 10
272 525f2979 Ilias Tsitsimpis
        fabric.env.shell = "/bin/bash -c"
273 525f2979 Ilias Tsitsimpis
        fabric.env.disable_known_hosts = True
274 525f2979 Ilias Tsitsimpis
        fabric.env.output_prefix = None
275 525f2979 Ilias Tsitsimpis
276 525f2979 Ilias Tsitsimpis
    def _check_hash_sum(self, localfile, remotefile):
277 525f2979 Ilias Tsitsimpis
        """Check hash sums of two files"""
278 525f2979 Ilias Tsitsimpis
        self.logger.debug("Check hash sum for local file %s" % localfile)
279 525f2979 Ilias Tsitsimpis
        hash1 = os.popen("sha256sum %s" % localfile).read().split(' ')[0]
280 525f2979 Ilias Tsitsimpis
        self.logger.debug("Local file has sha256 hash %s" % hash1)
281 525f2979 Ilias Tsitsimpis
        self.logger.debug("Check hash sum for remote file %s" % remotefile)
282 525f2979 Ilias Tsitsimpis
        hash2 = _run("sha256sum %s" % remotefile, False)
283 525f2979 Ilias Tsitsimpis
        hash2 = hash2.split(' ')[0]
284 525f2979 Ilias Tsitsimpis
        self.logger.debug("Remote file has sha256 hash %s" % hash2)
285 525f2979 Ilias Tsitsimpis
        if hash1 != hash2:
286 525f2979 Ilias Tsitsimpis
            self.logger.error("Hashes differ.. aborting")
287 525f2979 Ilias Tsitsimpis
            sys.exit(-1)
288 525f2979 Ilias Tsitsimpis
289 525f2979 Ilias Tsitsimpis
    @_check_fabric
290 525f2979 Ilias Tsitsimpis
    def clone_repo(self):
291 525f2979 Ilias Tsitsimpis
        """Clone Synnefo repo from slave server"""
292 525f2979 Ilias Tsitsimpis
        self.logger.info("Configure repositories on remote server..")
293 525f2979 Ilias Tsitsimpis
        self.logger.debug("Setup apt, install curl and git")
294 525f2979 Ilias Tsitsimpis
        cmd = """
295 525f2979 Ilias Tsitsimpis
        echo 'APT::Install-Suggests "false";' >> /etc/apt/apt.conf
296 525f2979 Ilias Tsitsimpis
        apt-get update
297 525f2979 Ilias Tsitsimpis
        apt-get install curl git --yes
298 525f2979 Ilias Tsitsimpis
        echo -e "\n\ndeb {0}" >> /etc/apt/sources.list
299 525f2979 Ilias Tsitsimpis
        curl https://dev.grnet.gr/files/apt-grnetdev.pub | apt-key add -
300 525f2979 Ilias Tsitsimpis
        apt-get update
301 525f2979 Ilias Tsitsimpis
        git config --global user.name {1}
302 525f2979 Ilias Tsitsimpis
        git config --global user.mail {2}
303 525f2979 Ilias Tsitsimpis
        """.format(self.config.get('Global', 'apt_repo'),
304 525f2979 Ilias Tsitsimpis
                   self.config.get('Global', 'git_config_name'),
305 525f2979 Ilias Tsitsimpis
                   self.config.get('Global', 'git_config_mail'))
306 525f2979 Ilias Tsitsimpis
        _run(cmd, False)
307 525f2979 Ilias Tsitsimpis
308 525f2979 Ilias Tsitsimpis
        synnefo_repo = self.config.get('Global', 'synnefo_repo')
309 525f2979 Ilias Tsitsimpis
        # Currently clonning synnefo can fail unexpectedly
310 525f2979 Ilias Tsitsimpis
        for i in range(3):
311 525f2979 Ilias Tsitsimpis
            self.logger.debug("Clone synnefo from %s" % synnefo_repo)
312 525f2979 Ilias Tsitsimpis
            try:
313 525f2979 Ilias Tsitsimpis
                _run("git clone %s" % synnefo_repo, False)
314 525f2979 Ilias Tsitsimpis
                break
315 525f2979 Ilias Tsitsimpis
            except:
316 525f2979 Ilias Tsitsimpis
                self.logger.warning("Clonning synnefo failed.. retrying %s" % i)
317 525f2979 Ilias Tsitsimpis
318 525f2979 Ilias Tsitsimpis
        synnefo_branch = self.config.get('Global', 'synnefo_branch')
319 525f2979 Ilias Tsitsimpis
        if synnefo_branch == "HEAD":
320 525f2979 Ilias Tsitsimpis
            # Get current branch
321 525f2979 Ilias Tsitsimpis
            synnefo_branch = os.popen("git rev-parse HEAD").read().strip()
322 525f2979 Ilias Tsitsimpis
            self.logger.debug(
323 525f2979 Ilias Tsitsimpis
                "Checkout %s in feature-ci branch" % synnefo_branch)
324 525f2979 Ilias Tsitsimpis
            with fabric.cd("synnefo"):
325 525f2979 Ilias Tsitsimpis
                _run("git checkout -b feature-ci %s" % synnefo_branch, False)
326 525f2979 Ilias Tsitsimpis
        elif synnefo_branch == "origin/master":
327 525f2979 Ilias Tsitsimpis
            pass
328 525f2979 Ilias Tsitsimpis
        elif "origin" in synnefo_branch:
329 525f2979 Ilias Tsitsimpis
            self.logger.debug("Checkout %s branch" % synnefo_branch)
330 525f2979 Ilias Tsitsimpis
            with fabric.cd("synnefo"):
331 525f2979 Ilias Tsitsimpis
                _run("git checkout -t %s" % synnefo_branch, False)
332 525f2979 Ilias Tsitsimpis
        else:
333 525f2979 Ilias Tsitsimpis
            self.logger.debug(
334 525f2979 Ilias Tsitsimpis
                "Checkout %s in feature-ci branch" % synnefo_branch)
335 525f2979 Ilias Tsitsimpis
            with fabric.cd("synnefo"):
336 525f2979 Ilias Tsitsimpis
                _run("git checkout -b feature-ci %s" % synnefo_branch, False)
337 525f2979 Ilias Tsitsimpis
338 525f2979 Ilias Tsitsimpis
        deploy_repo = self.config.get('Global', 'deploy_repo')
339 525f2979 Ilias Tsitsimpis
        self.logger.debug("Clone snf-deploy from %s" % deploy_repo)
340 525f2979 Ilias Tsitsimpis
        _run("git clone %s" % deploy_repo, False)
341 525f2979 Ilias Tsitsimpis
342 525f2979 Ilias Tsitsimpis
    @_check_fabric
343 525f2979 Ilias Tsitsimpis
    def build_synnefo(self):
344 525f2979 Ilias Tsitsimpis
        """Build Synnefo packages"""
345 525f2979 Ilias Tsitsimpis
        self.logger.info("Build Synnefo packages..")
346 525f2979 Ilias Tsitsimpis
        self.logger.debug("Install development packages")
347 525f2979 Ilias Tsitsimpis
        cmd = """
348 525f2979 Ilias Tsitsimpis
        apt-get update
349 525f2979 Ilias Tsitsimpis
        apt-get install zlib1g-dev dpkg-dev debhelper git-buildpackage \
350 525f2979 Ilias Tsitsimpis
                python-dev python-all python-pip --yes
351 525f2979 Ilias Tsitsimpis
        pip install devflow
352 525f2979 Ilias Tsitsimpis
        """
353 525f2979 Ilias Tsitsimpis
        _run(cmd, False)
354 525f2979 Ilias Tsitsimpis
355 525f2979 Ilias Tsitsimpis
        if eval(self.config.get('Global', 'patch_pydist')):
356 525f2979 Ilias Tsitsimpis
            self.logger.debug("Patch pydist.py module")
357 525f2979 Ilias Tsitsimpis
            cmd = r"""
358 525f2979 Ilias Tsitsimpis
            sed -r -i 's/(\(\?P<name>\[A-Za-z\]\[A-Za-z0-9_\.)/\1\\\-/' \
359 525f2979 Ilias Tsitsimpis
                /usr/share/python/debpython/pydist.py
360 525f2979 Ilias Tsitsimpis
            """
361 525f2979 Ilias Tsitsimpis
            _run(cmd, False)
362 525f2979 Ilias Tsitsimpis

363 525f2979 Ilias Tsitsimpis
        self.logger.debug("Build snf-deploy package")
364 525f2979 Ilias Tsitsimpis
        cmd = """
365 525f2979 Ilias Tsitsimpis
        git checkout -t origin/debian
366 525f2979 Ilias Tsitsimpis
        git-buildpackage --git-upstream-branch=master \
367 525f2979 Ilias Tsitsimpis
                --git-debian-branch=debian \
368 525f2979 Ilias Tsitsimpis
                --git-export-dir=../snf-deploy_build-area \
369 525f2979 Ilias Tsitsimpis
                -uc -us
370 525f2979 Ilias Tsitsimpis
        """
371 525f2979 Ilias Tsitsimpis
        with fabric.cd("snf-deploy"):
372 525f2979 Ilias Tsitsimpis
            _run(cmd, True)
373 525f2979 Ilias Tsitsimpis

374 525f2979 Ilias Tsitsimpis
        self.logger.debug("Install snf-deploy package")
375 525f2979 Ilias Tsitsimpis
        cmd = """
376 525f2979 Ilias Tsitsimpis
        dpkg -i snf-deploy*.deb
377 525f2979 Ilias Tsitsimpis
        apt-get -f install --yes
378 525f2979 Ilias Tsitsimpis
        """
379 525f2979 Ilias Tsitsimpis
        with fabric.cd("snf-deploy_build-area"):
380 525f2979 Ilias Tsitsimpis
            with fabric.settings(warn_only=True):
381 525f2979 Ilias Tsitsimpis
                _run(cmd, True)
382 525f2979 Ilias Tsitsimpis

383 525f2979 Ilias Tsitsimpis
        self.logger.debug("Build synnefo packages")
384 525f2979 Ilias Tsitsimpis
        cmd = """
385 525f2979 Ilias Tsitsimpis
        devflow-autopkg snapshot -b ~/synnefo_build-area --no-sign
386 525f2979 Ilias Tsitsimpis
        """
387 525f2979 Ilias Tsitsimpis
        with fabric.cd("synnefo"):
388 525f2979 Ilias Tsitsimpis
            _run(cmd, True)
389 525f2979 Ilias Tsitsimpis

390 525f2979 Ilias Tsitsimpis
        self.logger.debug("Copy synnefo debs to snf-deploy packages dir")
391 525f2979 Ilias Tsitsimpis
        cmd = """
392 525f2979 Ilias Tsitsimpis
        cp ~/synnefo_build-area/*.deb /var/lib/snf-deploy/packages/
393 525f2979 Ilias Tsitsimpis
        """
394 525f2979 Ilias Tsitsimpis
        _run(cmd, False)
395 525f2979 Ilias Tsitsimpis

396 525f2979 Ilias Tsitsimpis
    @_check_fabric
397 525f2979 Ilias Tsitsimpis
    def deploy_synnefo(self):
398 525f2979 Ilias Tsitsimpis
        """Deploy Synnefo using snf-deploy"""
399 525f2979 Ilias Tsitsimpis
        self.logger.info("Deploy Synnefo..")
400 525f2979 Ilias Tsitsimpis
        schema = self.config.get('Global', 'schema')
401 525f2979 Ilias Tsitsimpis
        schema_files = os.path.join(self.ci_dir, "schemas/%s/*" % schema)
402 525f2979 Ilias Tsitsimpis
        self.logger.debug("Will use %s schema" % schema)
403 525f2979 Ilias Tsitsimpis

404 525f2979 Ilias Tsitsimpis
        self.logger.debug("Upload schema files to server")
405 525f2979 Ilias Tsitsimpis
        with fabric.quiet():
406 525f2979 Ilias Tsitsimpis
            fabric.put(schema_files, "/etc/snf-deploy/")
407 525f2979 Ilias Tsitsimpis

408 525f2979 Ilias Tsitsimpis
        self.logger.debug("Change password in nodes.conf file")
409 525f2979 Ilias Tsitsimpis
        cmd = """
410 525f2979 Ilias Tsitsimpis
        sed -i 's/^password =.*/password = {0}/' /etc/snf-deploy/nodes.conf
411 525f2979 Ilias Tsitsimpis
        """.format(fabric.env.password)
412 525f2979 Ilias Tsitsimpis
        _run(cmd, False)
413 525f2979 Ilias Tsitsimpis

414 525f2979 Ilias Tsitsimpis
        self.logger.debug("Run snf-deploy")
415 525f2979 Ilias Tsitsimpis
        cmd = """
416 525f2979 Ilias Tsitsimpis
        snf-deploy all --autoconf
417 525f2979 Ilias Tsitsimpis
        """
418 525f2979 Ilias Tsitsimpis
        _run(cmd, True)
419 525f2979 Ilias Tsitsimpis

420 525f2979 Ilias Tsitsimpis
    @_check_fabric
421 525f2979 Ilias Tsitsimpis
    def unit_test(self):
422 525f2979 Ilias Tsitsimpis
        """Run Synnefo unit test suite"""
423 525f2979 Ilias Tsitsimpis
        self.logger.info("Run Synnefo unit test suite")
424 525f2979 Ilias Tsitsimpis
        component = self.config.get('Unit Tests', 'component')
425 525f2979 Ilias Tsitsimpis

426 525f2979 Ilias Tsitsimpis
        self.logger.debug("Install needed packages")
427 525f2979 Ilias Tsitsimpis
        cmd = """
428 525f2979 Ilias Tsitsimpis
        pip install mock
429 525f2979 Ilias Tsitsimpis
        pip install factory_boy
430 525f2979 Ilias Tsitsimpis
        """
431 525f2979 Ilias Tsitsimpis
        _run(cmd, False)
432 525f2979 Ilias Tsitsimpis

433 525f2979 Ilias Tsitsimpis
        self.logger.debug("Upload local_unit_tests.sh file")
434 525f2979 Ilias Tsitsimpis
        unit_tests_file = os.path.join(self.ci_dir, "local_unit_tests.sh")
435 525f2979 Ilias Tsitsimpis
        with fabric.quiet():
436 525f2979 Ilias Tsitsimpis
            fabric.put(unit_tests_file, ".")
437 525f2979 Ilias Tsitsimpis

438 525f2979 Ilias Tsitsimpis
        self.logger.debug("Run unit tests")
439 525f2979 Ilias Tsitsimpis
        cmd = """
440 525f2979 Ilias Tsitsimpis
        bash local_unit_tests.sh {0}
441 525f2979 Ilias Tsitsimpis
        """.format(component)
442 525f2979 Ilias Tsitsimpis
        _run(cmd, True)
443 525f2979 Ilias Tsitsimpis

444 525f2979 Ilias Tsitsimpis
    @_check_fabric
445 525f2979 Ilias Tsitsimpis
    def run_burnin(self):
446 525f2979 Ilias Tsitsimpis
        """Run burnin functional test suite"""
447 525f2979 Ilias Tsitsimpis
        self.logger.info("Run Burnin functional test suite")
448 525f2979 Ilias Tsitsimpis
        cmd = """
449 525f2979 Ilias Tsitsimpis
        auth_url=$(grep -e '^url =' .kamakirc | cut -d' ' -f3)
450 525f2979 Ilias Tsitsimpis
        token=$(grep -e '^token =' .kamakirc | cut -d' ' -f3)
451 525f2979 Ilias Tsitsimpis
        images_user=$(kamaki image list -l | grep owner | \
452 525f2979 Ilias Tsitsimpis
                      cut -d':' -f2 | tr -d ' ')
453 525f2979 Ilias Tsitsimpis
        snf-burnin --auth-url=$auth_url --token=$token \
454 525f2979 Ilias Tsitsimpis
            --force-flavor=2 --image-id=all \
455 525f2979 Ilias Tsitsimpis
            --system-images-user=$images_user \
456 525f2979 Ilias Tsitsimpis
            {0}
457 525f2979 Ilias Tsitsimpis
        log_folder=$(ls -1d /var/log/burnin/* | tail -n1)
458 525f2979 Ilias Tsitsimpis
        for i in $(ls $log_folder/*/details*); do
459 525f2979 Ilias Tsitsimpis
            echo -e "\\n\\n"
460 525f2979 Ilias Tsitsimpis
            echo -e "***** $i\\n"
461 525f2979 Ilias Tsitsimpis
            cat $i
462 525f2979 Ilias Tsitsimpis
        done
463 525f2979 Ilias Tsitsimpis
        """.format(self.config.get('Burnin', 'cmd_options'))
464 525f2979 Ilias Tsitsimpis
        _run(cmd, True)
465 525f2979 Ilias Tsitsimpis

466 525f2979 Ilias Tsitsimpis
    @_check_fabric
467 525f2979 Ilias Tsitsimpis
    def fetch_packages(self):
468 525f2979 Ilias Tsitsimpis
        """Download Synnefo packages"""
469 525f2979 Ilias Tsitsimpis
        self.logger.info("Download Synnefo packages")
470 525f2979 Ilias Tsitsimpis
        self.logger.debug("Create tarball with packages")
471 525f2979 Ilias Tsitsimpis
        cmd = """
472 525f2979 Ilias Tsitsimpis
        tar czf synnefo_build-area.tgz synnefo_build-area
473 525f2979 Ilias Tsitsimpis
        """
474 525f2979 Ilias Tsitsimpis
        _run(cmd, False)
475 525f2979 Ilias Tsitsimpis

476 525f2979 Ilias Tsitsimpis
        pkgs_dir = self.config.get('Global', 'pkgs_dir')
477 525f2979 Ilias Tsitsimpis
        self.logger.debug("Fetch packages to local dir %s" % pkgs_dir)
478 525f2979 Ilias Tsitsimpis
        os.makedirs(pkgs_dir)
479 525f2979 Ilias Tsitsimpis
        with fabric.quiet():
480 525f2979 Ilias Tsitsimpis
            fabric.get("synnefo_build-area.tgz", pkgs_dir)
481 525f2979 Ilias Tsitsimpis

482 525f2979 Ilias Tsitsimpis
        pkgs_file = os.path.join(pkgs_dir, "synnefo_build-area.tgz")
483 525f2979 Ilias Tsitsimpis
        self._check_hash_sum(pkgs_file, "synnefo_build-area.tgz")
484 525f2979 Ilias Tsitsimpis

485 525f2979 Ilias Tsitsimpis
        self.logger.debug("Untar packages file %s" % pkgs_file)
486 525f2979 Ilias Tsitsimpis
        os.system("cd %s; tar xzf synnefo_build-area.tgz" % pkgs_dir)