Merge lp:~ltrager/maas-images/squashfs into lp:maas-images

Proposed by Lee Trager
Status: Merged
Merged at revision: 316
Proposed branch: lp:~ltrager/maas-images/squashfs
Merge into: lp:maas-images
Diff against target: 204 lines (+89/-8)
4 files modified
bin/maas-cloudimg2eph2 (+9/-0)
meph2/commands/cloudimg_sync.py (+71/-6)
meph2/commands/meph2_util.py (+1/-1)
meph2/stream.py (+8/-1)
To merge this branch: bzr merge lp:~ltrager/maas-images/squashfs
Reviewer Review Type Date Requested Status
Andres Rodriguez (community) Approve
Review via email: mp+298852@code.launchpad.net

Commit message

If available build root-image.gz based off the upstream SquashFS image and republish the SquashFS image.

Description of the change

When generating Ubuntu images check if the upstream SimpleStream has published a SquashFS image. If so build root-image.gz based off the SquashFS image, instead of the tar.gz. The downloaded SquashFS image has its SHA256 verified and republished, with the same name as upstream, in the new stream alongside root-image.gz.

This won't be pushed into the image creation process for http://images.maas.io/ephemeral-v2/ for another couple of weeks. I need this to add SquashFS support to MAAS and wanted to get the review out of the way.

To post a comment you must log in.
Revision history for this message
Andres Rodriguez (andreserl) wrote :

Why do we need to create a root-image.gz anymore ? I don't think we want to create any images anymore. If there's a squashfs image, then we should use that and not have to create more and more and more stuff.

We are trying to reduce the amount of images and what we have available and what we use, creating a root-image.gz adds more stuff that we dont really need?

review: Needs Information
Revision history for this message
Scott Moser (smoser) :
Revision history for this message
Lee Trager (ltrager) wrote :

> Why do we need to create a root-image.gz anymore ? I don't think we want to
> create any images anymore. If there's a squashfs image, then we should use
> that and not have to create more and more and more stuff.
>
> We are trying to reduce the amount of images and what we have available and
> what we use, creating a root-image.gz adds more stuff that we dont really
> need?

root-image.gz is still needed for older releases until the SquashFS work is done. By having both we can update the stream while still developing the feature. Once the SquashFS work is done and has been pushed out we can remove the root-image.gz.

Revision history for this message
Lee Trager (ltrager) :
Revision history for this message
Lee Trager (ltrager) wrote :

Last night I created an MP which adds support for SquashFS images to MAAS.

https://code.launchpad.net/~ltrager/maas/squashfs/+merge/299264

lp:~ltrager/maas-images/squashfs updated
305. By Scott Moser

Disable metadata_csum when creating ext4 filesystems

In yakkety, we have sync'd an e2fsprogs version that supports metadata
checksumming in ext4 and enables the feature by default. Unfortunately,
some Launchpad buildds (specifically those for armhf and one for powerpc)
are running on a kernel that is too old to support this, which means an
unusable ext4 partition is created. To work around this issue, we disable
the metadata_csum option when we create an ext4 filesystem.

The Launchpad team are working to upgrade the offending build hosts, so we
should be able to back this change out before yakkety releases.

Revision history for this message
Lee Trager (ltrager) wrote :

I've added a flag(--squashfs) to meph2-cloudimg-sync. By default this branch now has no effect unless the flag is used. When used if a SquashFS image is available from the upstream SimpleStream the SquashFS image will be published alongside the boot kernel and initrd. The di-kernel, di-initrd, and root-image.gz will no longer be included.

I've also removed the code which downloads the squashfs.manifest file as we don't use it in MAAS.

lp:~ltrager/maas-images/squashfs updated
306. By Lee Trager

Import and publish bootloaders from a yaml file.

This allows the import subcommand to accept a yaml file containing a list of bootloaders. The latest version of the bootloader is downloaded from the Ubuntu archive. Files can be copied out of the bootloader or they can be processed with grub-mkimage.

This also fixes a bug with the import command where if any version of a product existed no newer version would be imported. This will allow more up-to-date CentOS images to be published.

307. By Lee Trager

Remove duplicated geturl function and add version to bootloader product listing

Revision history for this message
Andres Rodriguez (andreserl) wrote :

Questions inline.

review: Needs Information
lp:~ltrager/maas-images/squashfs updated
308. By Lee Trager

Allow a grub.cfg to be embedded into generated grub image

309. By Lee Trager

Allow bootloader files to be renamed when put into the stream

310. By Lee Trager

Strip renamed filenames

311. By Scott Moser

tox.ini: tweaks

 * recreate: do not recreate tox environments on every 'tox' run.
 * create separate tox environments rather than re-using via
   declaring the 'envdir'
 * flake8: list the directories to run flake8 on so it does
   not attempt to run on .tox/

312. By Scott Moser

dpkg.py: fix flake8 complaints

Simply fix flake8 complaints from dpkg.py.

313. By Scott Moser

netinst.py: handle identical data published at different paths

the process that builds the d-i netboot data began publishing a
kernel and initramfs at different paths in 20101020ubuntu318.39.
For example, under
   /ubuntu-ports/dists/trusty-updates/main/installer-arm64/\
      20101020ubuntu318.40/images/xenial-generic/netboot/

There are now the same kernel and initrd and kernel at
  xenial-generic/netboot/initrd.gz
  xenial-generic/netboot/ubuntu-installer/arm64/initrd.gz
  xenial-generic/netboot/ubuntu-installer/arm64/linux
  xenial-generic/netboot/vmlinuz

That would cause a Name Collision in mine_md error on these files.

The change to address this is to raise exception only if
a name collision has different data than the existing. Also
we specifically handle 'dtb' as currently the basename (derived
from the url) is used there.

Revision history for this message
Lee Trager (ltrager) wrote :

Responded inline

lp:~ltrager/maas-images/squashfs updated
314. By Lee Trager

Use /usr/bin/dpkg directly instead of apt_pkg to avoid tox build issues

315. By Lee Trager

Remove unneeded comparison

Revision history for this message
Andres Rodriguez (andreserl) wrote :

lgtm!

review: Approve
lp:~ltrager/maas-images/squashfs updated
316. By Lee Trager

Add --squashfs flag to meph2-cloudimg-sync

meph2-cloudimg-sync now downloads SquashFS images if available from the upstream source. If the --squashfs flag is used meph2-cloudimg-sync will publish the unmodified SquashFS images where available. The --squashfs flag also disables generating the di-kernel and di-initrd.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/maas-cloudimg2eph2'
2--- bin/maas-cloudimg2eph2 2016-07-11 15:18:00 +0000
3+++ bin/maas-cloudimg2eph2 2016-08-01 19:18:07 +0000
4@@ -646,6 +646,15 @@
5 mv --force "$timg" "$output" ||
6 { error "failed move to $output"; return 1; }
7 fi
8+
9+ if [[ "$src" == *squashfs ]]; then
10+ output_dir=$(dirname $output)
11+ cp "$src" "$output_dir" || {
12+ error "copy SquashFS image from $src -> $output_dir failed"
13+ return 1;
14+ }
15+ fi
16+
17 ddebug 1 "finished"
18 return 0
19 }
20
21=== modified file 'meph2/commands/cloudimg_sync.py'
22--- meph2/commands/cloudimg_sync.py 2016-03-01 16:01:41 +0000
23+++ meph2/commands/cloudimg_sync.py 2016-08-01 19:18:07 +0000
24@@ -11,7 +11,9 @@
25 from meph2.stream import CONTENT_ID, create_version
26
27 import argparse
28+import glob
29 import copy
30+import hashlib
31 import os
32 import sys
33 import yaml
34@@ -65,7 +67,7 @@
35
36 class CloudImg2Meph2Sync(mirrors.BasicMirrorWriter):
37 def __init__(self, config, out_d, target, v2config, rebuilds=None,
38- verbosity=0):
39+ verbosity=0, squashfs=False):
40 super(CloudImg2Meph2Sync, self).__init__(config=config)
41 if rebuilds is None:
42 rebuilds = {}
43@@ -74,7 +76,13 @@
44 self.target = target
45 self.v2config = v2config
46 self.filters = self.config.get('filters', [])
47- self.enable_di = self.config.get('enable_di', True)
48+ self.squashfs = squashfs
49+ if self.squashfs:
50+ # As of MAAS 2.0 DI is no longer supported but SquashFS is.
51+ # Since the DI won't be used don't generate them.
52+ self.enable_di = False
53+ else:
54+ self.enable_di = self.config.get('enable_di', True)
55
56 with open(v2config) as fp:
57 cfgdata = yaml.load(fp)
58@@ -117,6 +125,25 @@
59 self.content_t = my_prods
60 return v2_to_cloudimg_products(my_prods, rebuilds=self.rebuilds)
61
62+ def _verify_sha256(self, filename, expected_sha256):
63+ sha256 = hashlib.sha256()
64+ with open(filename, 'rb') as f:
65+ while True:
66+ data = f.read(2**18)
67+ if not data:
68+ break
69+ sha256.update(data)
70+ if sha256.hexdigest() != expected_sha256:
71+ raise ValueError(
72+ 'Expected SHA256 %s got %s on %s' %
73+ (expected_sha256, sha256.hexdigest(), filename))
74+
75+ def _remove_unused(self, filename):
76+ """Remove the specified file if a squashfs image exists."""
77+ squashfs_image = os.path.join(os.path.dirname(filename), '*.squashfs')
78+ if len(glob.glob(squashfs_image)) > 0 and os.path.exists(filename):
79+ os.remove(filename)
80+
81 def insert_item(self, data, src, target, pedigree, contentsource):
82 # create the ephemeral root
83
84@@ -138,8 +165,37 @@
85
86 for prodname, items in cvret.items():
87 for i in items:
88- sutil.products_set(self.content_t, items[i],
89- (prodname, vername, i))
90+ filename = os.path.join(self.out_d, items[i]['path'])
91+ if 'squashfs' in i and not self.squashfs:
92+ # If we're not publishing the SquashFS image but one
93+ # was used to generate root-image.gz delete it.
94+ os.remove(filename)
95+ continue
96+ elif i == 'root-image.gz' and self.squashfs:
97+ # If we're publishing the SquashFS image we don't need the
98+ # root-image after its been used to generate kernels
99+ self._remove_unused(filename)
100+ continue
101+ elif i == 'manifest' and self.squashfs:
102+ # If we're publishing the SquashFS image we don't need the
103+ # root-image manifest either.
104+ self._remove_unused(filename)
105+ continue
106+ if i == 'squashfs':
107+ # Verify upstream SHA256 of SquashFS images and add
108+ # SHA256 and size to our stream.
109+ self._verify_sha256(filename, flat['sha256'])
110+ items[i]['sha256'] = flat['sha256']
111+ items[i]['size'] = int(flat['size'])
112+ elif i == 'squashfs.manifest':
113+ manifest_pedigree = pedigree[:2] + ('squashfs.manifest',)
114+ manifest_flat = sutil.products_exdata(
115+ src, manifest_pedigree)
116+ self._verify_sha256(filename, manifest_flat['sha256'])
117+ items[i]['sha256'] = manifest_flat['sha256']
118+ items[i]['size'] = int(manifest_flat['size'])
119+ sutil.products_set(
120+ self.content_t, items[i], (prodname, vername, i))
121
122 def insert_products(self, path, target, content):
123 tree = copy.deepcopy(self.content_t)
124@@ -184,7 +240,12 @@
125 return True
126
127 def filter_item(self, data, src, target, pedigree):
128- if data['ftype'] != "tar.gz":
129+ # Only use tar.gz if no SquashFS image is available
130+ if data['ftype'] == 'tar.gz':
131+ product = src['products'][pedigree[0]]['versions'][pedigree[1]]
132+ if 'squashfs' in product['items'].keys():
133+ return False
134+ elif data['ftype'] != 'squashfs':
135 return False
136 return filters.filter_item(self.filters, data, src, pedigree)
137
138@@ -212,6 +273,9 @@
139 parser.add_argument('--verbose', '-v', action='count', default=0)
140 parser.add_argument('--log-file', default=sys.stderr,
141 type=argparse.FileType('w'))
142+ parser.add_argument('--squashfs', action='store_true', default=False,
143+ help='Download SquashFS root file systems if available'
144+ )
145
146 parser.add_argument('output_d')
147 parser.add_argument('filters', nargs='*', default=[])
148@@ -272,7 +336,8 @@
149
150 tmirror = CloudImg2Meph2Sync(config=mirror_config, out_d=args.output_d,
151 target=args.target, v2config=args.config,
152- rebuilds=rebuilds, verbosity=vlevel)
153+ rebuilds=rebuilds, verbosity=vlevel,
154+ squashfs=args.squashfs)
155
156 tmirror.sync(smirror, initial_path)
157
158
159=== modified file 'meph2/commands/meph2_util.py'
160--- meph2/commands/meph2_util.py 2016-07-29 22:28:22 +0000
161+++ meph2/commands/meph2_util.py 2016-08-01 19:18:07 +0000
162@@ -629,7 +629,7 @@
163 cfg_path = args.import_cfg
164 else:
165 print("Error: Unable to find config file %s" % args.import_cfg)
166- os.exit(1)
167+ sys.exit(1)
168
169 with open(cfg_path) as fp:
170 cfgdata = yaml.load(fp)
171
172=== modified file 'meph2/stream.py'
173--- meph2/stream.py 2016-05-11 18:41:21 +0000
174+++ meph2/stream.py 2016-08-01 19:18:07 +0000
175@@ -20,6 +20,10 @@
176 PATH_FORMATS = {
177 'root-image.gz': PATH_COMMON + "%(version_name)s/root-image.gz",
178 'manifest': PATH_COMMON + "%(version_name)s/root-image.manifest",
179+ 'squashfs': PATH_COMMON + "%(version_name)s/%(img_name)s",
180+ 'squashfs.manifest': (
181+ PATH_COMMON + "%(version_name)s/%(img_name)s.manifest"
182+ ),
183 'boot-dtb': BOOT_COMMON + "/boot-dtb%(suffix)s",
184 'boot-kernel': BOOT_COMMON + "/boot-kernel%(suffix)s",
185 'boot-initrd': BOOT_COMMON + "/boot-initrd%(suffix)s",
186@@ -116,7 +120,8 @@
187 newitems = {}
188
189 subs = {'release': release, 'arch': arch,
190- 'version_name': version_name, 'version': version}
191+ 'version_name': version_name, 'version': version,
192+ 'img_name': os.path.basename(img_url)}
193
194 rootimg_path = PATH_FORMATS['root-image.gz'] % subs
195 manifest_path = PATH_FORMATS['manifest'] % subs
196@@ -151,6 +156,8 @@
197
198 boot_keys = ['boot-kernel', 'boot-initrd']
199 ikeys = boot_keys + ['root-image.gz', 'manifest']
200+ if img_url.endswith('.squashfs'):
201+ ikeys += ['squashfs']
202
203 dtb = kdata.get('dtb')
204 if dtb:

Subscribers

People subscribed via source and target branches