예제 #1
0
    def __init__(self, recovery, version, media, target, overwrite):

        #Run the normal init first
        #This sets up lots of common variables as well as translation domain
        DellRecoveryToolGTK.__init__(self, recovery)

        #init the UI and translate widgets/connect signals
        self.widgets = Gtk.Builder()
        self.widgets.add_from_file(
            os.path.join(UIDIR, 'recovery_media_creator.ui'))

        #insert pages in reverse order
        wizard = self.widgets.get_object('wizard')
        titles = {
            'conf_page': _("Confirm Selections"),
            'media_type_page': _("Media Type")
        }
        for page in ['conf_page', 'media_type_page']:
            wizard.insert_page(self.widgets.get_object(page), 0)
            wizard.set_page_title(wizard.get_nth_page(0), titles[page])

        Gtk.Window.set_default_icon_from_file(
            os.path.join(SVGDIR, 'dell-dvd.svg'))
        translate_widgets(self.widgets)
        self.widgets.connect_signals(self)

        #setup spinner
        self.spinner = Gtk.Spinner()
        self.widgets.get_object('spinner_box').add(self.spinner)
        self.widgets.get_object('spinner_box').show_all()

        self._dbus_iface = None
        self.timeout = 0
        self.image = ''

        (self.dvd_burn_cmd, self.usb_burn_cmd) = find_burners()

        try:
            self.release = fetch_output(['lsb_release', '-r',
                                         '-s']).strip('\n')
            self.distributor = fetch_output(['lsb_release', '-i',
                                             '-s']).strip('\n').lower()
        except RuntimeError:
            self.release = '0.00'
            self.distributor = 'unknown'

        self.arch = ''

        for item in ['server', 'enterprise']:
            if item in self.distributor:
                self.distributor = self.distributor.split(item)[0]

        #set any command line arguments for this frontend
        self.widgets.get_object('version').set_text(version)
        self.media = media
        self.path = target
        self.overwrite = overwrite
    def __init__(self, recovery, version, media, target, overwrite):

        #Run the normal init first
        #This sets up lots of common variables as well as translation domain
        DellRecoveryToolGTK.__init__(self, recovery)

        #init the UI and translate widgets/connect signals
        self.widgets = Gtk.Builder()
        self.widgets.add_from_file(os.path.join(UIDIR,
                                   'recovery_media_creator.ui'))

        #insert pages in reverse order
        wizard = self.widgets.get_object('wizard')
        titles = {'conf_page': _("Confirm Selections"),
                 'media_type_page': _("Media Type")
                }
        for page in ['conf_page', 'media_type_page']:
            wizard.insert_page(self.widgets.get_object(page), 0)
            wizard.set_page_title(wizard.get_nth_page(0), titles[page])

        Gtk.Window.set_default_icon_from_file(os.path.join(SVGDIR, 'dell-dvd.svg'))
        translate_widgets(self.widgets)
        self.widgets.connect_signals(self)

        #setup spinner
        self.spinner = Gtk.Spinner()
        self.widgets.get_object('spinner_box').add(self.spinner)
        self.widgets.get_object('spinner_box').show_all()

        self._dbus_iface = None
        self.timeout = 0
        self.image = ''
        
        (self.dvd_burn_cmd, self.usb_burn_cmd) = find_burners()

        try:
            self.release = fetch_output(['lsb_release', '-r', '-s']).strip('\n')
            self.distributor = fetch_output(['lsb_release', '-i', '-s']).strip('\n').lower()
        except RuntimeError:
            self.release = '0.00'
            self.distributor = 'unknown'

        self.arch = ''

        for item in ['server', 'enterprise']:
            if item in self.distributor:
                self.distributor = self.distributor.split(item)[0]

        #set any command line arguments for this frontend
        self.widgets.get_object('version').set_text(version)
        self.media = media
        self.path = target
        self.overwrite = overwrite
예제 #3
0
 def find_arch(input_str):
     """Finds the architecture in an input string"""
     for item in input_str.split():
         for test in ('amd64', 'i386'):
             if test in item:
                 return test
     return fetch_output(['dpkg', '--print-architecture']).strip()
예제 #4
0
    def _test_for_new_dell_recovery(self, mount, assembly_tmp):
        """Tests if the distro currently on the system matches the recovery media.
           If it does, check for any potential SRUs to apply to the recovery media
        """
        logging.debug("_test_for_new_dell_recovery: testing mount %s and assembly_tmp %s" % (mount, assembly_tmp))

        output = fetch_output(['zcat', '/usr/share/doc/dell-recovery/changelog.gz'])
        package_distro = output.split('\n')[0].split()[2].strip(';')

        for info in ('info.recovery', 'info'):
            file_path = os.path.join(mount, '.disk', info)
            if os.path.exists(file_path):
                with open(file_path) as rfd:
                    rp_distro = rfd.readline().split()[2].strip('"').lower()
                    break

        if rp_distro in package_distro:
            logging.debug("_test_for_new_dell_recovery: Distro %s matches %s", rp_distro, package_distro)
            from apt.cache import Cache
            cache = Cache()
            package_version = cache['dell-recovery'].installed.version
            rp_version = self.query_have_dell_recovery(mount)

            if debian_support.version_compare(package_version, rp_version) > 0:
                logging.debug("_test_for_new_dell_recovery: Including updated dell-recovery package version, %s (original was %s)", package_version, rp_version)
                dest = os.path.join(assembly_tmp, 'debs')
                if not os.path.isdir(dest):
                    os.makedirs(dest)
                call = subprocess.Popen(['dpkg-repack', 'dell-recovery'],
                                        cwd=dest, universal_newlines=True)
                (out, err) = call.communicate()
        else:
            logging.debug("_test_for_new_dell_recovery: RP Distro %s doesn't match our distro %s, not injecting updated package", rp_distro, package_distro)
예제 #5
0
 def find_arch(input_str):
     """Finds the architecture in an input string"""
     for item in input_str.split():
         for test in ('amd64', 'i386'):
             if test in item:
                 return test
     return fetch_output(['dpkg', '--print-architecture']).strip()
예제 #6
0
    def _test_for_new_dell_recovery(self, mount, assembly_tmp):
        """Tests if the distro currently on the system matches the recovery media.
           If it does, check for any potential SRUs to apply to the recovery media
        """
        logging.debug("_test_for_new_dell_recovery: testing mount %s and assembly_tmp %s" % (mount, assembly_tmp))

        output = fetch_output(['zcat', '/usr/share/doc/dell-recovery/changelog.gz'])
        package_distro = output.split('\n')[0].split()[2].strip(';')

        for info in ('info.recovery', 'info'):
            file_path = os.path.join(mount, '.disk', info)
            if os.path.exists(file_path):
                with open(file_path) as rfd:
                    rp_distro = rfd.readline().split()[2].strip('"').lower()
                    break

        if rp_distro in package_distro:
            logging.debug("_test_for_new_dell_recovery: Distro %s matches %s", rp_distro, package_distro)
            from apt.cache import Cache
            cache = Cache()
            package_version = cache['dell-recovery'].installed.version
            rp_version = self.query_have_dell_recovery(mount)

            if debian_support.version_compare(package_version, rp_version) > 0:
                logging.debug("_test_for_new_dell_recovery: Including updated dell-recovery package version, %s (original was %s)", package_version, rp_version)
                dest = os.path.join(assembly_tmp, 'debs')
                if not os.path.isdir(dest):
                    os.makedirs(dest)
                call = subprocess.Popen(['dpkg-repack', 'dell-recovery'],
                                        cwd=dest, universal_newlines=True)
                (out, err) = call.communicate()
        else:
            logging.debug("_test_for_new_dell_recovery: RP Distro %s doesn't match our distro %s, not injecting updated package", rp_distro, package_distro)
예제 #7
0
 def Set_RootPartitionLabel(self):
     '''find the / mount partition then label it with UBUNTU for further use'''
     mount_output = magic.fetch_output(['mount']).split('\n')
     for line in mount_output:
         item = line.split()
         if '/' in item:
             try:
                 from ubiquity import misc
                 misc.execute_root('e2label',item[0],'UBUNTU')
             except Exception:
                 pass
예제 #8
0
    def query_bto_version(self, recovery, sender=None, conn=None):
        """Queries the BTO version number internally stored in an ISO or RP"""

        def test_initrd(cmd0):
            """Tests an initrd using the selected command"""
            cmd1 = ['unlzma']
            cmd2 = ['cpio', '-it', '--quiet']
            chain0 = subprocess.Popen(cmd0, stdout=subprocess.PIPE)
            chain1 = subprocess.Popen(cmd1, stdin=chain0.stdout, stdout=subprocess.PIPE)
            chain2 = subprocess.Popen(cmd2, stdin=chain1.stdout, stdout=subprocess.PIPE,
                                      universal_newlines=True)
            out, err = chain2.communicate()
            if chain2.returncode is None:
                chain2.wait()
            if out:
                for line in out.split('\n'):
                    if 'scripts/casper-bottom/99dell_bootstrap' in line:
                        return '[native]'
            return ''
        logging.debug("query_bto_version: recovery %s" % recovery)

        self._reset_timeout()
        self._check_polkit_privilege(sender, conn,
                                    'com.dell.recoverymedia.query_bto_version')

        #mount the recovery partition
        version = ''
        date = ''
        platform = ''

        if os.path.isfile(recovery) and recovery.endswith('.iso'):
            cmd = ['isoinfo', '-J', '-i', recovery, '-x', '/bto.xml']
            out = fetch_output(cmd)
            if out:
                self.xml_obj.load_bto_xml(out)
                version = self.xml_obj.fetch_node_contents('revision') or \
                          self.xml_obj.fetch_node_contents('iso')
                platform = self.xml_obj.fetch_node_contents('platform')
                date = self.xml_obj.fetch_node_contents('date')
            else:
                cmd = ['isoinfo', '-J', '-i', recovery, '-x', '/bto_version']
                out = fetch_output(cmd)
                if out:
                    out = out.split('\n')
                    if len(out) > 1:
                        version = out[0]
                        date = out[1]
                else:
                    version = test_initrd(['isoinfo', '-J', '-i', recovery, '-x', '/casper/initrd.lz'])

        else:
            mntdir = self.request_mount(recovery, "r", sender, conn)
            if os.path.exists(os.path.join(mntdir, 'bto.xml')):
                self.xml_obj.load_bto_xml(os.path.join(mntdir, 'bto.xml'))
                version = self.xml_obj.fetch_node_contents('revision') or \
                          self.xml_obj.fetch_node_contents('iso')
                platform = self.xml_obj.fetch_node_contents('platform')
                date = self.xml_obj.fetch_node_contents('date')
            elif os.path.exists(os.path.join(mntdir, 'bto_version')):
                with open(os.path.join(mntdir, 'bto_version'), 'r') as rfd:
                    version = rfd.readline().strip('\n')
                    date = rfd.readline().strip('\n')
            #no /bto.xml or /bto_version found, check initrd for bootsrap files
            elif os.path.exists(os.path.join(mntdir, 'casper', 'initrd.lz')):
                version = test_initrd(['cat', os.path.join(mntdir, 'casper', 'initrd.lz')])

        return (version, date, platform)
예제 #9
0
    def install(self, target, progress, *args, **kwargs):
        """Perform actual install time activities for oem-config"""
        if not 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
            return

        #find the '/' mount partition and then label it as UBUNTU
        self.Set_RootPartitionLabel()

        env = os.environ
        lang = progress.get('debian-installer/locale')
        env['LANG'] = lang

        dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
        self.progress = progress

        user = progress.get('passwd/username')
        uid = pwd.getpwnam(user).pw_uid
        gid = pwd.getpwnam(user).pw_gid

        rec_type = progress.get('dell-recovery/destination')
        if rec_type != "none":
            dvd, usb = magic.find_burners()
            rpart  = magic.find_partition()
            self.index = 0

            #build all the user's home directories a little earlier than normal
            subprocess.call(['su', user, '-c', 'xdg-user-dirs-update'])
            directory = magic.fetch_output(['su', user, '-c', '/usr/bin/xdg-user-dir DOWNLOAD']).strip()
            fname = os.path.join(directory, 'factory_image.iso')

            try:
                bus = dbus.SystemBus()
                dbus_iface = dbus.Interface(bus.get_object(magic.DBUS_BUS_NAME,
                                            '/RecoveryMedia'),
                                            magic.DBUS_INTERFACE_NAME)
            except Exception as err:
                self.log('install function exception while creating dbus backend: %s' % str(err))
                return

            progress.info('dell-recovery/build_start')

            #Determine internal version number of image
            (version, date, platform) = dbus_iface.query_bto_version(rpart)
            version = magic.increment_bto_version(version)
            self.log("Generating recovery media from %s : %s" % (version, date))

            #Build image
            try:
                magic.dbus_sync_call_signal_wrapper(dbus_iface,
                                                    'create_ubuntu',
                                                    {'report_progress':self._update_progress_gui},
                                                    rpart,
                                                    version,
                                                    fname,
                                                    platform)
                os.chown(fname.encode('utf-8'), uid, gid)
            except dbus.DBusException as err:
                self.log('install function exception while calling backend: %s' % str(err))
                return

            #Close backend
            try:
                dbus_iface.request_exit()
            except dbus.DBusException as err:
                if hasattr(err, '_dbus_error_name') and err._dbus_error_name == \
                        'org.freedesktop.DBus.Error.ServiceUnknown':
                    pass
                else:
                    self.log("Received %s when closing recovery-media-backend" \
                                                                     % str(err))
                    return

            if rec_type:
                if rec_type == "dvd":
                    cmd = ['dbus-launch'] + dvd + [fname.encode('utf-8')]
                else:
                    cmd = ['dbus-launch'] + usb + [fname.encode('utf-8')]
                if 'DBUS_SESSION_BUS_ADDRESS' in os.environ:
                    os.environ.pop('DBUS_SESSION_BUS_ADDRESS')
                progress.info('dell-recovery/burning')
                subprocess.call(cmd)
        else:
            #Mark burning tool to launch on 7th day
            directory = '/home/%s/.config/autostart' % user
            if not os.path.exists(directory):
                os.makedirs(directory)
                os.chown('/home/%s/.config' % user, uid, gid)
                os.chown(directory, uid, gid)
            fname = os.path.join(directory, 'dell-recovery.desktop')
            with open('/usr/share/applications/dell-recovery-media.desktop', encoding='utf-8') as rfd:
                with open(fname, 'w', encoding='utf-8') as wfd:
                    for line in rfd.readlines():
                        if line.startswith('Exec='):
                            line = 'Exec=/home/%s/.config/dell-recovery/reminder\n' % user
                        wfd.write(line)
            os.chown(fname, uid, gid)
            directory = '/home/%s/.config/dell-recovery' % user
            if not os.path.exists(directory):
                os.makedirs(directory)
                os.chown(directory, uid, gid)
            fname = os.path.join(directory, 'reminder')
            date = magic.fetch_output(['date', '-d', '+7 days', '+%y%m%d'])
            with open(fname, 'w', encoding='utf-8') as wfd:
                wfd.write('#!/bin/sh\n')
                wfd.write('LAUNCH=%s\n' % date)
                wfd.write('TODAY=$(date +"%y%m%d")\n')
                wfd.write('if [ $TODAY -ge $LAUNCH ]; then\n')
                wfd.write('    dell-recovery\n')
                wfd.write('fi\n')
            os.chown(fname, uid, gid)
            os.chmod(fname, 0o744)

        return InstallPlugin.install(self, target, progress, *args, **kwargs)
    def standalone_builder(self):
        """Queries the BTO version number internally stored in an ISO or RP"""
        # Partition Definitions
        EFI_ESP_PARTITION = '1'
        EFI_RP_PARTITION = '2'

        try:
            misc.execute_root('umount', '/mnt')
        except:
            pass

        cushion = 600
        if os.path.exists(magic.CDROM_MOUNT + '/IMAGE/rcx.flg'):
            cushion = 1600
        black_pattern = re.compile("no_black_pattern")

        # Check if we are booted from same device as target
        mounted_device = find_boot_device()
        if self.device in mounted_device:
            self.handle_exception(
                "Attempting to install to the same device as booted from.\n\
        You will need to clear the contents of the recovery partition\n\
        manually to proceed.")
            raise RuntimeError(
                "Attempting to install to the same device as booted from.\n\
        You will need to clear the contents of the recovery partition\n\
        manually to proceed.")
            # check base image and fish manifest

        if self.base_file:
            base_zip = self.base_file
            fish_file = None
            if self.fish_file:
                fish_file = self.fish_file
                # resize /tmp file size
            command = ('mount', '-o', 'remount,size=15g', '/tmp')
            result = misc.execute_root(*command)
            if result is False:
                self.handle_exception("Error Resize the /tmp Size")
                raise RuntimeError("Error Resize the /tmp Size")

            image_folder = os.path.join('/tmp', 'IMAGE')
            if os.path.exists(image_folder):
                shutil.rmtree(image_folder)
            os.mkdir(image_folder)

            import zipfile
            zf = zipfile.ZipFile(base_zip)
            zf_size = sum(map(lambda x: getattr(x, "file_size"),
                              zf.infolist()))
            size_thread = ProgressBySize("Extracting the Base Image ...",
                                         image_folder, zf_size)
            size_thread.progress = self.report_progress
            size_thread.reset_write(zf_size)
            size_thread.set_starting_value(2)
            size_thread.start()
            zf.extractall(path=image_folder)
            zf.close()
            size_thread.join()

            if fish_file:
                import tarfile
                zf = tarfile.open(fish_file)
                tarfile_size = sum(
                    map(lambda x: getattr(x, "size"), zf.getmembers()))
                zf_size += tarfile_size
                size_thread = ProgressBySize(
                    "Extracting the Fish packages ...", image_folder, zf_size)
                size_thread.progress = self.report_progress
                size_thread.reset_write(zf_size)
                size_thread.set_starting_value(2)
                size_thread.start()
                zf.extractall(path=image_folder)
                zf.close()
                size_thread.join()
            black_pattern = re.compile(".*\.base\.zip|.*\.fish\.tar\.gz")

        # Calculate RP size
        rp_size = magic.black_tree("size", black_pattern, image_folder)
        # in mbytes
        rp_size_mb = (rp_size / 1000000) + cushion

        # Build new partition table
        command = ('parted', '-s', self.device, 'mklabel', 'gpt')
        result = misc.execute_root(*command)
        if result is False:
            command = ('partprobe')
            result = misc.execute_root(*command)
            if result is False:
                self.handle_exception(
                    "Error creating new partition table on %s" % (self.device))
                raise RuntimeError("Error creating new partition table on %s" %
                                   (self.device))

        self.report_progress("Creating Partitions", 100)
        grub_size = 250
        commands = [('parted', '-a', 'optimal', '-s', self.device, 'mkpart',
                     'primary', 'fat32', '0', str(grub_size)),
                    ('parted', '-s', self.device, 'name', '1',
                     "'EFI System Partition'"),
                    ('parted', '-s', self.device, 'set', '1', 'boot', 'on')]
        if '/dev/nvme' in self.device or '/dev/mmcblk' in self.device:
            commands.append(
                ('mkfs.msdos', self.device + 'p' + EFI_ESP_PARTITION))
            rp_part = 'p' + EFI_RP_PARTITION
            esp_part = 'p' + EFI_ESP_PARTITION
        else:
            commands.append(('mkfs.msdos', self.device + EFI_ESP_PARTITION))
            rp_part = EFI_RP_PARTITION
            esp_part = EFI_ESP_PARTITION
        for command in commands:
            # wait for settle
            if command[0] == 'mkfs.msdos':
                while not os.path.exists(command[-1]):
                    time.sleep(1)
            result = misc.execute_root(*command)
            if result is False:
                self.handle_exception("Error formatting disk.")
                raise RuntimeError("Error formatting disk.")

        # Drag some variable of parted command to support RCX
        file_format = 'fat32'
        file_type = 'mkfs.msdos'
        file_para = '-n'
        part_label = 'OS'

        # Change file system if installed RCX
        if os.path.exists(image_folder + '/rcx.flg'):
            # Set RCX variable parameters
            file_format = 'ext2'
            file_type = 'mkfs.ext2'
            file_para = '-L'
            part_label = 'rhimg'
            # Build OS Part
            command = ('parted', '-a', 'optimal', '-s', self.device, 'mkpart',
                       'fat32', 'fat32', str(grub_size), str(250 + grub_size))
            result = misc.execute_root(*command)
            if result is False:
                self.handle_exception(
                    "Error creating new 250 mb OS partition on %s" %
                    (self.device))
                raise RuntimeError(
                    "Error creating new 250 mb OS partition on %s" %
                    (self.device))
            # Build OS filesystem
            command = ('mkfs.msdos', '-n', 'OS', self.device + rp_part)
            while not os.path.exists(command[-1]):
                time.sleep(1)
            result = misc.execute_root(*command)
            if result is False:
                self.handle_exception(
                    "Error creating fat32 filesystem on %s%s" %
                    (self.device, rp_part))
                raise RuntimeError("Error creating fat32 filesystem on %s%s" %
                                   (self.device, rp_part))
            # Refresh the grub_size and rp_part value
            grub_size = grub_size + 250
            rp_part = rp_part[:-1] + '3'
            rp_size_mb = rp_size_mb + 5000

        # Build RP
        command = ('parted', '-a', 'optimal', '-s', self.device, 'mkpart',
                   file_format, file_format, str(grub_size),
                   str(rp_size_mb + grub_size))
        result = misc.execute_root(*command)
        if result is False:
            self.handle_exception(
                "Error creating new %s mb recovery partition on %s" %
                (rp_size_mb, self.device))
            raise RuntimeError(
                "Error creating new %s mb recovery partition on %s" %
                (rp_size_mb, self.device))

        # Build RP filesystem
        self.report_progress(_('Formatting Partitions'), 200)
        if os.path.exists(image_folder + '/rcx.flg'):
            command = (file_type, '-F', file_para, part_label,
                       self.device + rp_part)
        else:
            command = (file_type, file_para, part_label, self.device + rp_part)
        while not os.path.exists(command[-1]):
            time.sleep(1)
        result = misc.execute_root(*command)
        if result is False:
            self.handle_exception("Error creating %s filesystem on %s%s" %
                                  (file_format, self.device, rp_part))
            raise RuntimeError("Error creating %s filesystem on %s%s" %
                               (file_format, self.device, rp_part))

        # Mount RP
        mount = misc.execute_root('mount', self.device + rp_part, '/mnt')
        if mount is False:
            self.handle_exception("Error mounting %s%s" %
                                  (self.device, rp_part))
            raise RuntimeError("Error mounting %s%s" % (self.device, rp_part))

        # Update status and start the file size thread
        size_thread = ProgressBySize("Copying Files", "/mnt", rp_size)
        size_thread.progress = self.report_progress
        size_thread.reset_write(rp_size)
        size_thread.set_starting_value(2)
        size_thread.start()

        # Copy RP Files
        with misc.raised_privileges():
            if os.path.exists(magic.ISO_MOUNT):
                magic.black_tree("copy", re.compile(".*\.iso$"),
                                 magic.ISO_MOUNT + '/IMAGE', '/mnt')
            magic.black_tree("copy", black_pattern, image_folder, '/mnt')

        size_thread.join()

        # combine the RCX iso image as its size is too larger to store in vfat sticky
        if os.path.exists(image_folder + '/rcx.flg'):
            # lock.acquire()
            tgz_file = "/tmp/RCX_ISO.tar.gz"
            with misc.raised_privileges():
                # merge compress iso files
                gza_files = glob.glob("/mnt/*.tar.gza*")
                with open(tgz_file, 'wb') as outfile:
                    ISO_size = sum(map(os.path.getsize, gza_files))
                    size_thread = ProgressBySize(
                        "Merge Compress RCX ISO Files ...", tgz_file, ISO_size)
                    size_thread.progress = self.report_progress
                    size_thread.reset_write(ISO_size)
                    size_thread.set_starting_value(2)
                    size_thread.start()
                    for fname in sorted(gza_files):
                        with open(fname, 'rb') as infile:
                            for line in infile:
                                outfile.write(line)
                    size_thread.join()
                # remove the gza files
                for gza_file in gza_files:
                    os.remove(gza_file)

            import tarfile
            tf = tarfile.open(tgz_file)
            tarfile_size = sum(
                map(lambda x: getattr(x, "size"), tf.getmembers()))
            ISO_file = os.path.join("/mnt", tf.getmembers()[0].name)
            if not os.path.exists(ISO_file):
                os.mknod(ISO_file)
            size_thread = ProgressBySize("Unpacking RCX ISO Image ...",
                                         ISO_file, tarfile_size)
            size_thread.progress = self.report_progress
            size_thread.reset_write(tarfile_size)
            size_thread.set_starting_value(2)
            size_thread.start()
            tf.extractall(path="/mnt/")
            tf.close()
            size_thread.join()
            os.remove(tgz_file)

        with misc.raised_privileges():
            blkid = magic.fetch_output(
                ['blkid', self.device + rp_part, "-p", "-o",
                 "udev"]).split('\n')
            for item in blkid:
                if item.startswith('ID_FS_UUID'):
                    uuid = item.split('=')[1]
                    break

            with misc.raised_privileges():
                magic.process_conf_file(image_folder + '/factory/grub.cfg', \
                                        '/mnt/factory/grub.cfg', uuid, EFI_RP_PARTITION)

        # Install grub
        self.report_progress(_('Installing GRUB'), 880)

        grub_files = []
        for root, dirs, files in os.walk(image_folder):
            for f in files:
                if f.lower() == "bootx64.efi":
                    grub_files.append(os.path.join(root, f))
                if f.lower() == "grubx64.efi":
                    grub_files.append(os.path.join(root, f))

        ##Mount ESP
        if not os.path.exists(os.path.join('/mnt', 'efi')):
            with misc.raised_privileges():
                os.makedirs(os.path.join('/mnt', 'efi'))
        mount = misc.execute_root('mount', self.device + esp_part, '/mnt/efi')
        if mount is False:
            self.handle_exception("Error mounting %s%s" %
                                  (self.device, esp_part))
            raise RuntimeError("Error mounting %s%s" % (self.device, esp_part))

        ##find old entries and prep directory
        direct_path = '/mnt/efi' + '/EFI/linux'
        with misc.raised_privileges():
            os.makedirs(direct_path)

            # copy boot loader files
            for item in grub_files:
                if not os.path.exists(item):
                    self.handle_exception("Error, %s doesn't exist." % item)
                    raise RuntimeError("Error, %s doesn't exist." % item)
                shutil.copy(item, direct_path)

            # find old entries
            bootmgr_output = magic.fetch_output(['efibootmgr',
                                                 '-v']).split('\n')

            # delete old entries
            for line in bootmgr_output:
                bootnum = ''
                if line.startswith('Boot') and 'linuxins' in line.lower():
                    bootnum = line.split('Boot')[1].replace('*', '').split()[0]
                if bootnum:
                    bootmgr = misc.execute_root('efibootmgr', '-v', '-b',
                                                bootnum, '-B')
                    if bootmgr is False:
                        self.handle_exception(
                            "Error removing old EFI boot manager entries")
                        raise RuntimeError(
                            "Error removing old EFI boot manager entries")

        target = 'shimx64.efi'
        source = 'bootx64.efi'
        # RCX bootloader source file name is different
        if os.path.exists(image_folder + '/rcx.flg'):
            source = 'grubx64.efi'

        with misc.raised_privileges():
            for f in os.listdir(direct_path):
                if f.lower() == source:
                    os.rename(os.path.join(direct_path, f),
                              os.path.join(direct_path, target))

        add = misc.execute_root('efibootmgr', '-v', '-c', '-d', self.device,
                                '-p', EFI_ESP_PARTITION, '-l',
                                '\\EFI\\linux\\%s' % target, '-L', 'LinuxIns')
        if add is False:
            self.handle_exception("Error adding efi entry to %s%s" %
                                  (self.device, esp_part))
            raise RuntimeError("Error adding efi entry to %s%s" %
                               (self.device, esp_part))
        # set the LinuxIns entry on the first place for next reboot
        with misc.raised_privileges():
            bootmgr_output = magic.fetch_output(['efibootmgr',
                                                 '-v']).split('\n')
            for line in bootmgr_output:
                bootnum = ''
                if line.startswith('Boot') and 'LinuxIns' in line:
                    bootnum = line.split('Boot')[1].replace('*', '').split()[0]
                    misc.execute_root('efibootmgr', '-n', bootnum)
        ##copy other neokylin bootloader files
        with misc.raised_privileges():
            if os.path.exists(magic.ISO_MOUNT):
                shutil.copy(magic.ISO_MOUNT + '/IMAGE/factory/grub.cfg',
                            '/mnt/efi/EFI/linux/grub.cfg')
            shutil.copy(image_folder + '/factory/grub.cfg',
                        '/mnt/efi/EFI/linux/grub.cfg')

        ##clean up ESP mount
        misc.execute_root('umount', '/mnt/efi')

        # set install_in_progress flag
        with misc.raised_privileges():
            magic.fetch_output([
                'grub-editenv', '/mnt/factory/grubenv', 'set',
                'install_in_progress=1'
            ])

        misc.execute_root('umount', '/mnt')

        for count in range(100, 0, -10):
            self.report_progress("Restarting in %d seconds." % int(count / 10),
                                 count)
            time.sleep(1)

        reboot_machine(None)
예제 #11
0
    def query_bto_version(self, recovery, sender=None, conn=None):
        """Queries the BTO version number internally stored in an ISO or RP"""
        def test_initrd(cmd0):
            """Tests an initrd using the selected command"""
            cmd1 = ['unlzma']
            cmd2 = ['cpio', '-it', '--quiet']
            chain0 = subprocess.Popen(cmd0, stdout=subprocess.PIPE)
            chain1 = subprocess.Popen(cmd1,
                                      stdin=chain0.stdout,
                                      stdout=subprocess.PIPE)
            chain2 = subprocess.Popen(cmd2,
                                      stdin=chain1.stdout,
                                      stdout=subprocess.PIPE,
                                      universal_newlines=True)
            out, err = chain2.communicate()
            if chain2.returncode is None:
                chain2.wait()
            if out:
                for line in out.split('\n'):
                    if 'scripts/casper-bottom/99dell_bootstrap' in line:
                        return '[native]'
            return ''

        logging.debug("query_bto_version: recovery %s" % recovery)

        self._reset_timeout()
        self._check_polkit_privilege(
            sender, conn, 'com.dell.recoverymedia.query_bto_version')

        #mount the recovery partition
        version = ''
        date = ''

        if os.path.isfile(recovery) and recovery.endswith('.iso'):
            cmd = ['isoinfo', '-J', '-i', recovery, '-x', '/bto.xml']
            out = fetch_output(cmd)
            if out:
                self.xml_obj.load_bto_xml(out)
                version = self.xml_obj.fetch_node_contents('iso')
                date = self.xml_obj.fetch_node_contents('date')
            else:
                cmd = ['isoinfo', '-J', '-i', recovery, '-x', '/bto_version']
                out = fetch_output(cmd)
                if out:
                    out = out.split('\n')
                    if len(out) > 1:
                        version = out[0]
                        date = out[1]
                else:
                    version = test_initrd([
                        'isoinfo', '-J', '-i', recovery, '-x',
                        '/casper/initrd.lz'
                    ])

        else:
            mntdir = self.request_mount(recovery, "r", sender, conn)
            if os.path.exists(os.path.join(mntdir, 'bto.xml')):
                self.xml_obj.load_bto_xml(os.path.join(mntdir, 'bto.xml'))
                version = self.xml_obj.fetch_node_contents('iso')
                date = self.xml_obj.fetch_node_contents('date')
            elif os.path.exists(os.path.join(mntdir, 'bto_version')):
                with open(os.path.join(mntdir, 'bto_version'), 'r') as rfd:
                    version = rfd.readline().strip('\n')
                    date = rfd.readline().strip('\n')
            #no /bto.xml or /bto_version found, check initrd for bootsrap files
            elif os.path.exists(os.path.join(mntdir, 'casper', 'initrd.lz')):
                version = test_initrd(
                    ['cat', os.path.join(mntdir, 'casper', 'initrd.lz')])

        return (version, date)