6 |
6 |
import tempfile
|
7 |
7 |
import uuid
|
8 |
8 |
import re
|
|
9 |
import sys
|
|
10 |
import guestfs
|
|
11 |
|
9 |
12 |
from pbs import dmsetup
|
10 |
13 |
from pbs import blockdev
|
11 |
14 |
from pbs import dd
|
12 |
|
from pbs import kpartx
|
13 |
|
from pbs import mount
|
14 |
|
from pbs import umount
|
|
15 |
|
|
16 |
class DiskError(Exception): pass
|
15 |
17 |
|
16 |
18 |
class Disk(object):
|
17 |
19 |
|
... | ... | |
33 |
35 |
raise NotImplementedError
|
34 |
36 |
|
35 |
37 |
def cleanup(self):
|
|
38 |
while len(self._devices):
|
|
39 |
device = self._devices.pop()
|
|
40 |
device.destroy()
|
|
41 |
|
36 |
42 |
while len(self._cleanup_jobs):
|
37 |
43 |
job, args = self._cleanup_jobs.pop()
|
38 |
44 |
job(*args)
|
... | ... | |
65 |
71 |
finally:
|
66 |
72 |
os.unlink(table)
|
67 |
73 |
|
68 |
|
new_device = DiskDevice(self, "/dev/mapper/%s" % snapshot)
|
|
74 |
new_device = DiskDevice("/dev/mapper/%s" % snapshot)
|
69 |
75 |
self._devices.append(new_device)
|
70 |
76 |
return new_device
|
71 |
77 |
|
|
78 |
def destroy_device(self, device):
|
|
79 |
self._devices.remove(device)
|
|
80 |
device.destroy()
|
|
81 |
|
72 |
82 |
class DiskDevice(object):
|
73 |
83 |
|
74 |
|
def __init__(self, disk, device, bootable = True):
|
75 |
|
self.disk = disk
|
|
84 |
def __init__(self, device, bootable = True):
|
76 |
85 |
self.device = device
|
77 |
|
self.is_bootable = bootable
|
78 |
|
self.partitions_mapped = False
|
79 |
|
self.magic_number = uuid.uuid4().hex
|
80 |
|
|
81 |
|
def list_partitions(self):
|
82 |
|
if not self.partitions_mapped:
|
83 |
|
kpartx("-a", "-p", self.magic_number, self.dev)
|
84 |
|
self.disk._cleanup_jobs.append(kpartx, "-d", "-p",
|
85 |
|
self.magic_number, self.dev)
|
86 |
|
self.partitions_mapped = True
|
87 |
|
|
88 |
|
output = kpartx("-l", "-p", self.magic_number, self.dev)
|
89 |
|
return [ "/dev/mapper/%s" % x for x in
|
90 |
|
re.findall('^\S+', str(output), flags=re.MULTILINE)]
|
91 |
|
|
92 |
|
def mount(self, partition):
|
93 |
|
if not self.partitions_mapped:
|
94 |
|
self.list_partitions()
|
95 |
|
kpartx("-a", "-p", self.magic_number, self.dev)
|
96 |
|
self.disk._cleanup_jobs.append(kpartx, "-d", "-p",
|
97 |
|
self.magic_number, self.dev)
|
98 |
|
self.partitions_mapped = True
|
99 |
|
|
100 |
|
targetfd, target = tempfile.mkdtemp()
|
101 |
|
try:
|
102 |
|
mount(dev, partition)
|
103 |
|
except:
|
104 |
|
os.rmdir(table)
|
105 |
|
raise
|
106 |
|
return target
|
107 |
|
|
108 |
|
def unmount(self, partition):
|
109 |
|
umount(target)
|
110 |
|
|
111 |
|
mode = os.stat(self.source).st_mode
|
112 |
|
if stat.S_ISDIR(mode):
|
113 |
|
os.rmdir(target)
|
|
86 |
self.bootable = bootable
|
|
87 |
|
|
88 |
self.g = guestfs.GuestFS()
|
|
89 |
self.g.add_drive_opts(device, readonly = 0)
|
|
90 |
self.g.launch()
|
|
91 |
roots = self.g.inspect_os()
|
|
92 |
if len(roots) == 0:
|
|
93 |
raise DiskError("No operating system found")
|
|
94 |
if len(roots) > 1:
|
|
95 |
raise DiskError("Multiple operating systems found")
|
|
96 |
|
|
97 |
self.root = roots[0]
|
|
98 |
|
|
99 |
def destroy(self):
|
|
100 |
self.g.umount_all()
|
|
101 |
self.g.sync()
|
|
102 |
# Close the guestfs handler
|
|
103 |
del self.g
|
|
104 |
|
|
105 |
def get_image_metadata(self):
|
|
106 |
meta = {}
|
|
107 |
meta["OSFAMILY"] = self.g.inspect_get_type(self.root)
|
|
108 |
meta["OS"] = self.g.inspect_get_distro(self.root)
|
|
109 |
meta["description"] = self.g.inspect_get_product_name(self.root)
|
|
110 |
return meta
|
|
111 |
|
|
112 |
def mount(self):
|
|
113 |
mps = g.inspect_get_mountpoints(self.root)
|
|
114 |
# Sort the keys to mount the fs in a correct order.
|
|
115 |
# / should be mounted befor /boot, etc
|
|
116 |
def compare (a, b):
|
|
117 |
if len(a[0]) > len(b[0]): return 1
|
|
118 |
elif len(a[0]) == len(b[0]): return 0
|
|
119 |
else: return -1
|
|
120 |
mps.sort(compare)
|
|
121 |
for mp, dev in mps:
|
|
122 |
try:
|
|
123 |
self.g.mount(dev, mp)
|
|
124 |
except RuntimeError as msg:
|
|
125 |
print "%s (ignored)" % msg
|
114 |
126 |
|
115 |
127 |
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :
|