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
=== modified file 'bin/maas-cloudimg2eph2'
--- bin/maas-cloudimg2eph2 2016-07-11 15:18:00 +0000
+++ bin/maas-cloudimg2eph2 2016-08-01 19:18:07 +0000
@@ -646,6 +646,15 @@
646 mv --force "$timg" "$output" ||646 mv --force "$timg" "$output" ||
647 { error "failed move to $output"; return 1; }647 { error "failed move to $output"; return 1; }
648 fi648 fi
649
650 if [[ "$src" == *squashfs ]]; then
651 output_dir=$(dirname $output)
652 cp "$src" "$output_dir" || {
653 error "copy SquashFS image from $src -> $output_dir failed"
654 return 1;
655 }
656 fi
657
649 ddebug 1 "finished"658 ddebug 1 "finished"
650 return 0659 return 0
651}660}
652661
=== modified file 'meph2/commands/cloudimg_sync.py'
--- meph2/commands/cloudimg_sync.py 2016-03-01 16:01:41 +0000
+++ meph2/commands/cloudimg_sync.py 2016-08-01 19:18:07 +0000
@@ -11,7 +11,9 @@
11from meph2.stream import CONTENT_ID, create_version11from meph2.stream import CONTENT_ID, create_version
1212
13import argparse13import argparse
14import glob
14import copy15import copy
16import hashlib
15import os17import os
16import sys18import sys
17import yaml19import yaml
@@ -65,7 +67,7 @@
6567
66class CloudImg2Meph2Sync(mirrors.BasicMirrorWriter):68class CloudImg2Meph2Sync(mirrors.BasicMirrorWriter):
67 def __init__(self, config, out_d, target, v2config, rebuilds=None,69 def __init__(self, config, out_d, target, v2config, rebuilds=None,
68 verbosity=0):70 verbosity=0, squashfs=False):
69 super(CloudImg2Meph2Sync, self).__init__(config=config)71 super(CloudImg2Meph2Sync, self).__init__(config=config)
70 if rebuilds is None:72 if rebuilds is None:
71 rebuilds = {}73 rebuilds = {}
@@ -74,7 +76,13 @@
74 self.target = target76 self.target = target
75 self.v2config = v2config77 self.v2config = v2config
76 self.filters = self.config.get('filters', [])78 self.filters = self.config.get('filters', [])
77 self.enable_di = self.config.get('enable_di', True)79 self.squashfs = squashfs
80 if self.squashfs:
81 # As of MAAS 2.0 DI is no longer supported but SquashFS is.
82 # Since the DI won't be used don't generate them.
83 self.enable_di = False
84 else:
85 self.enable_di = self.config.get('enable_di', True)
7886
79 with open(v2config) as fp:87 with open(v2config) as fp:
80 cfgdata = yaml.load(fp)88 cfgdata = yaml.load(fp)
@@ -117,6 +125,25 @@
117 self.content_t = my_prods125 self.content_t = my_prods
118 return v2_to_cloudimg_products(my_prods, rebuilds=self.rebuilds)126 return v2_to_cloudimg_products(my_prods, rebuilds=self.rebuilds)
119127
128 def _verify_sha256(self, filename, expected_sha256):
129 sha256 = hashlib.sha256()
130 with open(filename, 'rb') as f:
131 while True:
132 data = f.read(2**18)
133 if not data:
134 break
135 sha256.update(data)
136 if sha256.hexdigest() != expected_sha256:
137 raise ValueError(
138 'Expected SHA256 %s got %s on %s' %
139 (expected_sha256, sha256.hexdigest(), filename))
140
141 def _remove_unused(self, filename):
142 """Remove the specified file if a squashfs image exists."""
143 squashfs_image = os.path.join(os.path.dirname(filename), '*.squashfs')
144 if len(glob.glob(squashfs_image)) > 0 and os.path.exists(filename):
145 os.remove(filename)
146
120 def insert_item(self, data, src, target, pedigree, contentsource):147 def insert_item(self, data, src, target, pedigree, contentsource):
121 # create the ephemeral root148 # create the ephemeral root
122149
@@ -138,8 +165,37 @@
138165
139 for prodname, items in cvret.items():166 for prodname, items in cvret.items():
140 for i in items:167 for i in items:
141 sutil.products_set(self.content_t, items[i],168 filename = os.path.join(self.out_d, items[i]['path'])
142 (prodname, vername, i))169 if 'squashfs' in i and not self.squashfs:
170 # If we're not publishing the SquashFS image but one
171 # was used to generate root-image.gz delete it.
172 os.remove(filename)
173 continue
174 elif i == 'root-image.gz' and self.squashfs:
175 # If we're publishing the SquashFS image we don't need the
176 # root-image after its been used to generate kernels
177 self._remove_unused(filename)
178 continue
179 elif i == 'manifest' and self.squashfs:
180 # If we're publishing the SquashFS image we don't need the
181 # root-image manifest either.
182 self._remove_unused(filename)
183 continue
184 if i == 'squashfs':
185 # Verify upstream SHA256 of SquashFS images and add
186 # SHA256 and size to our stream.
187 self._verify_sha256(filename, flat['sha256'])
188 items[i]['sha256'] = flat['sha256']
189 items[i]['size'] = int(flat['size'])
190 elif i == 'squashfs.manifest':
191 manifest_pedigree = pedigree[:2] + ('squashfs.manifest',)
192 manifest_flat = sutil.products_exdata(
193 src, manifest_pedigree)
194 self._verify_sha256(filename, manifest_flat['sha256'])
195 items[i]['sha256'] = manifest_flat['sha256']
196 items[i]['size'] = int(manifest_flat['size'])
197 sutil.products_set(
198 self.content_t, items[i], (prodname, vername, i))
143199
144 def insert_products(self, path, target, content):200 def insert_products(self, path, target, content):
145 tree = copy.deepcopy(self.content_t)201 tree = copy.deepcopy(self.content_t)
@@ -184,7 +240,12 @@
184 return True240 return True
185241
186 def filter_item(self, data, src, target, pedigree):242 def filter_item(self, data, src, target, pedigree):
187 if data['ftype'] != "tar.gz":243 # Only use tar.gz if no SquashFS image is available
244 if data['ftype'] == 'tar.gz':
245 product = src['products'][pedigree[0]]['versions'][pedigree[1]]
246 if 'squashfs' in product['items'].keys():
247 return False
248 elif data['ftype'] != 'squashfs':
188 return False249 return False
189 return filters.filter_item(self.filters, data, src, pedigree)250 return filters.filter_item(self.filters, data, src, pedigree)
190251
@@ -212,6 +273,9 @@
212 parser.add_argument('--verbose', '-v', action='count', default=0)273 parser.add_argument('--verbose', '-v', action='count', default=0)
213 parser.add_argument('--log-file', default=sys.stderr,274 parser.add_argument('--log-file', default=sys.stderr,
214 type=argparse.FileType('w'))275 type=argparse.FileType('w'))
276 parser.add_argument('--squashfs', action='store_true', default=False,
277 help='Download SquashFS root file systems if available'
278 )
215279
216 parser.add_argument('output_d')280 parser.add_argument('output_d')
217 parser.add_argument('filters', nargs='*', default=[])281 parser.add_argument('filters', nargs='*', default=[])
@@ -272,7 +336,8 @@
272336
273 tmirror = CloudImg2Meph2Sync(config=mirror_config, out_d=args.output_d,337 tmirror = CloudImg2Meph2Sync(config=mirror_config, out_d=args.output_d,
274 target=args.target, v2config=args.config,338 target=args.target, v2config=args.config,
275 rebuilds=rebuilds, verbosity=vlevel)339 rebuilds=rebuilds, verbosity=vlevel,
340 squashfs=args.squashfs)
276341
277 tmirror.sync(smirror, initial_path)342 tmirror.sync(smirror, initial_path)
278343
279344
=== modified file 'meph2/commands/meph2_util.py'
--- meph2/commands/meph2_util.py 2016-07-29 22:28:22 +0000
+++ meph2/commands/meph2_util.py 2016-08-01 19:18:07 +0000
@@ -629,7 +629,7 @@
629 cfg_path = args.import_cfg629 cfg_path = args.import_cfg
630 else:630 else:
631 print("Error: Unable to find config file %s" % args.import_cfg)631 print("Error: Unable to find config file %s" % args.import_cfg)
632 os.exit(1)632 sys.exit(1)
633633
634 with open(cfg_path) as fp:634 with open(cfg_path) as fp:
635 cfgdata = yaml.load(fp)635 cfgdata = yaml.load(fp)
636636
=== modified file 'meph2/stream.py'
--- meph2/stream.py 2016-05-11 18:41:21 +0000
+++ meph2/stream.py 2016-08-01 19:18:07 +0000
@@ -20,6 +20,10 @@
20PATH_FORMATS = {20PATH_FORMATS = {
21 'root-image.gz': PATH_COMMON + "%(version_name)s/root-image.gz",21 'root-image.gz': PATH_COMMON + "%(version_name)s/root-image.gz",
22 'manifest': PATH_COMMON + "%(version_name)s/root-image.manifest",22 'manifest': PATH_COMMON + "%(version_name)s/root-image.manifest",
23 'squashfs': PATH_COMMON + "%(version_name)s/%(img_name)s",
24 'squashfs.manifest': (
25 PATH_COMMON + "%(version_name)s/%(img_name)s.manifest"
26 ),
23 'boot-dtb': BOOT_COMMON + "/boot-dtb%(suffix)s",27 'boot-dtb': BOOT_COMMON + "/boot-dtb%(suffix)s",
24 'boot-kernel': BOOT_COMMON + "/boot-kernel%(suffix)s",28 'boot-kernel': BOOT_COMMON + "/boot-kernel%(suffix)s",
25 'boot-initrd': BOOT_COMMON + "/boot-initrd%(suffix)s",29 'boot-initrd': BOOT_COMMON + "/boot-initrd%(suffix)s",
@@ -116,7 +120,8 @@
116 newitems = {}120 newitems = {}
117121
118 subs = {'release': release, 'arch': arch,122 subs = {'release': release, 'arch': arch,
119 'version_name': version_name, 'version': version}123 'version_name': version_name, 'version': version,
124 'img_name': os.path.basename(img_url)}
120125
121 rootimg_path = PATH_FORMATS['root-image.gz'] % subs126 rootimg_path = PATH_FORMATS['root-image.gz'] % subs
122 manifest_path = PATH_FORMATS['manifest'] % subs127 manifest_path = PATH_FORMATS['manifest'] % subs
@@ -151,6 +156,8 @@
151156
152 boot_keys = ['boot-kernel', 'boot-initrd']157 boot_keys = ['boot-kernel', 'boot-initrd']
153 ikeys = boot_keys + ['root-image.gz', 'manifest']158 ikeys = boot_keys + ['root-image.gz', 'manifest']
159 if img_url.endswith('.squashfs'):
160 ikeys += ['squashfs']
154161
155 dtb = kdata.get('dtb')162 dtb = kdata.get('dtb')
156 if dtb:163 if dtb:

Subscribers

People subscribed via source and target branches