~canonical-platform-qa/snappy-ecosystem-tests/remove-unneeded-FIXMEs

« back to all changes in this revision

Viewing changes to snappy_ecosystem_tests/environment/managers.py

  • Committer: Omer Akram
  • Date: 2017-03-03 14:12:16 UTC
  • mfrom: (22.1.6 trunk)
  • Revision ID: om26er@ubuntu.com-20170303141216-ny9pnukubbfhaz9z
merge with trnk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
 
2
 
 
3
#
 
4
# Ubuntu System Tests
 
5
# Copyright (C) 2017 Canonical
 
6
#
 
7
# This program is free software: you can redistribute it and/or modify
 
8
# it under the terms of the GNU General Public License as published by
 
9
# the Free Software Foundation, either version 3 of the License, or
 
10
# (at your option) any later version.
 
11
#
 
12
# This program is distributed in the hope that it will be useful,
 
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
# GNU General Public License for more details.
 
16
#
 
17
# You should have received a copy of the GNU General Public License
 
18
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
#
 
20
 
 
21
"""Managers to setup the environment"""
 
22
 
 
23
import os
 
24
import shlex
 
25
from pylxd import Client
 
26
from pylxd.exceptions import NotFound, LXDAPIException
 
27
from retrying import retry
 
28
 
 
29
from snappy_ecosystem_tests.environment import constants
 
30
from snappy_ecosystem_tests.environment.constants import (
 
31
    PROFILES, DEPENDENCIES)
 
32
from snappy_ecosystem_tests.environment.data.snapcraft import (
 
33
    SNAPCRAFT_CONTAINER_NAME)
 
34
from snappy_ecosystem_tests.environment.data.snapd import (
 
35
    DEFAULT_CONTAINER_CONFIG, SNAPD_CONTAINER_NAME)
 
36
 
 
37
def get_manager(mode):
 
38
    """Get the manager for the given mode"""
 
39
    supported_modules = {
 
40
        "lxd": LxdManager
 
41
    }
 
42
    try:
 
43
        manager = supported_modules[mode]
 
44
        return manager()
 
45
    except KeyError:
 
46
        raise RuntimeError("Mode: {} is not supported".format(mode))
 
47
 
 
48
 
 
49
class LxdManager:
 
50
    """Manage lxd containers"""
 
51
 
 
52
    def __init__(self):
 
53
        self.client = Client()
 
54
 
 
55
    def launch(self, container_name, release='16.04'):
 
56
        """Launch a container"""
 
57
        try:
 
58
            container = self.client.containers.get(container_name)
 
59
            if container.status == "Running":
 
60
                container.stop(wait=True)
 
61
            container.delete(wait=True)
 
62
        except NotFound:
 
63
            pass
 
64
        container_config = DEFAULT_CONTAINER_CONFIG.copy()
 
65
        container_config['source']['alias'] = release
 
66
        container_config['name'] = container_name
 
67
        container = self.client.containers.create(container_config, wait=True)
 
68
        container.start(wait=True)
 
69
 
 
70
    def execute_command(self, container_name, command):
 
71
        """execute command"""
 
72
        container = self.client.containers.get(container_name)
 
73
        container.execute(command)
 
74
 
 
75
    def install(self, container_name, packages, channel=None):
 
76
        """Install a packages"""
 
77
        container = self.client.containers.get(container_name)
 
78
        container.execute(shlex.split('apt-get update'))
 
79
        install_command = 'apt-get install {} -y'.format(
 
80
            ' '.join(packages))
 
81
        if channel:
 
82
            install_command += ' -t {}'.format(channel)
 
83
        container.execute(shlex.split(install_command))
 
84
 
 
85
    def install_dependencies(self, container_name, container_type):
 
86
        """Install a dependencies"""
 
87
        self.install(
 
88
            container_name,
 
89
            DEPENDENCIES[container_type] + DEPENDENCIES['shared'])
 
90
 
 
91
 
 
92
    def configure(self, container_name, container_type, profile):
 
93
        """Configure a given container"""
 
94
        container = self.client.containers.get(container_name)
 
95
        for key, value in \
 
96
                PROFILES[profile][container_type]['environment_variables'].\
 
97
                        items():
 
98
            container.config.update({'environment.{}'.format(
 
99
                key): value})
 
100
        container.save(wait=True)
 
101
 
 
102
    @retry(stop_max_attempt_number=5, wait_fixed=3000,
 
103
           retry_on_exception=lambda exception: isinstance(
 
104
               exception, LXDAPIException))
 
105
    def enable_ssh(self, container_name):
 
106
        """Enable the ssh connection on the container"""
 
107
        container = self.client.containers.get(container_name)
 
108
        pub_key = open(
 
109
            os.path.expanduser('~') + '/.ssh/id_rsa.pub').read().strip('\n')
 
110
        container.files.put('/home/ubuntu/.ssh/authorized_keys', pub_key)
 
111
 
 
112
 
 
113
    def setup(self, profile):
 
114
        """setup the container based on the profile"""
 
115
        self._setup(SNAPD_CONTAINER_NAME, constants.SNAPD, profile)
 
116
        self._setup(
 
117
            SNAPCRAFT_CONTAINER_NAME, constants.SNAPCRAFT, profile)
 
118
 
 
119
 
 
120
    def _setup(self, container_name, container_type, profile):
 
121
        """
 
122
        Launch a container, enable ssh, install dependencies
 
123
        and setup the needed environment variables
 
124
        """
 
125
        self.launch(container_name)
 
126
        self.enable_ssh(container_name)
 
127
        self.install(
 
128
            container_name,
 
129
            packages=[PROFILES[profile][container_type]["package_name"]],
 
130
            channel=PROFILES[profile][container_type]["channel"])
 
131
        self.install_dependencies(container_name, container_type)
 
132
        self.configure(container_name, container_type, profile)
 
133
 
 
134
    def get_ip(self, container_name):
 
135
        """Gets the ip address for a given container"""
 
136
        networks = self.client.containers.get(
 
137
            container_name).state().network['eth0']['addresses']
 
138
 
 
139
        for network in networks:
 
140
            if network['address']:
 
141
                return network['address']
 
142
        raise RuntimeError(
 
143
            "The container {} does not have an IPV4 connection".format(
 
144
                container_name))