diff --git a/image_creator/dialog_main.py b/image_creator/dialog_main.py index 0586327855cbade694d8d0764dc56c24adb30967..2a56a1c2a0238a39c6d1516a7e16cc2dd1573d8f 100644 --- a/image_creator/dialog_main.py +++ b/image_creator/dialog_main.py @@ -101,7 +101,7 @@ def create_image(d, media, out, tmp): "image": image, "metadata": metadata} - if hasattr(image, "unsupported"): + if image.is_unsupported(): session['excluded_tasks'] = [-1] session['task_metadata'] = ["EXCLUDE_ALL_TASKS"] @@ -112,7 +112,7 @@ def create_image(d, media, out, tmp): "since the image won't be cleaned up and you will not be " \ "able to configure it during the deployment. Press <YES> if " \ "you still want to continue with the image creation process." \ - % image.unsupported + % image._unsupported if not d.yesno(msg, width=WIDTH, defaultno=1, height=12): main_menu(session) diff --git a/image_creator/dialog_menu.py b/image_creator/dialog_menu.py index ba29ea1051403288cb225859bed12b929f9ad966..1e7497072e832e82b38ebb3898e284638d5f6468 100644 --- a/image_creator/dialog_menu.py +++ b/image_creator/dialog_menu.py @@ -585,9 +585,9 @@ def exclude_tasks(session): d = session['dialog'] image = session['image'] - if hasattr(image, "unsupported"): - d.msgbox("You cannot configure the deployment tasks for an unsupported" - " image.", width=SMALL_WIDTH) + if image.is_unsupported(): + d.msgbox("Image deployment configuration is disabled for unsupported " + "images.", width=SMALL_WIDTH) return False index = 0 diff --git a/image_creator/image.py b/image_creator/image.py index 2eb97ddfc2fd59b7a4933b5c058c6ae0e004130b..bbc53ae13d0d8c377eb65747bb399ca8d195e5d1 100644 --- a/image_creator/image.py +++ b/image_creator/image.py @@ -95,23 +95,19 @@ class Image(object): self.distro = "unsupported" self.guestfs_device = '/dev/sda' self.size = self.g.blockdev_getsize64(self.guestfs_device) + if len(roots) > 1: - self.unsupported = "Multiple operating systems found on the " \ - "media. We only support images with one OS." + reason = "Multiple operating systems found on the media." else: - self.unsupported = \ - "Unable to detect any operating system on the media" + reason = "Unable to detect any operating system on the media." - self.meta['UNSUPPORTED'] = "Reason: %s" % self.unsupported - self.out.warn('Media is not supported. %s' % - self.meta['UNSUPPORTED']) + self.set_unsupported(reason) return self.root = roots[0] - self.guestfs_device = self.g.part_to_dev(self.root) + self.meta['PARTITION_TABLE'] = self.g.part_get_parttype('/dev/sda') + self.guestfs_device = '/dev/sda' # self.g.part_to_dev(self.root) self.size = self.g.blockdev_getsize64(self.guestfs_device) - self.meta['PARTITION_TABLE'] = \ - self.g.part_get_parttype(self.guestfs_device) self.ostype = self.g.inspect_get_type(self.root) self.distro = self.g.inspect_get_distro(self.root) @@ -119,6 +115,20 @@ class Image(object): 'found a(n) %s system' % self.ostype if self.distro == "unknown" else self.distro) + # Run OS-specific diagnostics + self.os.diagnose() + + def set_unsupported(self, reason): + """Flag this image us ansupported""" + + self._unsupported = reason + self.meta['UNSUPPORTED'] = reason + self.out.warn('Media is not supported. Reason: %s' % reason) + + def is_unsupported(self): + """Returns if this image is unsupported""" + return hasattr(self, '_unsupported') + def enable_guestfs(self): """Enable the guestfs handler""" @@ -278,8 +288,8 @@ class Image(object): self.out.output("Shrinking image (this may take a while) ...", False) - if hasattr(self, "unsupported"): - self.out.warn("Unable to shrink unsupported image") + if self.is_unsupported(): + self.out.warn("Shrinking is disabled for unsupported images") return self.size sector_size = self.g.blockdev_getss(self.guestfs_device) diff --git a/image_creator/main.py b/image_creator/main.py index 29ed0682c13fc9deed577831018e3f4ffed8d2ea..26e1be510e431f0957d072947c71037c5cb81817 100644 --- a/image_creator/main.py +++ b/image_creator/main.py @@ -50,6 +50,7 @@ import optparse import StringIO import signal import json +import textwrap def check_writable_dir(option, opt_str, value, parser): @@ -277,13 +278,15 @@ def image_creator(): image = disk.get_image(snapshot, sysprep_params=options.sysprep_params) - if hasattr(image, 'unsupported') and not options.allow_unsupported: + if image.is_unsupported() and not options.allow_unsupported: raise FatalError( - "The media seems to be unsupported. If you insist on creating " - "an image out of it, use the `--allow-unsupported' option. " - "Using this is highly discouraged, since the resulting image " - "will not be cleaned up from sensitive data and will not get " - "configured during the deployment") + "The media seems to be unsupported.\n\n" + + textwrap.fill("To create an image from an unsupported media, " + "you'll need to use the`--allow-unsupported' " + "command line option. Using this is highly " + "discouraged, since the resulting image will " + "not be cleared out of sensitive data and will " + "not get customized during the deployment.")) for sysprep in options.disabled_syspreps: image.os.disable_sysprep(image.os.get_sysprep_by_name(sysprep)) @@ -310,7 +313,7 @@ def image_creator(): size = options.shrink and image.shrink() or image.size metadata.update(image.meta) - if hasattr(image, 'unsupported'): + if image.is_unsupported(): metadata['EXCLUDE_ALL_TASKS'] = "yes" # Add command line metadata to the collected ones... diff --git a/image_creator/os_type/__init__.py b/image_creator/os_type/__init__.py index ff51debd3244377aa2ec28c28a074e9308c31ed8..63b7f5a2de158ad8eb8c775afae0cc8d5804ec4b 100644 --- a/image_creator/os_type/__init__.py +++ b/image_creator/os_type/__init__.py @@ -144,6 +144,22 @@ class OSBase(object): except RuntimeError: self._scrub_support = False + def diagnose(self): + """Run diagnostics to check if the media is supported""" + + if self.image.is_unsupported(): + return + + self.out.output('Running OS diagnostics:') + try: + if not self.mount(readonly=True): + raise FatalError("Unable to mount the media read-only") + self._do_diagnose() + finally: + self.umount() + + self.out.output() + def collect_metadata(self): """Collect metadata about the OS""" try: @@ -249,7 +265,7 @@ class OSBase(object): self.out.output('Preparing system for image creation:') - if hasattr(self.image, "unsupported"): + if self.image.is_unsupported(): self.out.warn( "System preparation is disabled for unsupported media") return @@ -356,10 +372,20 @@ class OSBase(object): if has_ftype(f, ftype): action(full_path) + def _do_diagnose(self): + """helper method for diagnose""" + pass + def _do_collect_metadata(self): """helper method for collect_metadata""" - self.meta['ROOT_PARTITION'] = \ - "%d" % self.image.g.part_to_partnum(self.root) + + try: + self.meta['ROOT_PARTITION'] = \ + "%d" % self.image.g.part_to_partnum(self.root) + except RuntimeError: + self.out.warn("Unable to identify the partition number from root " + "partition: %s" % self.root) + self.meta['OSFAMILY'] = self.image.g.inspect_get_type(self.root) self.meta['OS'] = self.image.g.inspect_get_distro(self.root) if self.meta['OS'] == "unknown": diff --git a/image_creator/os_type/freebsd.py b/image_creator/os_type/freebsd.py index 5f814818eb8a243a26b141be7d70c9284ab60446..8ee54278a3363922608007073094ca39376e193f 100644 --- a/image_creator/os_type/freebsd.py +++ b/image_creator/os_type/freebsd.py @@ -82,6 +82,18 @@ class Freebsd(Unix): self.out.warn("No passworded users found!") del self.meta['USERS'] + def _do_diagnose(self): + """Run various diagnostics to check if media is supported""" + + self.out.output('Checking partition table type...', False) + ptype = self.image.g.part_get_parttype(self.image.guestfs_device) + if ptype != 'gpt': + self.out.warn("partition table type is: `%s'" % ptype) + self.image.set_unsupported( + 'On FreeBSD only GUID partition tables are supported') + else: + self.out.success(ptype) + def _get_passworded_users(self): """Returns a list of non-locked user accounts""" users = [] diff --git a/image_creator/os_type/linux.py b/image_creator/os_type/linux.py index 31b660f01fcedf275f336671073109bc707917ff..d0ca04a178657b40445a915fb1ff39970fa9008d 100644 --- a/image_creator/os_type/linux.py +++ b/image_creator/os_type/linux.py @@ -298,6 +298,20 @@ class Linux(Unix): return orig, dev, mpoint + def _do_diagnose(self): + """Run various diagnostics to check if media is supported""" + + self.out.output( + 'Checking if the media contains logical volumes (LVM)...', False) + + has_lvm = True if len(self.image.g.lvs()) else False + + if has_lvm: + self.out.output() + self.image.set_unsupported('The media contains logical volumes') + else: + self.out.success('no') + def _do_collect_metadata(self): """Collect metadata about the OS""" super(Linux, self)._do_collect_metadata()