31 |
31 |
# interpreted as representing official policies, either expressed
|
32 |
32 |
# or implied, of GRNET S.A.
|
33 |
33 |
|
34 |
|
from image_creator.util import get_command, warn, progress_generator
|
|
34 |
from image_creator.util import get_command, warn, progress_generator, success
|
35 |
35 |
from image_creator import FatalError
|
36 |
|
from clint.textui import indent, puts, colored
|
|
36 |
from clint.textui import puts
|
37 |
37 |
|
38 |
38 |
import stat
|
39 |
39 |
import os
|
... | ... | |
43 |
43 |
import sys
|
44 |
44 |
import guestfs
|
45 |
45 |
import time
|
|
46 |
from sendfile import sendfile
|
46 |
47 |
|
47 |
48 |
|
48 |
49 |
class DiskError(Exception):
|
... | ... | |
104 |
105 |
sourcedev = self.source
|
105 |
106 |
mode = os.stat(self.source).st_mode
|
106 |
107 |
if stat.S_ISDIR(mode):
|
107 |
|
puts(colored.green('looks like a directory'))
|
|
108 |
success('looks like a directory')
|
108 |
109 |
return self._losetup(self._dir_to_disk())
|
109 |
110 |
elif stat.S_ISREG(mode):
|
110 |
|
puts(colored.green('looks like an image file'))
|
|
111 |
success('looks like an image file')
|
111 |
112 |
sourcedev = self._losetup(self.source)
|
112 |
113 |
elif not stat.S_ISBLK(mode):
|
113 |
114 |
raise ValueError("Invalid media source. Only block devices, "
|
114 |
115 |
"regular files and directories are supported.")
|
115 |
116 |
else:
|
116 |
|
puts(colored.green('looks like a block device'))
|
|
117 |
success('looks like a block device')
|
117 |
118 |
|
118 |
119 |
# Take a snapshot and return it to the user
|
119 |
120 |
puts("Snapshotting media source...", False)
|
... | ... | |
140 |
141 |
|
141 |
142 |
finally:
|
142 |
143 |
os.unlink(table)
|
143 |
|
puts(colored.green('done'))
|
|
144 |
success('done')
|
144 |
145 |
new_device = DiskDevice("/dev/mapper/%s" % snapshot)
|
145 |
146 |
self._devices.append(new_device)
|
146 |
147 |
new_device.enable()
|
... | ... | |
197 |
198 |
self.root = roots[0]
|
198 |
199 |
self.ostype = self.g.inspect_get_type(self.root)
|
199 |
200 |
self.distro = self.g.inspect_get_distro(self.root)
|
200 |
|
puts(colored.green('found a %s system' % self.distro))
|
|
201 |
success('found a %s system' % self.distro)
|
201 |
202 |
|
202 |
203 |
def destroy(self):
|
203 |
204 |
"""Destroy this DiskDevice instance."""
|
... | ... | |
250 |
251 |
(in bytes) is returned.
|
251 |
252 |
"""
|
252 |
253 |
puts("Shrinking image (this may take a while)...", False)
|
|
254 |
sys.stdout.flush()
|
253 |
255 |
|
254 |
256 |
dev = self.g.part_to_dev(self.root)
|
255 |
257 |
parttype = self.g.part_get_parttype(dev)
|
... | ... | |
287 |
289 |
self.g.part_add(dev, 'p', start, end)
|
288 |
290 |
|
289 |
291 |
new_size = (end + 1) * sector_size
|
290 |
|
puts(colored.green("new image size is %dMB\n" % (new_size // 2 ** 20)))
|
291 |
|
|
|
292 |
success("new image size is %dMB" %
|
|
293 |
((new_size + 2 ** 20 - 1) // 2 ** 20))
|
292 |
294 |
return new_size
|
293 |
295 |
|
294 |
296 |
def size(self):
|
... | ... | |
302 |
304 |
|
303 |
305 |
return last['part_end'] + 1
|
304 |
306 |
|
|
307 |
def dump(self, outfile):
|
|
308 |
"""Dumps the content of device into a file.
|
|
309 |
|
|
310 |
This method will only dump the actual payload, found by reading the
|
|
311 |
partition table. Empty space in the end of the device will be ignored.
|
|
312 |
"""
|
|
313 |
blocksize = 2 ** 22 # 4MB
|
|
314 |
size = self.size()
|
|
315 |
progress_size = (size + 2 ** 20 - 1) // 2 ** 20 # in MB
|
|
316 |
progressbar = progress_generator("Dumping image file: ", progress_size)
|
|
317 |
|
|
318 |
source = open(self.device, "r")
|
|
319 |
try:
|
|
320 |
dest = open(outfile, "w")
|
|
321 |
try:
|
|
322 |
left = size
|
|
323 |
offset = 0
|
|
324 |
progressbar.next()
|
|
325 |
while left > 0:
|
|
326 |
length = min(left, blocksize)
|
|
327 |
sent = sendfile(dest.fileno(), source.fileno(), offset,
|
|
328 |
length)
|
|
329 |
offset += sent
|
|
330 |
left -= sent
|
|
331 |
for i in range((length + 2 ** 20 - 1) // 2 ** 20):
|
|
332 |
progressbar.next()
|
|
333 |
finally:
|
|
334 |
dest.close()
|
|
335 |
finally:
|
|
336 |
source.close()
|
|
337 |
|
|
338 |
success('Image file %s was successfully created' % outfile)
|
|
339 |
|
305 |
340 |
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :
|