Merge lp:~sbaldassin/snappy-ecosystem-tests/merge_driver_and_container into lp:snappy-ecosystem-tests

Proposed by Santiago Baldassin
Status: Merged
Approved by: Heber Parrucci
Approved revision: 39
Merged at revision: 34
Proposed branch: lp:~sbaldassin/snappy-ecosystem-tests/merge_driver_and_container
Merge into: lp:snappy-ecosystem-tests
Diff against target: 363 lines (+165/-126)
5 files modified
snappy_ecosystem_tests/environment/containers/lxd.py (+118/-0)
snappy_ecosystem_tests/environment/data/snapd.py (+2/-1)
snappy_ecosystem_tests/environment/managers.py (+27/-122)
snappy_ecosystem_tests/environment/setup.py (+17/-2)
snappy_ecosystem_tests/utils/user.py (+1/-1)
To merge this branch: bzr merge lp:~sbaldassin/snappy-ecosystem-tests/merge_driver_and_container
Reviewer Review Type Date Requested Status
Heber Parrucci (community) Approve
Omer Akram (community) Approve
platform-qa-bot continuous-integration Approve
Review via email: mp+319125@code.launchpad.net

Commit message

Splitting responsibilities between driver and manager

Description of the change

This mp makes a better use of the Manager and Builder and split the responsibilities between them

To post a comment you must log in.
Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Heber Parrucci (heber013) wrote :

Comment inline

review: Needs Fixing
Revision history for this message
Santiago Baldassin (sbaldassin) wrote :

Reply inline

Revision history for this message
Omer Akram (om26er) wrote :

The approach to start multiple containers and not waiting for them is problematic and its enforcing use to use random sleeps. Added inline comment on how that is a problem.

If you really want to start multiple containers, ask pylxd to do that for you in a loop.

review: Needs Fixing
34. By Santiago Baldassin

Addressing comments from the reviews

Revision history for this message
Santiago Baldassin (sbaldassin) wrote :

Thanks for the feedback Omer. All comments were addressed, however, I did leave the option to create containers and not wait and I also leave a wait period for starting the containers faster. Please do take a look

Revision history for this message
Omer Akram (om26er) wrote :

Added inline comment, yesterday I started working on actually fixing the snapd staging environment but when you proposed this branch, it had a potential of conflict. So I am waiting for this branch to either land or the comment that I just made inline addressed.

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
35. By Santiago Baldassin

Fixing pylint

Revision history for this message
Omer Akram (om26er) wrote :

Added comments inline.

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Santiago Baldassin (sbaldassin) wrote :

Thanks Omer, I riplied inline. We'll need a phone call to get everyone on the same page

Revision history for this message
Santiago Baldassin (sbaldassin) wrote :

Replied inline

Revision history for this message
Omer Akram (om26er) wrote :

Added comments inline. Lets aim to land this sooner.

36. By Santiago Baldassin

Addressing comments from the reviews

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
37. By Santiago Baldassin

Minor refactor

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Omer Akram (om26er) wrote :

please merge with trunk, there are conflicts.

review: Needs Fixing
38. By Santiago Baldassin

Merge from trunk

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Omer Akram (om26er) wrote :

Seems jenkins is again having issues. Anyways can you please add this bug report into your `launch` https://github.com/lxc/pylxd/issues/221

Revision history for this message
Heber Parrucci (heber013) wrote :

> Seems jenkins is again having issues. Anyways can you please add this bug
> report into your `launch` https://github.com/lxc/pylxd/issues/221

Actually jenkins is not having issues. There is a pylint issue in the revision:
W: 26, 0: Unused sleep imported from time (unused-import)

Revision history for this message
Omer Akram (om26er) wrote :

hmm, I mis-interpretted the output https://platform-qa-jenkins.ubuntu.com/job/snappy-ecosystem-tests-ci/258/console

had the impression that line: error: <urlopen error Tunnel connection failed: 403 Forbidden> was the cause. But you are right, its pylint complaint that needs fixing.

39. By Santiago Baldassin

Fixing pylint

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Omer Akram (om26er) wrote :

LGTM.

review: Approve
Revision history for this message
Heber Parrucci (heber013) wrote :

Code LGTM. Let's land it.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'snappy_ecosystem_tests/environment/containers'
2=== added file 'snappy_ecosystem_tests/environment/containers/__init__.py'
3=== added file 'snappy_ecosystem_tests/environment/containers/lxd.py'
4--- snappy_ecosystem_tests/environment/containers/lxd.py 1970-01-01 00:00:00 +0000
5+++ snappy_ecosystem_tests/environment/containers/lxd.py 2017-03-08 15:34:35 +0000
6@@ -0,0 +1,118 @@
7+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
8+
9+#
10+# Snappy Ecosystem Tests
11+# Copyright (C) 2017 Canonical
12+#
13+# This program is free software: you can redistribute it and/or modify
14+# it under the terms of the GNU General Public License as published by
15+# the Free Software Foundation, either version 3 of the License, or
16+# (at your option) any later version.
17+#
18+# This program is distributed in the hope that it will be useful,
19+# but WITHOUT ANY WARRANTY; without even the implied warranty of
20+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21+# GNU General Public License for more details.
22+#
23+# You should have received a copy of the GNU General Public License
24+# along with this program. If not, see <http://www.gnu.org/licenses/>.
25+#
26+"""Module top interact with lxd containers"""
27+
28+import os
29+import shlex
30+
31+import logging
32+
33+from pylxd import Client
34+from pylxd.exceptions import LXDAPIException, NotFound
35+from retrying import retry
36+
37+from snappy_ecosystem_tests.environment.data.snapd import (
38+ DEFAULT_CONTAINER_CONFIG)
39+
40+COMMAND_ALLOW_ENV_VARS = 'sed -i \'/^AcceptEnv/ s/$/ {}/\' ' \
41+ '/etc/ssh/sshd_config'
42+
43+LOGGER = logging.getLogger(__name__)
44+DOMAIN_PING = 'ubuntu.com'
45+
46+class LxdDriver:
47+ """Manage lxd containers"""
48+
49+ def __init__(self):
50+ self.client = Client()
51+
52+ def launch(self, containers):
53+ """Launch a container"""
54+ created_containers = []
55+ for cont in containers:
56+
57+ if self.client.containers.exists(cont):
58+ container = self.client.containers.get(cont)
59+ try:
60+ if container.status == "Running":
61+ container.stop(wait=True)
62+ container.delete(wait=True)
63+ except NotFound:
64+ # If using ephemeral stop will delete the container and try
65+ # to sync which will fail because the container does not
66+ # exist. container.delete will be only execute if stop did
67+ # not raise an exception:
68+ # https://github.com/lxc/pylxd/issues/221
69+ pass
70+
71+ container_config = DEFAULT_CONTAINER_CONFIG.copy()
72+ container_config['source']['alias'] = containers[cont]['release']
73+ container_config['name'] = cont
74+ created_containers.append(self.client.containers.create(
75+ container_config, wait=True))
76+ self.start(created_containers)
77+ return created_containers
78+
79+ @staticmethod
80+ def start(containers):
81+ """start all containers received as parameter"""
82+ for cont in containers:
83+ if not cont.state().status == 'Running':
84+ cont.start(wait=True)
85+
86+ @staticmethod
87+ def install(container, packages, channel=None):
88+ """Install packages"""
89+ container.execute(shlex.split('apt-get update'))
90+ install_command = 'apt-get install {} -y'.format(
91+ ' '.join(packages))
92+ if channel:
93+ install_command += ' -t {}'.format(channel)
94+ container.execute(shlex.split(install_command))
95+
96+ @staticmethod
97+ @retry(stop_max_attempt_number=5, wait_fixed=3000,
98+ retry_on_exception=lambda exception: isinstance(
99+ exception, LXDAPIException))
100+ def enable_ssh(container):
101+ """Enable the ssh connection on the container"""
102+ pub_key = open(
103+ os.path.expanduser('~') + '/.ssh/id_rsa.pub').read().strip('\n')
104+ container.files.put('/home/ubuntu/.ssh/authorized_keys', pub_key)
105+
106+ @staticmethod
107+ def get_ip(container):
108+ """Gets the ip address for a given container"""
109+ networks = container.state().network['eth0']['addresses']
110+
111+ for network in networks:
112+ if network['address']:
113+ return network['address']
114+ raise RuntimeError(
115+ "The container {} does not have an IPV4 connection".format(
116+ container.name))
117+
118+ @staticmethod
119+ def export_environment_variables(container,
120+ environment_variables):
121+ """Allow export of environment variables over ssh."""
122+ container.execute(shlex.split(COMMAND_ALLOW_ENV_VARS.format(
123+ ' '.join(environment_variables))))
124+ container.execute(shlex.split('service ssh restart'))
125
126=== modified file 'snappy_ecosystem_tests/environment/data/snapd.py'
127--- snappy_ecosystem_tests/environment/data/snapd.py 2017-03-02 10:51:37 +0000
128+++ snappy_ecosystem_tests/environment/data/snapd.py 2017-03-08 15:34:35 +0000
129@@ -93,5 +93,6 @@
130 "server": "https://cloud-images.ubuntu.com/releases",
131 "protocol": "simplestreams",
132 "fingerprint": "16.04"
133- }
134+ },
135+ "ephemeral": True
136 }
137
138=== modified file 'snappy_ecosystem_tests/environment/managers.py'
139--- snappy_ecosystem_tests/environment/managers.py 2017-03-07 17:41:31 +0000
140+++ snappy_ecosystem_tests/environment/managers.py 2017-03-08 15:34:35 +0000
141@@ -1,7 +1,7 @@
142 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
143
144 #
145-# Ubuntu System Tests
146+# Snappy Ecosystem Tests
147 # Copyright (C) 2017 Canonical
148 #
149 # This program is free software: you can redistribute it and/or modify
150@@ -17,134 +17,39 @@
151 # You should have received a copy of the GNU General Public License
152 # along with this program. If not, see <http://www.gnu.org/licenses/>.
153 #
154-
155 """Managers to setup the environment"""
156
157-import os
158-import shlex
159-from pylxd import Client
160-from pylxd.exceptions import NotFound, LXDAPIException
161-from retrying import retry
162-
163-from snappy_ecosystem_tests.environment import constants
164 from snappy_ecosystem_tests.environment.constants import (
165 PROFILES, DEPENDENCIES)
166-from snappy_ecosystem_tests.environment.data.snapcraft import (
167- SNAPCRAFT_CONTAINER_NAME)
168-from snappy_ecosystem_tests.environment.data.snapd import (
169- DEFAULT_CONTAINER_CONFIG, SNAPD_CONTAINER_NAME)
170-
171-COMMAND_ALLOW_ENV_VARS = 'sed -i \'/^AcceptEnv/ s/$/ {}/\' ' \
172- '/etc/ssh/sshd_config'
173-
174-
175-def get_manager(mode):
176- """Get the manager for the given mode"""
177- supported_modules = {
178- "lxd": LxdManager
179+from snappy_ecosystem_tests.environment.containers.lxd import LxdDriver
180+
181+CONTAINERS = {
182+ "snapd":{
183+ "release": "16.04"
184+ },
185+ "snapcraft":{
186+ "release": "16.04"
187 }
188- try:
189- manager = supported_modules[mode]
190- return manager()
191- except KeyError:
192- raise RuntimeError("Mode: {} is not supported".format(mode))
193-
194-
195-class LxdManager:
196- """Manage lxd containers"""
197+}
198+
199+class _LxdManager:
200+ """Manager for lxd containers"""
201
202 def __init__(self):
203- self.client = Client()
204-
205- def launch(self, container_name, release='16.04'):
206- """Launch a container"""
207- try:
208- container = self.client.containers.get(container_name)
209- if container.status == "Running":
210- container.stop(wait=True)
211- container.delete(wait=True)
212- except NotFound:
213- pass
214- container_config = DEFAULT_CONTAINER_CONFIG.copy()
215- container_config['source']['alias'] = release
216- container_config['name'] = container_name
217- container = self.client.containers.create(container_config, wait=True)
218- container.start(wait=True)
219-
220- def execute_command(self, container_name, command):
221- """execute command"""
222- container = self.client.containers.get(container_name)
223- container.execute(command)
224-
225- def install(self, container_name, packages, channel=None):
226- """Install a packages"""
227- container = self.client.containers.get(container_name)
228- container.execute(shlex.split('apt-get update'))
229- install_command = 'apt-get install {} -y'.format(
230- ' '.join(packages))
231- if channel:
232- install_command += ' -t {}'.format(channel)
233- container.execute(shlex.split(install_command))
234-
235- def install_dependencies(self, container_name, container_type):
236- """Install a dependencies"""
237- self.install(
238- container_name,
239- DEPENDENCIES[container_type] + DEPENDENCIES['shared'])
240-
241- def configure(self, container_name, container_type, profile):
242- """Configure a given container"""
243- container = self.client.containers.get(container_name)
244- for key, value in \
245- PROFILES[profile][container_type]['environment_variables'].\
246- items():
247- container.config.update({'environment.{}'.format(
248- key): value})
249- container.save(wait=True)
250-
251- @retry(stop_max_attempt_number=5, wait_fixed=3000,
252- retry_on_exception=lambda exception: isinstance(
253- exception, LXDAPIException))
254- def enable_ssh(self, container_name, container_type, profile):
255- """Enable the ssh connection on the container"""
256- container = self.client.containers.get(container_name)
257- pub_key = open(
258- os.path.expanduser('~') + '/.ssh/id_rsa.pub').read().strip('\n')
259- container.files.put('/home/ubuntu/.ssh/authorized_keys', pub_key)
260- # Allow export of environment variables over ssh.
261- container.execute(shlex.split(COMMAND_ALLOW_ENV_VARS.format(
262- ' '.join(PROFILES[profile][container_type]
263- ['environment_variables'].keys()))))
264- container.execute(shlex.split('service ssh restart'))
265+ self.driver = LxdDriver()
266
267 def setup(self, profile):
268 """setup the container based on the profile"""
269- self._setup(SNAPD_CONTAINER_NAME, constants.SNAPD, profile)
270- self._setup(
271- SNAPCRAFT_CONTAINER_NAME, constants.SNAPCRAFT, profile)
272-
273- def _setup(self, container_name, container_type, profile):
274- """
275- Launch a container, enable ssh, install dependencies
276- and setup the needed environment variables
277- """
278- self.launch(container_name)
279- self.enable_ssh(container_name, container_type, profile)
280- self.install(
281- container_name,
282- packages=[PROFILES[profile][container_type]["package_name"]],
283- channel=PROFILES[profile][container_type]["channel"])
284- self.install_dependencies(container_name, container_type)
285- self.configure(container_name, container_type, profile)
286-
287- def get_ip(self, container_name):
288- """Gets the ip address for a given container"""
289- networks = self.client.containers.get(
290- container_name).state().network['eth0']['addresses']
291-
292- for network in networks:
293- if network['address']:
294- return network['address']
295- raise RuntimeError(
296- "The container {} does not have an IPV4 connection".format(
297- container_name))
298+ containers = self.driver.launch(CONTAINERS)
299+
300+ for cont in containers:
301+ deps = DEPENDENCIES[cont.name] + DEPENDENCIES["shared"]
302+ self.driver.install(cont, packages=deps)
303+ self.driver.install(
304+ cont,
305+ packages=[PROFILES[profile][cont.name]["package_name"]],
306+ channel=PROFILES[profile][cont.name]["channel"])
307+ self.driver.enable_ssh(cont)
308+ self.driver.export_environment_variables(
309+ cont,
310+ PROFILES[profile][cont.name]["environment_variables"].keys())
311
312=== modified file 'snappy_ecosystem_tests/environment/setup.py'
313--- snappy_ecosystem_tests/environment/setup.py 2017-03-03 18:58:19 +0000
314+++ snappy_ecosystem_tests/environment/setup.py 2017-03-08 15:34:35 +0000
315@@ -1,7 +1,7 @@
316 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
317
318 #
319-# Ubuntu System Tests
320+# Snappy Ecosystem Tests
321 # Copyright (C) 2017 Canonical
322 #
323 # This program is free software: you can redistribute it and/or modify
324@@ -24,11 +24,26 @@
325
326 import logging
327
328-from snappy_ecosystem_tests.environment.managers import get_manager
329+from snappy_ecosystem_tests.environment.managers import _LxdManager
330
331 logging.basicConfig(level=logging.DEBUG)
332
333
334+SUPPORTED_MODULES = {
335+ "lxd": _LxdManager
336+}
337+
338+
339+def get_manager(mode):
340+ """Get the manager for the given mode"""
341+
342+ try:
343+ manager = SUPPORTED_MODULES[mode]
344+ return manager()
345+ except KeyError:
346+ raise RuntimeError("Mode: {} is not supported".format(mode))
347+
348+
349 def main(mode, profile):
350 """Main script"""
351 manager = get_manager(mode)
352
353=== modified file 'snappy_ecosystem_tests/utils/user.py'
354--- snappy_ecosystem_tests/utils/user.py 2017-03-01 21:51:29 +0000
355+++ snappy_ecosystem_tests/utils/user.py 2017-03-08 15:34:35 +0000
356@@ -23,7 +23,7 @@
357 import os
358
359 from snappy_ecosystem_tests.commons.config import USER_CONFIG_STACK
360-from snappy_ecosystem_tests.environment.managers import get_manager
361+from snappy_ecosystem_tests.environment.setup import get_manager
362
363 MANAGER = get_manager(os.environ['target'])
364

Subscribers

People subscribed via source and target branches

to all changes: