"""The instances of this class can create images out of block devices."""
def __init__(self, device, output, bootable=True, meta={}):
- """Create a new ImageCreator."""
+ """Create a new Image instance"""
self.device = device
self.out = output
self.guestfs_device = None
self.size = 0
self.mounted = False
+ self.mounted_ro = False
self.g = guestfs.GuestFS()
self.g.add_drive_opts(self.device, readonly=0, format="raw")
self.guestfs_enabled = False
def enable(self):
- """Enable a newly created ImageCreator"""
+ """Enable a newly created Image instance"""
self.out.output('Launching helper VM (may take a while) ...', False)
# self.progressbar = self.out.Progress(100, "Launching helper VM",
self.ostype = self.g.inspect_get_type(self.root)
self.distro = self.g.inspect_get_distro(self.root)
- self.out.success('found a(n) %s system' % self.distro)
+ self.out.success(
+ 'found a(n) %s system' %
+ self.ostype if self.distro == "unknown" else self.distro)
def _get_os(self):
+ """Return an OS class instance for this image"""
if hasattr(self, "_os"):
return self._os
os = property(_get_os)
def destroy(self):
- """Destroy this ImageCreator instance."""
+ """Destroy this Image instance."""
# In new guestfs versions, there is a handy shutdown method for this
try:
def mount(self, readonly=False):
"""Mount all disk partitions in a correct order."""
- mount = self.g.mount_ro if readonly else self.g.mount
- msg = " read-only" if readonly else ""
- self.out.output("Mounting the media%s ..." % msg, False)
- mps = self.g.inspect_get_mountpoints(self.root)
+ msg = "Mounting the media%s ..." % (" read-only" if readonly else "")
+ self.out.output(msg, False)
+
+ #If something goes wrong when mounting rw, remount the filesystem ro
+ remount_ro = False
+ rw_mpoints = ('/', '/etc', '/root', '/home', '/var')
# Sort the keys to mount the fs in a correct order.
# / should be mounted befor /boot, etc
return 0
else:
return -1
+ mps = self.g.inspect_get_mountpoints(self.root)
mps.sort(compare)
+
+ mopts = 'ro' if readonly else 'rw'
for mp, dev in mps:
+ if self.ostype == 'freebsd':
+ # libguestfs can't handle correct freebsd partitions on GUID
+ # Partition Table. We have to do the translation to linux
+ # device names ourselves
+ m = re.match('^/dev/((?:ada)|(?:vtbd))(\d+)p(\d+)$', dev)
+ if m:
+ m2 = int(m.group(2))
+ m3 = int(m.group(3))
+ dev = '/dev/sd%c%d' % (chr(ord('a') + m2), m3)
try:
- mount(dev, mp)
+ self.g.mount_options(mopts, dev, mp)
except RuntimeError as msg:
- self.out.warn("%s (ignored)" % msg)
-
- self.mounted = True
- self.out.success("done")
+ if self.ostype == 'freebsd':
+ freebsd_mopts = "ufstype=ufs2,%s" % mopts
+ try:
+ self.g.mount_vfs(freebsd_mopts, 'ufs', dev, mp)
+ except RuntimeError as msg:
+ if readonly is False and mp in rw_mpoints:
+ remount_ro = True
+ break
+ elif readonly is False and mp in rw_mpoints:
+ remount_ro = True
+ break
+ else:
+ self.out.warn("%s (ignored)" % msg)
+ if remount_ro:
+ self.out.warn("Unable to mount %s read-write. "
+ "Remounting everything read-only..." % mp)
+ self.umount()
+ self.mount(True)
+ else:
+ self.mounted = True
+ self.mounted_ro = readonly
+ self.out.success("done")
def umount(self):
"""Umount all mounted filesystems."""
self.mounted = False
def _last_partition(self):
+ """Return the last partition of the image disk"""
if self.meta['PARTITION_TABLE'] not in 'msdos' 'gpt':
msg = "Unsupported partition table: %s. Only msdos and gpt " \
"partition tables are supported" % self.meta['PARTITION_TABLE']
return last_partition
def shrink(self):
- """Shrink the disk.
+ """Shrink the image.
- This is accomplished by shrinking the last filesystem in the
- disk and then updating the partition table. The new disk size
+ This is accomplished by shrinking the last file system of the
+ image and then updating the partition table. The new disk size
(in bytes) is returned.
ATTENTION: make sure unmount is called before shrink
return self.size
def dump(self, outfile):
- """Dumps the content of device into a file.
+ """Dumps the content of the image into a file.
This method will only dump the actual payload, found by reading the
partition table. Empty space in the end of the device will be ignored.