Ejemplo n.º 1
0
    def __init__(self, image_folder, target_device,
                 status_callback, partitions=None,
                 expand=2):
        # expand -> 0 Expande a ultima particao
        #        -> 1 Formata a ultima particao
        #        -> 2 Nenhuma operacao (ele aplica a imagem e nao faz mais nada)
        #        -> 3 Ele nao aplica a ultima particao

        assert check_if_root(), "You need to run this application as root"

        self.image_path = adjust_path(image_folder)
        self.target_device = target_device
        self.notify_status = status_callback
        self.partitions = partitions
        self.expand = expand

        self.timer = Timer(self.notify_percent)
        self.total_blocks = 0
        self.processed_blocks = 0
        self.current_percent = -1
        self.active = False
        self.canceled = False

        if not os.path.isdir(self.image_path):
            log.info("The folder is invalid")
            self.notify_status("invalid_folder", \
                               {"invalid_folder":self.image_path})
            raise InvalidFolder("Invalid folder {0}".format(output_folder))
Ejemplo n.º 2
0
 def stop(self):
     if self.active:
         if hasattr(self, "buffer_manager"):
             self.buffer_manager.stop()
     self.active = False
     self.timer.stop() 
     log.info("Create image stopped")
Ejemplo n.º 3
0
def mount_partition(device, folder = None):
    ''' 
    Monta a particao recebida.(Ex.: /dev/sda1)
    Caso 'folder'  nao tenha um destino valido,
     a particao eh montada em uma pasta temporaria
    '''
    mount_device = None    
    if folder is None:
        tmpd = make_temp_dir()
    else:
        tmpd = folder

    if device is None:
        log.error("No device given")
        return False
        
    output,erro,ret =  run_simple_command_echo("mount {0} {1} {2}".format(MOUNT_OPTIONS, 
        device, tmpd),True)
        
    if "already" in erro:
        log.error("{0} is arealdy exclusively mounted.".format(mount_device))
        log.info("Trying to umount device above, and re-run")
        umount_real(mount_device)
        output,erro,ret =  run_simple_command_echo("mount {0} {1} {2}".format(MOUNT_OPTIONS, 
            mount_device, tmpd),True)
            
    if ret is not 0:
        log.error("{0}".format(erro))
        
        #raise ErrorMountingFilesystem
    if folder is not None:
        mounted_devices.insert(0, folder)
    else:
        mounted_devices.append(tmpd)
        return tmpd    
Ejemplo n.º 4
0
 def stop(self):
     # When restoring only a swap partition, buffer_manager
     # isnt necessary
     if self.active and hasattr(self, "buffer_manager"):
         self.buffer_manager.stop()
     self.active = False
     self.timer.stop()
     log.info("Restore image stopped")
Ejemplo n.º 5
0
 def stop(self):
     # When restoring only a swap partition, buffer_manager
     # isnt necessary
     if self.active and hasattr(self, "buffer_manager"):
         self.buffer_manager.stop()
     self.active = False
     self.timer.stop()
     log.info("Restore image stopped")
Ejemplo n.º 6
0
def chroot(root):
    real_root = os.open("/", os.O_RDONLY)
    mount_device("dev",root)
    mount_device("sys",root)
    mount_device("proc",root)
    os.chdir(root)
    log.info("chroot {0}".format(root))
    os.chroot(root)
    return "/",real_root
Ejemplo n.º 7
0
 def expand_last_partition(self):
     # After all data is copied to the disk
     # we instance class again to reload
     sync()
     device = Device(self.target_device)
     disk = Disk(device)
     partition = disk.get_last_partition()
     if partition is not None:
         if partition.type == PARTITION_NORMAL:
             log.info("Expanding {0} filesystem".\
                      format(partition.get_path()))
             self.notify_status("expand", {"device": partition.get_path()})
             partition.filesystem.resize()
Ejemplo n.º 8
0
 def expand_last_partition(self):
     # After all data is copied to the disk
     # we instance class again to reload
     sync()
     device = Device(self.target_device)
     disk = Disk(device)
     partition = disk.get_last_partition()
     if partition is not None:
         if partition.type == PARTITION_NORMAL:
             log.info("Expanding {0} filesystem".\
                      format(partition.get_path()))
             self.notify_status("expand", {"device":
                                partition.get_path()})
             partition.filesystem.resize()
Ejemplo n.º 9
0
def run_simple_command_echo(cmd, echo=False):
    ''' 
    run a given command
    returns the output, errors (if any) and returncode
    '''    
    if echo:
        log.info("{0}".format(cmd))
    p = subprocess.Popen(cmd, shell=True,
                         stdout=subprocess.PIPE,
                         stdin=subprocess.PIPE,
                         stderr=subprocess.PIPE)
    p.wait()
    output, err = p.communicate()
    ret = p.returncode
    return output,err,ret
Ejemplo n.º 10
0
    def __init__(self, source_device, output_folder,
                 status_callback, image_name="image", compressor_level=6,
                 raw=False, split_size=0, create_iso=False,
                 fill_with_zeros=False):

        self.image_name = image_name
        self.device_path = source_device
        self.target_path = adjust_path(output_folder)
        self.notify_status = status_callback
        self.compressor_level = compressor_level
        self.raw = raw
        self.split_size = split_size
        self.create_iso = create_iso
        self.fill_with_zeros = fill_with_zeros

        self.timer = Timer(self.notify_percent)
        self.total_blocks = 0
        self.processed_blocks = 0
        self.current_percent = -1
        self.active = False
        self.canceled = False
        self.partclone_stderr = None
        self.partclone_sucess = False
        self.data_is_eof = False

        if not check_if_root():
            log.info("You need to run this application as root")
            self.notify_status("not_root", \
                              {"not_root":"You dont't have permission"})

        if not os.path.isdir(output_folder):
            try:
                os.mkdir(output_folder)
            except Exception as e:
                log.info("The folder is invalid. {0}".format(e))
                self.notify_status("invalid_folder",\
                                {"invalid_folder":output_folder})
                raise InvalidFolder("Invalid folder {0}".format(output_folder))
Ejemplo n.º 11
0
    def notify_percent(self):
        #refresh the interface percentage
        percent = (self.processed_blocks/float(self.total_blocks)) * 100
        if percent > self.current_percent:
            self.current_percent = percent
            self.notify_status("progress", {"percent": percent})

        #verify stderr from partclone
        if self.partclone_stderr != None:
            partclone_status = self.partclone_stderr.readline()
            if partclone_status.startswith("Partclone successfully cloned the device"):
                self.partclone_sucess = True
            else:
                if self.data_is_eof:
                    part_list = partclone_status.split()
                    if part_list[0] == "current":
                        if len(part_list) >= 13:
                            try:
                                status = partclone_status.split()[13].split(",")[0]
                                status2 = status.split("%")[0]
                                self.notify_status("waiting_partclone",{"partclone_percent":float(status2)})
                            except Exception as e:
                                log.info(e)
                                raise ErrorCreatingImage("Create image wasn't made with success")
Ejemplo n.º 12
0
            self.notify_status("no_valid_partitions", \
                 {"no_valid_partitions":partitions})
            raise ErrorRestoringImage("No valid partitions found")

        self.timer.stop()

        if self.expand != 2:
            if information.get_image_is_disk():
                self.expand_last_partition(self.expand)

        if self.canceled:
            self.notify_status("canceled", {"operation":
                                            "Restore image"})
        else:
            self._finish()
            log.info("Restoration finished")
            log.info("Iniciando gtk grubinstall")
            cmd = "{0}".format(which("grubinstall"))
            try:
                os.system("{0} &".format(cmd))
            except:
                log.error("Erro ao iniciar grubinstall. {0}".format(e))

    def expand_last_partition(self,opt_expand):
        # After all data is copied to the disk
        # we instance class again to reload

        sync()
        device = Device(self.target_device)
        disk = Disk(device)
        partition = disk.get_last_partition()
Ejemplo n.º 13
0
    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
Ejemplo n.º 14
0
    def create_image(self):
        """ """
        if is_mounted(self.device_path):
            log.error("The partition {0} is mounted, please umount first, and try again".format(self.device_path))
            self.notify_status("mounted_partition_error",{"mounted_partition_error":self.device_path})
            raise DeviceIsMounted("Please umount first")

        self.active = True
        device = Device(self.device_path)
        disk = Disk(device)

        if device.is_disk():
            try:
                mbr = Mbr(self.target_path)
                mbr.save_to_file(self.device_path)
                dlm = DiskLayoutManager(self.target_path)
                dlm.save_to_file(disk)
            except Exception as e:
                log.info(e)
                self.notify_status("write_error", \
                                   {"write_error":self.target_path})
                raise ErrorWritingToDevice("Write error in {0}".format(self.target_path))

        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)
        if device.is_disk():
            disk_info = DiskInfo()
            disk_dict = disk_info.formated_disk(self.device_path)
            information.set_disk_size(disk_dict["size"])
        # 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()))
            self.notify_status("image_creator", \
                               {"image_creator ": 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()

            #check if partclone is running
            if type in  ("ext2","ext3","ext4"):
                self.partclone_stderr = part.filesystem.get_error_ext()

            compact_callback = None
            if self.compressor_level:
                compressor = Compressor(self.compressor_level)
                compact_callback = compressor.compact

            self.buffer_manager = BufferManagerFactory(
                                  part.filesystem.read_block,
                                  self.notify_status,
                                  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
                try:
                    fd = open(file_path, "wb")
                except Exception as e:
                    log.info(e)
                    self.notify_status("open_file", \
                                       {"open_file":file_path})
                    raise ImageNotFound("The file wasn't found {0}". \
                                        format(file_path))
                next_partition = False
                while self.active:
                    try:
                        data = buffer.get()
                    except IOError, e:
                        #self.notify_status("read_buffer_error", \
                        #           {"read_buffer_error":str(e)})
                        if e.errno == errno.EINTR:
                            self.notify_status("read_buffer_error", \
                                       {"read_buffer_error":str(e)})
                            data = ""
                            self.cancel()
                            raise ErrorReadingFromDevice(e)
                            break


                    if data == EOF:
                        if (self.partclone_stderr != None):
                            self.data_is_eof = True
                            while self.partclone_sucess == False:
                                pass

                        self.partclone_stderr = None
                        self.partclone_sucess = False
                        self.data_is_eof = False

                        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
                    try:
                        fd.write(data)
                    except Exception as e:
                        log.info("{0}".format(e))
                        self.notify_status("disk_full")
                        self.cancel()
                        raise ErrorWritingToDevice("Error in write file {0}".\
                                                   format(file_path))

                    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
                try:
                    fd.close()
                except Exception as e:
                    log.info(e)
                    self.notify_status("write_error",{"write_error":e})
                    raise ErrorCloseToWrite("Close Error {0}".format(e))

                if next_partition: break

            self.buffer_manager.join()
            part.filesystem.close()
            information.add_partition(number, type, volumes,
                                      part.filesystem.get_used_size(),
                                      uuid, label)
Ejemplo n.º 15
0
                self.processed_blocks += 1

            self.buffer_manager.join()
            partition.filesystem.close()

        self.timer.stop()

        if self.expand:
            if information.get_image_is_disk():
                self.expand_last_partition()

        if self.canceled:
            self.notify_status("canceled", {"operation": "Restore image"})
        else:
            self._finish()
        log.info("Restoration finished")

    def expand_last_partition(self):
        # After all data is copied to the disk
        # we instance class again to reload
        sync()
        device = Device(self.target_device)
        disk = Disk(device)
        partition = disk.get_last_partition()
        if partition is not None:
            if partition.type == PARTITION_NORMAL:
                log.info("Expanding {0} filesystem".\
                         format(partition.get_path()))
                self.notify_status("expand", {"device": partition.get_path()})
                partition.filesystem.resize()
Ejemplo n.º 16
0
    def build_grub_legacy_menu(self,boot_folder, dev_boot_tuples=None):
    
        '''
        search for linux kernels in all devices. search windows boot files.
        built the menu.lst in the target device, also copy grub-legacy files there.
        '''
        cont = 0
        menu_linux = []
        menu_windows = []
        FILE = "{0}/grub/menu.lst".format(boot_folder)        
        try:
            f = open(FILE,"w")
        except:
            os.makedirs("{0}/grub/".format(boot_folder))
            ret,err,out = run_simple_command_echo("touch {0}/grub/menu.lst".format(boot_folder))
            f = open(FILE,"w")
        menu_linux.append("#AUTOMAGIC GENERATED\n")
        menu_linux.append("default saved\n")
        menu_linux.append("timeout 10\n")
        menu_linux.append("password --md5 $1$7QG0J0$l2j8MS763EKQ3u.sDdh8Z0\n")     
            
        dev = os.listdir("/dev")

        for i in dev:
            if ("sd" in i) and (len(i)==3):        
                devices_linux,devices_windows = list_devices(i)
                if devices_linux is not None:
                    for lin in devices_linux:
                        directory = mount_partition(lin)
                        boot_directory = directory+"/boot"
                        try:
                            filenames = os.listdir("{0}".format(boot_directory))
                        except:
                            filenames=None
                        try: 
                            filenames2 = os.listdir("{0}".format(directory))
                        except:
                            filenames2 = None
                        var_temp = None
                        vmlinuz = None
                        if filenames is not None:
                            filenames.sort()
                            boot_me = "/boot"                
                            for aux in filenames:
                                if "init" in aux:
                                    initrd = aux
                                    if len(aux) < 12:
                                        var_temp=""
                                    else:
                                        var_temp = aux[11:] # take just the kernel version
                                elif ((var_temp is not None) and ("vmlinuz" in aux) and (var_temp in aux)) or ("vmlinuz"==aux):
                                    vmlinuz = aux
                                    cont+=1
                        if (filenames2 is not None) and (vmlinuz is None):
                            filenames2.sort()
                            boot_me = ""                
                            for aux in filenames2:
                                if "init" in aux:
                                    initrd = aux
                                    if len(aux) < 12:
                                        var_temp=""
                                    else:
                                        var_temp = aux[11:] # take just the kernel version
                                elif ((var_temp is not None) and ("vmlinuz" in aux) and (var_temp in aux)) or ("vmlinuz"==aux):
                                    vmlinuz = aux#+"MAOEEE"
                                    cont+=1

                        if (vmlinuz is not None):
                            line = distro_name(directory)
                            if  line is None:
                                line = cont
                            menu_linux.append("\ntitle Linux {0} in {1}\n".format(line,lin))
                            menu_linux.append("root (hd0,{0})\n".format(int(lin[8:])-1))
                            temp = False
                            
                            if (dev_boot_tuples is not None):
                                for i in dev_boot_tuples:
                                    if lin in i[0]:
                                        temp = True
                                        menu_linux.append("kernel {0}/{1} root={2} ro quiet splash\
                                            \n".format(boot_me,vmlinuz,i[1]))
                                        dev_boot_tuples.pop(dev_boot_tuples.index(i))
                                if not dev_boot_tuples:
                                    dev_boot_tuples = None
                            if not temp:
                                #if temp_dev is None:
                                menu_linux.append("kernel {0}/{1} root={2} ro quiet splash\
                                      \n".format(boot_me,vmlinuz,lin))
                                #else:
                                #   menu_linux.append("kernel {0}/{1} root = {2} ro quiet splash\
                                #      \n".format(boot_me,vmlinuz,temp_dev))
                                #    temp_dev = None
                            menu_linux.append("initrd {0}/{1}\n".format(boot_me,initrd))
                            menu_linux.append("quiet\n")
                            menu_linux.append("savedefault\n")
                        else:
                            temp_dev = lin   
                        
                        umount_partition(directory)
                    cont = 0
                    for win in devices_windows:
                        cont+= 1
                        filenames = None
                        directory = mount_partition(win)
                        try:
                            filenames = os.listdir("{0}".format(directory))
                        except:
                            log.info("Folder {0} didn't exist or it'a empty".format(directory))

                        if filenames is not None:
                            bootWin = False
                            for i in filenames:
                                if "boot" in i.lower():
                                    bootWin = True
                            if bootWin:
                                windev = int(win[8:])
                                
                                menu_windows.append("\ntitle Windows {0}\n".format(cont))
                                '''
                                the two line below should exist if windows is on sdb
                                '''
                                if "1" not in win:
                                    #if windows is not in the firs filesystem
                                    menu_windows.append("map (hd0) (hd{0})\n".format(windev))
                                    menu_windows.append("map (hd{0}) (hd0)\n".format(windev)) 
                                menu_windows.append("rootnoverify (hd0,{0})\n".format(windev-1))
                                menu_windows.append("makeactive\n")
                                menu_windows.append("chainloader +1\n")

        for i in menu_linux:
            f.write(i)
        for i in menu_windows:
            f.write(i)
        f.close()
Ejemplo n.º 17
0
    def install_syslinux(self, device, directory):
    
        boot_folder = directory+"boot"
        dev = device[:8]
        try:
            log.info("cp /usr/lib/syslinux/menu.c32 {0}/syslinux".format(boot_folder))
            copyFile("/usr/lib/syslinux/menu.c32", boot_folder+"/syslinux")
            log.info("cp /usr/lib/syslinux/chain.c32 {0}/syslinux".format(boot_folder))
            copyFile("/usr/lib/syslinux/chain.c32", boot_folder+"/syslinux")
            log.info("cp /usr/lib/syslinux/reboot.c32 {0}/syslinux".format(boot_folder))
            copyFile("/usr/lib/syslinux/reboot.c32", boot_folder+"/syslinux")
            log.info("cp /usr/lib/syslinux/poweroff.com {0}/syslinux".format(boot_folder))
            copyFile("/usr/lib/syslinux/poweroff.com", boot_folder+"/syslinux")

        except:
            log.error("Error copying files")
            return False
        try:
            aux = get_filesystem_type(device)
            if "fat" in aux:
               run_simple_command_echo("syslinux -d {0}/syslinux {1}".format(boot_folder,device),True)
            elif "ext" in aux:
                log.info("extlinux --install {0}/syslinux".format(boot_folder))                      
                run_simple_command_echo("extlinux --install {0}/syslinux".format(boot_folder),True)

            else:
                log.error("Filesystem not accepted.")
                return False

        except:
            log.error("installing syslinux in {0} failed".format(device))
            return False        
        try:
            run_simple_command_echo("dd if=/usr/lib/syslinux/mbr.bin of={0} \
                bs=440 conv=notrunc count=1".format(dev),True)
        except:
            log.error("dd failed")
            return False
            
        if not get_boot_flag(device):
            unset_all_boot_flags(device)
            if set_boot_flag(device):
                log.info("{0} has been set as bootable device".format(device))
        return True
Ejemplo n.º 18
0
def undo_chroot(real_root):
    log.info("Exiting chroot")
    os.fchdir(real_root)
    os.chroot(".")
    os.close(real_root)
    os.chdir("/")
Ejemplo n.º 19
0
class ImageCreator:

    def __init__(self, source_device, output_folder,
                 status_callback, image_name="image", compressor_level=6,
                 raw=False, split_size=0, create_iso=False,
                 fill_with_zeros=False):

        assert check_if_root(), "You need to run this application as root"
        assert os.path.isdir(output_folder), "{0} folder is invalid".\
                                             format(output_folder)

        self.image_name = image_name
        self.device_path = source_device
        self.target_path = adjust_path(output_folder)
        self.notify_status = status_callback
        self.compressor_level = compressor_level
        self.raw = raw
        self.split_size = split_size
        self.create_iso = create_iso
        self.fill_with_zeros = fill_with_zeros

        self.timer = Timer(self.notify_percent)
        self.total_blocks = 0
        self.processed_blocks = 0
        self.current_percent = -1
        self.active = False
        self.canceled = False

    def notify_percent(self):
        percent = (self.processed_blocks/float(self.total_blocks)) * 100
        if percent > self.current_percent:
            self.current_percent = percent
            self.notify_status("progress", {"percent": percent})

    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)

        # We dont need to save the data of the swap partition
        # we just copy the informations and re-create when
        # restoring
        swap = disk.get_swap_partition()
        if swap is not None:
            log.info("Swap path {0}".format(swap.get_path()))
            number = swap.get_number()
            uuid = swap.filesystem.uuid()
            type = swap.filesystem.type
            information.add_partition(number, type, 0, 0, uuid)

        information.save()
        self.stop()

        if self.create_iso:
            log.info("Starting create ISO operation")
            iso_creator = IsoCreator(self.target_path, slices,
                                     self.image_name,
                                     self.notify_status,
                                     device.is_disk())
            iso_creator.run()

        if self.canceled:
            self.notify_status("canceled", {"operation": 
                                            "Create image"})
        else:
            self.notify_status("finish")
        log.info("Creation finished")
Ejemplo n.º 20
0
 def cancel(self):
     if not self.canceled:
         log.info("Create image canceled")
         self.canceled = True
         self.stop()
Ejemplo n.º 21
0
    def expand_last_partition(self,opt_expand):
        # After all data is copied to the disk
        # we instance class again to reload

        sync()
        device = Device(self.target_device)
        disk = Disk(device)
        partition = disk.get_last_partition()
        if partition is not None:
            if partition.type == PARTITION_NORMAL:
                expander = PartitionExpander(device.path)
                log.info("Checking and try expand {0}".format(partition.get_path()))
                new_size = expander.try_expand()
                log.info("The new_size of the disk will be {0}".format(new_size))
                if new_size!= -1:

                    if opt_expand == 0:
                        log.info("Expanding {0} filesystem".format(partition.get_path()))
                        self.notify_status("expand", {"device":
                                               partition.get_path()})
                        returncode = partition.filesystem.resize()
                        if returncode == True:
                            log.info("Resize in {0} was made with sucess".format(partition.get_path()))
                        else:
                            log.info("Resize in {0} failed - Versao sem mensagem!".format(partition.get_path()))
                            #self.notify_status("expand_last_partition_error", {"last_partition":partition.get_path()})
                            #self.canceled = True
                    else:
                        if opt_expand == 1:
                            log.info("Formating {0} filesystem".format(partition.get_path()))
                            self.notify_status("format", {"device":
                                                   partition.get_path()})
                            partition.filesystem.format_filesystem()
Ejemplo n.º 22
0
    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)
Ejemplo n.º 23
0
    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
Ejemplo n.º 24
0
    def restore_image(self):
        """ """
        invalid_partitions = False

        if is_mounted(self.target_device):
            log.error("The partition {0} is mounted, please umount first, and try again".format(self.target_device))
            self.notify_status("mounted_partition_error",{"mounted_partition_error":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)
            self.notify_status("write_error", \
                               {"write_error":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():
            if ("msdos" not in disk.getPedDisk().type.name):
                #se a tabela nao for msdos, recria ela como msdos para nao haver problemas
                d = disk_new_fresh(device.getPedDevice(), _ped.disk_type_get("msdos"))
                d.commit_to_dev()
                disk = Disk(device)

            #Get total disk target size
            disk_size = get_disk_size(self.target_device)
            if (total_bytes > disk_size):
                log.info("Total size of image is {0}".format(total_bytes))
                log.info("Total size of {0} is {1}".format(self.target_device,disk_size))
                log.error("The size of {0} is {1}, is not enough to apply the selected image".format(self.target_device, disk_size))
                disk_space_info = []
                disk_space_info.append(total_bytes)
                disk_space_info.append(disk_size)
                self.notify_status("no_enough_space", {"disk_minimum_size":disk_space_info})
                raise ErrorRestoringImage("No enough space on disk")

            log.info("Restoring MBR and Disk Layout")
            mbr = Mbr(self.image_path)
            try:
                mbr.restore_from_file(self.target_device)
            except Exception as e:
                log.error("Error to restore the Mbr file")
                image_path = self.image_path.split("/")[3] + "/mbr.bin"
                self.notify_status("file_not_found",{"file_not_found":image_path})
                raise ErrorFileNotFound("File not Found {0}".format(image_path))

            dlm = DiskLayoutManager(self.image_path)
            #try:
            if self.expand != 2:
                dlm.restore_from_file(disk, True)
            else:
                dlm.restore_from_file(disk, False)
            #except Exception as e:
            #        log.error("Error to restore the disk.dl file")
            #        image_path = self.image_path.split("/")[3] + "/disk.dl"
            #        self.notify_status("file_not_found",{"file_not_found":image_path})
            #        raise ErrorFileNotFound("File not found {0}".format(image_path))

        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)
            part_size = partition.getSize('b')
            if (total_bytes > part_size):
                 part_space_info = []
                 part_space_info.append(total_bytes)
                 part_space_info.append(part_size)
                 log.error("The partition selected is smaller than the image")
                 self.notify_status("no_enough_space_part", {"disk_minimum_size":part_space_info})
                 raise ErrorRestoringImage("No enought space on partition")

        self.timer.start()

        total_partitions = len(partitions)
        for part in partitions:
            total_partitions -= 1

            if not self.active: break

            if (self.expand == 3) and (total_partitions == 0): 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)

            if partition is None:
                invalid_partitions = True
                continue

            log.info("Restoring partition {0}".format(partition.get_path()))
            self.notify_status("restore_partition",\
                               {"restoring_partition":partition.get_path()})

            invalid_partitions = False

            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
            try:
                image_reader = ImageReaderFactory(self.image_path, pattern,
                                                  volumes, compressor_level,
                                                  self.notify_status)
            except Exception as e:
                log.info(e)

            extract_callback = None
            if compressor_level:
                compressor = Compressor(compressor_level)
                extract_callback = compressor.extract

            self.buffer_manager = BufferManagerFactory(image_reader.read_block,
                                                       self.notify_status,
                                                       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.notify_status("read_buffer_error",{"read_buffer_error":str(e)})
                        data = ""
                        self.cancel()
                        raise ErrorReadingFromDevice(e)
                        break

                if data == EOF:
                    break

                try:
                    partition.filesystem.write_block(data)
                except ErrorWritingToDevice, e:
                    self.notify_status("write_partition_error")
                    if not self.canceled:
                        self.stop()
                        raise e

                self.processed_blocks += 1
Ejemplo n.º 25
0
            self.buffer_manager.join()
            partition.filesystem.close()

        self.timer.stop()

        if self.expand:
            if information.get_image_is_disk():
                self.expand_last_partition()

        if self.canceled:
            self.notify_status("canceled", {"operation": 
                                            "Restore image"})
        else:
            self._finish()
        log.info("Restoration finished")

    def expand_last_partition(self):
        # After all data is copied to the disk
        # we instance class again to reload
        sync()
        device = Device(self.target_device)
        disk = Disk(device)
        partition = disk.get_last_partition()
        if partition is not None:
            if partition.type == PARTITION_NORMAL:
                log.info("Expanding {0} filesystem".\
                         format(partition.get_path()))
                self.notify_status("expand", {"device":
                                   partition.get_path()})
                partition.filesystem.resize()