Skip to content
Snippets Groups Projects
Commit 1377b8a7 authored by Nikos Skalkotos's avatar Nikos Skalkotos
Browse files

Use libguestfs to access the image

parent 333ff548
No related branches found
No related tags found
No related merge requests found
...@@ -6,12 +6,14 @@ import os ...@@ -6,12 +6,14 @@ import os
import tempfile import tempfile
import uuid import uuid
import re import re
import sys
import guestfs
from pbs import dmsetup from pbs import dmsetup
from pbs import blockdev from pbs import blockdev
from pbs import dd from pbs import dd
from pbs import kpartx
from pbs import mount class DiskError(Exception): pass
from pbs import umount
class Disk(object): class Disk(object):
...@@ -33,6 +35,10 @@ class Disk(object): ...@@ -33,6 +35,10 @@ class Disk(object):
raise NotImplementedError raise NotImplementedError
def cleanup(self): def cleanup(self):
while len(self._devices):
device = self._devices.pop()
device.destroy()
while len(self._cleanup_jobs): while len(self._cleanup_jobs):
job, args = self._cleanup_jobs.pop() job, args = self._cleanup_jobs.pop()
job(*args) job(*args)
...@@ -65,51 +71,57 @@ class Disk(object): ...@@ -65,51 +71,57 @@ class Disk(object):
finally: finally:
os.unlink(table) os.unlink(table)
new_device = DiskDevice(self, "/dev/mapper/%s" % snapshot) new_device = DiskDevice("/dev/mapper/%s" % snapshot)
self._devices.append(new_device) self._devices.append(new_device)
return new_device return new_device
def destroy_device(self, device):
self._devices.remove(device)
device.destroy()
class DiskDevice(object): class DiskDevice(object):
def __init__(self, disk, device, bootable = True): def __init__(self, device, bootable = True):
self.disk = disk
self.device = device self.device = device
self.is_bootable = bootable self.bootable = bootable
self.partitions_mapped = False
self.magic_number = uuid.uuid4().hex self.g = guestfs.GuestFS()
self.g.add_drive_opts(device, readonly = 0)
def list_partitions(self): self.g.launch()
if not self.partitions_mapped: roots = self.g.inspect_os()
kpartx("-a", "-p", self.magic_number, self.dev) if len(roots) == 0:
self.disk._cleanup_jobs.append(kpartx, "-d", "-p", raise DiskError("No operating system found")
self.magic_number, self.dev) if len(roots) > 1:
self.partitions_mapped = True raise DiskError("Multiple operating systems found")
output = kpartx("-l", "-p", self.magic_number, self.dev) self.root = roots[0]
return [ "/dev/mapper/%s" % x for x in
re.findall('^\S+', str(output), flags=re.MULTILINE)] def destroy(self):
self.g.umount_all()
def mount(self, partition): self.g.sync()
if not self.partitions_mapped: # Close the guestfs handler
self.list_partitions() del self.g
kpartx("-a", "-p", self.magic_number, self.dev)
self.disk._cleanup_jobs.append(kpartx, "-d", "-p", def get_image_metadata(self):
self.magic_number, self.dev) meta = {}
self.partitions_mapped = True meta["OSFAMILY"] = self.g.inspect_get_type(self.root)
meta["OS"] = self.g.inspect_get_distro(self.root)
targetfd, target = tempfile.mkdtemp() meta["description"] = self.g.inspect_get_product_name(self.root)
try: return meta
mount(dev, partition)
except: def mount(self):
os.rmdir(table) mps = g.inspect_get_mountpoints(self.root)
raise # Sort the keys to mount the fs in a correct order.
return target # / should be mounted befor /boot, etc
def compare (a, b):
def unmount(self, partition): if len(a[0]) > len(b[0]): return 1
umount(target) elif len(a[0]) == len(b[0]): return 0
else: return -1
mode = os.stat(self.source).st_mode mps.sort(compare)
if stat.S_ISDIR(mode): for mp, dev in mps:
os.rmdir(target) try:
self.g.mount(dev, mp)
except RuntimeError as msg:
print "%s (ignored)" % msg
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai : # vim: set sta sts=4 shiftwidth=4 sw=4 et ai :
...@@ -45,7 +45,9 @@ def main(): ...@@ -45,7 +45,9 @@ def main():
disk = Disk(source) disk = Disk(source)
try: try:
dev = disk.get_device() dev = disk.get_device()
metadata = dev.get_image_metadata()
for key, val in metadata.iteritems():
print "%s=%s" % (key,val)
finally: finally:
disk.cleanup() disk.cleanup()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment