1
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
5
# Copyright (C) 2017 Canonical
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.
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.
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/>.
21
"""Managers to setup the environment"""
25
from pylxd import Client
26
from pylxd.exceptions import NotFound, LXDAPIException
27
from retrying import retry
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)
37
def get_manager(mode):
38
"""Get the manager for the given mode"""
43
manager = supported_modules[mode]
46
raise RuntimeError("Mode: {} is not supported".format(mode))
50
"""Manage lxd containers"""
53
self.client = Client()
55
def launch(self, container_name, release='16.04'):
56
"""Launch a container"""
58
container = self.client.containers.get(container_name)
59
if container.status == "Running":
60
container.stop(wait=True)
61
container.delete(wait=True)
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)
70
def execute_command(self, container_name, command):
72
container = self.client.containers.get(container_name)
73
container.execute(command)
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(
82
install_command += ' -t {}'.format(channel)
83
container.execute(shlex.split(install_command))
85
def install_dependencies(self, container_name, container_type):
86
"""Install a dependencies"""
89
DEPENDENCIES[container_type] + DEPENDENCIES['shared'])
92
def configure(self, container_name, container_type, profile):
93
"""Configure a given container"""
94
container = self.client.containers.get(container_name)
96
PROFILES[profile][container_type]['environment_variables'].\
98
container.config.update({'environment.{}'.format(
100
container.save(wait=True)
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)
109
os.path.expanduser('~') + '/.ssh/id_rsa.pub').read().strip('\n')
110
container.files.put('/home/ubuntu/.ssh/authorized_keys', pub_key)
113
def setup(self, profile):
114
"""setup the container based on the profile"""
115
self._setup(SNAPD_CONTAINER_NAME, constants.SNAPD, profile)
117
SNAPCRAFT_CONTAINER_NAME, constants.SNAPCRAFT, profile)
120
def _setup(self, container_name, container_type, profile):
122
Launch a container, enable ssh, install dependencies
123
and setup the needed environment variables
125
self.launch(container_name)
126
self.enable_ssh(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)
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']
139
for network in networks:
140
if network['address']:
141
return network['address']
143
"The container {} does not have an IPV4 connection".format(