Revision 3f70f242 image_creator/disk.py
b/image_creator/disk.py | ||
---|---|---|
100 | 100 |
the Disk instance. |
101 | 101 |
""" |
102 | 102 |
|
103 |
puts("Examining source media `%s'" % self.source) |
|
104 |
with indent(4): |
|
105 |
sourcedev = self.source |
|
106 |
mode = os.stat(self.source).st_mode |
|
107 |
if stat.S_ISDIR(mode): |
|
108 |
puts(colored.green('Looks like a directory')) |
|
109 |
return self._losetup(self._dir_to_disk()) |
|
110 |
elif stat.S_ISREG(mode): |
|
111 |
puts(colored.green('Looks like an image file')) |
|
112 |
sourcedev = self._losetup(self.source) |
|
113 |
elif not stat.S_ISBLK(mode): |
|
114 |
raise ValueError("Invalid media source. Only block devices, " |
|
115 |
"regular files and directories are supported.") |
|
116 |
else: |
|
117 |
puts(colored.green('Looks like a block device')) |
|
118 |
#puts() |
|
103 |
puts("Examining source media `%s'..." % self.source, False) |
|
104 |
sourcedev = self.source |
|
105 |
mode = os.stat(self.source).st_mode |
|
106 |
if stat.S_ISDIR(mode): |
|
107 |
puts(colored.green('looks like a directory')) |
|
108 |
return self._losetup(self._dir_to_disk()) |
|
109 |
elif stat.S_ISREG(mode): |
|
110 |
puts(colored.green('looks like an image file')) |
|
111 |
sourcedev = self._losetup(self.source) |
|
112 |
elif not stat.S_ISBLK(mode): |
|
113 |
raise ValueError("Invalid media source. Only block devices, " |
|
114 |
"regular files and directories are supported.") |
|
115 |
else: |
|
116 |
puts(colored.green('looks like a block device')) |
|
119 | 117 |
|
120 | 118 |
# Take a snapshot and return it to the user |
121 |
puts("Snapshotting media source") |
|
122 |
with indent(4): |
|
123 |
size = blockdev('--getsize', sourcedev) |
|
124 |
cowfd, cow = tempfile.mkstemp() |
|
125 |
os.close(cowfd) |
|
126 |
self._add_cleanup(os.unlink, cow) |
|
127 |
# Create 1G cow sparse file |
|
128 |
dd('if=/dev/null', 'of=%s' % cow, 'bs=1k', \ |
|
129 |
'seek=%d' % (1024 * 1024)) |
|
130 |
cowdev = self._losetup(cow) |
|
131 |
|
|
132 |
snapshot = uuid.uuid4().hex |
|
133 |
tablefd, table = tempfile.mkstemp() |
|
134 |
try: |
|
135 |
os.write(tablefd, "0 %d snapshot %s %s n 8" % \ |
|
136 |
(int(size), sourcedev, cowdev)) |
|
137 |
dmsetup('create', snapshot, table) |
|
138 |
self._add_cleanup(dmsetup, 'remove', snapshot) |
|
139 |
# Sometimes dmsetup remove fails with Device or resource busy, |
|
140 |
# although everything is cleaned up and the snapshot is not |
|
141 |
# used by anyone. Add a 2 seconds delay to be on the safe side. |
|
142 |
self._add_cleanup(time.sleep, 2) |
|
143 |
|
|
144 |
finally: |
|
145 |
os.unlink(table) |
|
146 |
puts(colored.green('Done')) |
|
147 |
# puts() |
|
119 |
puts("Snapshotting media source...", False) |
|
120 |
size = blockdev('--getsize', sourcedev) |
|
121 |
cowfd, cow = tempfile.mkstemp() |
|
122 |
os.close(cowfd) |
|
123 |
self._add_cleanup(os.unlink, cow) |
|
124 |
# Create 1G cow sparse file |
|
125 |
dd('if=/dev/null', 'of=%s' % cow, 'bs=1k', \ |
|
126 |
'seek=%d' % (1024 * 1024)) |
|
127 |
cowdev = self._losetup(cow) |
|
128 |
|
|
129 |
snapshot = uuid.uuid4().hex |
|
130 |
tablefd, table = tempfile.mkstemp() |
|
131 |
try: |
|
132 |
os.write(tablefd, "0 %d snapshot %s %s n 8" % \ |
|
133 |
(int(size), sourcedev, cowdev)) |
|
134 |
dmsetup('create', snapshot, table) |
|
135 |
self._add_cleanup(dmsetup, 'remove', snapshot) |
|
136 |
# Sometimes dmsetup remove fails with Device or resource busy, |
|
137 |
# although everything is cleaned up and the snapshot is not |
|
138 |
# used by anyone. Add a 2 seconds delay to be on the safe side. |
|
139 |
self._add_cleanup(time.sleep, 2) |
|
140 |
|
|
141 |
finally: |
|
142 |
os.unlink(table) |
|
143 |
puts(colored.green('done')) |
|
148 | 144 |
new_device = DiskDevice("/dev/mapper/%s" % snapshot) |
149 | 145 |
self._devices.append(new_device) |
150 | 146 |
new_device.enable() |
... | ... | |
181 | 177 |
def enable(self): |
182 | 178 |
"""Enable a newly created DiskDevice""" |
183 | 179 |
self.progressbar = progress_generator("Launching helper VM: ") |
184 |
with indent(4): |
|
185 |
self.progressbar.next() |
|
186 |
eh = self.g.set_event_callback(self.progress_callback, |
|
187 |
guestfs.EVENT_PROGRESS) |
|
188 |
self.g.launch() |
|
189 |
self.guestfs_enabled = True |
|
190 |
self.g.delete_event_callback(eh) |
|
191 |
if self.progressbar is not None: |
|
192 |
self.progressbar.send(100) |
|
193 |
self.progressbar = None |
|
194 |
puts(colored.green('Done')) |
|
195 |
|
|
196 |
puts('Inspecting Operating System') |
|
197 |
with indent(4): |
|
198 |
roots = self.g.inspect_os() |
|
199 |
if len(roots) == 0: |
|
200 |
raise FatalError("No operating system found") |
|
201 |
if len(roots) > 1: |
|
202 |
raise FatalError("Multiple operating systems found." |
|
203 |
"We only support images with one filesystem.") |
|
204 |
self.root = roots[0] |
|
205 |
self.ostype = self.g.inspect_get_type(self.root) |
|
206 |
self.distro = self.g.inspect_get_distro(self.root) |
|
207 |
puts(colored.green('Found a %s system' % self.distro)) |
|
208 |
puts() |
|
180 |
self.progressbar.next() |
|
181 |
eh = self.g.set_event_callback(self.progress_callback, |
|
182 |
guestfs.EVENT_PROGRESS) |
|
183 |
self.g.launch() |
|
184 |
self.guestfs_enabled = True |
|
185 |
self.g.delete_event_callback(eh) |
|
186 |
if self.progressbar is not None: |
|
187 |
self.progressbar.send(100) |
|
188 |
self.progressbar = None |
|
189 |
|
|
190 |
puts('Inspecting Operating System...', False) |
|
191 |
roots = self.g.inspect_os() |
|
192 |
if len(roots) == 0: |
|
193 |
raise FatalError("No operating system found") |
|
194 |
if len(roots) > 1: |
|
195 |
raise FatalError("Multiple operating systems found." |
|
196 |
"We only support images with one filesystem.") |
|
197 |
self.root = roots[0] |
|
198 |
self.ostype = self.g.inspect_get_type(self.root) |
|
199 |
self.distro = self.g.inspect_get_distro(self.root) |
|
200 |
puts(colored.green('found a %s system' % self.distro)) |
|
209 | 201 |
|
210 | 202 |
def destroy(self): |
211 | 203 |
"""Destroy this DiskDevice instance.""" |
... | ... | |
257 | 249 |
disk and then updating the partition table. The new disk size |
258 | 250 |
(in bytes) is returned. |
259 | 251 |
""" |
260 |
puts("Shrinking image (this may take a while)")
|
|
261 |
|
|
252 |
puts("Shrinking image (this may take a while)...", False)
|
|
253 |
|
|
262 | 254 |
dev = self.g.part_to_dev(self.root) |
263 | 255 |
parttype = self.g.part_get_parttype(dev) |
264 | 256 |
if parttype != 'msdos': |
... | ... | |
277 | 269 |
warn("Don't know how to resize %s partitions." % vfs_type) |
278 | 270 |
return |
279 | 271 |
|
280 |
with indent(4): |
|
281 |
self.g.e2fsck_f(part_dev) |
|
282 |
self.g.resize2fs_M(part_dev) |
|
272 |
self.g.e2fsck_f(part_dev) |
|
273 |
self.g.resize2fs_M(part_dev) |
|
274 |
|
|
275 |
output = self.g.tune2fs_l(part_dev) |
|
276 |
block_size = int( |
|
277 |
filter(lambda x: x[0] == 'Block size', output)[0][1]) |
|
278 |
block_cnt = int( |
|
279 |
filter(lambda x: x[0] == 'Block count', output)[0][1]) |
|
283 | 280 |
|
284 |
output = self.g.tune2fs_l(part_dev) |
|
285 |
block_size = int( |
|
286 |
filter(lambda x: x[0] == 'Block size', output)[0][1]) |
|
287 |
block_cnt = int( |
|
288 |
filter(lambda x: x[0] == 'Block count', output)[0][1]) |
|
281 |
sector_size = self.g.blockdev_getss(dev) |
|
289 | 282 |
|
290 |
sector_size = self.g.blockdev_getss(dev) |
|
283 |
start = last_partition['part_start'] / sector_size |
|
284 |
end = start + (block_size * block_cnt) / sector_size - 1 |
|
291 | 285 |
|
292 |
start = last_partition['part_start'] / sector_size
|
|
293 |
end = start + (block_size * block_cnt) / sector_size - 1
|
|
286 |
self.g.part_del(dev, last_partition['part_num'])
|
|
287 |
self.g.part_add(dev, 'p', start, end)
|
|
294 | 288 |
|
295 |
self.g.part_del(dev, last_partition['part_num'])
|
|
296 |
self.g.part_add(dev, 'p', start, end)
|
|
289 |
new_size = (end + 1) * sector_size
|
|
290 |
puts(colored.green("new image size is %dMB\n" % (new_size // 2 ** 20)))
|
|
297 | 291 |
|
298 |
new_size = (end + 1) * sector_size |
|
299 |
puts(" New image size is %dMB\n" % (new_size // 2 ** 20)) |
|
300 | 292 |
return new_size |
301 | 293 |
|
302 | 294 |
def size(self): |
Also available in: Unified diff