Merge lp:~racb/ubuntu/saucy/autopkgtest/lxc into lp:ubuntu/saucy/autopkgtest
- Saucy (13.10)
- lxc
- Merge into saucy
Status: | Merged |
---|---|
Merge reported by: | Martin Pitt |
Merged at revision: | not available |
Proposed branch: | lp:~racb/ubuntu/saucy/autopkgtest/lxc |
Merge into: | lp:ubuntu/saucy/autopkgtest |
Diff against target: |
362 lines (+342/-0) 3 files modified
Makefile (+1/-0) virt-subproc/adt-virt-lxc (+217/-0) virt-subproc/adt-virt-lxc.1 (+124/-0) |
To merge this branch: | bzr merge lp:~racb/ubuntu/saucy/autopkgtest/lxc |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Martin Pitt | Approve | ||
Jean-Baptiste Lallement (community) | Needs Fixing | ||
Ubuntu branches | Pending | ||
Review via email: mp+172856@code.launchpad.net |
Commit message
Add LXC support: adt-virt-lxc
Description of the change
Martin Pitt (pitti) wrote : | # |
James Hunt (jamesodhunt) wrote : | # |
Great! This might go some way towards providing the facility outlined on bug 1158391.
Jean-Baptiste Lallement (jibel) wrote : | # |
Thanks for your work!
I tested the following scenarios:
- i386 / amd64
- test package from dsc and source tree
- unbuilt tree and binary package
- clone mode, as well as options ephemeral and eatmydata
Overall it works fine but:
1. If the base container is not created from an ubuntu-cloud template (i.e debootstrap based), the driver goes to an infinite wait loop. It should fail gracefully in that case
2. The requirement for a cloud template means that the usage of this driver is limited to Ubuntu. Using any type of lxc container would allow to run tests in LXC on Debian for example.
3. This requirement is not documented
4. More generally there is no man page for this driver while there are for the other drivers
5. If eatmydata is not installed into the container and the driver is invoked with option --eatmydata then it crashes with
lxc-attach: No such file or directory - failed to exec 'eatmydata'
<VirtSubproc>: failure: (down) mkdir failed (exit status 255)
* It should either:
- Fail gracefully,
- or install eatmydata if not installed (but an implicit installation might be confusing and affect the test)
- or run without eatmydata (and display a warning)
I think at least 1, 3 and 5 should be fixed
Iain Lane (laney) wrote : | # |
→ WIP based on the last comments. Please reset to Needs Review once addressed.
Robie Basak (racb) wrote : | # |
Thanks for the review, Jean-Baptiste. I've addressed 1, 3, 4 and 5. This driver could in theory work in Debian with Debian's cloud-init. The only real issue is that there's no standard way to detect if an LXC container has finished booting, so I used cloud-init's boot-finished sentinel file.
Specifically:
> 1. If the base container is not created from an ubuntu-cloud template (i.e debootstrap based), the driver goes to an infinite wait loop. It should fail gracefully in that case
Now explicitly checked and fails with a specific error message for this case.
> 2. The requirement for a cloud template means that the usage of this driver is limited to Ubuntu. Using any type of lxc container would allow to run tests in LXC on Debian for example.
As above. Anything with cloud-init should work, and if we can have some generic lxc-wait type mechanism for boot finished detection, we could expand support in the future.
> 3. This requirement is not documented
> 4. More generally there is no man page for this driver while there are for the other drivers
Man page written.
> 5. If eatmydata is not installed into the container and the driver is invoked with option --eatmydata then it crashes with...
I now explicitly check that the container has eatmydata if --eatmydata is specified, and fail with a specific error in that case. I thought that this would be better than printing a warning, as chances are that the developer won't see it (and the developer can trivially work around the problem by not using the --eatmydata option). Like you, I felt that an implicit installation might be confusing.
Martin Pitt (pitti) wrote : | # |
Thanks for the updates!
I adjusted the code to be PEP8 compliant and fixed the pyflakes errors, and pushed to the Debian git:
http://
I also created a set of test cases:
http://
I'm closing this MP now. It's not formally merged into the ubuntu branch, but we'll sync it in the t-series.
Thanks!
Preview Diff
1 | === modified file 'Makefile' | |||
2 | --- Makefile 2011-07-30 17:57:27 +0000 | |||
3 | +++ Makefile 2013-10-16 16:21:23 +0000 | |||
4 | @@ -26,6 +26,7 @@ | |||
5 | 26 | virt-subproc/adt-virt-xenlvm \ | 26 | virt-subproc/adt-virt-xenlvm \ |
6 | 27 | virt-subproc/adt-virt-null \ | 27 | virt-subproc/adt-virt-null \ |
7 | 28 | virt-subproc/adt-virt-schroot \ | 28 | virt-subproc/adt-virt-schroot \ |
8 | 29 | virt-subproc/adt-virt-lxc \ | ||
9 | 29 | runner/adt-run \ | 30 | runner/adt-run \ |
10 | 30 | runner/adt-testreport-onepackage \ | 31 | runner/adt-testreport-onepackage \ |
11 | 31 | runner/adt-testreport-runloop \ | 32 | runner/adt-testreport-runloop \ |
12 | 32 | 33 | ||
13 | === added file 'virt-subproc/adt-virt-lxc' | |||
14 | --- virt-subproc/adt-virt-lxc 1970-01-01 00:00:00 +0000 | |||
15 | +++ virt-subproc/adt-virt-lxc 2013-10-16 16:21:23 +0000 | |||
16 | @@ -0,0 +1,217 @@ | |||
17 | 1 | #!/usr/bin/python | ||
18 | 2 | # | ||
19 | 3 | # adt-virt-lxc is part of autopkgtest | ||
20 | 4 | # autopkgtest is a tool for testing Debian binary packages | ||
21 | 5 | # | ||
22 | 6 | # autopkgtest is Copyright (C) 2006-2007, 2013 Canonical Ltd. | ||
23 | 7 | # | ||
24 | 8 | # adt-virt-lxc was derived from adt-virt-schroot and modified to suit LXC by | ||
25 | 9 | # Robie Basak <robie.basak@canonical.com>. | ||
26 | 10 | # | ||
27 | 11 | # This program is free software; you can redistribute it and/or modify | ||
28 | 12 | # it under the terms of the GNU General Public License as published by | ||
29 | 13 | # the Free Software Foundation; either version 2 of the License, or | ||
30 | 14 | # (at your option) any later version. | ||
31 | 15 | # | ||
32 | 16 | # This program is distributed in the hope that it will be useful, | ||
33 | 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
34 | 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
35 | 19 | # GNU General Public License for more details. | ||
36 | 20 | # | ||
37 | 21 | # You should have received a copy of the GNU General Public License | ||
38 | 22 | # along with this program; if not, write to the Free Software | ||
39 | 23 | # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
40 | 24 | # | ||
41 | 25 | # See the file CREDITS for a full list of credits information (often | ||
42 | 26 | # installed as /usr/share/doc/autopkgtest/CREDITS). | ||
43 | 27 | |||
44 | 28 | import sys | ||
45 | 29 | import os | ||
46 | 30 | import string | ||
47 | 31 | import re as regexp | ||
48 | 32 | import grp | ||
49 | 33 | import pwd | ||
50 | 34 | from optparse import OptionParser | ||
51 | 35 | import random | ||
52 | 36 | import subprocess | ||
53 | 37 | import time | ||
54 | 38 | |||
55 | 39 | LXC_WAIT_RETRY_TIME = 0.2 | ||
56 | 40 | |||
57 | 41 | try: our_base = os.environ['AUTOPKGTEST_BASE']+'/lib' | ||
58 | 42 | except KeyError: our_base = '/usr/share/autopkgtest/python'; | ||
59 | 43 | sys.path.insert(1, our_base) | ||
60 | 44 | |||
61 | 45 | import VirtSubproc as vsp | ||
62 | 46 | |||
63 | 47 | def pw_uid(exp_name): | ||
64 | 48 | try: | ||
65 | 49 | return pwd.getpwnam(exp_name).pw_uid | ||
66 | 50 | except KeyError: | ||
67 | 51 | return None | ||
68 | 52 | |||
69 | 53 | def gr_gid(exp_name): | ||
70 | 54 | try: | ||
71 | 55 | return grp.getgrnam(exp_name).gr_gid | ||
72 | 56 | except KeyError: | ||
73 | 57 | return None | ||
74 | 58 | |||
75 | 59 | def match(exp_names, ids, extract_id): | ||
76 | 60 | for exp_name in [n for n in exp_names.split(',') if n]: | ||
77 | 61 | if extract_id(exp_name) in ids: | ||
78 | 62 | return True | ||
79 | 63 | return False | ||
80 | 64 | |||
81 | 65 | def parse_args(): | ||
82 | 66 | global lxc_template, debuglevel, eatmydata, ephemeral | ||
83 | 67 | |||
84 | 68 | usage = "%prog [<options>] <template>" | ||
85 | 69 | parser = OptionParser(usage=usage) | ||
86 | 70 | pa = parser.add_option | ||
87 | 71 | pe = parser.error | ||
88 | 72 | |||
89 | 73 | pa('-d', '--debug', action='store_true', dest='debug'); | ||
90 | 74 | pa('--eatmydata', action='store_true') | ||
91 | 75 | pa('--ephemeral', action='store_true') | ||
92 | 76 | |||
93 | 77 | (opts,args) = parser.parse_args() | ||
94 | 78 | if len(args) != 1: pe("need exactly one arg, template lxc container name") | ||
95 | 79 | |||
96 | 80 | lxc_template = args[0] | ||
97 | 81 | eatmydata = opts.eatmydata | ||
98 | 82 | ephemeral = opts.ephemeral | ||
99 | 83 | |||
100 | 84 | vsp.debuglevel = opts.debug | ||
101 | 85 | |||
102 | 86 | def check_for_cloud_init(container, template_name): | ||
103 | 87 | with open('/dev/null', 'wb') as null: | ||
104 | 88 | result = subprocess.call( | ||
105 | 89 | ['sudo', 'lxc-attach', '-n', container, '--', 'dpkg-query', '-W', | ||
106 | 90 | 'cloud-init'], | ||
107 | 91 | close_fds=True, stdout=null, stderr=null) | ||
108 | 92 | if result: | ||
109 | 93 | raise RuntimeError( | ||
110 | 94 | ("Container %s does not use cloud-init, and this driver " + | ||
111 | 95 | "requires it. Use eg. " + | ||
112 | 96 | "\"lxc-create -t ubuntu-cloud ...\" to create your " + | ||
113 | 97 | "container instead.") | ||
114 | 98 | % repr(template_name) | ||
115 | 99 | ) | ||
116 | 100 | |||
117 | 101 | def check_for_eatmydata(container, template_name): | ||
118 | 102 | with open('/dev/null', 'wb') as null: | ||
119 | 103 | result = subprocess.call( | ||
120 | 104 | ['sudo', 'lxc-attach', '-n', container, '--', 'sh', '-c', | ||
121 | 105 | 'command -v eatmydata'], | ||
122 | 106 | close_fds=True, stdout=null, stderr=null) | ||
123 | 107 | if result: | ||
124 | 108 | raise RuntimeError( | ||
125 | 109 | ("Container %s does not contain eatmydata, which is required " | ||
126 | 110 | "for the --eatmydata option." | ||
127 | 111 | % repr(template_name)) | ||
128 | 112 | ) | ||
129 | 113 | |||
130 | 114 | def full_path_split(path): | ||
131 | 115 | head, tail = os.path.split(os.path.normpath(path)) | ||
132 | 116 | if head in ['', os.path.sep, 2 * os.path.sep]: | ||
133 | 117 | return [head, tail] | ||
134 | 118 | else: | ||
135 | 119 | return full_path_split(head) + [tail] | ||
136 | 120 | |||
137 | 121 | def wait_for_lexists(path): | ||
138 | 122 | vsp.debug('waiting for %s to exist' % repr(path)) | ||
139 | 123 | while not os.path.lexists(path): | ||
140 | 124 | time.sleep(LXC_WAIT_RETRY_TIME) | ||
141 | 125 | |||
142 | 126 | def wait_for_lxc_guest_start(lxc_name, template_name): | ||
143 | 127 | check_for_cloud_init(lxc_name, template_name) | ||
144 | 128 | for subdir in ['delta0', 'rootfs']: | ||
145 | 129 | host_guest_root = '/var/lib/lxc/%s/%s' % (lxc_name, subdir) | ||
146 | 130 | if os.path.lexists(host_guest_root): | ||
147 | 131 | break | ||
148 | 132 | else: | ||
149 | 133 | raise RuntimeError( | ||
150 | 134 | "Failed to find host root directory for container %s." % | ||
151 | 135 | repr(lxc_name) | ||
152 | 136 | ) | ||
153 | 137 | host_instance_path = os.path.join( | ||
154 | 138 | host_guest_root, 'var/lib/cloud/instance') | ||
155 | 139 | wait_for_lexists(host_instance_path) | ||
156 | 140 | guest_instance_link = os.readlink(host_instance_path) | ||
157 | 141 | # Due to overlayfs, we can sometimes read the link when it doesn't | ||
158 | 142 | # officially exist in the guest. Keep waiting in this case. The | ||
159 | 143 | # "(overlay-whiteout)" string is defined by the overlayfs module. | ||
160 | 144 | while guest_instance_link == '(overlay-whiteout)': # do not translate | ||
161 | 145 | time.sleep(LXC_WAIT_RETRY_TIME) | ||
162 | 146 | guest_instance_link = os.readlink(host_instance_path) | ||
163 | 147 | host_instance_link = os.path.join( | ||
164 | 148 | host_guest_root, *full_path_split(guest_instance_link)[1:]) | ||
165 | 149 | host_boot_finished_path = os.path.join( | ||
166 | 150 | host_instance_link, 'boot-finished') | ||
167 | 151 | wait_for_lexists(host_boot_finished_path) | ||
168 | 152 | |||
169 | 153 | def generate_random_lxc_container_name(): | ||
170 | 154 | return ('adt-virt-lxc-' + | ||
171 | 155 | ''.join([random.choice(string.ascii_lowercase) for i in range(6)])) | ||
172 | 156 | |||
173 | 157 | def get_available_lxc_container_name(): | ||
174 | 158 | '''Return an LXC container name that isn't already taken. | ||
175 | 159 | |||
176 | 160 | There is a race condition between returning this name and creation of | ||
177 | 161 | the container. Ideally lxc-start-ephemeral would generate a name in a | ||
178 | 162 | race free way and return the name used in machine-readable way, so that | ||
179 | 163 | this function would not be necessary. See LP: #1197754. | ||
180 | 164 | ''' | ||
181 | 165 | |||
182 | 166 | candidate = generate_random_lxc_container_name() | ||
183 | 167 | while os.path.lexists('/var/lib/lxc/%s' % candidate): | ||
184 | 168 | candidate = generate_random_lxc_container_name() | ||
185 | 169 | return candidate | ||
186 | 170 | |||
187 | 171 | def hook_open(): | ||
188 | 172 | global sessid, downtmp, lxc_container_name | ||
189 | 173 | lxc_container_name = get_available_lxc_container_name() | ||
190 | 174 | if ephemeral: | ||
191 | 175 | vsp.execute('sudo lxc-start-ephemeral -n %s -k -d -o' % lxc_container_name,[lxc_template], downp=False, outp=True) | ||
192 | 176 | else: | ||
193 | 177 | vsp.execute('sudo lxc-clone -n %s -o' % lxc_container_name,[lxc_template], downp=False, outp=True) | ||
194 | 178 | vsp.execute('sudo lxc-start -n %s -d' % lxc_container_name,[], downp=False, outp=True) | ||
195 | 179 | try: | ||
196 | 180 | vsp.debug('waiting for lxc guest start') | ||
197 | 181 | wait_for_lxc_guest_start(lxc_container_name, lxc_template) | ||
198 | 182 | vsp.debug('lxc guest started') | ||
199 | 183 | vsp.down = ['sudo', '-E', 'lxc-attach','-n',lxc_container_name,'--'] | ||
200 | 184 | if eatmydata: | ||
201 | 185 | check_for_eatmydata(lxc_container_name, lxc_template) | ||
202 | 186 | vsp.down.extend(['eatmydata', '--']) | ||
203 | 187 | vsp.downkind = 'auxverb' | ||
204 | 188 | except: | ||
205 | 189 | # Clean up on failure | ||
206 | 190 | vsp.execute('sudo lxc-stop -n',[lxc_container_name], downp=False, outp=True) | ||
207 | 191 | vsp.execute('sudo lxc-destroy -n',[lxc_container_name], downp=False, outp=True) | ||
208 | 192 | raise | ||
209 | 193 | |||
210 | 194 | def hook_downtmp(): | ||
211 | 195 | downtmp = '/tmp/adt-downtmp' | ||
212 | 196 | vsp.execute('mkdir %s' % downtmp, downp=True) | ||
213 | 197 | return downtmp | ||
214 | 198 | |||
215 | 199 | def hook_revert(): | ||
216 | 200 | vsp.downtmp_remove() | ||
217 | 201 | hook_cleanup() | ||
218 | 202 | hook_open() | ||
219 | 203 | |||
220 | 204 | def hook_cleanup(): | ||
221 | 205 | global sessid, downtmp | ||
222 | 206 | vsp.downtmp_remove() | ||
223 | 207 | vsp.execute('sudo lxc-stop -n',[lxc_container_name], downp=False, outp=True) | ||
224 | 208 | vsp.execute('sudo lxc-destroy -n',[lxc_container_name], downp=False, outp=True) | ||
225 | 209 | |||
226 | 210 | def hook_forked_inchild(): | ||
227 | 211 | pass | ||
228 | 212 | |||
229 | 213 | def hook_capabilities(): | ||
230 | 214 | return ['revert', 'revert-full-system', 'root-on-testbed', 'suggested-normal-user=ubuntu'] | ||
231 | 215 | |||
232 | 216 | parse_args() | ||
233 | 217 | vsp.main() | ||
234 | 0 | 218 | ||
235 | === added file 'virt-subproc/adt-virt-lxc.1' | |||
236 | --- virt-subproc/adt-virt-lxc.1 1970-01-01 00:00:00 +0000 | |||
237 | +++ virt-subproc/adt-virt-lxc.1 2013-10-16 16:21:23 +0000 | |||
238 | @@ -0,0 +1,124 @@ | |||
239 | 1 | .TH adt\-virt-lxc 1 2013 "Linux Programmer's Manual" | ||
240 | 2 | .SH NAME | ||
241 | 3 | adt\-virt\-lxc \- autopkgtest virtualisation server using LXC | ||
242 | 4 | .SH SYNOPSYS | ||
243 | 5 | .B adt\-virt\-lxc | ||
244 | 6 | .RB [ \-\-d | \-\-debug ] | ||
245 | 7 | .RB [ \-\-eatmydata ] | ||
246 | 8 | .RB [ \-\-ephemeral ] | ||
247 | 9 | .I lxc\-template | ||
248 | 10 | .SH DESCRIPTION | ||
249 | 11 | .B adt-virt-lxc | ||
250 | 12 | provides an autopkgtest virtualisation server using LXC. It adapts the raw | ||
251 | 13 | functionality provided by the | ||
252 | 14 | .BR lxc- * | ||
253 | 15 | tools for use by autopkgtest. | ||
254 | 16 | |||
255 | 17 | Normally | ||
256 | 18 | .B adt-virt-lxc | ||
257 | 19 | will be invoked by | ||
258 | 20 | .BR adt-run . | ||
259 | 21 | |||
260 | 22 | .SH REQUIREMENTS | ||
261 | 23 | .B adt-virt-lxc | ||
262 | 24 | assumes that you have already prepared a suitable LXC template container. The | ||
263 | 25 | template must be Debian-based and use cloud-init. \fBdebootstrap\fR(8)-based | ||
264 | 26 | containers such as those created with the \fIdebian\fR or \fIubuntu\fR LXC | ||
265 | 27 | templates will not work. | ||
266 | 28 | |||
267 | 29 | On Ubuntu, you can automatically download and install a suitable template using | ||
268 | 30 | the command: | ||
269 | 31 | |||
270 | 32 | .RS | ||
271 | 33 | .EX | ||
272 | 34 | lxc-create -t ubuntu-cloud -n adt -- -r $(distro-info --devel) -d daily | ||
273 | 35 | .EE | ||
274 | 36 | .RE | ||
275 | 37 | |||
276 | 38 | The supplied LXC template must be clean. The \fBcloud-init\fR | ||
277 | 39 | \fI/var/cloud/instance\fR symlink should not exist, and the subsequent | ||
278 | 40 | \fI/var/lib/cloud/instance/boot-finished\fR should also not exist. If you start | ||
279 | 41 | your template container in order to modify it, make sure you remove these | ||
280 | 42 | artifacts when you have finished making your modifications. | ||
281 | 43 | |||
282 | 44 | |||
283 | 45 | .SH OPTIONS | ||
284 | 46 | .TP | ||
285 | 47 | .B --eatmydata | ||
286 | 48 | This option is intended for test developer use. It enables the use of | ||
287 | 49 | \fBeatmydata\fR(1) inside the container on all commands in order to improve | ||
288 | 50 | performance. This requires | ||
289 | 51 | .BR eatmydata (1) | ||
290 | 52 | to already be installed inside the supplied template, which you will need to do | ||
291 | 53 | manually. | ||
292 | 54 | |||
293 | 55 | However, since eatmydata is not part of the dep8 specification and may affect | ||
294 | 56 | the test | ||
295 | 57 | environment, it is not recommended for use in automation. | ||
296 | 58 | .TP | ||
297 | 59 | .B --ephemeral | ||
298 | 60 | This option makes use of lxc-start-ephemeral to create temporary containers, | ||
299 | 61 | instead of the default behaviour of cloning your containers. This can be used | ||
300 | 62 | to dramatically improve performance, although you may see issues due to the | ||
301 | 63 | overlayfs filesystem as used by lxc-start-ephemeral not being completely | ||
302 | 64 | transparent. To avoid issues, you should not use this option in automation. | ||
303 | 65 | .TP | ||
304 | 66 | .BR \-d " | " \-\-debug | ||
305 | 67 | Enables debugging output. | ||
306 | 68 | .SH INPUT, OUTPUT AND EXIT STATUS | ||
307 | 69 | The behaviour of | ||
308 | 70 | .B adt-virt-lxc | ||
309 | 71 | is as described by the AutomatedTesting virtualisation regime | ||
310 | 72 | specification. | ||
311 | 73 | |||
312 | 74 | .SH NOTES | ||
313 | 75 | |||
314 | 76 | \fBadt-run\fR assumes it can use \fBfakeroot\fR(1) to gain root for the | ||
315 | 77 | \fIbinary\fR target in a package build. If \fBfakeroot\fR(1) isn't available in | ||
316 | 78 | your template container, you should use \fBadt-run\fR's \fB\-\-gain\-root\fR | ||
317 | 79 | option to specify what to use instead. On Ubuntu, you can use | ||
318 | 80 | \fB\-\-gain\-root=sudo\fR since this is included in Ubuntu cloud images | ||
319 | 81 | configured to permit root access without a password for the default user. See | ||
320 | 82 | the example below. | ||
321 | 83 | |||
322 | 84 | \fBadt-run\fR does not run \fBapt-get update\fR at the start of a package | ||
323 | 85 | build, which can cause a build failure if you are using a development release | ||
324 | 86 | template. You will need to run \fBapt-get update\fR in the template yourself as | ||
325 | 87 | required, and remove the boot artifacts as discussed in \fBREQUIREMENTS\fR | ||
326 | 88 | before trying again. | ||
327 | 89 | |||
328 | 90 | .SH EXAMPLE | ||
329 | 91 | |||
330 | 92 | On Ubuntu, download and install a suitable template and call it \fIadt\fR: | ||
331 | 93 | |||
332 | 94 | .RS | ||
333 | 95 | .EX | ||
334 | 96 | lxc-create -t ubuntu-cloud -n \fIadt\fR -- -r $(distro-info --devel) -d daily | ||
335 | 97 | .EE | ||
336 | 98 | .RE | ||
337 | 99 | |||
338 | 100 | Run tests against \fIhello_2.8\-4.dsc\fR, using the LXC template \fIadt\fR, | ||
339 | 101 | and with an ephemeral container for speed: | ||
340 | 102 | |||
341 | 103 | .RS | ||
342 | 104 | .EX | ||
343 | 105 | adt-run --gain-root=sudo \fIhello_2.8\-4.dsc\fR --- adt-virt-lxc --ephemeral \fIadt\fR | ||
344 | 106 | .EE | ||
345 | 107 | .RE | ||
346 | 108 | |||
347 | 109 | .SH SEE ALSO | ||
348 | 110 | \fBadt-run\fR(1), | ||
349 | 111 | \fBadt\-virt-null\fR(1), | ||
350 | 112 | \fBadt\-virt-chroot\fR(1), | ||
351 | 113 | \fBeatmydata\fR(1), | ||
352 | 114 | \fB/usr/share/doc/autopkgtest/\fR. | ||
353 | 115 | |||
354 | 116 | .SH AUTHORS AND COPYRIGHT | ||
355 | 117 | .B adt-virt-lxc | ||
356 | 118 | was written by Robie Basak <robie.basak@canonical.com>. | ||
357 | 119 | |||
358 | 120 | This manpage is part of autopkgtest, a tool for testing Debian binary | ||
359 | 121 | packages. autopkgtest is Copyright (C) 2006-2013 Canonical Ltd and others. | ||
360 | 122 | |||
361 | 123 | See \fB/usr/share/doc/autopkgtest/CREDITS\fR for the list of | ||
362 | 124 | contributors and full copying conditions. |
Hey Robie, many thanks for working on this! That's a nice addition.
Some things which I noticed during first spot-check:
+# autopkgtest is Copyright (C) 2006-2007 Canonical Ltd.
Please add a copyright for you, you wrote that file after all.
127 + lxc_container_name = 'adt-virt-lxc-' + ''.join( [random. choice( string. ascii_lowercase ) for i in range(6)]) name,[lxc_ template] , downp=False, outp=True)
128 + vsp.execute('sudo lxc-start-ephemeral -n %s --keep-data -d -o' % lxc_container_
I'm not entirely sure what that does, but it looks like lxc_container_name is a temporary file name of some sort? Would it be more adequate to use the standard mkstemp() function, or is that really just a name? In the latter case, how does this make sure that it doesn't use an existing name?