Commit fcc4df5d authored by Nikos Skalkotos's avatar Nikos Skalkotos
Browse files

Add device attribute in Disk class

This attribute hosts the block device associated with this Disk
instance. This can be the original media if the source media is a block
device, a loop device of the original media if the original media is a
regular file or a loop device of a temporary object if the original
media is a directory.
parent b349c125
......@@ -61,8 +61,11 @@ def create_image(d, media, out, tmp):
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
try:
snapshot = disk.snapshot()
image = disk.get_image(snapshot)
# There is no need to snapshot the media if it was created by the Disk
# instance as a temporary object.
device = disk.device if disk.source == '/' else disk.snapshot()
image = disk.get_image(device)
out.output("Collecting image metadata ...")
metadata = {}
......
......@@ -72,6 +72,7 @@ class Disk(object):
"""
self._cleanup_jobs = []
self._images = []
self._device = None
self.source = source
self.out = output
self.meta = {}
......@@ -123,29 +124,36 @@ class Disk(object):
job, args = self._cleanup_jobs.pop()
job(*args)
def snapshot(self):
"""Creates a snapshot of the original source media of the Disk
instance.
"""
@property
def device(self):
"""Convert the source media into a block device"""
if self._device is not None:
return self._device
self.out.output("Examining source media `%s' ..." % self.source, False)
sourcedev = self.source
mode = os.stat(self.source).st_mode
if stat.S_ISDIR(mode):
self.out.success('looks like a directory')
return self._dir_to_disk()
self._device = self._dir_to_disk()
elif stat.S_ISREG(mode):
self.out.success('looks like an image file')
sourcedev = self._losetup(self.source)
self._device = self._losetup(self.source)
elif not stat.S_ISBLK(mode):
raise FatalError("Invalid media source. Only block devices, "
"regular files and directories are supported.")
else:
self.out.success('looks like a block device')
self._device = self.source
# Take a snapshot and return it to the user
return self._device
def snapshot(self):
"""Creates a snapshot of the original source media of the Disk
instance.
"""
self.out.output("Snapshotting media source ...", False)
size = blockdev('--getsz', sourcedev)
size = blockdev('--getsz', self.device)
cowfd, cow = tempfile.mkstemp(dir=self.tmp)
os.close(cowfd)
self._add_cleanup(os.unlink, cow)
......@@ -158,7 +166,7 @@ class Disk(object):
try:
try:
os.write(tablefd, "0 %d snapshot %s %s n 8" %
(int(size), sourcedev, cowdev))
(int(size), self.device, cowdev))
finally:
os.close(tablefd)
......
......@@ -257,9 +257,10 @@ def image_creator():
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
try:
snapshot = disk.snapshot()
image = disk.get_image(snapshot, sysprep_params=options.sysprep_params)
# There is no need to snapshot the media if it was created by the Disk
# instance as a temporary object.
device = disk.device if disk.source == '/' else disk.snapshot()
image = disk.get_image(device, sysprep_params=options.sysprep_params)
if image.is_unsupported() and not options.allow_unsupported:
raise FatalError(
......@@ -323,7 +324,7 @@ def image_creator():
os.path.basename(options.outfile)))
out.success('done')
# Destroy the image instance. We only need the snapshot from now on
# Destroy the image instance. We only need the disk device from now on
disk.destroy_image(image)
out.output()
......@@ -331,7 +332,7 @@ def image_creator():
uploaded_obj = ""
if options.upload:
out.output("Uploading image to the storage service:")
with open(snapshot, 'rb') as f:
with open(device, 'rb') as f:
uploaded_obj = kamaki.upload(
f, size, options.upload,
"(1/3) Calculating block hashes",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment