Statistics
| Branch: | Tag: | Revision:

root / ci / utils.py @ ddd240ff

History | View | Annotate | Download (18.7 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 da593e0c Christos Stavrakakis
from kamaki.cli import config as kamaki_config
15 525f2979 Ilias Tsitsimpis
from kamaki.clients.astakos import AstakosClient
16 525f2979 Ilias Tsitsimpis
from kamaki.clients.cyclades import CycladesClient
17 525f2979 Ilias Tsitsimpis
from kamaki.clients.image import ImageClient
18 525f2979 Ilias Tsitsimpis
19 525f2979 Ilias Tsitsimpis
20 525f2979 Ilias Tsitsimpis
def _run(cmd, verbose):
21 525f2979 Ilias Tsitsimpis
    """Run fabric with verbose level"""
22 525f2979 Ilias Tsitsimpis
    if verbose:
23 525f2979 Ilias Tsitsimpis
        args = ('running',)
24 525f2979 Ilias Tsitsimpis
    else:
25 525f2979 Ilias Tsitsimpis
        args = ('running', 'stdout',)
26 525f2979 Ilias Tsitsimpis
    with fabric.hide(*args):
27 525f2979 Ilias Tsitsimpis
        return fabric.run(cmd)
28 525f2979 Ilias Tsitsimpis
29 525f2979 Ilias Tsitsimpis
30 525f2979 Ilias Tsitsimpis
def _red(msg):
31 525f2979 Ilias Tsitsimpis
    """Red color"""
32 525f2979 Ilias Tsitsimpis
    #return "\x1b[31m" + str(msg) + "\x1b[0m"
33 525f2979 Ilias Tsitsimpis
    return str(msg)
34 525f2979 Ilias Tsitsimpis
35 525f2979 Ilias Tsitsimpis
36 525f2979 Ilias Tsitsimpis
def _yellow(msg):
37 525f2979 Ilias Tsitsimpis
    """Yellow color"""
38 525f2979 Ilias Tsitsimpis
    #return "\x1b[33m" + str(msg) + "\x1b[0m"
39 525f2979 Ilias Tsitsimpis
    return str(msg)
40 525f2979 Ilias Tsitsimpis
41 525f2979 Ilias Tsitsimpis
42 525f2979 Ilias Tsitsimpis
def _green(msg):
43 525f2979 Ilias Tsitsimpis
    """Green color"""
44 525f2979 Ilias Tsitsimpis
    #return "\x1b[32m" + str(msg) + "\x1b[0m"
45 525f2979 Ilias Tsitsimpis
    return str(msg)
46 525f2979 Ilias Tsitsimpis
47 525f2979 Ilias Tsitsimpis
48 525f2979 Ilias Tsitsimpis
def _check_fabric(fun):
49 525f2979 Ilias Tsitsimpis
    """Check if fabric env has been set"""
50 947b6106 Christos Stavrakakis
    def wrapper(self, *args, **kwargs):
51 525f2979 Ilias Tsitsimpis
        """wrapper function"""
52 525f2979 Ilias Tsitsimpis
        if not self.fabric_installed:
53 525f2979 Ilias Tsitsimpis
            self.setup_fabric()
54 947b6106 Christos Stavrakakis
        return fun(self, *args, **kwargs)
55 525f2979 Ilias Tsitsimpis
    return wrapper
56 525f2979 Ilias Tsitsimpis
57 525f2979 Ilias Tsitsimpis
58 525f2979 Ilias Tsitsimpis
def _check_kamaki(fun):
59 525f2979 Ilias Tsitsimpis
    """Check if kamaki has been initialized"""
60 947b6106 Christos Stavrakakis
    def wrapper(self, *args, **kwargs):
61 525f2979 Ilias Tsitsimpis
        """wrapper function"""
62 525f2979 Ilias Tsitsimpis
        if not self.kamaki_installed:
63 525f2979 Ilias Tsitsimpis
            self.setup_kamaki()
64 947b6106 Christos Stavrakakis
        return fun(self, *args, **kwargs)
65 525f2979 Ilias Tsitsimpis
    return wrapper
66 525f2979 Ilias Tsitsimpis
67 525f2979 Ilias Tsitsimpis
68 525f2979 Ilias Tsitsimpis
class _MyFormatter(logging.Formatter):
69 525f2979 Ilias Tsitsimpis
    """Logging Formatter"""
70 525f2979 Ilias Tsitsimpis
    def format(self, record):
71 525f2979 Ilias Tsitsimpis
        format_orig = self._fmt
72 525f2979 Ilias Tsitsimpis
        if record.levelno == logging.DEBUG:
73 525f2979 Ilias Tsitsimpis
            self._fmt = "  %(msg)s"
74 525f2979 Ilias Tsitsimpis
        elif record.levelno == logging.INFO:
75 525f2979 Ilias Tsitsimpis
            self._fmt = "%(msg)s"
76 525f2979 Ilias Tsitsimpis
        elif record.levelno == logging.WARNING:
77 525f2979 Ilias Tsitsimpis
            self._fmt = _yellow("[W] %(msg)s")
78 525f2979 Ilias Tsitsimpis
        elif record.levelno == logging.ERROR:
79 525f2979 Ilias Tsitsimpis
            self._fmt = _red("[E] %(msg)s")
80 525f2979 Ilias Tsitsimpis
        result = logging.Formatter.format(self, record)
81 525f2979 Ilias Tsitsimpis
        self._fmt = format_orig
82 525f2979 Ilias Tsitsimpis
        return result
83 525f2979 Ilias Tsitsimpis
84 525f2979 Ilias Tsitsimpis
85 525f2979 Ilias Tsitsimpis
class SynnefoCI(object):
86 525f2979 Ilias Tsitsimpis
    """SynnefoCI python class"""
87 525f2979 Ilias Tsitsimpis
88 da593e0c Christos Stavrakakis
    def __init__(self, cleanup_config=False, cloud=None):
89 525f2979 Ilias Tsitsimpis
        """ Initialize SynnefoCI python class
90 525f2979 Ilias Tsitsimpis

91 525f2979 Ilias Tsitsimpis
        Setup logger, local_dir, config and kamaki
92 525f2979 Ilias Tsitsimpis
        """
93 525f2979 Ilias Tsitsimpis
        # Setup logger
94 525f2979 Ilias Tsitsimpis
        self.logger = logging.getLogger('synnefo-ci')
95 525f2979 Ilias Tsitsimpis
        self.logger.setLevel(logging.DEBUG)
96 525f2979 Ilias Tsitsimpis
        handler = logging.StreamHandler()
97 525f2979 Ilias Tsitsimpis
        handler.setFormatter(_MyFormatter())
98 525f2979 Ilias Tsitsimpis
        self.logger.addHandler(handler)
99 525f2979 Ilias Tsitsimpis
100 525f2979 Ilias Tsitsimpis
        # Get our local dir
101 525f2979 Ilias Tsitsimpis
        self.ci_dir = os.path.dirname(os.path.abspath(__file__))
102 525f2979 Ilias Tsitsimpis
        self.repo_dir = os.path.dirname(self.ci_dir)
103 525f2979 Ilias Tsitsimpis
104 525f2979 Ilias Tsitsimpis
        # Read config file
105 133e5a5b Christos Stavrakakis
        default_conffile = os.path.join(self.ci_dir, "new_config")
106 133e5a5b Christos Stavrakakis
        self.conffile = os.environ.get("SYNNEFO_CI_CONFIG_FILE",
107 133e5a5b Christos Stavrakakis
                                       default_conffile)
108 133e5a5b Christos Stavrakakis
109 525f2979 Ilias Tsitsimpis
        self.config = ConfigParser()
110 525f2979 Ilias Tsitsimpis
        self.config.optionxform = str
111 525f2979 Ilias Tsitsimpis
        self.config.read(self.conffile)
112 525f2979 Ilias Tsitsimpis
        temp_config = self.config.get('Global', 'temporary_config')
113 525f2979 Ilias Tsitsimpis
        if cleanup_config:
114 525f2979 Ilias Tsitsimpis
            try:
115 525f2979 Ilias Tsitsimpis
                os.remove(temp_config)
116 525f2979 Ilias Tsitsimpis
            except:
117 525f2979 Ilias Tsitsimpis
                pass
118 525f2979 Ilias Tsitsimpis
        else:
119 525f2979 Ilias Tsitsimpis
            self.config.read(self.config.get('Global', 'temporary_config'))
120 525f2979 Ilias Tsitsimpis
121 da593e0c Christos Stavrakakis
        # Set kamaki cloud
122 da593e0c Christos Stavrakakis
        if cloud is not None:
123 da593e0c Christos Stavrakakis
            self.kamaki_cloud = cloud
124 da593e0c Christos Stavrakakis
        elif self.config.has_option("Deployment", "kamaki_cloud"):
125 da593e0c Christos Stavrakakis
            kamaki_cloud = self.config.get("Deployment", "kamaki_cloud")
126 da593e0c Christos Stavrakakis
            if kamaki_cloud == "":
127 da593e0c Christos Stavrakakis
                self.kamaki_cloud = None
128 da593e0c Christos Stavrakakis
        else:
129 da593e0c Christos Stavrakakis
            self.kamaki_cloud = None
130 da593e0c Christos Stavrakakis
131 525f2979 Ilias Tsitsimpis
        # Initialize variables
132 525f2979 Ilias Tsitsimpis
        self.fabric_installed = False
133 525f2979 Ilias Tsitsimpis
        self.kamaki_installed = False
134 525f2979 Ilias Tsitsimpis
        self.cyclades_client = None
135 525f2979 Ilias Tsitsimpis
        self.image_client = None
136 525f2979 Ilias Tsitsimpis
137 525f2979 Ilias Tsitsimpis
    def setup_kamaki(self):
138 525f2979 Ilias Tsitsimpis
        """Initialize kamaki
139 525f2979 Ilias Tsitsimpis

140 525f2979 Ilias Tsitsimpis
        Setup cyclades_client and image_client
141 525f2979 Ilias Tsitsimpis
        """
142 da593e0c Christos Stavrakakis
143 da593e0c Christos Stavrakakis
        config = kamaki_config.Config()
144 da593e0c Christos Stavrakakis
        if self.kamaki_cloud is None:
145 da593e0c Christos Stavrakakis
            self.kamaki_cloud = config.get_global("default_cloud")
146 da593e0c Christos Stavrakakis
147 da593e0c Christos Stavrakakis
        self.logger.info("Setup kamaki client, using cloud '%s'.." %
148 da593e0c Christos Stavrakakis
                         self.kamaki_cloud)
149 da593e0c Christos Stavrakakis
        auth_url = config.get_cloud(self.kamaki_cloud, "url")
150 525f2979 Ilias Tsitsimpis
        self.logger.debug("Authentication URL is %s" % _green(auth_url))
151 da593e0c Christos Stavrakakis
        token = config.get_cloud(self.kamaki_cloud, "token")
152 525f2979 Ilias Tsitsimpis
        #self.logger.debug("Token is %s" % _green(token))
153 525f2979 Ilias Tsitsimpis
154 525f2979 Ilias Tsitsimpis
        astakos_client = AstakosClient(auth_url, token)
155 525f2979 Ilias Tsitsimpis
156 525f2979 Ilias Tsitsimpis
        cyclades_url = \
157 525f2979 Ilias Tsitsimpis
            astakos_client.get_service_endpoints('compute')['publicURL']
158 525f2979 Ilias Tsitsimpis
        self.logger.debug("Cyclades API url is %s" % _green(cyclades_url))
159 525f2979 Ilias Tsitsimpis
        self.cyclades_client = CycladesClient(cyclades_url, token)
160 525f2979 Ilias Tsitsimpis
        self.cyclades_client.CONNECTION_RETRY_LIMIT = 2
161 525f2979 Ilias Tsitsimpis
162 525f2979 Ilias Tsitsimpis
        image_url = \
163 525f2979 Ilias Tsitsimpis
            astakos_client.get_service_endpoints('image')['publicURL']
164 525f2979 Ilias Tsitsimpis
        self.logger.debug("Images API url is %s" % _green(image_url))
165 525f2979 Ilias Tsitsimpis
        self.image_client = ImageClient(cyclades_url, token)
166 525f2979 Ilias Tsitsimpis
        self.image_client.CONNECTION_RETRY_LIMIT = 2
167 525f2979 Ilias Tsitsimpis
168 525f2979 Ilias Tsitsimpis
    def _wait_transition(self, server_id, current_status, new_status):
169 525f2979 Ilias Tsitsimpis
        """Wait for server to go from current_status to new_status"""
170 525f2979 Ilias Tsitsimpis
        self.logger.debug("Waiting for server to become %s" % new_status)
171 525f2979 Ilias Tsitsimpis
        timeout = self.config.getint('Global', 'build_timeout')
172 525f2979 Ilias Tsitsimpis
        sleep_time = 5
173 525f2979 Ilias Tsitsimpis
        while True:
174 525f2979 Ilias Tsitsimpis
            server = self.cyclades_client.get_server_details(server_id)
175 525f2979 Ilias Tsitsimpis
            if server['status'] == new_status:
176 525f2979 Ilias Tsitsimpis
                return server
177 525f2979 Ilias Tsitsimpis
            elif timeout < 0:
178 525f2979 Ilias Tsitsimpis
                self.logger.error(
179 525f2979 Ilias Tsitsimpis
                    "Waiting for server to become %s timed out" % new_status)
180 525f2979 Ilias Tsitsimpis
                self.destroy_server(False)
181 525f2979 Ilias Tsitsimpis
                sys.exit(-1)
182 525f2979 Ilias Tsitsimpis
            elif server['status'] == current_status:
183 525f2979 Ilias Tsitsimpis
                # Sleep for #n secs and continue
184 525f2979 Ilias Tsitsimpis
                timeout = timeout - sleep_time
185 525f2979 Ilias Tsitsimpis
                time.sleep(sleep_time)
186 525f2979 Ilias Tsitsimpis
            else:
187 525f2979 Ilias Tsitsimpis
                self.logger.error(
188 525f2979 Ilias Tsitsimpis
                    "Server failed with status %s" % server['status'])
189 525f2979 Ilias Tsitsimpis
                self.destroy_server(False)
190 525f2979 Ilias Tsitsimpis
                sys.exit(-1)
191 525f2979 Ilias Tsitsimpis
192 525f2979 Ilias Tsitsimpis
    @_check_kamaki
193 525f2979 Ilias Tsitsimpis
    def destroy_server(self, wait=True):
194 525f2979 Ilias Tsitsimpis
        """Destroy slave server"""
195 525f2979 Ilias Tsitsimpis
        server_id = self.config.getint('Temporary Options', 'server_id')
196 525f2979 Ilias Tsitsimpis
        self.logger.info("Destoying server with id %s " % server_id)
197 525f2979 Ilias Tsitsimpis
        self.cyclades_client.delete_server(server_id)
198 525f2979 Ilias Tsitsimpis
        if wait:
199 525f2979 Ilias Tsitsimpis
            self._wait_transition(server_id, "ACTIVE", "DELETED")
200 525f2979 Ilias Tsitsimpis
201 525f2979 Ilias Tsitsimpis
    @_check_kamaki
202 947b6106 Christos Stavrakakis
    def create_server(self, image_id=None, flavor_id=None):
203 525f2979 Ilias Tsitsimpis
        """Create slave server"""
204 525f2979 Ilias Tsitsimpis
        self.logger.info("Create a new server..")
205 947b6106 Christos Stavrakakis
        if image_id is None:
206 947b6106 Christos Stavrakakis
            image = self._find_image()
207 947b6106 Christos Stavrakakis
            self.logger.debug("Will use image \"%s\"" % _green(image['name']))
208 947b6106 Christos Stavrakakis
            image_id = image["id"]
209 947b6106 Christos Stavrakakis
        self.logger.debug("Image has id %s" % _green(image_id))
210 947b6106 Christos Stavrakakis
        if flavor_id is None:
211 947b6106 Christos Stavrakakis
            flavor_id = self.config.getint("Deployment", "flavor_id")
212 525f2979 Ilias Tsitsimpis
        server = self.cyclades_client.create_server(
213 525f2979 Ilias Tsitsimpis
            self.config.get('Deployment', 'server_name'),
214 947b6106 Christos Stavrakakis
            flavor_id,
215 947b6106 Christos Stavrakakis
            image_id)
216 525f2979 Ilias Tsitsimpis
        server_id = server['id']
217 525f2979 Ilias Tsitsimpis
        self.write_config('server_id', server_id)
218 525f2979 Ilias Tsitsimpis
        self.logger.debug("Server got id %s" % _green(server_id))
219 525f2979 Ilias Tsitsimpis
        server_user = server['metadata']['users']
220 525f2979 Ilias Tsitsimpis
        self.write_config('server_user', server_user)
221 525f2979 Ilias Tsitsimpis
        self.logger.debug("Server's admin user is %s" % _green(server_user))
222 525f2979 Ilias Tsitsimpis
        server_passwd = server['adminPass']
223 525f2979 Ilias Tsitsimpis
        self.write_config('server_passwd', server_passwd)
224 525f2979 Ilias Tsitsimpis
225 525f2979 Ilias Tsitsimpis
        server = self._wait_transition(server_id, "BUILD", "ACTIVE")
226 525f2979 Ilias Tsitsimpis
        self._get_server_ip_and_port(server)
227 5c3b5c9f Christos Stavrakakis
        self._copy_ssh_keys()
228 525f2979 Ilias Tsitsimpis
229 525f2979 Ilias Tsitsimpis
        self.setup_fabric()
230 525f2979 Ilias Tsitsimpis
        self.logger.info("Setup firewall")
231 525f2979 Ilias Tsitsimpis
        accept_ssh_from = self.config.get('Global', 'filter_access_network')
232 525f2979 Ilias Tsitsimpis
        self.logger.debug("Block ssh except from %s" % accept_ssh_from)
233 525f2979 Ilias Tsitsimpis
        cmd = """
234 c04c5379 Ilias Tsitsimpis
        local_ip=$(/sbin/ifconfig eth0 | grep 'inet addr:' | \
235 c04c5379 Ilias Tsitsimpis
            cut -d':' -f2 | cut -d' ' -f1)
236 525f2979 Ilias Tsitsimpis
        iptables -A INPUT -s localhost -j ACCEPT
237 2255812d Ilias Tsitsimpis
        iptables -A INPUT -s $local_ip -j ACCEPT
238 525f2979 Ilias Tsitsimpis
        iptables -A INPUT -s {0} -p tcp --dport 22 -j ACCEPT
239 525f2979 Ilias Tsitsimpis
        iptables -A INPUT -p tcp --dport 22 -j DROP
240 525f2979 Ilias Tsitsimpis
        """.format(accept_ssh_from)
241 525f2979 Ilias Tsitsimpis
        _run(cmd, False)
242 525f2979 Ilias Tsitsimpis
243 525f2979 Ilias Tsitsimpis
    def _find_image(self):
244 525f2979 Ilias Tsitsimpis
        """Find a suitable image to use
245 525f2979 Ilias Tsitsimpis

246 525f2979 Ilias Tsitsimpis
        It has to belong to the `system_uuid' user and
247 525f2979 Ilias Tsitsimpis
        contain the word `image_name'
248 525f2979 Ilias Tsitsimpis
        """
249 525f2979 Ilias Tsitsimpis
        system_uuid = self.config.get('Deployment', 'system_uuid')
250 525f2979 Ilias Tsitsimpis
        image_name = self.config.get('Deployment', 'image_name').lower()
251 525f2979 Ilias Tsitsimpis
        images = self.image_client.list_public(detail=True)['images']
252 525f2979 Ilias Tsitsimpis
        # Select images by `system_uuid' user
253 525f2979 Ilias Tsitsimpis
        images = [x for x in images if x['user_id'] == system_uuid]
254 525f2979 Ilias Tsitsimpis
        # Select images with `image_name' in their names
255 525f2979 Ilias Tsitsimpis
        images = \
256 525f2979 Ilias Tsitsimpis
            [x for x in images if x['name'].lower().find(image_name) != -1]
257 525f2979 Ilias Tsitsimpis
        # Let's select the first one
258 525f2979 Ilias Tsitsimpis
        return images[0]
259 525f2979 Ilias Tsitsimpis
260 525f2979 Ilias Tsitsimpis
    def _get_server_ip_and_port(self, server):
261 525f2979 Ilias Tsitsimpis
        """Compute server's IPv4 and ssh port number"""
262 525f2979 Ilias Tsitsimpis
        self.logger.info("Get server connection details..")
263 525f2979 Ilias Tsitsimpis
        server_ip = server['attachments'][0]['ipv4']
264 ddd240ff Christos Stavrakakis
        if ".okeanos.io" in self.cyclades_client.base_url:
265 525f2979 Ilias Tsitsimpis
            tmp1 = int(server_ip.split(".")[2])
266 525f2979 Ilias Tsitsimpis
            tmp2 = int(server_ip.split(".")[3])
267 525f2979 Ilias Tsitsimpis
            server_ip = "gate.okeanos.io"
268 525f2979 Ilias Tsitsimpis
            server_port = 10000 + tmp1 * 256 + tmp2
269 525f2979 Ilias Tsitsimpis
        else:
270 525f2979 Ilias Tsitsimpis
            server_port = 22
271 525f2979 Ilias Tsitsimpis
        self.write_config('server_ip', server_ip)
272 525f2979 Ilias Tsitsimpis
        self.logger.debug("Server's IPv4 is %s" % _green(server_ip))
273 525f2979 Ilias Tsitsimpis
        self.write_config('server_port', server_port)
274 525f2979 Ilias Tsitsimpis
        self.logger.debug("Server's ssh port is %s" % _green(server_port))
275 525f2979 Ilias Tsitsimpis
276 5c3b5c9f Christos Stavrakakis
    @_check_fabric
277 5c3b5c9f Christos Stavrakakis
    def _copy_ssh_keys(self):
278 5c3b5c9f Christos Stavrakakis
        authorized_keys = self.config.get("Deployment",
279 5c3b5c9f Christos Stavrakakis
                                          "ssh_keys")
280 5c3b5c9f Christos Stavrakakis
        if os.path.exists(authorized_keys):
281 5c3b5c9f Christos Stavrakakis
            keyfile = '/tmp/%s.pub' % fabric.env.user
282 5c3b5c9f Christos Stavrakakis
            _run('mkdir -p ~/.ssh && chmod 700 ~/.ssh', False)
283 5c3b5c9f Christos Stavrakakis
            fabric.put(authorized_keys, keyfile)
284 5c3b5c9f Christos Stavrakakis
            _run('cat %s >> ~/.ssh/authorized_keys' % keyfile, False)
285 5c3b5c9f Christos Stavrakakis
            _run('rm %s' % keyfile, False)
286 5c3b5c9f Christos Stavrakakis
            self.logger.debug("Uploaded ssh authorized keys")
287 5c3b5c9f Christos Stavrakakis
        else:
288 5c3b5c9f Christos Stavrakakis
            self.logger.debug("No ssh keys found")
289 5c3b5c9f Christos Stavrakakis
290 525f2979 Ilias Tsitsimpis
    def write_config(self, option, value, section="Temporary Options"):
291 525f2979 Ilias Tsitsimpis
        """Write changes back to config file"""
292 525f2979 Ilias Tsitsimpis
        try:
293 525f2979 Ilias Tsitsimpis
            self.config.add_section(section)
294 525f2979 Ilias Tsitsimpis
        except DuplicateSectionError:
295 525f2979 Ilias Tsitsimpis
            pass
296 525f2979 Ilias Tsitsimpis
        self.config.set(section, option, str(value))
297 525f2979 Ilias Tsitsimpis
        temp_conf_file = self.config.get('Global', 'temporary_config')
298 525f2979 Ilias Tsitsimpis
        with open(temp_conf_file, 'wb') as tcf:
299 525f2979 Ilias Tsitsimpis
            self.config.write(tcf)
300 525f2979 Ilias Tsitsimpis
301 525f2979 Ilias Tsitsimpis
    def setup_fabric(self):
302 525f2979 Ilias Tsitsimpis
        """Setup fabric environment"""
303 525f2979 Ilias Tsitsimpis
        self.logger.info("Setup fabric parameters..")
304 525f2979 Ilias Tsitsimpis
        fabric.env.user = self.config.get('Temporary Options', 'server_user')
305 525f2979 Ilias Tsitsimpis
        fabric.env.host_string = \
306 525f2979 Ilias Tsitsimpis
            self.config.get('Temporary Options', 'server_ip')
307 133e5a5b Christos Stavrakakis
        fabric.env.port = self.config.getint('Temporary Options',
308 133e5a5b Christos Stavrakakis
                                             'server_port')
309 133e5a5b Christos Stavrakakis
        fabric.env.password = self.config.get('Temporary Options',
310 133e5a5b Christos Stavrakakis
                                              'server_passwd')
311 525f2979 Ilias Tsitsimpis
        fabric.env.connection_attempts = 10
312 525f2979 Ilias Tsitsimpis
        fabric.env.shell = "/bin/bash -c"
313 525f2979 Ilias Tsitsimpis
        fabric.env.disable_known_hosts = True
314 525f2979 Ilias Tsitsimpis
        fabric.env.output_prefix = None
315 525f2979 Ilias Tsitsimpis
316 525f2979 Ilias Tsitsimpis
    def _check_hash_sum(self, localfile, remotefile):
317 525f2979 Ilias Tsitsimpis
        """Check hash sums of two files"""
318 525f2979 Ilias Tsitsimpis
        self.logger.debug("Check hash sum for local file %s" % localfile)
319 525f2979 Ilias Tsitsimpis
        hash1 = os.popen("sha256sum %s" % localfile).read().split(' ')[0]
320 525f2979 Ilias Tsitsimpis
        self.logger.debug("Local file has sha256 hash %s" % hash1)
321 525f2979 Ilias Tsitsimpis
        self.logger.debug("Check hash sum for remote file %s" % remotefile)
322 525f2979 Ilias Tsitsimpis
        hash2 = _run("sha256sum %s" % remotefile, False)
323 525f2979 Ilias Tsitsimpis
        hash2 = hash2.split(' ')[0]
324 525f2979 Ilias Tsitsimpis
        self.logger.debug("Remote file has sha256 hash %s" % hash2)
325 525f2979 Ilias Tsitsimpis
        if hash1 != hash2:
326 525f2979 Ilias Tsitsimpis
            self.logger.error("Hashes differ.. aborting")
327 525f2979 Ilias Tsitsimpis
            sys.exit(-1)
328 525f2979 Ilias Tsitsimpis
329 525f2979 Ilias Tsitsimpis
    @_check_fabric
330 525f2979 Ilias Tsitsimpis
    def clone_repo(self):
331 525f2979 Ilias Tsitsimpis
        """Clone Synnefo repo from slave server"""
332 525f2979 Ilias Tsitsimpis
        self.logger.info("Configure repositories on remote server..")
333 525f2979 Ilias Tsitsimpis
        self.logger.debug("Setup apt, install curl and git")
334 525f2979 Ilias Tsitsimpis
        cmd = """
335 525f2979 Ilias Tsitsimpis
        echo 'APT::Install-Suggests "false";' >> /etc/apt/apt.conf
336 525f2979 Ilias Tsitsimpis
        apt-get update
337 525f2979 Ilias Tsitsimpis
        apt-get install curl git --yes
338 525f2979 Ilias Tsitsimpis
        echo -e "\n\ndeb {0}" >> /etc/apt/sources.list
339 525f2979 Ilias Tsitsimpis
        curl https://dev.grnet.gr/files/apt-grnetdev.pub | apt-key add -
340 525f2979 Ilias Tsitsimpis
        apt-get update
341 525f2979 Ilias Tsitsimpis
        git config --global user.name {1}
342 525f2979 Ilias Tsitsimpis
        git config --global user.mail {2}
343 525f2979 Ilias Tsitsimpis
        """.format(self.config.get('Global', 'apt_repo'),
344 525f2979 Ilias Tsitsimpis
                   self.config.get('Global', 'git_config_name'),
345 525f2979 Ilias Tsitsimpis
                   self.config.get('Global', 'git_config_mail'))
346 525f2979 Ilias Tsitsimpis
        _run(cmd, False)
347 525f2979 Ilias Tsitsimpis
348 525f2979 Ilias Tsitsimpis
        synnefo_repo = self.config.get('Global', 'synnefo_repo')
349 133e5a5b Christos Stavrakakis
        synnefo_branch = self.config.get('Global', 'synnefo_branch')
350 525f2979 Ilias Tsitsimpis
        # Currently clonning synnefo can fail unexpectedly
351 133e5a5b Christos Stavrakakis
        cloned = False
352 525f2979 Ilias Tsitsimpis
        for i in range(3):
353 525f2979 Ilias Tsitsimpis
            self.logger.debug("Clone synnefo from %s" % synnefo_repo)
354 133e5a5b Christos Stavrakakis
            cmd = ("git clone --branch %s %s"
355 133e5a5b Christos Stavrakakis
                   % (synnefo_branch, synnefo_repo))
356 525f2979 Ilias Tsitsimpis
            try:
357 133e5a5b Christos Stavrakakis
                _run(cmd, False)
358 133e5a5b Christos Stavrakakis
                cloned = True
359 525f2979 Ilias Tsitsimpis
                break
360 525f2979 Ilias Tsitsimpis
            except:
361 133e5a5b Christos Stavrakakis
                self.logger.warning("Clonning synnefo failed.. retrying %s"
362 133e5a5b Christos Stavrakakis
                                    % i)
363 133e5a5b Christos Stavrakakis
        if not cloned:
364 133e5a5b Christos Stavrakakis
            self.logger.error("Can not clone Synnefo repo.")
365 133e5a5b Christos Stavrakakis
            sys.exit(-1)
366 525f2979 Ilias Tsitsimpis
367 525f2979 Ilias Tsitsimpis
        deploy_repo = self.config.get('Global', 'deploy_repo')
368 525f2979 Ilias Tsitsimpis
        self.logger.debug("Clone snf-deploy from %s" % deploy_repo)
369 133e5a5b Christos Stavrakakis
        _run("git clone --depth 1 %s" % deploy_repo, False)
370 525f2979 Ilias Tsitsimpis
371 525f2979 Ilias Tsitsimpis
    @_check_fabric
372 525f2979 Ilias Tsitsimpis
    def build_synnefo(self):
373 525f2979 Ilias Tsitsimpis
        """Build Synnefo packages"""
374 525f2979 Ilias Tsitsimpis
        self.logger.info("Build Synnefo packages..")
375 525f2979 Ilias Tsitsimpis
        self.logger.debug("Install development packages")
376 525f2979 Ilias Tsitsimpis
        cmd = """
377 525f2979 Ilias Tsitsimpis
        apt-get update
378 525f2979 Ilias Tsitsimpis
        apt-get install zlib1g-dev dpkg-dev debhelper git-buildpackage \
379 525f2979 Ilias Tsitsimpis
                python-dev python-all python-pip --yes
380 525f2979 Ilias Tsitsimpis
        pip install devflow
381 525f2979 Ilias Tsitsimpis
        """
382 525f2979 Ilias Tsitsimpis
        _run(cmd, False)
383 525f2979 Ilias Tsitsimpis
384 133e5a5b Christos Stavrakakis
        if self.config.get('Global', 'patch_pydist') == "True":
385 525f2979 Ilias Tsitsimpis
            self.logger.debug("Patch pydist.py module")
386 525f2979 Ilias Tsitsimpis
            cmd = r"""
387 525f2979 Ilias Tsitsimpis
            sed -r -i 's/(\(\?P<name>\[A-Za-z\]\[A-Za-z0-9_\.)/\1\\\-/' \
388 525f2979 Ilias Tsitsimpis
                /usr/share/python/debpython/pydist.py
389 525f2979 Ilias Tsitsimpis
            """
390 525f2979 Ilias Tsitsimpis
            _run(cmd, False)
391 525f2979 Ilias Tsitsimpis

392 525f2979 Ilias Tsitsimpis
        self.logger.debug("Build snf-deploy package")
393 525f2979 Ilias Tsitsimpis
        cmd = """
394 525f2979 Ilias Tsitsimpis
        git checkout -t origin/debian
395 525f2979 Ilias Tsitsimpis
        git-buildpackage --git-upstream-branch=master \
396 525f2979 Ilias Tsitsimpis
                --git-debian-branch=debian \
397 525f2979 Ilias Tsitsimpis
                --git-export-dir=../snf-deploy_build-area \
398 525f2979 Ilias Tsitsimpis
                -uc -us
399 525f2979 Ilias Tsitsimpis
        """
400 525f2979 Ilias Tsitsimpis
        with fabric.cd("snf-deploy"):
401 525f2979 Ilias Tsitsimpis
            _run(cmd, True)
402 525f2979 Ilias Tsitsimpis

403 525f2979 Ilias Tsitsimpis
        self.logger.debug("Install snf-deploy package")
404 525f2979 Ilias Tsitsimpis
        cmd = """
405 525f2979 Ilias Tsitsimpis
        dpkg -i snf-deploy*.deb
406 525f2979 Ilias Tsitsimpis
        apt-get -f install --yes
407 525f2979 Ilias Tsitsimpis
        """
408 525f2979 Ilias Tsitsimpis
        with fabric.cd("snf-deploy_build-area"):
409 525f2979 Ilias Tsitsimpis
            with fabric.settings(warn_only=True):
410 525f2979 Ilias Tsitsimpis
                _run(cmd, True)
411 525f2979 Ilias Tsitsimpis

412 525f2979 Ilias Tsitsimpis
        self.logger.debug("Build synnefo packages")
413 525f2979 Ilias Tsitsimpis
        cmd = """
414 525f2979 Ilias Tsitsimpis
        devflow-autopkg snapshot -b ~/synnefo_build-area --no-sign
415 525f2979 Ilias Tsitsimpis
        """
416 525f2979 Ilias Tsitsimpis
        with fabric.cd("synnefo"):
417 525f2979 Ilias Tsitsimpis
            _run(cmd, True)
418 525f2979 Ilias Tsitsimpis

419 525f2979 Ilias Tsitsimpis
        self.logger.debug("Copy synnefo debs to snf-deploy packages dir")
420 525f2979 Ilias Tsitsimpis
        cmd = """
421 525f2979 Ilias Tsitsimpis
        cp ~/synnefo_build-area/*.deb /var/lib/snf-deploy/packages/
422 525f2979 Ilias Tsitsimpis
        """
423 525f2979 Ilias Tsitsimpis
        _run(cmd, False)
424 525f2979 Ilias Tsitsimpis

425 525f2979 Ilias Tsitsimpis
    @_check_fabric
426 525f2979 Ilias Tsitsimpis
    def deploy_synnefo(self):
427 525f2979 Ilias Tsitsimpis
        """Deploy Synnefo using snf-deploy"""
428 525f2979 Ilias Tsitsimpis
        self.logger.info("Deploy Synnefo..")
429 525f2979 Ilias Tsitsimpis
        schema = self.config.get('Global', 'schema')
430 525f2979 Ilias Tsitsimpis
        schema_files = os.path.join(self.ci_dir, "schemas/%s/*" % schema)
431 525f2979 Ilias Tsitsimpis
        self.logger.debug("Will use %s schema" % schema)
432 525f2979 Ilias Tsitsimpis

433 525f2979 Ilias Tsitsimpis
        self.logger.debug("Upload schema files to server")
434 525f2979 Ilias Tsitsimpis
        with fabric.quiet():
435 525f2979 Ilias Tsitsimpis
            fabric.put(schema_files, "/etc/snf-deploy/")
436 525f2979 Ilias Tsitsimpis

437 525f2979 Ilias Tsitsimpis
        self.logger.debug("Change password in nodes.conf file")
438 525f2979 Ilias Tsitsimpis
        cmd = """
439 525f2979 Ilias Tsitsimpis
        sed -i 's/^password =.*/password = {0}/' /etc/snf-deploy/nodes.conf
440 525f2979 Ilias Tsitsimpis
        """.format(fabric.env.password)
441 525f2979 Ilias Tsitsimpis
        _run(cmd, False)
442 525f2979 Ilias Tsitsimpis

443 525f2979 Ilias Tsitsimpis
        self.logger.debug("Run snf-deploy")
444 525f2979 Ilias Tsitsimpis
        cmd = """
445 525f2979 Ilias Tsitsimpis
        snf-deploy all --autoconf
446 525f2979 Ilias Tsitsimpis
        """
447 525f2979 Ilias Tsitsimpis
        _run(cmd, True)
448 525f2979 Ilias Tsitsimpis

449 525f2979 Ilias Tsitsimpis
    @_check_fabric
450 525f2979 Ilias Tsitsimpis
    def unit_test(self):
451 525f2979 Ilias Tsitsimpis
        """Run Synnefo unit test suite"""
452 525f2979 Ilias Tsitsimpis
        self.logger.info("Run Synnefo unit test suite")
453 525f2979 Ilias Tsitsimpis
        component = self.config.get('Unit Tests', 'component')
454 525f2979 Ilias Tsitsimpis

455 525f2979 Ilias Tsitsimpis
        self.logger.debug("Install needed packages")
456 525f2979 Ilias Tsitsimpis
        cmd = """
457 525f2979 Ilias Tsitsimpis
        pip install mock
458 525f2979 Ilias Tsitsimpis
        pip install factory_boy
459 525f2979 Ilias Tsitsimpis
        """
460 525f2979 Ilias Tsitsimpis
        _run(cmd, False)
461 525f2979 Ilias Tsitsimpis

462 2255812d Ilias Tsitsimpis
        self.logger.debug("Upload tests.sh file")
463 2255812d Ilias Tsitsimpis
        unit_tests_file = os.path.join(self.ci_dir, "tests.sh")
464 525f2979 Ilias Tsitsimpis
        with fabric.quiet():
465 525f2979 Ilias Tsitsimpis
            fabric.put(unit_tests_file, ".")
466 525f2979 Ilias Tsitsimpis

467 525f2979 Ilias Tsitsimpis
        self.logger.debug("Run unit tests")
468 525f2979 Ilias Tsitsimpis
        cmd = """
469 2255812d Ilias Tsitsimpis
        bash tests.sh {0}
470 525f2979 Ilias Tsitsimpis
        """.format(component)
471 525f2979 Ilias Tsitsimpis
        _run(cmd, True)
472 525f2979 Ilias Tsitsimpis

473 525f2979 Ilias Tsitsimpis
    @_check_fabric
474 525f2979 Ilias Tsitsimpis
    def run_burnin(self):
475 525f2979 Ilias Tsitsimpis
        """Run burnin functional test suite"""
476 525f2979 Ilias Tsitsimpis
        self.logger.info("Run Burnin functional test suite")
477 525f2979 Ilias Tsitsimpis
        cmd = """
478 525f2979 Ilias Tsitsimpis
        auth_url=$(grep -e '^url =' .kamakirc | cut -d' ' -f3)
479 525f2979 Ilias Tsitsimpis
        token=$(grep -e '^token =' .kamakirc | cut -d' ' -f3)
480 525f2979 Ilias Tsitsimpis
        images_user=$(kamaki image list -l | grep owner | \
481 525f2979 Ilias Tsitsimpis
                      cut -d':' -f2 | tr -d ' ')
482 525f2979 Ilias Tsitsimpis
        snf-burnin --auth-url=$auth_url --token=$token \
483 525f2979 Ilias Tsitsimpis
            --force-flavor=2 --image-id=all \
484 525f2979 Ilias Tsitsimpis
            --system-images-user=$images_user \
485 525f2979 Ilias Tsitsimpis
            {0}
486 525f2979 Ilias Tsitsimpis
        log_folder=$(ls -1d /var/log/burnin/* | tail -n1)
487 525f2979 Ilias Tsitsimpis
        for i in $(ls $log_folder/*/details*); do
488 525f2979 Ilias Tsitsimpis
            echo -e "\\n\\n"
489 525f2979 Ilias Tsitsimpis
            echo -e "***** $i\\n"
490 525f2979 Ilias Tsitsimpis
            cat $i
491 525f2979 Ilias Tsitsimpis
        done
492 525f2979 Ilias Tsitsimpis
        """.format(self.config.get('Burnin', 'cmd_options'))
493 525f2979 Ilias Tsitsimpis
        _run(cmd, True)
494 525f2979 Ilias Tsitsimpis

495 525f2979 Ilias Tsitsimpis
    @_check_fabric
496 525f2979 Ilias Tsitsimpis
    def fetch_packages(self):
497 525f2979 Ilias Tsitsimpis
        """Download Synnefo packages"""
498 525f2979 Ilias Tsitsimpis
        self.logger.info("Download Synnefo packages")
499 525f2979 Ilias Tsitsimpis
        self.logger.debug("Create tarball with packages")
500 525f2979 Ilias Tsitsimpis
        cmd = """
501 525f2979 Ilias Tsitsimpis
        tar czf synnefo_build-area.tgz synnefo_build-area
502 525f2979 Ilias Tsitsimpis
        """
503 525f2979 Ilias Tsitsimpis
        _run(cmd, False)
504 525f2979 Ilias Tsitsimpis

505 525f2979 Ilias Tsitsimpis
        pkgs_dir = self.config.get('Global', 'pkgs_dir')
506 525f2979 Ilias Tsitsimpis
        self.logger.debug("Fetch packages to local dir %s" % pkgs_dir)
507 525f2979 Ilias Tsitsimpis
        os.makedirs(pkgs_dir)
508 525f2979 Ilias Tsitsimpis
        with fabric.quiet():
509 525f2979 Ilias Tsitsimpis
            fabric.get("synnefo_build-area.tgz", pkgs_dir)
510 525f2979 Ilias Tsitsimpis

511 525f2979 Ilias Tsitsimpis
        pkgs_file = os.path.join(pkgs_dir, "synnefo_build-area.tgz")
512 525f2979 Ilias Tsitsimpis
        self._check_hash_sum(pkgs_file, "synnefo_build-area.tgz")
513 525f2979 Ilias Tsitsimpis

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