def restore_image(self): """ """ information = Information(self.image_path) information.load() image_name = information.get_image_name() compressor_level = information.get_image_compressor_level() total_bytes = information.get_image_total_bytes() total_blocks = long(math.ceil(total_bytes / float(BLOCK_SIZE))) compressor = Compressor(compressor_level) device = Device(self.target_device) if device.is_disk() != \ information.get_image_is_disk(): raise ErrorRestoringImage("Invalid target dispositive") try: disk = Disk(device) except _ped.DiskLabelException: try: device.fix_disk_label() disk = Disk(device) except: raise ErrorRestoringImage("Unrecognized disk label") if information.get_image_is_disk(): mbr = Mbr(self.image_path) mbr.restore_from_file(self.target_device) dlm = DiskLayoutManager(self.image_path) dlm.restore_from_file(disk) self._print_informations(total_bytes, image_name) progress = Progress(total_blocks) progress.start() partitions = information.get_partitions() for p in partitions: if information.get_image_is_disk(): partition = disk.get_partition_by_number(p.number, p.type) else: parent_path = get_parent_path(self.target_device) parent_device = Device(parent_path) parent_disk = Disk(parent_device) partition = parent_disk.get_partition_by_path( self.target_device, p.type) if partition is None: raise ErrorRestoringImage("No valid partitions found") if p.uuid is not None: partition.filesystem.open_to_write(p.uuid) else: partition.filesystem.open_to_write() if partition.filesystem.is_swap(): continue file_name = FILE_PATTERN % (image_name, p.number) with open(self.image_path + file_name, 'rb') as f: # TODO: Work with parallelism while True: # Ugly header = f.read(compressor.get_header_size()) if not len(header): break size = compressor.read_block_header(header) cdata = f.read(size) data = compressor.extract(cdata) partition.filesystem.write(data) progress.increment(1) partition.filesystem.close() progress.stop() print "completed."
def create_image(self): """ """ if is_mounted(self.device_path): raise DeviceIsMounted("Please umount first") self.active = True device = Device(self.device_path) disk = Disk(device) if device.is_disk(): mbr = Mbr(self.target_path) mbr.save_to_file(self.device_path) dlm = DiskLayoutManager(self.target_path) dlm.save_to_file(disk) partition_list = disk.get_valid_partitions(self.raw) if not partition_list: raise ErrorCreatingImage("Partition(s) hasn't a " +\ "valid filesystem") # check partitions filesystem if not self.raw: for part in partition_list: log.info("Checking filesystem of {0}".format(part.get_path())) self.notify_status("checking_filesystem", {"device": part.get_path()}) if not part.filesystem.check(): log.error("{0} Filesystem is not clean".\ format(part.get_path())) raise ErrorCreatingImage("{0} Filesystem is not clean".\ format(part.get_path())) # fill partitions with zeroes if self.raw and self.fill_with_zeros: for part in partition_list: log.info("{0} Filling with zeros".format(part.get_path())) self.notify_status("filling_with_zeros", {"device": part.get_path()}) part.filesystem.fill_with_zeros() # get total size total_bytes = 0 for part in partition_list: total_bytes += part.filesystem.get_used_size() self.total_blocks = long(math.ceil(total_bytes/float(BLOCK_SIZE))) information = Information(self.target_path) information.set_image_is_disk(device.is_disk()) information.set_image_name(self.image_name) information.set_image_compressor_level(self.compressor_level) # TODO: Abstract this whole part, when creating isos, # splitting in files, etc... self.timer.start() remaining_size = self.split_size if self.create_iso: remaining_size -= BASE_SYSTEM_SIZE slices = dict() # Used when creating iso iso_volume = 1 # Used when creating iso for part in partition_list: if not self.active: break log.info("Creating image of {0}".format(part.get_path())) number = part.get_number() uuid = part.filesystem.uuid() label = part.filesystem.read_label() type = part.filesystem.type part.filesystem.open_to_read() compact_callback = None if self.compressor_level: compressor = Compressor(self.compressor_level) compact_callback = compressor.compact self.buffer_manager = BufferManagerFactory( part.filesystem.read_block, compact_callback) self.buffer_manager.start() buffer = self.buffer_manager.output_buffer volumes = 1 while self.active: total_written = 0 # Used to help splitting the file pattern = FILE_PATTERN.format(name=self.image_name, partition=number, volume=volumes) file_path = self.target_path + pattern fd = open(file_path, "wb") next_partition = False while self.active: try: data = buffer.get() except IOError, e: if e.errno == errno.EINTR: self.cancel() break if data == EOF: next_partition = True if self.create_iso: remaining_size -= total_written if not slices.has_key(iso_volume): slices[iso_volume] = list() slices[iso_volume].append(file_path) break fd.write(data) self.processed_blocks += 1 if self.split_size: bytes_written = len(data) total_written += bytes_written if (total_written + bytes_written) >= remaining_size: volumes += 1 remaining_size = self.split_size if self.create_iso: if not slices.has_key(iso_volume): slices[iso_volume] = list() slices[iso_volume].append(file_path) iso_volume += 1 break fd.close() if next_partition: break self.buffer_manager.join() part.filesystem.close() information.add_partition(number, type, volumes, part.filesystem.get_used_size(), uuid, label)
def restore_image(self): """ """ if is_mounted(self.target_device): raise DeviceIsMounted("Please umount first") self.active = True information = Information(self.image_path) information.load() if self.partitions: information.set_partitions(self.partitions) image_name = information.get_image_name() compressor_level = information.get_image_compressor_level() partitions = information.get_partitions() # Get total size total_bytes = 0 for part in partitions: total_bytes += part.size self.total_blocks = long(math.ceil(total_bytes / float(BLOCK_SIZE))) device = Device(self.target_device) if device.is_disk() != \ information.get_image_is_disk(): log.error("Invalid target device %s" % device.path) raise ErrorRestoringImage("Invalid target device") try: disk = Disk(device) except _ped.DiskLabelException: try: device.fix_disk_label() disk = Disk(device) except: log.error("Unrecognized disk label") raise ErrorRestoringImage("Unrecognized disk label") if information.get_image_is_disk(): log.info("Restoring MBR and Disk Layout") mbr = Mbr(self.image_path) mbr.restore_from_file(self.target_device) dlm = DiskLayoutManager(self.image_path) dlm.restore_from_file(disk, self.expand) self.timer.start() for part in partitions: if not self.active: break if information.get_image_is_disk(): partition = disk.get_partition_by_number( part.number, part.type) else: parent_path = get_parent_path(self.target_device) parent_device = Device(parent_path) parent_disk = Disk(parent_device) partition = parent_disk.get_partition_by_path( self.target_device, part.type) log.info("Restoring partition {0}".format(partition.get_path())) if partition is None: raise ErrorRestoringImage("No valid partitions found") if hasattr(part, "uuid"): partition.filesystem.open_to_write(part.uuid) else: partition.filesystem.open_to_write() if hasattr(part, "label"): partition.filesystem.write_label(part.label) if partition.filesystem.is_swap(): continue pattern = FILE_PATTERN.format(name=image_name, partition=part.number, volume="{volume}") volumes = 1 if hasattr(part, "volumes"): volumes = part.volumes image_reader = ImageReaderFactory(self.image_path, pattern, volumes, compressor_level, self.notify_status) extract_callback = None if compressor_level: compressor = Compressor(compressor_level) extract_callback = compressor.extract self.buffer_manager = BufferManagerFactory(image_reader.read_block, extract_callback) # open the file after instantiating BufferManager, cause of a # problem on multiprocessing module, FD_CLOEXE doesn't work # (I don't want to dup the file descriptor). image_reader.open() self.buffer_manager.start() buffer = self.buffer_manager.output_buffer while self.active: try: data = buffer.get() except IOError, e: if e.errno == errno.EINTR: self.cancel() break if data == EOF: break try: partition.filesystem.write_block(data) except ErrorWritingToDevice, e: if not self.canceled: self.stop() raise e self.processed_blocks += 1
def __init__(self, image_path, pattern, volumes, compressor_level, notify_status): GenericReader.__init__(self, image_path, pattern, volumes, notify_status) self.compressor = Compressor(compressor_level)