def menu_item_clicked(self, widget): """Callback for help menu items""" if widget == self.tool_widgets.get_object('get_help_menu_item'): # run yelp proc = subprocess.Popen([ "yelp", "file:///usr/share/help/C/dell-recovery/dell-recovery.xml" ]) # collect the exit status (otherwise we leave zombies) GLib.timeout_add_seconds(1, lambda proc: proc.poll() == None, proc) elif widget == self.tool_widgets.get_object('about_menu_item'): tool_selector = self.tool_widgets.get_object('tool_selector') if not self.about_box: self.about_box = Gtk.AboutDialog() self.about_box.set_version(check_version()) self.about_box.set_name(_("Dell Recovery")) self.about_box.set_copyright( _("Copyright 2008-2022 Dell Inc.")) self.about_box.set_website("http://www.dell.com/ubuntu") self.about_box.set_authors(["Mario Limonciello"]) self.about_box.set_modal(True) self.about_box.set_transient_for(tool_selector) tool_selector.set_sensitive(False) self.about_box.run() self.about_box.hide() tool_selector.set_sensitive(True)
def menu_item_clicked(self, widget): """Callback for help menu items""" if widget == self.tool_widgets.get_object('get_help_menu_item'): # run yelp proc = subprocess.Popen(["yelp", "ghelp:dell-recovery"]) # collect the exit status (otherwise we leave zombies) GLib.timeout_add_seconds(1, lambda proc: proc.poll() == None, proc) elif widget == self.tool_widgets.get_object('about_menu_item'): tool_selector = self.tool_widgets.get_object('tool_selector') if not self.about_box: self.about_box = Gtk.AboutDialog() self.about_box.set_version(check_version()) self.about_box.set_name(_("Dell Recovery")) self.about_box.set_copyright(_("Copyright 2008-2012 Dell Inc.")) self.about_box.set_website("http://www.dell.com/ubuntu") self.about_box.set_authors(["Mario Limonciello"]) self.about_box.set_destroy_with_transient_for(True) self.about_box.set_modal(True) self.about_box.set_transient_for(tool_selector) tool_selector.set_sensitive(False) self.about_box.run() self.about_box.hide() tool_selector.set_sensitive(True)
def create_ubuntu(self, recovery, revision, iso, platform, no_update, sender=None, conn=None): """Creates Ubuntu compatible recovery media""" self._reset_timeout() self._check_polkit_privilege(sender, conn, 'com.dell.recoverymedia.create') logging.debug("create_ubuntu: recovery %s, revision %s, iso %s, platform %s" % (recovery, revision, iso, platform)) #create temporary workspace tmpdir = tempfile.mkdtemp() atexit.register(walk_cleanup, tmpdir) #mount the recovery partition mntdir = self.request_mount(recovery, "r", sender, conn) #validate that ubuntu is on the partition if not os.path.exists(os.path.join(mntdir, '.disk', 'info')) and \ not os.path.exists(os.path.join(mntdir, '.disk', 'info.recovery')): logging.warning("create_ubuntu: recovery partition missing .disk/info and .disk/info.recovery") if os.path.exists(os.path.join(mntdir, 'bootmgr')): raise CreateFailed("This tool can not create a recovery image from a Windows recovery partition.") raise CreateFailed("Recovery partition is missing critical ubuntu files.") #test for an updated dell recovery deb to put in if not no_update: try: self._test_for_new_dell_recovery(mntdir, tmpdir) except: raise CreateFailed("Error injecting updated Dell Recovery into image.") #check for a nested ISO image if os.path.exists(os.path.join(mntdir, 'ubuntu.iso')): pattern = re.compile('^ubuntu.iso|^.disk') w_size = black_tree("size", pattern, mntdir) self.start_sizable_progress_thread(_('Preparing nested image'), tmpdir, w_size) black_tree("copy", pattern, mntdir, tmpdir) self.stop_progress_thread() mntdir = self.request_mount(os.path.join(mntdir, 'ubuntu.iso'), "r", sender, conn) #Generate BTO XML File self.xml_obj.replace_node_contents('date', str(datetime.date.today())) self.xml_obj.replace_node_contents('iso', os.path.basename(iso)) self.xml_obj.replace_node_contents('revision', revision) self.xml_obj.replace_node_contents('platform', platform) self.xml_obj.replace_node_contents('generator', check_version()) self.xml_obj.write_xml(os.path.join(tmpdir, 'bto.xml')) #Arg list xorrisoargs = ['xorriso', '-as', 'mkisofs', '-R', '-r', '-J', '-joliet-long', '-l', '-iso-level', '3', '-sysid', 'Linux', '-V', 'Dell Recovery Media', '-A', 'Dell Recovery', '-p', 'Dell', '-publisher', 'Dell', '-o', iso, '-m', '*.exe', '-m', '*.sys', '-m', '*.SDR', '-m', 'SDR', '-m', 'syslinux', '-m', 'syslinux.cfg', '-m', os.path.join(mntdir, 'bto.xml'), '-m', os.path.join(mntdir, 'bto_version')] if platform and revision: xorrisoargs.append('-volset') xorrisoargs.append(platform + ' ' + revision) if os.path.exists(os.path.join('/', 'usr', 'lib', 'ISOLINUX', 'isohdpfx.bin')) and \ os.path.exists(os.path.join(mntdir, 'isolinux', 'boot.cat')) and \ os.path.exists(os.path.join(mntdir, 'isolinux', 'isolinux.bin')): xorrisoargs.append('-c') xorrisoargs.append('isolinux/boot.cat') xorrisoargs.append('-b') xorrisoargs.append('isolinux/isolinux.bin') xorrisoargs.append('-no-emul-boot') xorrisoargs.append('-boot-load-size') xorrisoargs.append('4') xorrisoargs.append('-boot-info-table') xorrisoargs.append('-isohybrid-mbr') xorrisoargs.append(os.path.join('/', 'usr', 'lib', 'ISOLINUX', 'isohdpfx.bin')) #include bootloader as eltorito if we have it if os.path.exists(os.path.join(mntdir, 'boot', 'efi.img')): xorrisoargs.append('-eltorito-alt-boot') xorrisoargs.append('-e') xorrisoargs.append('boot/efi.img') xorrisoargs.append('-no-emul-boot') xorrisoargs.append('-isohybrid-gpt-basdat') #disable 32 bit bootloader if it was there. grub_path = os.path.join(mntdir, 'boot', 'grub', 'i386-pc') if os.path.exists(grub_path): xorrisoargs.append('-m') xorrisoargs.append(grub_path) grub_path = os.path.join(tmpdir, 'boot', 'grub', 'i386-pc') os.makedirs(grub_path) for name in ['boot.img', 'core.img']: with open(os.path.join(grub_path, name), 'w'): pass #include EFI binaries if os.path.exists(os.path.join(mntdir, 'efi.factory')) and \ not os.path.exists(os.path.join(mntdir, 'efi')): xorrisoargs.append('-m') xorrisoargs.append('efi.factory') shutil.copytree(os.path.join(mntdir, 'efi.factory'), os.path.join(tmpdir, 'efi')) #if no bootstrap in RP, we'll put it in the initrd bootstrap_initrd = not os.path.exists(os.path.join(mntdir, 'scripts', 'bootstrap.sh')) #Renerate UUID os.mkdir(os.path.join(tmpdir, '.disk')) os.mkdir(os.path.join(tmpdir, 'casper')) self.start_pulsable_progress_thread(_('Regenerating UUID / Rebuilding initramfs')) (old_initrd, old_uuid) = create_new_uuid(os.path.join(mntdir, 'casper'), os.path.join(mntdir, '.disk'), os.path.join(tmpdir, 'casper'), os.path.join(tmpdir, '.disk'), new_compression="auto", include_bootstrap=bootstrap_initrd) self.stop_progress_thread() xorrisoargs.append('-m') xorrisoargs.append(os.path.join('.disk', old_uuid)) xorrisoargs.append('-m') xorrisoargs.append(os.path.join('casper', old_initrd)) #Renew .disk/ubuntu_dist_channel for ubuntu-report ubuntu_dist_channel = os.path.join(mntdir, '.disk', 'ubuntu_dist_channel') if os.path.exists(ubuntu_dist_channel) and platform and revision: xorrisoargs.append('-m') xorrisoargs.append(ubuntu_dist_channel) with open(os.path.join(tmpdir, '.disk', 'ubuntu_dist_channel'), 'w') as target, \ open(ubuntu_dist_channel) as source: for line in source: if line.startswith('canonical-oem-somerville-') and \ not line.strip().endswith('+' + platform + '+' + revision): target.write(line.strip() + '+' + platform + '+' + revision + '\n') else: target.write(line) #Restore .disk/info info_path = os.path.join(mntdir, '.disk', 'info.recovery') if os.path.exists(info_path): xorrisoargs.append('-m') xorrisoargs.append(info_path) shutil.copy(info_path, os.path.join(tmpdir, '.disk', 'info')) #if we have any any ISO/USB bootable bootloader on the image, copy in a theme grub_theme = False for topdir in [mntdir, tmpdir]: if os.path.exists(os.path.join(topdir, 'boot', 'grub', 'x86_64-efi')): grub_theme = True if grub_theme: if not os.path.exists(os.path.join(tmpdir, 'boot', 'grub')): os.makedirs(os.path.join(tmpdir, 'boot', 'grub')) #conffiles shutil.copy('/usr/share/dell/grub/theme/grub.cfg', os.path.join(tmpdir, 'boot', 'grub', 'grub.cfg')) xorrisoargs.append('-m') xorrisoargs.append(os.path.join(mntdir,'boot/grub/grub.cfg')) directory = os.path.join(mntdir, 'boot', 'grub', 'x86-64_efi') if os.path.exists(directory): if not os.path.exists(os.path.join(tmpdir, 'boot', 'grub', 'x86_64-efi')): os.makedirs(os.path.join(tmpdir, 'boot', 'grub', 'x86_64-efi')) shutil.copy('/usr/share/dell/grub/theme/%s/grub.cfg' % 'x86_64-efi', os.path.join(tmpdir, 'boot', 'grub', 'x86_64-efi', 'grub.cfg')) xorrisoargs.append('-m') xorrisoargs.append(os.path.join(mntdir,'boot/grub/%s/grub.cfg' % 'x86_64-efi')) #theme if not os.path.exists(os.path.join(mntdir, 'boot', 'grub', 'dell')): shutil.copytree('/usr/share/dell/grub/theme/dell', os.path.join(tmpdir, 'boot', 'grub', 'dell')) #fonts if not os.path.exists(os.path.join(mntdir, 'boot', 'grub', 'dejavu-sans-12.pf2')): ret = subprocess.call(['grub-mkfont', '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf', '-s=12', '--output=%s' % os.path.join(tmpdir, 'boot', 'grub', 'dejavu-sans-12.pf2')]) if ret is not 0: raise CreateFailed("Creating GRUB fonts failed.") if not os.path.exists(os.path.join(mntdir, 'boot', 'grub', 'dejavu-sans-bold-14.pf2')): ret = subprocess.call(['grub-mkfont', '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf', '-s=14', '--output=%s' % os.path.join(tmpdir, 'boot', 'grub', 'dejavu-sans-bold-14.pf2')]) if ret is not 0: raise CreateFailed("Creating GRUB fonts failed.") #if we previously backed up a grub.cfg or common.cfg for path in ['factory/grub.cfg', 'factory/common.cfg']: if os.path.exists(os.path.join(mntdir, path + '.old')): xorrisoargs.append('-m') xorrisoargs.append(os.path.join(mntdir, path) + '*') if not os.path.exists(os.path.join(tmpdir, 'factory')): os.makedirs(os.path.join(tmpdir, 'factory')) shutil.copy(os.path.join(mntdir, path + '.old'), os.path.join(tmpdir, path)) #regenerate md5sum file if os.path.exists(os.path.join(mntdir, 'md5sum.txt')): xorrisoargs.append('-m') xorrisoargs.append(os.path.join(mntdir, 'md5sum.txt')) regenerate_md5sum(tmpdir, mntdir) #ignore any failures on disk if os.path.exists(os.path.join(mntdir, 'factory', 'grubenv')): xorrisoargs.append('-m') xorrisoargs.append(os.path.join(mntdir, 'factory', 'grubenv')) #Directories to install xorrisoargs.append(tmpdir + '/') xorrisoargs.append(mntdir + '/') #ISO Creation seg1 = subprocess.Popen(xorrisoargs, stderr=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True) pipe = seg1.stderr fcntl.fcntl( pipe.fileno(), fcntl.F_SETFL, fcntl.fcntl(pipe.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK) retval = seg1.poll() logging.debug(" create_ubuntu: xorriso debug") while (retval is None): readx = select.select([pipe.fileno()], [], [])[0] if readx: output = pipe.read() if output.strip(): logging.debug(output.strip()) split = output.split() if (len(split) > 4): progress = split[4] if (progress[-1:] == '%'): self.report_progress(_('Building ISO'), progress[:-1]) retval = seg1.poll() if retval is not 0: logging.error(" create_ubuntu: xorriso exited with a nonstandard return value.") logging.error(" cmd: %s" % xorrisoargs) logging.error(" stderror: %s" % pipe.readlines()) logging.error(" error: %s" % output.strip()) raise CreateFailed("ISO Building exited unexpectedly:\n%s" % output.strip())
def create_ubuntu(self, recovery, version, iso, sender=None, conn=None): """Creates Ubuntu compatible recovery media""" self._reset_timeout() self._check_polkit_privilege(sender, conn, 'com.dell.recoverymedia.create') logging.debug("create_ubuntu: recovery %s, version %s, iso %s" % (recovery, version, iso)) #create temporary workspace tmpdir = tempfile.mkdtemp() atexit.register(walk_cleanup, tmpdir) #mount the recovery partition mntdir = self.request_mount(recovery, "r", sender, conn) #validate that ubuntu is on the partition if not os.path.exists(os.path.join(mntdir, '.disk', 'info')) and \ not os.path.exists(os.path.join(mntdir, '.disk', 'info.recovery')): logging.warning( "create_ubuntu: recovery partition missing .disk/info and .disk/info.recovery" ) if os.path.exists(os.path.join(mntdir, 'bootmgr')): raise CreateFailed( "This tool can not create a recovery image from a Windows recovery partition." ) raise CreateFailed( "Recovery partition is missing critical ubuntu files.") #test for an updated dell recovery deb to put in try: self._test_for_new_dell_recovery(mntdir, tmpdir) except: raise CreateFailed( "Error injecting updated Dell Recovery into image.") #check for a nested ISO image if os.path.exists(os.path.join(mntdir, 'ubuntu.iso')): pattern = re.compile('^ubuntu.iso|^.disk') w_size = black_tree("size", pattern, mntdir) self.start_sizable_progress_thread(_('Preparing nested image'), tmpdir, w_size) black_tree("copy", pattern, mntdir, tmpdir) self.stop_progress_thread() mntdir = self.request_mount(os.path.join(mntdir, 'ubuntu.iso'), "r", sender, conn) #Generate BTO XML File self.xml_obj.replace_node_contents('date', str(datetime.date.today())) self.xml_obj.replace_node_contents('iso', version) self.xml_obj.replace_node_contents('generator', check_version()) self.xml_obj.write_xml(os.path.join(tmpdir, 'bto.xml')) #Arg list xorrisoargs = [ 'xorriso', '-as', 'mkisofs', '-R', '-r', '-J', '-joliet-long', '-l', '-cache-inodes', '-iso-level', '3', '-A', 'Dell Recovery', '-p', 'Dell', '-publisher', 'Dell', '-o', iso, '-m', '*.exe', '-m', '*.sys', '-m', 'syslinux', '-m', 'syslinux.cfg', '-m', os.path.join(mntdir, 'bto.xml'), '-m', os.path.join(mntdir, 'isolinux'), '-m', os.path.join(mntdir, 'bto_version') ] #include bootloader as eltorito if we have it if os.path.exists(os.path.join(mntdir, 'boot', 'efi.img')): xorrisoargs.append('-e') xorrisoargs.append('boot/efi.img') xorrisoargs.append('-no-emul-boot') xorrisoargs.append('-append_partition') xorrisoargs.append('2') xorrisoargs.append('0xef') xorrisoargs.append(os.path.join(mntdir, 'boot', 'efi.img')) xorrisoargs.append('-partition_cyl_align') xorrisoargs.append('all') #disable 32 bit bootloader if it was there. grub_path = os.path.join(mntdir, 'boot', 'grub', 'i386-pc') if os.path.exists(grub_path): xorrisoargs.append('-m') xorrisoargs.append(grub_path) grub_path = os.path.join(tmpdir, 'boot', 'grub', 'i386-pc') os.makedirs(grub_path) for name in ['boot.img', 'core.img']: with open(os.path.join(grub_path, name), 'w'): pass #include EFI binaries if os.path.exists(os.path.join(mntdir, 'efi.factory')) and \ not os.path.exists(os.path.join(mntdir, 'efi')): xorrisoargs.append('-m') xorrisoargs.append('efi.factory') shutil.copytree(os.path.join(mntdir, 'efi.factory'), os.path.join(tmpdir, 'efi')) #if no bootstrap in RP, we'll put it in the initrd bootstrap_initrd = not os.path.exists( os.path.join(mntdir, 'scripts', 'bootstrap.sh')) #Renerate UUID os.mkdir(os.path.join(tmpdir, '.disk')) os.mkdir(os.path.join(tmpdir, 'casper')) self.start_pulsable_progress_thread( _('Regenerating UUID / Rebuilding initramfs')) (old_initrd, old_uuid) = create_new_uuid(os.path.join(mntdir, 'casper'), os.path.join(mntdir, '.disk'), os.path.join(tmpdir, 'casper'), os.path.join(tmpdir, '.disk'), new_compression="auto", include_bootstrap=bootstrap_initrd) self.stop_progress_thread() xorrisoargs.append('-m') xorrisoargs.append(os.path.join('.disk', old_uuid)) xorrisoargs.append('-m') xorrisoargs.append(os.path.join('casper', old_initrd)) #Restore .disk/info info_path = os.path.join(mntdir, '.disk', 'info.recovery') if os.path.exists(info_path): xorrisoargs.append('-m') xorrisoargs.append(info_path) shutil.copy(info_path, os.path.join(tmpdir, '.disk', 'info')) #if we have any any ISO/USB bootable bootloader on the image, copy in a theme grub_theme = False for topdir in [mntdir, tmpdir]: if os.path.exists( os.path.join(topdir, 'boot', 'grub', 'x86_64-efi')): grub_theme = True if grub_theme: if not os.path.exists(os.path.join(tmpdir, 'boot', 'grub')): os.makedirs(os.path.join(tmpdir, 'boot', 'grub')) #conffiles shutil.copy('/usr/share/dell/grub/theme/grub.cfg', os.path.join(tmpdir, 'boot', 'grub', 'grub.cfg')) xorrisoargs.append('-m') xorrisoargs.append(os.path.join(mntdir, 'boot/grub/grub.cfg')) directory = os.path.join(mntdir, 'boot', 'grub', 'x86-64_efi') if os.path.exists(directory): if not os.path.exists( os.path.join(tmpdir, 'boot', 'grub', 'x86_64-efi')): os.makedirs( os.path.join(tmpdir, 'boot', 'grub', 'x86_64-efi')) shutil.copy( '/usr/share/dell/grub/theme/%s/grub.cfg' % 'x86_64-efi', os.path.join(tmpdir, 'boot', 'grub', 'x86_64-efi', 'grub.cfg')) xorrisoargs.append('-m') xorrisoargs.append( os.path.join(mntdir, 'boot/grub/%s/grub.cfg' % 'x86_64-efi')) #theme if not os.path.exists(os.path.join(mntdir, 'boot', 'grub', 'dell')): shutil.copytree('/usr/share/dell/grub/theme/dell', os.path.join(tmpdir, 'boot', 'grub', 'dell')) #fonts if not os.path.exists( os.path.join(mntdir, 'boot', 'grub', 'dejavu-sans-12.pf2')): ret = subprocess.call([ 'grub-mkfont', '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf', '-s=12', '--output=%s' % os.path.join(tmpdir, 'boot', 'grub', 'dejavu-sans-12.pf2') ]) if ret is not 0: raise CreateFailed("Creating GRUB fonts failed.") if not os.path.exists( os.path.join(mntdir, 'boot', 'grub', 'dejavu-sans-bold-14.pf2')): ret = subprocess.call([ 'grub-mkfont', '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf', '-s=14', '--output=%s' % os.path.join(tmpdir, 'boot', 'grub', 'dejavu-sans-bold-14.pf2') ]) if ret is not 0: raise CreateFailed("Creating GRUB fonts failed.") #if we previously backed up a grub.cfg or common.cfg for path in ['factory/grub.cfg', 'factory/common.cfg']: if os.path.exists(os.path.join(mntdir, path + '.old')): xorrisoargs.append('-m') xorrisoargs.append(os.path.join(mntdir, path) + '*') if not os.path.exists(os.path.join(tmpdir, 'factory')): os.makedirs(os.path.join(tmpdir, 'factory')) shutil.copy(os.path.join(mntdir, path + '.old'), os.path.join(tmpdir, path)) #regenerate md5sum file if os.path.exists(os.path.join(mntdir, 'md5sum.txt')): xorrisoargs.append('-m') xorrisoargs.append(os.path.join(mntdir, 'md5sum.txt')) regenerate_md5sum(tmpdir, mntdir) #Directories to install xorrisoargs.append(tmpdir + '/') xorrisoargs.append(mntdir + '/') #ISO Creation seg1 = subprocess.Popen(xorrisoargs, stderr=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True) pipe = seg1.stderr fcntl.fcntl(pipe.fileno(), fcntl.F_SETFL, fcntl.fcntl(pipe.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK) retval = seg1.poll() logging.debug(" create_ubuntu: xorriso debug") while (retval is None): readx = select.select([pipe.fileno()], [], [])[0] if readx: output = pipe.read() if output.strip(): logging.debug(output.strip()) split = output.split() if (len(split) > 4): progress = split[4] if (progress[-1:] == '%'): self.report_progress(_('Building ISO'), progress[:-1]) retval = seg1.poll() if retval is not 0: logging.error( " create_ubuntu: xorriso exited with a nonstandard return value." ) logging.error(" cmd: %s" % xorrisoargs) logging.error(" stderror: %s" % pipe.readlines()) logging.error(" error: %s" % output.strip()) raise CreateFailed("ISO Building exited unexpectedly:\n%s" % output.strip())