Merge lp:~smoser/ubuntu/xenial/curtin/pkg-sru-r437 into lp:~smoser/ubuntu/xenial/curtin/pkg

Proposed by Scott Moser
Status: Merged
Merged at revision: 58
Proposed branch: lp:~smoser/ubuntu/xenial/curtin/pkg-sru-r437
Merge into: lp:~smoser/ubuntu/xenial/curtin/pkg
Diff against target: 1365 lines (+661/-168)
24 files modified
curtin/block/__init__.py (+1/-1)
curtin/commands/apt_config.py (+16/-6)
curtin/commands/block_meta.py (+1/-2)
curtin/commands/curthooks.py (+28/-1)
curtin/deps/__init__.py (+11/-2)
curtin/util.py (+15/-6)
debian/changelog (+20/-0)
debian/new-upstream-snapshot (+47/-3)
examples/tests/centos_basic.yaml (+13/-0)
examples/tests/mirrorboot-msdos-partition.yaml (+82/-0)
helpers/list-flash-kernel-packages (+13/-0)
tests/unittests/test_apt_source.py (+1/-0)
tests/unittests/test_block.py (+2/-0)
tests/unittests/test_curthooks.py (+134/-0)
tests/vmtests/__init__.py (+83/-102)
tests/vmtests/helpers.py (+20/-8)
tests/vmtests/image_sync.py (+31/-17)
tests/vmtests/releases.py (+38/-10)
tests/vmtests/test_apt_config_cmd.py (+4/-0)
tests/vmtests/test_centos_basic.py (+42/-0)
tests/vmtests/test_mdadm_bcache.py (+39/-0)
tests/vmtests/test_raid5_bcache.py (+2/-1)
tools/vmtest-sync-images (+15/-6)
tools/xkvm (+3/-3)
To merge this branch: bzr merge lp:~smoser/ubuntu/xenial/curtin/pkg-sru-r437
Reviewer Review Type Date Requested Status
Ryan Harper (community) Approve
Scott Moser Pending
Review via email: mp+315035@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Ryan Harper (raharper) wrote :

+LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'curtin/block/__init__.py'
2--- curtin/block/__init__.py 2016-10-03 18:43:46 +0000
3+++ curtin/block/__init__.py 2017-01-18 16:16:23 +0000
4@@ -120,7 +120,7 @@
5 """
6 Add number to disk_kname prepending a 'p' if needed
7 """
8- for dev_type in ['nvme', 'mmcblk', 'cciss', 'mpath', 'dm']:
9+ for dev_type in ['nvme', 'mmcblk', 'cciss', 'mpath', 'dm', 'md']:
10 if disk_kname.startswith(dev_type):
11 partition_number = "p%s" % partition_number
12 break
13
14=== modified file 'curtin/commands/apt_config.py'
15--- curtin/commands/apt_config.py 2016-10-03 18:42:29 +0000
16+++ curtin/commands/apt_config.py 2017-01-18 16:16:23 +0000
17@@ -24,6 +24,7 @@
18 import os
19 import re
20 import sys
21+import time
22 import yaml
23
24 from curtin.log import LOG
25@@ -402,13 +403,21 @@
26 ent['filename'] += ".list"
27
28 if aa_repo_match(source):
29- try:
30- with util.ChrootableTarget(
31- target, sys_resolvconf=True) as in_chroot:
32+ with util.ChrootableTarget(
33+ target, sys_resolvconf=True) as in_chroot:
34+ time_entered = time.time()
35+ try:
36 in_chroot.subp(["add-apt-repository", source])
37- except util.ProcessExecutionError:
38- LOG.exception("add-apt-repository failed.")
39- raise
40+ except util.ProcessExecutionError:
41+ LOG.exception("add-apt-repository failed.")
42+ raise
43+ finally:
44+ # workaround to gnupg >=2.x spawning daemons (LP: #1645680)
45+ seconds_since = time.time() - time_entered + 1
46+ in_chroot.subp(['killall', '--wait', '--quiet',
47+ '--younger-than', '%ds' % seconds_since,
48+ '--regexp', '(dirmngr|gpg-agent)'],
49+ rcs=[0, 1])
50 continue
51
52 sourcefn = util.target_path(target, ent['filename'])
53@@ -661,6 +670,7 @@
54 """Populate subcommand option parsing for apt-config"""
55 populate_one_subcmd(parser, CMD_ARGUMENTS, apt_command)
56
57+
58 CONFIG_CLEANERS = {
59 'cloud-init': clean_cloud_init,
60 }
61
62=== modified file 'curtin/commands/block_meta.py'
63--- curtin/commands/block_meta.py 2016-10-03 18:43:46 +0000
64+++ curtin/commands/block_meta.py 2017-01-18 16:16:23 +0000
65@@ -417,8 +417,7 @@
66 try:
67 lbs_path = os.path.join(disk_sysfs_path, 'queue', 'logical_block_size')
68 with open(lbs_path, 'r') as f:
69- l = f.readline()
70- logical_block_size_bytes = int(l)
71+ logical_block_size_bytes = int(f.readline())
72 except:
73 logical_block_size_bytes = 512
74 LOG.debug(
75
76=== modified file 'curtin/commands/curthooks.py'
77--- curtin/commands/curthooks.py 2016-10-03 18:43:46 +0000
78+++ curtin/commands/curthooks.py 2017-01-18 16:16:23 +0000
79@@ -159,6 +159,25 @@
80 in_chroot.subp(['zipl'])
81
82
83+def get_flash_kernel_pkgs(arch=None, uefi=None):
84+ if arch is None:
85+ arch = util.get_architecture()
86+ if uefi is None:
87+ uefi = util.is_uefi_bootable()
88+ if uefi:
89+ return None
90+ if not arch.startswith('arm'):
91+ return None
92+
93+ try:
94+ fk_packages, _ = util.subp(
95+ ['list-flash-kernel-packages'], capture=True)
96+ return fk_packages
97+ except util.ProcessExecutionError:
98+ # Ignore errors
99+ return None
100+
101+
102 def install_kernel(cfg, target):
103 kernel_cfg = cfg.get('kernel', {'package': None,
104 'fallback-package': "linux-generic",
105@@ -173,6 +192,13 @@
106 mapping = copy.deepcopy(KERNEL_MAPPING)
107 config.merge_config(mapping, kernel_cfg.get('mapping', {}))
108
109+ # Machines using flash-kernel may need additional dependencies installed
110+ # before running. Run those checks in the ephemeral environment so the
111+ # target only has required packages installed. See LP:1640519
112+ fk_packages = get_flash_kernel_pkgs()
113+ if fk_packages:
114+ util.install_packages(fk_packages.split(), target=target)
115+
116 if kernel_package:
117 util.install_packages([kernel_package], target=target)
118 return
119@@ -344,7 +370,8 @@
120 cmd = ['update-initramfs', '-u']
121 if all_kernels:
122 cmd.extend(['-k', 'all'])
123- util.subp(cmd, target=target)
124+ with util.ChrootableTarget(target) as in_chroot:
125+ in_chroot.subp(cmd)
126
127
128 def copy_fstab(fstab, target):
129
130=== modified file 'curtin/deps/__init__.py'
131--- curtin/deps/__init__.py 2016-03-18 14:16:45 +0000
132+++ curtin/deps/__init__.py 2017-01-18 16:16:23 +0000
133@@ -17,8 +17,14 @@
134 import os
135 import sys
136
137-from curtin.util import (which, install_packages, lsb_release,
138- ProcessExecutionError)
139+from curtin.util import (
140+ ProcessExecutionError,
141+ get_architecture,
142+ install_packages,
143+ is_uefi_bootable,
144+ lsb_release,
145+ which,
146+)
147
148 REQUIRED_IMPORTS = [
149 # import string to execute, python2 package, python3 package
150@@ -47,6 +53,9 @@
151 REQUIRED_IMPORTS.append(
152 ('import oauthlib.oauth1', 'python-oauthlib', 'python3-oauthlib'),)
153
154+if not is_uefi_bootable() and 'arm' in get_architecture():
155+ REQUIRED_EXECUTABLES.append(('flash-kernel', 'flash-kernel'))
156+
157
158 class MissingDeps(Exception):
159 def __init__(self, message, deps):
160
161=== modified file 'curtin/util.py'
162--- curtin/util.py 2016-10-03 18:43:46 +0000
163+++ curtin/util.py 2017-01-18 16:16:23 +0000
164@@ -45,6 +45,12 @@
165 except NameError:
166 string_types = (str,)
167
168+try:
169+ numeric_types = (int, float, long)
170+except NameError:
171+ # python3 does not have a long type.
172+ numeric_types = (int, float)
173+
174 from .log import LOG
175
176 _INSTALLED_HELPERS_PATH = '/usr/lib/curtin/helpers'
177@@ -871,14 +877,17 @@
178
179 def bytes2human(size):
180 """convert size in bytes to human readable"""
181- if not (isinstance(size, (int, float)) and
182- int(size) == size and
183- int(size) >= 0):
184- raise ValueError('size must be a integral value')
185+ if not isinstance(size, numeric_types):
186+ raise ValueError('size must be a numeric value, not %s', type(size))
187+ isize = int(size)
188+ if isize != size:
189+ raise ValueError('size "%s" is not a whole number.' % size)
190+ if isize < 0:
191+ raise ValueError('size "%d" < 0.' % isize)
192 mpliers = {'B': 1, 'K': 2 ** 10, 'M': 2 ** 20, 'G': 2 ** 30, 'T': 2 ** 40}
193 unit_order = sorted(mpliers, key=lambda x: -1 * mpliers[x])
194- unit = next((u for u in unit_order if (size / mpliers[u]) >= 1), 'B')
195- return str(int(size / mpliers[unit])) + unit
196+ unit = next((u for u in unit_order if (isize / mpliers[u]) >= 1), 'B')
197+ return str(int(isize / mpliers[unit])) + unit
198
199
200 def import_module(import_str):
201
202=== modified file 'debian/changelog'
203--- debian/changelog 2016-10-03 19:12:33 +0000
204+++ debian/changelog 2017-01-18 16:16:23 +0000
205@@ -1,3 +1,23 @@
206+curtin (0.1.0~bzr437-0ubuntu1~16.04.1) UNRELEASED; urgency=medium
207+
208+ * debian/new-upstream-snapshot: change to not use bzr merge-upstream.
209+ * New upstream snapshot.
210+ - revert: Test Workaround: skip XenialTestNvme for a short time.
211+ - Test Workaround: skip XenialTestNvme for a short time.
212+ - pep8: fix pep8 errors found with 'make pep8' on zesty.
213+ - Workaround failures caused by gpg2 daemons left running in chroot.
214+ (LP: #1645680)
215+ - Install u-boot-tools when running on a system with u-boot. (LP: #1640519)
216+ - block: fix partition kname for raid devices (LP: #1641661)
217+ - Fix up tox errors that slipped in and new pycodestyle 2.1.0 complaints.
218+ - vmtests: adjust vmtest image sync metadata filenames
219+ - vmtests: Add centos support
220+ - Disable WilyTestRaid5Bcache vmtest
221+ - tools/xkvm: fix --netdev=<bridge>
222+ - bytes2human: fix for values larger than 32 bit int on 32 bit python2.
223+
224+ -- Scott Moser <smoser@ubuntu.com> Wed, 18 Jan 2017 10:56:59 -0500
225+
226 curtin (0.1.0~bzr425-0ubuntu1~16.04.1) xenial-proposed; urgency=medium
227
228 [ Scott Moser ]
229
230=== modified file 'debian/new-upstream-snapshot'
231--- debian/new-upstream-snapshot 2016-10-03 17:23:32 +0000
232+++ debian/new-upstream-snapshot 2017-01-18 16:16:23 +0000
233@@ -23,7 +23,7 @@
234 print_commit() {
235 local subject="$1" author="$2" bugs="$3" aname=""
236 aname=${author% <*}
237- echo " - $subject ${aname:+[${aname}]}${bugs:+ (LP: ${bugs})}"
238+ echo " - $subject${aname:+ [${aname}]}${bugs:+ (LP: ${bugs})}"
239 }
240
241 # unfortunately seems like no easy way to get 'Author' unless
242@@ -99,8 +99,52 @@
243 bzr export --format=tgz "--revision=${revno}" "$tarball" "${trunk}" ||
244 fail "failed exporting bzr in $trunk to $tarball"
245 fi
246-bzr merge-upstream "$tarball" "--version=${version}" ||
247- fail "failed merge-upstream of $tarball at version=$version"
248+#bzr merge-upstream "$tarball" "--version=${version}" ||
249+# fail "failed merge-upstream of $tarball at version=$version"
250+tmpd=$(mktemp -d "${TMPDIR:-/tmp}/curtin.${0##*/}.XXXXXX")
251+trap 'rm -Rf "$tmpd"' EXIT
252+newflist="${tmpd}/new-files"
253+oldflist="${tmpd}/old-files"
254+
255+tar -tf "$tarball" \
256+ --strip-components=1 --exclude="*/debian" > "$newflist.full" ||
257+ fail "failed tar tf on $tarball"
258+sed 's,^[^/]*/,,' "$newflist.full" > "$newflist"
259+
260+bzr ls --recursive --versioned > "$oldflist.full" ||
261+ fail "failed bzr ls --recursive"
262+grep -v "^debian/" "$oldflist.full" > "$oldflist"
263+
264+cat "$oldflist" "$newflist" "$newflist" > "$tmpd/all-old" ||
265+ fail "failed getting all old files"
266+cat "$newflist" "$oldflist" "$oldflist" > "$tmpd/all-new" ||
267+ fail "failed getting all new"
268+
269+removed="${tmpd}/removed"
270+added="$tmpd/added"
271+sort "$tmpd/all-old" | uniq --uniq > "$removed"
272+sort "$tmpd/all-new" | uniq --uniq > "$added"
273+
274+while read rmfile; do
275+ case "$rmfile" in
276+ .pc/*) continue;;
277+ */) rflag="-r";;
278+ *) rflag="";;
279+ esac
280+ bzr rm $rflag "$rmfile" || fail "failed bzr rm${rflag:+ ${rflag}} $rmfile"
281+done < "$removed"
282+
283+for f in *; do
284+ [ "$f" = "debian" ] && continue
285+ rm -rf "$f" || fail "failed removing '$f'"
286+done
287+
288+tar --strip-components=1 --exclude "*/debian/*" -xf "$tarball" ||
289+ fail "failed extraction of $tarball"
290+
291+while read newfile; do
292+ bzr add "$newfile" || fail "failed adding '$newfile'"
293+done < "$added"
294
295 oldrev=$(($prevno+1))
296 ( cd "$trunk" && bzr log -r "${oldrev}..${revno}" ) > new-changes.log ||
297
298=== added file 'examples/tests/centos_basic.yaml'
299--- examples/tests/centos_basic.yaml 1970-01-01 00:00:00 +0000
300+++ examples/tests/centos_basic.yaml 2017-01-18 16:16:23 +0000
301@@ -0,0 +1,13 @@
302+showtrace: true
303+hook_commands:
304+ builtin: null
305+network:
306+ version: 1
307+ config:
308+ - type: physical
309+ name: interface0
310+ mac_address: "52:54:00:12:34:00"
311+ subnets:
312+ - type: static
313+ address: 10.0.2.15/24
314+ gateway: 10.0.2.2
315
316=== added file 'examples/tests/mirrorboot-msdos-partition.yaml'
317--- examples/tests/mirrorboot-msdos-partition.yaml 1970-01-01 00:00:00 +0000
318+++ examples/tests/mirrorboot-msdos-partition.yaml 2017-01-18 16:16:23 +0000
319@@ -0,0 +1,82 @@
320+showtrace: true
321+storage:
322+ version: 1
323+ config:
324+ - id: sda
325+ type: disk
326+ ptable: msdos
327+ model: QEMU HARDDISK
328+ path: /dev/vdb
329+ name: main_disk
330+ grub_device: true
331+ wipe: superblock
332+ - id: sdb
333+ type: disk
334+ ptable: msdos
335+ model: QEMU HARDDISK
336+ path: /dev/vdc
337+ name: second_disk
338+ wipe: superblock
339+ - id: sda-part1
340+ name: sda-part1
341+ type: partition
342+ size: 5GB
343+ number: 1
344+ device: sda
345+ uuid: bbfd7fc9-fd0c-4151-99d4-a48c148c46b1
346+ wipe: superblock
347+ - id: sdb-part1
348+ name: sdb-part1
349+ type: partition
350+ size: 5GB
351+ number: 1
352+ device: sdb
353+ uuid: b37f57af-52b9-4ffc-98cf-08b7f7f4bed1
354+ wipe: superblock
355+ - id: md0
356+ name: md0
357+ type: raid
358+ ptable: gpt
359+ raidlevel: 1
360+ devices:
361+ - sda-part1
362+ - sdb-part1
363+ spare_devices: []
364+ - device: md0
365+ id: md0-part1
366+ name: md0-part1
367+ number: 1
368+ offset: 4194304B
369+ size: 2GB
370+ type: partition
371+ uuid: 4f4fa336-2762-48e4-ae54-9451141665cd
372+ wipe: superblock
373+ - device: md0
374+ id: md0-part2
375+ name: md0-part2
376+ number: 2
377+ size: 2GB
378+ type: partition
379+ uuid: c2d21fd3-3cde-4432-8eab-f08594bbe76e
380+ wipe: superblock
381+ - fstype: ext4
382+ id: md0-part1_format
383+ label: ''
384+ type: format
385+ uuid: c4024546-ad9d-4d85-adfa-c4b22611baa8
386+ volume: md0-part1
387+ - fstype: swap
388+ id: md0-part2_format
389+ label: ''
390+ type: format
391+ uuid: f68507ce-6d3d-4087-83e8-d8e531d7ec7d
392+ volume: md0-part2
393+ - device: md0-part1_format
394+ id: md0-part1_mount
395+ options: ''
396+ path: /
397+ type: mount
398+ - device: md0-part2_format
399+ id: md0-part2_mount
400+ options: ''
401+ type: mount
402
403=== added file 'helpers/list-flash-kernel-packages'
404--- helpers/list-flash-kernel-packages 1970-01-01 00:00:00 +0000
405+++ helpers/list-flash-kernel-packages 2017-01-18 16:16:23 +0000
406@@ -0,0 +1,13 @@
407+#!/bin/sh -e
408+# Return the list of packages flash-kernel requires for this machine if
409+# supported. If not supported return a non-zero return code.
410+
411+FK_DIR=/usr/share/flash-kernel
412+. ${FK_DIR}/functions
413+
414+machine="$(get_cpuinfo_hardware)"
415+check_supported "${machine}"
416+# get_machine_field gives a non-zero return code when no additional packages
417+# are required. Ignore it so the script succeeds allowing just flash-kernel to
418+# be installed in the target.
419+get_machine_field "${machine}" "Required-Packages" ||:
420
421=== modified file 'tests/unittests/test_apt_source.py'
422--- tests/unittests/test_apt_source.py 2016-10-03 18:42:29 +0000
423+++ tests/unittests/test_apt_source.py 2017-01-18 16:16:23 +0000
424@@ -58,6 +58,7 @@
425 def __exit__(self, exc_type, exc_value, traceback):
426 return
427
428+
429 ChrootableTargetStr = "curtin.commands.apt_config.util.ChrootableTarget"
430
431
432
433=== modified file 'tests/unittests/test_block.py'
434--- tests/unittests/test_block.py 2016-10-03 18:42:29 +0000
435+++ tests/unittests/test_block.py 2017-01-18 16:16:23 +0000
436@@ -302,6 +302,7 @@
437 (('mmcblk0', 1), 'mmcblk0p1'),
438 (('cciss!c0d0', 1), 'cciss!c0d0p1'),
439 (('dm-0', 1), 'dm-0p1'),
440+ (('md0', 1), 'md0p1'),
441 (('mpath1', 2), 'mpath1p2')]
442 for ((disk_kname, part_number), part_kname) in part_knames:
443 self.assertEqual(block.partition_kname(disk_kname, part_number),
444@@ -313,6 +314,7 @@
445 path_knames = [('/dev/sda', 'sda'),
446 ('/dev/sda1', 'sda1'),
447 ('/dev////dm-0/', 'dm-0'),
448+ ('/dev/md0p1', 'md0p1'),
449 ('vdb', 'vdb'),
450 ('/dev/mmcblk0p1', 'mmcblk0p1'),
451 ('/dev/nvme0n0p1', 'nvme0n0p1'),
452
453=== added file 'tests/unittests/test_curthooks.py'
454--- tests/unittests/test_curthooks.py 1970-01-01 00:00:00 +0000
455+++ tests/unittests/test_curthooks.py 2017-01-18 16:16:23 +0000
456@@ -0,0 +1,134 @@
457+import os
458+from unittest import TestCase
459+from mock import call, patch
460+import shutil
461+import tempfile
462+
463+from curtin.commands import curthooks
464+from curtin import util
465+
466+
467+class CurthooksBase(TestCase):
468+ def setUp(self):
469+ super(CurthooksBase, self).setUp()
470+
471+ def add_patch(self, target, attr):
472+ """Patches specified target object and sets it as attr on test
473+ instance also schedules cleanup"""
474+ m = patch(target, autospec=True)
475+ p = m.start()
476+ self.addCleanup(m.stop)
477+ setattr(self, attr, p)
478+
479+
480+class TestGetFlashKernelPkgs(CurthooksBase):
481+ def setUp(self):
482+ super(TestGetFlashKernelPkgs, self).setUp()
483+ self.add_patch('curtin.util.subp', 'mock_subp')
484+ self.add_patch('curtin.util.get_architecture', 'mock_get_architecture')
485+ self.add_patch('curtin.util.is_uefi_bootable', 'mock_is_uefi_bootable')
486+
487+ def test__returns_none_when_uefi(self):
488+ self.assertIsNone(curthooks.get_flash_kernel_pkgs(uefi=True))
489+ self.assertFalse(self.mock_subp.called)
490+
491+ def test__returns_none_when_not_arm(self):
492+ self.assertIsNone(curthooks.get_flash_kernel_pkgs('amd64', False))
493+ self.assertFalse(self.mock_subp.called)
494+
495+ def test__returns_none_on_error(self):
496+ self.mock_subp.side_effect = util.ProcessExecutionError()
497+ self.assertIsNone(curthooks.get_flash_kernel_pkgs('arm64', False))
498+ self.mock_subp.assert_called_with(
499+ ['list-flash-kernel-packages'], capture=True)
500+
501+ def test__returns_flash_kernel_pkgs(self):
502+ self.mock_subp.return_value = 'u-boot-tools', ''
503+ self.assertEquals(
504+ 'u-boot-tools', curthooks.get_flash_kernel_pkgs('arm64', False))
505+ self.mock_subp.assert_called_with(
506+ ['list-flash-kernel-packages'], capture=True)
507+
508+ def test__calls_get_arch_and_is_uefi_bootable_when_undef(self):
509+ curthooks.get_flash_kernel_pkgs()
510+ self.mock_get_architecture.assert_called_once_with()
511+ self.mock_is_uefi_bootable.assert_called_once_with()
512+
513+
514+class TestCurthooksInstallKernel(CurthooksBase):
515+ def setUp(self):
516+ super(TestCurthooksInstallKernel, self).setUp()
517+ self.add_patch('curtin.util.has_pkg_available', 'mock_haspkg')
518+ self.add_patch('curtin.util.install_packages', 'mock_instpkg')
519+ self.add_patch(
520+ 'curtin.commands.curthooks.get_flash_kernel_pkgs',
521+ 'mock_get_flash_kernel_pkgs')
522+
523+ self.kernel_cfg = {'kernel': {'package': 'mock-linux-kernel',
524+ 'fallback-package': 'mock-fallback',
525+ 'mapping': {}}}
526+ # Tests don't actually install anything so we just need a name
527+ self.target = tempfile.mktemp()
528+
529+ def test__installs_flash_kernel_packages_when_needed(self):
530+ kernel_package = self.kernel_cfg.get('kernel', {}).get('package', {})
531+ self.mock_get_flash_kernel_pkgs.return_value = 'u-boot-tools'
532+
533+ curthooks.install_kernel(self.kernel_cfg, self.target)
534+
535+ inst_calls = [
536+ call(['u-boot-tools'], target=self.target),
537+ call([kernel_package], target=self.target)]
538+
539+ self.mock_instpkg.assert_has_calls(inst_calls)
540+
541+ def test__installs_kernel_package(self):
542+ kernel_package = self.kernel_cfg.get('kernel', {}).get('package', {})
543+ self.mock_get_flash_kernel_pkgs.return_value = None
544+
545+ curthooks.install_kernel(self.kernel_cfg, self.target)
546+
547+ self.mock_instpkg.assert_called_with(
548+ [kernel_package], target=self.target)
549+
550+
551+class TestUpdateInitramfs(CurthooksBase):
552+ def setUp(self):
553+ super(TestUpdateInitramfs, self).setUp()
554+ self.add_patch('curtin.util.subp', 'mock_subp')
555+ self.target = tempfile.mkdtemp()
556+
557+ def tearDown(self):
558+ shutil.rmtree(self.target)
559+
560+ def _mnt_call(self, point):
561+ target = os.path.join(self.target, point)
562+ return call(['mount', '--bind', '/%s' % point, target])
563+
564+ def test_mounts_and_runs(self):
565+ curthooks.update_initramfs(self.target)
566+
567+ print('subp calls: %s' % self.mock_subp.mock_calls)
568+ subp_calls = [
569+ self._mnt_call('dev'),
570+ self._mnt_call('proc'),
571+ self._mnt_call('sys'),
572+ call(['update-initramfs', '-u'], target=self.target),
573+ call(['udevadm', 'settle']),
574+ ]
575+ self.mock_subp.assert_has_calls(subp_calls)
576+
577+ def test_mounts_and_runs_for_all_kernels(self):
578+ curthooks.update_initramfs(self.target, True)
579+
580+ print('subp calls: %s' % self.mock_subp.mock_calls)
581+ subp_calls = [
582+ self._mnt_call('dev'),
583+ self._mnt_call('proc'),
584+ self._mnt_call('sys'),
585+ call(['update-initramfs', '-u', '-k', 'all'], target=self.target),
586+ call(['udevadm', 'settle']),
587+ ]
588+ self.mock_subp.assert_has_calls(subp_calls)
589+
590+# vi: ts=4 expandtab syntax=python
591
592=== modified file 'tests/vmtests/__init__.py'
593--- tests/vmtests/__init__.py 2016-10-03 18:43:46 +0000
594+++ tests/vmtests/__init__.py 2017-01-18 16:16:23 +0000
595@@ -4,7 +4,6 @@
596 import logging
597 import json
598 import os
599-import pathlib
600 import random
601 import re
602 import shutil
603@@ -19,14 +18,10 @@
604
605 from .image_sync import query as imagesync_query
606 from .image_sync import mirror as imagesync_mirror
607+from .image_sync import (IMAGE_SRC_URL, IMAGE_DIR)
608 from .helpers import check_call, TimeoutExpired
609 from unittest import TestCase, SkipTest
610
611-IMAGE_SRC_URL = os.environ.get(
612- 'IMAGE_SRC_URL',
613- "http://maas.ubuntu.com/images/ephemeral-v2/daily/streams/v1/index.sjson")
614-
615-IMAGE_DIR = os.environ.get("IMAGE_DIR", "/srv/images")
616 try:
617 IMAGES_TO_KEEP = int(os.environ.get("IMAGES_TO_KEEP", 1))
618 except ValueError:
619@@ -37,6 +32,7 @@
620
621 DEVNULL = open(os.devnull, 'w')
622 KEEP_DATA = {"pass": "none", "fail": "all"}
623+CURTIN_VMTEST_IMAGE_SYNC = os.environ.get("CURTIN_VMTEST_IMAGE_SYNC", False)
624 IMAGE_SYNCS = []
625 TARGET_IMAGE_FORMAT = "raw"
626
627@@ -169,20 +165,25 @@
628 return
629
630
631-def get_images(src_url, local_d, release, arch, krel=None, sync=True):
632+def get_images(src_url, local_d, distro, release, arch, krel=None, sync=True,
633+ ftypes=None):
634 # ensure that the image items (roottar, kernel, initrd)
635 # we need for release and arch are available in base_dir.
636 # returns updated ftypes dictionary {ftype: item_url}
637- if krel is None:
638- krel = release
639- ftypes = {
640- 'vmtest.root-image': '',
641- 'vmtest.root-tgz': '',
642- 'boot-kernel': '',
643- 'boot-initrd': ''
644- }
645- common_filters = ['release=%s' % release, 'krel=%s' % krel,
646- 'arch=%s' % arch]
647+ if not ftypes:
648+ ftypes = {
649+ 'vmtest.root-image': '',
650+ 'vmtest.root-tgz': '',
651+ 'boot-kernel': '',
652+ 'boot-initrd': ''
653+ }
654+ elif isinstance(ftypes, (list, tuple)):
655+ ftypes = dict().fromkeys(ftypes)
656+
657+ common_filters = ['release=%s' % release,
658+ 'arch=%s' % arch, 'os=%s' % distro]
659+ if krel:
660+ common_filters.append('krel=%s' % krel)
661 filters = ['ftype~(%s)' % ("|".join(ftypes.keys()))] + common_filters
662
663 if sync:
664@@ -208,16 +209,17 @@
665 # try to fix this with a sync
666 logger.info(fail_msg + " Attempting to fix with an image sync. (%s)",
667 query_str)
668- return get_images(src_url, local_d, release, arch, krel, sync=True)
669+ return get_images(src_url, local_d, distro, release, arch,
670+ krel=krel, sync=True, ftypes=ftypes)
671 elif not results:
672 raise ValueError("Nothing found in query: %s" % query_str)
673
674 missing = []
675- expected = sorted(ftypes.keys())
676 found = sorted(f.get('ftype') for f in results)
677- if expected != found:
678- raise ValueError("Query returned unexpected ftypes=%s. "
679- "Expected=%s" % (found, expected))
680+ for ftype in ftypes.keys():
681+ if ftype not in found:
682+ raise ValueError("Expected ftype '{}' but not in results"
683+ .format(ftype))
684 for item in results:
685 ftypes[item['ftype']] = item['item_url']
686 last_item = item
687@@ -235,42 +237,6 @@
688 return version_info, ftypes
689
690
691-class ImageStore:
692- """Local mirror of MAAS images simplestreams data."""
693-
694- # By default sync on demand.
695- sync = True
696-
697- # images are expected in dirs named <release>/<arch>/YYYYMMDD[.X]
698- image_dir_re = re.compile(r"^[0-9]{4}[01][0-9][0123][0-9]([.][0-9])*$")
699-
700- def __init__(self, source_url, base_dir):
701- """Initialize the ImageStore.
702-
703- source_url is the simplestreams source from where the images will be
704- downloaded.
705- base_dir is the target dir in the filesystem to keep the mirror.
706- """
707- self.source_url = source_url
708- self.base_dir = base_dir
709- if not os.path.isdir(self.base_dir):
710- os.makedirs(self.base_dir)
711- self.url = pathlib.Path(self.base_dir).as_uri()
712-
713- def get_image(self, release, arch, krel=None):
714- """Return tuple of version info, and paths for root image,
715- kernel, initrd, tarball."""
716- if krel is None:
717- krel = release
718- ver_info, ftypes = get_images(
719- self.source_url, self.base_dir, release, arch, krel, self.sync)
720- root_image_path = ftypes['vmtest.root-image']
721- kernel_path = ftypes['boot-kernel']
722- initrd_path = ftypes['boot-initrd']
723- tarball = ftypes['vmtest.root-tgz']
724- return ver_info, (root_image_path, kernel_path, initrd_path, tarball)
725-
726-
727 class TempDir(object):
728 boot = None
729 collect = None
730@@ -356,7 +322,6 @@
731 extra_disks = []
732 extra_kern_args = None
733 fstab_expected = {}
734- image_store_class = ImageStore
735 boot_cloudconf = None
736 install_timeout = INSTALL_TIMEOUT
737 interactive = False
738@@ -372,6 +337,30 @@
739 release = None
740 arch = None
741 krel = None
742+ distro = None
743+ target_distro = None
744+ target_release = None
745+ target_krel = None
746+
747+ @classmethod
748+ def get_test_files(cls):
749+ img_verstr, ftypes = get_images(
750+ IMAGE_SRC_URL, IMAGE_DIR, cls.distro, cls.release, cls.arch,
751+ krel=cls.krel if cls.krel else cls.release,
752+ ftypes=('boot-initrd', 'boot-kernel', 'vmtest.root-image'))
753+ logger.debug("Install Image %s\n, ftypes: %s\n", img_verstr, ftypes)
754+ logger.info("Install Image: %s", img_verstr)
755+ if not cls.target_krel and cls.krel:
756+ cls.target_krel = cls.krel
757+ img_verstr, found = get_images(
758+ IMAGE_SRC_URL, IMAGE_DIR,
759+ cls.target_distro if cls.target_distro else cls.distro,
760+ cls.target_release if cls.target_release else cls.release,
761+ cls.arch, krel=cls.target_krel, ftypes=('vmtest.root-tgz',))
762+ logger.debug("Target Tarball %s\n, ftypes: %s\n", img_verstr, found)
763+ logger.info("Target Tarball: %s", img_verstr)
764+ ftypes.update(found)
765+ return ftypes
766
767 @classmethod
768 def setUpClass(cls):
769@@ -383,27 +372,17 @@
770
771 setup_start = time.time()
772 logger.info('Starting setup for testclass: {}'.format(cls.__name__))
773- # get boot img
774- image_store = cls.image_store_class(IMAGE_SRC_URL, IMAGE_DIR)
775- # Disable sync if env var is set.
776- image_store.sync = get_env_var_bool('CURTIN_VMTEST_IMAGE_SYNC', False)
777- logger.debug("Image sync = %s", image_store.sync)
778- img_verstr, (boot_img, boot_kernel, boot_initrd, tarball) = (
779- image_store.get_image(cls.release, cls.arch, cls.krel))
780- logger.debug("Image %s\n boot=%s\n kernel=%s\n initrd=%s\n"
781- " tarball=%s\n", img_verstr, boot_img, boot_kernel,
782- boot_initrd, tarball)
783 # set up tempdir
784 cls.td = TempDir(
785 name=cls.__name__,
786 user_data=generate_user_data(collect_scripts=cls.collect_scripts,
787 boot_cloudconf=cls.boot_cloudconf))
788- logger.info('Using tempdir: %s , Image: %s', cls.td.tmpdir,
789- img_verstr)
790+ logger.info('Using tempdir: %s', cls.td.tmpdir)
791 cls.install_log = os.path.join(cls.td.logs, 'install-serial.log')
792 cls.boot_log = os.path.join(cls.td.logs, 'boot-serial.log')
793 logger.debug('Install console log: {}'.format(cls.install_log))
794 logger.debug('Boot console log: {}'.format(cls.boot_log))
795+ ftypes = cls.get_test_files()
796
797 # if interactive, launch qemu without 'background & wait'
798 if cls.interactive:
799@@ -422,8 +401,8 @@
800 cmd.extend(["--append=" + cls.extra_kern_args])
801
802 # publish the root tarball
803- install_src = "PUBURL/" + os.path.basename(tarball)
804- cmd.append("--publish=%s" % tarball)
805+ install_src = "PUBURL/" + os.path.basename(ftypes['vmtest.root-tgz'])
806+ cmd.append("--publish=%s" % ftypes['vmtest.root-tgz'])
807
808 # check for network configuration
809 cls.network_state = curtin_net.parse_net_config(cls.conf_file)
810@@ -520,8 +499,9 @@
811 disks = disks * cls.multipath_num_paths
812
813 cmd.extend(uefi_flags + netdevs + disks +
814- [boot_img, "--kernel=%s" % boot_kernel, "--initrd=%s" %
815- boot_initrd, "--", "curtin", "-vv", "install"] +
816+ [ftypes['vmtest.root-image'], "--kernel=%s" %
817+ ftypes['boot-kernel'], "--initrd=%s" %
818+ ftypes['boot-initrd'], "--", "curtin", "-vv", "install"] +
819 ["--config=%s" % f for f in configs] +
820 [install_src])
821
822@@ -539,8 +519,8 @@
823 raise
824 finally:
825 if os.path.exists(cls.install_log):
826- with open(cls.install_log, 'rb') as l:
827- content = l.read().decode('utf-8', errors='replace')
828+ with open(cls.install_log, 'rb') as lfh:
829+ content = lfh.read().decode('utf-8', errors='replace')
830 logger.debug('install serial console output:\n%s', content)
831 else:
832 logger.warn("Boot for install did not produce a console log.")
833@@ -548,8 +528,8 @@
834 logger.debug('')
835 try:
836 if os.path.exists(cls.install_log):
837- with open(cls.install_log, 'rb') as l:
838- install_log = l.read().decode('utf-8', errors='replace')
839+ with open(cls.install_log, 'rb') as lfh:
840+ install_log = lfh.read().decode('utf-8', errors='replace')
841 errmsg, errors = check_install_log(install_log)
842 if errmsg:
843 for e in errors:
844@@ -650,8 +630,8 @@
845 raise e
846 finally:
847 if os.path.exists(cls.boot_log):
848- with open(cls.boot_log, 'rb') as l:
849- content = l.read().decode('utf-8', errors='replace')
850+ with open(cls.boot_log, 'rb') as lfh:
851+ content = lfh.read().decode('utf-8', errors='replace')
852 logger.debug('boot serial console output:\n%s', content)
853 else:
854 logger.warn("Booting after install not produce"
855@@ -837,21 +817,6 @@
856 separators=(',', ': ')) + "\n")
857
858
859-class PsuedoImageStore(object):
860- def __init__(self, source_url, base_dir):
861- self.source_url = source_url
862- self.base_dir = base_dir
863-
864- def get_image(self, release, arch, krel=None):
865- """Return tuple of version info, and paths for root image,
866- kernel, initrd, tarball."""
867- names = ['psuedo-root-image', 'psuedo-kernel', 'psuedo-initrd',
868- 'psuedo-tarball']
869- return (
870- "psuedo-%s %s/hwe-P 20160101" % (release, arch),
871- [os.path.join(self.base_dir, release, arch, f) for f in names])
872-
873-
874 class PsuedoVMBaseClass(VMBaseClass):
875 # This mimics much of the VMBaseClass just with faster setUpClass
876 # The tests here will fail only if CURTIN_VMTEST_DEBUG_ALLOW_FAIL
877@@ -859,7 +824,6 @@
878 # during a 'make vmtest' (keeping it running) but not to break test.
879 #
880 # boot_timeouts is a dict of {'purpose': 'mesg'}
881- image_store_class = PsuedoImageStore
882 # boot_results controls what happens when boot_system is called
883 # a dictionary with key of the 'purpose'
884 # inside each dictionary:
885@@ -883,6 +847,21 @@
886 "LABEL=root / ext4 defaults 0 1")))
887
888 @classmethod
889+ def get_test_files(cls):
890+ """Return tuple of version info, and paths for root image,
891+ kernel, initrd, tarball."""
892+
893+ def get_psuedo_path(name):
894+ return os.path.join(IMAGE_DIR, cls.release, cls.arch, name)
895+
896+ return {
897+ 'vmtest.root-image': get_psuedo_path('psuedo-root-image'),
898+ 'boot-kernel': get_psuedo_path('psuedo-kernel'),
899+ 'boot-initrd': get_psuedo_path('psuedo-initrd'),
900+ 'vmtest.root-tgz': get_psuedo_path('psuedo-root-tgz')
901+ }
902+
903+ @classmethod
904 def boot_system(cls, cmd, console_log, proc_out, timeout, purpose):
905 # this is separated for easy override in Psuedo classes
906 data = {'timeout_msg': None, 'timeout': 0,
907@@ -1011,15 +990,17 @@
908 collect_post = textwrap.dedent(
909 'tar -C "%s" -cf "%s" .' % (output_dir, output_device))
910
911- # failsafe poweroff runs on precise only, where power_state does
912+ # failsafe poweroff runs on precise and centos only, where power_state does
913 # not exist.
914- precise_poweroff = textwrap.dedent("""#!/bin/sh -x
915- [ "$(lsb_release -sc)" = "precise" ] || exit 0;
916- shutdown -P now "Shutting down on precise"
917+ failsafe_poweroff = textwrap.dedent("""#!/bin/sh -x
918+ [ -e /etc/centos-release -o -e /etc/redhat-release ] &&
919+ { shutdown -P now "Shutting down on centos"; }
920+ [ "$(lsb_release -sc)" = "precise" ] &&
921+ { shutdown -P now "Shutting down on precise"; }
922 """)
923
924 scripts = ([collect_prep] + collect_scripts + [collect_post] +
925- [precise_poweroff])
926+ [failsafe_poweroff])
927
928 for part in scripts:
929 if not part.startswith("#!"):
930
931=== modified file 'tests/vmtests/helpers.py'
932--- tests/vmtests/helpers.py 2016-10-03 18:43:46 +0000
933+++ tests/vmtests/helpers.py 2017-01-18 16:16:23 +0000
934@@ -67,6 +67,7 @@
935
936 return 0
937
938+
939 try:
940 TimeoutExpired = subprocess.TimeoutExpired
941 except AttributeError:
942@@ -99,10 +100,13 @@
943 return Command(cmd, signal).run(**kwargs)
944
945
946-def find_releases():
947- """Return a sorted list of releases defined in test cases."""
948- # Use the TestLoader to load all tests cases defined within
949- # tests/vmtests/ and figure out which releases they are testing.
950+def find_releases_by_distro():
951+ """
952+ Returns a dictionary of distros and the distro releases that will be tested
953+ """
954+ # Use the TestLoder to load all test cases defined within tests/vmtests/
955+ # and figure out what distros and releases they are testing. Any tests
956+ # which are disabled will be excluded.
957 loader = TestLoader()
958 # dir with the vmtest modules (i.e. tests/vmtests/)
959 tests_dir = os.path.dirname(__file__)
960@@ -110,13 +114,21 @@
961 root_dir = os.path.split(os.path.split(tests_dir)[0])[0]
962 # Find all test modules defined in curtin/tests/vmtests/
963 module_test_suites = loader.discover(tests_dir, top_level_dir=root_dir)
964- releases = set()
965+ # find all distros and releases tested for each distro
966+ distros = {}
967 for mts in module_test_suites:
968 for class_test_suite in mts:
969 for test_case in class_test_suite:
970- if getattr(test_case, 'release', ''):
971- releases.add(getattr(test_case, 'release'))
972- return sorted(releases)
973+ # skip disabled tests
974+ if not getattr(test_case, '__test__', False):
975+ continue
976+ for (dist, rel) in (
977+ (getattr(test_case, a, None) for a in attrs)
978+ for attrs in (('distro', 'release'),
979+ ('target_distro', 'target_release'))):
980+ if dist and rel:
981+ distros[dist] = distros.get(dist, set()).union((rel,))
982+ return {k: sorted(v) for (k, v) in distros.items()}
983
984
985 def _parse_ip_a(ip_a):
986
987=== modified file 'tests/vmtests/image_sync.py'
988--- tests/vmtests/image_sync.py 2016-10-03 18:00:41 +0000
989+++ tests/vmtests/image_sync.py 2017-01-18 16:16:23 +0000
990@@ -22,12 +22,16 @@
991 IMAGE_SRC_URL = os.environ.get(
992 'IMAGE_SRC_URL',
993 "http://maas.ubuntu.com/images/ephemeral-v2/daily/streams/v1/index.sjson")
994+IMAGE_DIR = os.environ.get("IMAGE_DIR", "/srv/images")
995
996 KEYRING = '/usr/share/keyrings/ubuntu-cloudimage-keyring.gpg'
997-ITEM_NAME_FILTERS = ['ftype~(root-image.gz|boot-initrd|boot-kernel)']
998+ITEM_NAME_FILTERS = ['ftype~(root-image.gz|boot-initrd|boot-kernel|root-tgz)']
999 FORMAT_JSON = 'JSON'
1000-VMTEST_CONTENT_ID = 'com.ubuntu.maas:daily:v2:download'
1001-VMTEST_JSON_PATH = "streams/v1/vmtest.json"
1002+STREAM_BASE = 'com.ubuntu.maas:daily'
1003+VMTEST_CONTENT_ID_PATH_MAP = {
1004+ STREAM_BASE + ":v2:download": "streams/v1/vmtest.json",
1005+ STREAM_BASE + ":centos-bases-download": "streams/v1/vmtest-centos.json",
1006+}
1007
1008 DEFAULT_OUTPUT_FORMAT = (
1009 "%(release)-7s %(arch)s/%(subarch)s %(version_name)-10s %(item_name)s")
1010@@ -222,7 +226,10 @@
1011 tver_data = products_version_get(target, pedigree)
1012 titems = tver_data.get('items')
1013
1014- if ('root-image.gz' in titems and
1015+ if not titems or 'root-image.gz' not in titems:
1016+ return
1017+
1018+ if (titems['root-image.gz']['ftype'] == 'root-image.gz' and
1019 not (ri_name in titems and rtgz_name in titems)):
1020 # generate the root-image and root-tgz
1021 derived_items = generate_root_derived(
1022@@ -231,6 +238,18 @@
1023 for fname, item in derived_items.items():
1024 self.insert_item(item, src, target, pedigree + (fname,),
1025 FakeContentSource(item['path']))
1026+ elif (titems['root-image.gz']['ftype'] == 'root-tgz' and
1027+ rtgz_name not in titems):
1028+ # already have the root tgz, just need to add content as a
1029+ # vmtest.root-tgz
1030+ # TODO: may need to generate the vmtest.root-image at some point in
1031+ # the future if there is a need to use the centos image as an
1032+ # ephemeral environment rather than installing centos from
1033+ # an ubuntu ephemeral image
1034+ self.insert_item(
1035+ {'ftype': rtgz_name, 'path': titems['root-image.gz']['path']},
1036+ src, target, pedigree + (rtgz_name,),
1037+ FakeContentSource(titems['root-image.gz']['path']))
1038
1039 def get_file_info(self, path):
1040 # check and see if we might know checksum and size
1041@@ -262,11 +281,11 @@
1042 self.store.insert_content(path, content)
1043
1044 # for our vmtest content id, we want to write
1045- # a vmtest.json in streams/v1/vmtest.json that can be queried
1046+ # a json file in streams/v1/<distro>.json that can be queried
1047 # even though it will not appear in index
1048- if target['content_id'] == VMTEST_CONTENT_ID:
1049- self.store.insert_content(VMTEST_JSON_PATH,
1050- util.json_dumps(target))
1051+ vmtest_json = VMTEST_CONTENT_ID_PATH_MAP.get(target['content_id'])
1052+ if vmtest_json:
1053+ self.store.insert_content(vmtest_json, util.json_dumps(target))
1054
1055 def insert_index_entry(self, data, src, pedigree, contentsource):
1056 # this is overridden, because the default implementation
1057@@ -377,20 +396,15 @@
1058 def query(mirror, max_items=1, filter_list=None, verbosity=0):
1059 if filter_list is None:
1060 filter_list = []
1061-
1062 ifilters = filters.get_filters(filter_list)
1063
1064 def fpath(path):
1065- # return the full path to a local file in the mirror
1066 return os.path.join(mirror, path)
1067
1068- try:
1069- stree = sutil.load_content(util.load_file(fpath(VMTEST_JSON_PATH)))
1070- except OSError:
1071- raise
1072- results = query_ptree(stree, max_num=max_items, ifilters=ifilters,
1073- path2url=fpath)
1074- return results
1075+ return next((q for q in (
1076+ query_ptree(sutil.load_content(util.load_file(fpath(path))),
1077+ max_num=max_items, ifilters=ifilters, path2url=fpath)
1078+ for path in VMTEST_CONTENT_ID_PATH_MAP.values()) if q), None)
1079
1080
1081 def main_query(args):
1082
1083=== modified file 'tests/vmtests/releases.py'
1084--- tests/vmtests/releases.py 2016-10-03 18:00:41 +0000
1085+++ tests/vmtests/releases.py 2017-01-18 16:16:23 +0000
1086@@ -6,47 +6,68 @@
1087 arch = get_platform_arch()
1088
1089
1090-class _PreciseBase(_ReleaseBase):
1091+class _UbuntuBase(_ReleaseBase):
1092+ distro = "ubuntu"
1093+
1094+
1095+class _CentosFromUbuntuBase(_UbuntuBase):
1096+ # base for installing centos tarballs from ubuntu base
1097+ target_distro = "centos"
1098+
1099+
1100+class _Centos70FromXenialBase(_CentosFromUbuntuBase):
1101+ # release for boot
1102+ release = "xenial"
1103+ # release for target
1104+ target_release = "centos70"
1105+
1106+
1107+class _Centos66FromXenialBase(_CentosFromUbuntuBase):
1108+ release = "xenial"
1109+ target_release = "centos66"
1110+
1111+
1112+class _PreciseBase(_UbuntuBase):
1113 release = "precise"
1114
1115
1116-class _PreciseHWET(_ReleaseBase):
1117+class _PreciseHWET(_UbuntuBase):
1118 release = "precise"
1119 krel = "trusty"
1120
1121
1122-class _TrustyBase(_ReleaseBase):
1123+class _TrustyBase(_UbuntuBase):
1124 release = "trusty"
1125
1126
1127-class _TrustyHWEU(_ReleaseBase):
1128+class _TrustyHWEU(_UbuntuBase):
1129 release = "trusty"
1130 krel = "utopic"
1131
1132
1133-class _TrustyHWEV(_ReleaseBase):
1134+class _TrustyHWEV(_UbuntuBase):
1135 release = "trusty"
1136 krel = "vivid"
1137
1138
1139-class _TrustyHWEW(_ReleaseBase):
1140+class _TrustyHWEW(_UbuntuBase):
1141 release = "trusty"
1142 krel = "wily"
1143
1144
1145-class _VividBase(_ReleaseBase):
1146+class _VividBase(_UbuntuBase):
1147 release = "vivid"
1148
1149
1150-class _WilyBase(_ReleaseBase):
1151+class _WilyBase(_UbuntuBase):
1152 release = "wily"
1153
1154
1155-class _XenialBase(_ReleaseBase):
1156+class _XenialBase(_UbuntuBase):
1157 release = "xenial"
1158
1159
1160-class _YakketyBase(_ReleaseBase):
1161+class _YakketyBase(_UbuntuBase):
1162 release = "yakkety"
1163
1164
1165@@ -62,6 +83,13 @@
1166 xenial = _XenialBase
1167 yakkety = _YakketyBase
1168
1169+
1170+class _CentosReleases(object):
1171+ centos70fromxenial = _Centos70FromXenialBase
1172+ centos66fromxenial = _Centos66FromXenialBase
1173+
1174+
1175 base_vm_classes = _Releases
1176+centos_base_vm_classes = _CentosReleases
1177
1178 # vi: ts=4 expandtab syntax=python
1179
1180=== modified file 'tests/vmtests/test_apt_config_cmd.py'
1181--- tests/vmtests/test_apt_config_cmd.py 2016-10-03 18:42:29 +0000
1182+++ tests/vmtests/test_apt_config_cmd.py 2017-01-18 16:16:23 +0000
1183@@ -53,3 +53,7 @@
1184 apt feature Test for Xenial using the standalone command
1185 """
1186 __test__ = True
1187+
1188+
1189+class YakketyTestAptConfigCMDCMD(relbase.yakkety, TestAptConfigCMD):
1190+ __test__ = True
1191
1192=== added file 'tests/vmtests/test_centos_basic.py'
1193--- tests/vmtests/test_centos_basic.py 1970-01-01 00:00:00 +0000
1194+++ tests/vmtests/test_centos_basic.py 2017-01-18 16:16:23 +0000
1195@@ -0,0 +1,42 @@
1196+from . import VMBaseClass
1197+from .releases import centos_base_vm_classes as relbase
1198+
1199+import textwrap
1200+
1201+
1202+# FIXME: should eventually be integrated with the real TestBasic
1203+class CentosTestBasicAbs(VMBaseClass):
1204+ __test__ = False
1205+ conf_file = "examples/tests/centos_basic.yaml"
1206+ extra_kern_args = "BOOTIF=eth0-52:54:00:12:34:00"
1207+ collect_scripts = [textwrap.dedent(
1208+ """
1209+ cd OUTPUT_COLLECT_D
1210+ cat /etc/fstab > fstab
1211+ """)]
1212+ fstab_expected = {
1213+ 'LABEL=cloudimg-rootfs': '/',
1214+ }
1215+
1216+ def test_dname(self):
1217+ pass
1218+
1219+ def test_interfacesd_eth0_removed(self):
1220+ pass
1221+
1222+ def test_output_files_exist(self):
1223+ self.output_files_exist(["fstab"])
1224+
1225+
1226+# FIXME: this naming scheme needs to be replaced
1227+class Centos70FromXenialTestBasic(relbase.centos70fromxenial,
1228+ CentosTestBasicAbs):
1229+ __test__ = True
1230+
1231+
1232+class Centos66FromXenialTestBasic(relbase.centos66fromxenial,
1233+ CentosTestBasicAbs):
1234+ __test__ = False
1235+ # FIXME: test is disabled because the grub config script in target
1236+ # specifies drive using hd(1,0) syntax, which breaks when the
1237+ # installation medium is removed. other than this, the install works
1238
1239=== modified file 'tests/vmtests/test_mdadm_bcache.py'
1240--- tests/vmtests/test_mdadm_bcache.py 2016-10-03 18:43:46 +0000
1241+++ tests/vmtests/test_mdadm_bcache.py 2017-01-18 16:16:23 +0000
1242@@ -182,6 +182,45 @@
1243 __test__ = True
1244
1245
1246+class TestMirrorbootPartitionsAbs(TestMdadmAbs):
1247+ # alternative config for more complex setup
1248+ conf_file = "examples/tests/mirrorboot-msdos-partition.yaml"
1249+ # initialize secondary disk
1250+ extra_disks = ['10G']
1251+ disk_to_check = [('main_disk', 1),
1252+ ('second_disk', 1),
1253+ ('md0', 2)]
1254+
1255+
1256+class TrustyTestMirrorbootPartitions(relbase.trusty,
1257+ TestMirrorbootPartitionsAbs):
1258+ __test__ = True
1259+
1260+ # FIXME(LP: #1523037): dname does not work on trusty
1261+ # when dname works on trusty, then we need to re-enable by removing line.
1262+ def test_dname(self):
1263+ print("test_dname does not work for Trusty")
1264+
1265+ def test_ptable(self):
1266+ print("test_ptable does not work for Trusty")
1267+
1268+
1269+class TrustyHWEUTestMirrorbootPartitions(relbase.trusty_hwe_u,
1270+ TrustyTestMirrorbootPartitions):
1271+ # This tests kernel upgrade in target
1272+ __test__ = True
1273+
1274+
1275+class XenialTestMirrorbootPartitions(relbase.xenial,
1276+ TestMirrorbootPartitionsAbs):
1277+ __test__ = True
1278+
1279+
1280+class YakketyTestMirrorbootPartitions(relbase.yakkety,
1281+ TestMirrorbootPartitionsAbs):
1282+ __test__ = True
1283+
1284+
1285 class TestRaid5bootAbs(TestMdadmAbs):
1286 # alternative config for more complex setup
1287 conf_file = "examples/tests/raid5boot.yaml"
1288
1289=== modified file 'tests/vmtests/test_raid5_bcache.py'
1290--- tests/vmtests/test_raid5_bcache.py 2016-10-03 18:43:46 +0000
1291+++ tests/vmtests/test_raid5_bcache.py 2017-01-18 16:16:23 +0000
1292@@ -91,7 +91,8 @@
1293
1294
1295 class WilyTestRaid5Bcache(relbase.wily, TestMdadmBcacheAbs):
1296- __test__ = True
1297+ # EOL - 2016-07-28
1298+ __test__ = False
1299
1300
1301 class XenialTestRaid5Bcache(relbase.xenial, TestMdadmBcacheAbs):
1302
1303=== modified file 'tools/vmtest-sync-images'
1304--- tools/vmtest-sync-images 2016-10-03 18:00:41 +0000
1305+++ tools/vmtest-sync-images 2017-01-18 16:16:23 +0000
1306@@ -12,12 +12,16 @@
1307 from tests.vmtests import (
1308 IMAGE_DIR, IMAGE_SRC_URL, sync_images)
1309 from tests.vmtests.image_sync import ITEM_NAME_FILTERS
1310-from tests.vmtests.helpers import find_releases
1311+from tests.vmtests.helpers import find_releases_by_distro
1312 from curtin.util import get_platform_arch
1313
1314 DEFAULT_ARCH = get_platform_arch()
1315
1316
1317+def _fmt_list_filter(filter_name, matches):
1318+ return '~'.join((filter_name, '|'.join(matches)))
1319+
1320+
1321 if __name__ == '__main__':
1322 if len(sys.argv) > 1 and sys.argv[1] == "--clean":
1323 print("cleaning image dir %s" % IMAGE_DIR)
1324@@ -35,11 +39,16 @@
1325 os.unlink(fpath)
1326
1327 arg_releases = [r for r in sys.argv[1:] if r != "--clean"]
1328+ arch_filters = ['arch={}'.format(DEFAULT_ARCH)]
1329+ filter_sets = []
1330 if len(arg_releases):
1331- releases = arg_releases
1332+ filter_sets.append([_fmt_list_filter('release', arg_releases)])
1333 else:
1334- releases = find_releases()
1335- release_filter = 'release~{}'.format('|'.join(releases))
1336- my_filters = ['arch=' + DEFAULT_ARCH, release_filter] + ITEM_NAME_FILTERS
1337+ filter_sets.extend(
1338+ (['os={}'.format(distro), _fmt_list_filter('release', rels)]
1339+ for (distro, rels) in find_releases_by_distro().items()))
1340+
1341 # Sync images.
1342- sync_images(IMAGE_SRC_URL, IMAGE_DIR, filters=my_filters, verbosity=1)
1343+ for filter_set in filter_sets:
1344+ sync_images(IMAGE_SRC_URL, IMAGE_DIR, verbosity=1,
1345+ filters=filter_set + ITEM_NAME_FILTERS + arch_filters)
1346
1347=== modified file 'tools/xkvm'
1348--- tools/xkvm 2016-10-03 18:43:46 +0000
1349+++ tools/xkvm 2017-01-18 16:16:23 +0000
1350@@ -572,12 +572,12 @@
1351
1352 if [ $need_taps -ne 0 ]; then
1353 local missing="" missing_pkgs="" reqs="" req="" pkgs="" pkg=""
1354- for i in "${connections[*]}"; do
1355- [ "$i" = "user" -o -e "/sys/class/net/dev/$i" ] ||
1356+ for i in "${connections[@]}"; do
1357+ [ "$i" = "user" -o -e "/sys/class/net/$i" ] ||
1358 missing="${missing} $i"
1359 done
1360 [ -z "$missing" ] || {
1361- error "cannot create connection on ${missing# }."
1362+ error "cannot create connection on: ${missing# }."
1363 error "bridges do not exist.";
1364 return 1;
1365 }

Subscribers

People subscribed via source and target branches

to all changes: