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
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()
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)
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()
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)
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
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)
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)
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)