def restore_file(src_base, f, d=None): if not d: d = f src = os.path.join(src_base, f) dst = os.path.join(mounts['root'], d) if os.path.exists(src): xelogging.log("Restoring /%s" % f) util.assertDir(os.path.dirname(dst)) if os.path.isdir(src): util.runCmd2(['cp', '-a', src, os.path.dirname(dst)]) else: util.runCmd2(['cp', '-a', src, dst]) abs_f = os.path.join('/', f) abs_d = os.path.join('/', d) copy_ownership(src_base, abs_f, mounts['root'], abs_d) for dirpath, dirnames, filenames in os.walk(src): for i in dirnames + filenames: src_path = os.path.join(dirpath, i)[len(src_base):] dst_path = os.path.join(abs_d, src_path[len(abs_f) + 1:]) copy_ownership(src_base, src_path, mounts['root'], dst_path) else: xelogging.log( "WARNING: /%s did not exist in the backup image." % f)
def run_script(script, stage, *args): xelogging.log("Running script for stage %s: %s %s" % (stage, script, " ".join(args))) util.assertDir(constants.SCRIPTS_DIR) fd, local_name = tempfile.mkstemp(prefix=stage, dir=constants.SCRIPTS_DIR) try: util.fetchFile(script, local_name) # check the interpreter fh = os.fdopen(fd) fh.seek(0) line = fh.readline(40) fh.close() except: raise RuntimeError, "Unable to fetch script %s" % script if not line.startswith("#!"): raise RuntimeError, "Missing interpreter in %s." % script interp = line[2:].split() if interp[0] == "/usr/bin/env": if len(interp) < 2 or interp[1] not in ["python"]: raise RuntimeError, "Invalid interpreter %s in." % (interp[1], script) elif interp[0] not in ["/bin/sh", "/bin/bash", "/usr/bin/python"]: raise RuntimeError, "Invalid interpreter %s in %s." % (interp[0], script) cmd = [local_name] cmd.extend(args) os.chmod(local_name, stat.S_IRUSR | stat.S_IXUSR) os.environ["XS_STAGE"] = stage rc, out, err = util.runCmd2(cmd, with_stdout=True, with_stderr=True) xelogging.log("Script returned %d" % rc) # keep script, will be collected in support tarball return rc, out, err
def run_script(script, stage, *args): xelogging.log("Running script for stage %s: %s %s" % (stage, script, ' '.join(args))) util.assertDir(constants.SCRIPTS_DIR) fd, local_name = tempfile.mkstemp(prefix = stage, dir = constants.SCRIPTS_DIR) try: util.fetchFile(script, local_name) # check the interpreter fh = os.fdopen(fd) fh.seek(0) line = fh.readline(40) fh.close() except: raise RuntimeError, "Unable to fetch script %s" % script if not line.startswith('#!'): raise RuntimeError, "Missing interpreter in %s." % script interp = line[2:].split() if interp[0] == '/usr/bin/env': if len (interp) < 2 or interp[1] not in ['python']: raise RuntimeError, "Invalid interpreter %s in %s." % (interp[1], script) elif interp[0] not in ['/bin/sh', '/bin/bash', '/usr/bin/python']: raise RuntimeError, "Invalid interpreter %s in %s." % (interp[0], script) cmd = [local_name] cmd.extend(args) os.chmod(local_name, stat.S_IRUSR | stat.S_IXUSR) os.environ['XS_STAGE'] = stage rc, out, err = util.runCmd2(cmd, with_stdout = True, with_stderr = True) xelogging.log("Script returned %d" % rc) # keep script, will be collected in support tarball return rc, out, err
def completeUpgrade(self, mounts, prev_install, target_disk, backup_partnum, logs_partnum, admin_iface, admin_bridge, admin_config): util.assertDir(os.path.join(mounts['root'], "var/lib/xcp")) util.assertDir(os.path.join(mounts['root'], "etc/xensource")) Upgrader.completeUpgrade(self, mounts, target_disk, backup_partnum) v = Version(prev_install.version.ver) f = open(os.path.join(mounts['root'], 'var/tmp/.previousVersion'), 'w') f.write("PLATFORM_VERSION='%s'\n" % v) f.close() state = open( os.path.join(mounts['root'], constants.FIRSTBOOT_DATA_DIR, 'host.conf'), 'w') print >> state, "UPGRADE=true" state.close() # The existence of the static-rules.conf is used to detect upgrade from Boston or newer if os.path.exists( os.path.join( mounts['root'], 'etc/sysconfig/network-scripts/interface-rename-data/static-rules.conf' )): # CA-82901 - convert any old style ppn referenced to new style ppn references util.runCmd2([ 'sed', r's/pci\([0-9]\+p[0-9]\+\)/p\1/g', '-i', os.path.join( mounts['root'], 'etc/sysconfig/network-scripts/interface-rename-data/static-rules.conf' ) ]) net_dict = util.readKeyValueFile( os.path.join(mounts['root'], 'etc/sysconfig/network')) if net_dict.get('NETWORKING_IPV6', 'no') == 'no': nfd = open(os.path.join(mounts['root'], 'etc/sysconfig/network'), 'a') nfd.write("NETWORKING_IPV6=no\n") nfd.close() netutil.disable_ipv6_module(mounts["root"]) # handle the conversion of devices from aacraid to smartpqi primary_disk = self.source.getInventoryValue("PRIMARY_DISK") target_link = diskutil.idFromPartition(target_disk) or target_disk if primary_disk.startswith('/dev/disk/by-id/scsi-') and \ target_link.startswith('/dev/disk/by-id/scsi-') and \ primary_disk != target_link: for i in (os.path.join(constants.FIRSTBOOT_DATA_DIR, 'default-storage.conf'), constants.XAPI_DB): util.runCmd2([ 'sed', '-i', '-e', "s#%s#%s#g" % (primary_disk, target_link), os.path.join(mounts['root'], i) ])
def restore_file(src_base, f, d = None): if not d: d = f src = os.path.join(src_base, f) dst = os.path.join(mounts['root'], d) if os.path.exists(src): xelogging.log("Restoring /%s" % f) if os.path.isdir(src): util.runCmd2(['cp', '-rp', src, os.path.dirname(dst)]) else: util.assertDir(os.path.dirname(dst)) util.runCmd2(['cp', '-p', src, dst]) else: xelogging.log("WARNING: /%s did not exist in the backup image." % f)
def completeUpgrade(self, mounts, prev_install, target_disk, backup_partnum, admin_iface, admin_bridge, admin_config): util.assertDir(os.path.join(mounts['root'], "var/lib/xcp")) util.assertDir(os.path.join(mounts['root'], "etc/xensource")) Upgrader.completeUpgrade(self, mounts, target_disk, backup_partnum) v = Version(prev_install.version.ver) f = open(os.path.join(mounts['root'], 'var/tmp/.previousVersion'), 'w') f.write("PLATFORM_VERSION='%s'\n" % v) f.close() state = open( os.path.join(mounts['root'], constants.FIRSTBOOT_DATA_DIR, 'host.conf'), 'w') print >> state, "UPGRADE=true" state.close() # The existence of the static-rules.conf is used to detect upgrade from Boston or newer if os.path.exists( os.path.join( mounts['root'], 'etc/sysconfig/network-scripts/interface-rename-data/static-rules.conf' )): # CA-82901 - convert any old style ppn referenced to new style ppn references util.runCmd2([ 'sed', r's/pci\([0-9]\+p[0-9]\+\)/p\1/g', '-i', os.path.join( mounts['root'], 'etc/sysconfig/network-scripts/interface-rename-data/static-rules.conf' ) ]) net_dict = util.readKeyValueFile( os.path.join(mounts['root'], 'etc/sysconfig/network')) if 'NETWORKING_IPV6' not in net_dict: nfd = open(os.path.join(mounts['root'], 'etc/sysconfig/network'), 'a') nfd.write("NETWORKING_IPV6=no\n") nfd.close() netutil.disable_ipv6_module(mounts["root"]) # handle the conversion of HP Gen6 controllers from cciss to scsi primary_disk = self.source.getInventoryValue("PRIMARY_DISK") target_link = diskutil.idFromPartition(target_disk) or target_disk if 'cciss' in primary_disk and 'scsi' in target_link: util.runCmd2([ 'sed', '-i', '-e', "s#%s#%s#g" % (primary_disk, target_link), os.path.join(mounts['root'], constants.FIRSTBOOT_DATA_DIR, 'default-storage.conf') ]) util.runCmd2([ 'sed', '-i', '-e', "s#%s#%s#g" % (primary_disk, target_link), os.path.join(mounts['root'], constants.XAPI_DB) ]) # handle the conversion of RAID devices from /dev/md_* to /dev/disk/by-id/md-uuid-* if primary_disk.startswith('/dev/md_') and target_link.startswith( '/dev/disk/by-id/md-uuid-'): for i in (os.path.join(constants.FIRSTBOOT_DATA_DIR, 'default-storage.conf'), constants.XAPI_DB): # First convert partitions from *pN to *-partN util.runCmd2([ 'sed', '-i', '-e', "s#\(%s\)p\([[:digit:]]\+\)#\\1-part\\2#g" % primary_disk, os.path.join(mounts['root'], i) ]) # Then conert from /dev/md_* to /dev/disk/by-id/md-uuid-* util.runCmd2([ 'sed', '-i', '-e', "s#%s#%s#g" % (primary_disk, target_link), os.path.join(mounts['root'], i) ]) # handle the conversion of devices from scsi-* links to ata-* links if primary_disk.startswith( '/dev/disk/by-id/scsi-') and target_link.startswith( '/dev/disk/by-id/ata-'): for i in (os.path.join(constants.FIRSTBOOT_DATA_DIR, 'default-storage.conf'), constants.XAPI_DB): util.runCmd2([ 'sed', '-i', '-e', "s#%s#%s#g" % (primary_disk, target_link), os.path.join(mounts['root'], i) ])
def completeUpgrade(self, mounts, prev_install, target_disk, backup_partnum, admin_iface, admin_bridge, admin_config): util.assertDir(os.path.join(mounts['root'], "var/xapi")) util.assertDir(os.path.join(mounts['root'], "etc/xensource")) Upgrader.completeUpgrade(self, mounts, target_disk, backup_partnum) if not os.path.exists(os.path.join(mounts['root'], constants.DBCACHE)): # upgrade from 5.5, generate dbcache save_dir = os.path.join(mounts['root'], constants.FIRSTBOOT_DATA_DIR, 'initial-ifcfg') util.assertDir(save_dir) dbcache_file = os.path.join(mounts['root'], constants.DBCACHE) dbcache_fd = open(dbcache_file, 'w') network_uid = util.getUUID() dbcache_fd.write('<?xml version="1.0" ?>\n<xenserver-network-configuration>\n') if admin_iface.startswith('bond'): top_pif_uid = bond_pif_uid = util.getUUID() bond_uid = util.getUUID() # find slaves of this bond and write PIFs for them slaves = [] for file in [ f for f in os.listdir(os.path.join(mounts['root'], constants.NET_SCR_DIR)) if re.match('ifcfg-eth[0-9]+$', f) ]: slavecfg = util.readKeyValueFile(os.path.join(mounts['root'], constants.NET_SCR_DIR, file), strip_quotes = False) if slavecfg.has_key('MASTER') and slavecfg['MASTER'] == admin_iface: slave_uid = util.getUUID() slave_net_uid = util.getUUID() slaves.append(slave_uid) slave = NetInterface.loadFromIfcfg(os.path.join(mounts['root'], constants.NET_SCR_DIR, file)) slave.writePif(slavecfg['DEVICE'], dbcache_fd, slave_uid, slave_net_uid, ('slave-of', bond_uid)) # locate bridge that has this interface as its PIFDEV bridge = None for file in [ f for f in os.listdir(os.path.join(mounts['root'], constants.NET_SCR_DIR)) if re.match('ifcfg-xenbr[0-9]+$', f) ]: brcfg = util.readKeyValueFile(os.path.join(mounts['root'], constants.NET_SCR_DIR, file), strip_quotes = False) if brcfg.has_key('PIFDEV') and brcfg['PIFDEV'] == slavecfg['DEVICE']: bridge = brcfg['DEVICE'] break assert bridge dbcache_fd.write('\t<network ref="OpaqueRef:%s">\n' % slave_net_uid) dbcache_fd.write('\t\t<uuid>%sSlaveNetwork</uuid>\n' % slavecfg['DEVICE']) dbcache_fd.write('\t\t<PIFs>\n\t\t\t<PIF>OpaqueRef:%s</PIF>\n\t\t</PIFs>\n' % slave_uid) dbcache_fd.write('\t\t<bridge>%s</bridge>\n' % bridge) dbcache_fd.write('\t\t<other_config/>\n\t</network>\n') # write bond dbcache_fd.write('\t<bond ref="OpaqueRef:%s">\n' % bond_uid) dbcache_fd.write('\t\t<master>OpaqueRef:%s</master>\n' % bond_pif_uid) dbcache_fd.write('\t\t<uuid>InitialManagementBond</uuid>\n\t\t<slaves>\n') for slave_uid in slaves: dbcache_fd.write('\t\t\t<slave>OpaqueRef:%s</slave>\n' % slave_uid) dbcache_fd.write('\t\t</slaves>\n\t</bond>\n') # write bond PIF admin_config.writePif(admin_iface, dbcache_fd, bond_pif_uid, network_uid, ('master-of', bond_uid)) else: top_pif_uid = util.getUUID() # write PIF admin_config.writePif(admin_iface, dbcache_fd, top_pif_uid, network_uid) dbcache_fd.write('\t<network ref="OpaqueRef:%s">\n' % network_uid) dbcache_fd.write('\t\t<uuid>InitialManagementNetwork</uuid>\n') dbcache_fd.write('\t\t<PIFs>\n\t\t\t<PIF>OpaqueRef:%s</PIF>\n\t\t</PIFs>\n' % top_pif_uid) dbcache_fd.write('\t\t<bridge>%s</bridge>\n' % admin_bridge) dbcache_fd.write('\t\t<other_config/>\n\t</network>\n') dbcache_fd.write('</xenserver-network-configuration>\n') dbcache_fd.close() util.runCmd2(['cp', '-p', dbcache_file, save_dir]) else: # upgrade from 5.6 changed = False dbcache_file = os.path.join(mounts['root'], constants.DBCACHE) rdbcache_fd = open(dbcache_file) wdbcache_fd = open(dbcache_file + '.new', 'w') for line in rdbcache_fd: wdbcache_fd.write(line) if '<pif ref=' in line: wdbcache_fd.write("\t\t<tunnel_access_PIF_of/>\n") changed = True rdbcache_fd.close() wdbcache_fd.close() if changed: os.rename(dbcache_file + '.new', dbcache_file) else: os.remove(dbcache_file + '.new') v = Version(prev_install.version.ver) f = open(os.path.join(mounts['root'], 'var/tmp/.previousVersion'), 'w') f.write("PRODUCT_VERSION='%s'\n" % v) f.close() state = open(os.path.join(mounts['root'], constants.FIRSTBOOT_DATA_DIR, 'host.conf'), 'w') print >>state, "UPGRADE=true" state.close() # CP-1508: preserve AD service state ad_on = False try: fh = open(os.path.join(mounts['root'], 'etc/nsswitch.conf'), 'r') for line in fh: if line.startswith('passwd:') and 'lsass' in line: ad_on = True break fh.close() except: pass if ad_on: for service in ['dcerpd', 'eventlogd', 'netlogond', 'npcmuxd', 'lsassd']: util.runCmd2(['chroot', mounts['root'], 'chkconfig', '--add', service]) # EA-1069: create interface-rename state from old xapi database if it doesnt currently exist (static-rules.conf) if not os.path.exists(os.path.join(mounts['root'], 'etc/sysconfig/network-scripts/interface-rename-data/static-rules.conf')): static_text = ( "# Static rules. Autogenerated by the installer from either the answerfile or from previous install\n" "# WARNING - rules in this file override the 'lastboot' assignment of names,\n" "# so editing it may cause unexpected renaming on next boot\n\n" "# Rules are of the form:\n" "# target name: id method = \"value\"\n\n" "# target name must be in the form eth*\n" "# id methods are:\n" "# mac: value should be the mac address of a device (e.g. DE:AD:C0:DE:00:00)\n" "# pci: value should be the pci bus location of the device (e.g. 0000:01:01.1)\n" "# ppn: value should be the result of the biosdevname physical naming policy of a device (e.g. pci1p1)\n" "# label: value should be the SMBios label of a device (for SMBios 2.6 or above)\n") if not os.path.exists(os.path.join(mounts['root'], 'etc/sysconfig/network-scripts/interface-rename-data/.from_install/')): os.makedirs(os.path.join(mounts['root'], 'etc/sysconfig/network-scripts/interface-rename-data/.from_install/'), 0775) fout1 = open(os.path.join(mounts['root'], 'etc/sysconfig/network-scripts/interface-rename-data/static-rules.conf'), "w") fout1.write(static_text) fout1.close() fout2 = open(os.path.join(mounts['root'], 'etc/sysconfig/network-scripts/interface-rename-data/.from_install/static-rules.conf'), "w") fout2.write(static_text) fout2.close() bdn = BiosDevName() bdn.run() devices = bdn.devices # this is a dirty hack but I cant think of much better dbcache = open(os.path.join(mounts['root'], constants.DBCACHE), "r") past_devs = [] mac_next = False eth_next = False for line in ( x.strip() for x in dbcache ): if mac_next: past_devs.append([line.upper()]) mac_next = False continue if eth_next: for bdev in devices: if bdev.get('Assigned MAC', None) == past_devs[-1][0] and 'Bus Info' in bdev: past_devs[-1].extend([bdev['Bus Info'], line]) break eth_next = False continue if line == "<MAC>": mac_next = True continue if line == "<device>": eth_next = True dbcache.close() def jsonify(mac, pci, dev): return '[ "%s", "%s", "%s" ]' % (mac, pci, dev) dynamic_text = ("# Automatically adjusted file. Do not edit unless you are certain you know how to\n") dynamic_text += '{"lastboot":[%s],"old":[]}' % (','.join(map(lambda x: jsonify(*x), (x for x in past_devs if len(x) == 3))), ) fout3 = open(os.path.join(mounts['root'], 'etc/sysconfig/network-scripts/interface-rename-data/dynamic-rules.json'), "w") fout3.write(dynamic_text) fout3.close() fout4 = open(os.path.join(mounts['root'], 'etc/sysconfig/network-scripts/interface-rename-data/.from_install/dynamic-rules.json'), "w") fout4.write(dynamic_text) fout4.close() if Version(prev_install.version.ver) < product.THIS_PRODUCT_VERSION: # set journalling option on EXT local SRs l = LVMTool() for lv in l.lvs: if lv['vg_name'].startswith(l.VG_EXT_SR_PREFIX): l.activateVG(lv['vg_name']) path = '/dev/mapper/%s-%s' % (lv['vg_name'].replace('-', '--'), lv['lv_name'].replace('-', '--')) xelogging.log("Setting ordered on " + path) util.runCmd2(['tune2fs', '-o', 'journal_data_ordered', path]) l.deactivateVG(lv['vg_name'])
def restoreFromBackup(backup, progress=lambda x: ()): """ Restore files from backup_partition to the root partition on disk. Call progress with a value between 0 and 100. Re-install bootloader. Fails if backup is not same version as the CD in use.""" label = None bootlabel = None disk = backup.root_disk tool = PartitionTool(disk) _, boot_partnum, primary_partnum, backup_partnum, logs_partnum, swap_partnum, _ = backend.inspectTargetDisk( disk, None, [], constants.PRESERVE_IF_UTILITY, True, True) backup_fs = util.TempMount(backup.partition, 'backup-', options=['ro']) inventory = util.readKeyValueFile(os.path.join(backup_fs.mount_point, constants.INVENTORY_FILE), strip_quotes=True) backup_partition_layout = inventory['PARTITION_LAYOUT'].split(',') backup_fs.unmount() xelogging.log("BACKUP DISK PARTITION LAYOUT: %s" % backup_partition_layout) backup_partition = backup.partition assert backup_partition.startswith('/dev/') assert disk.startswith('/dev/') restore_partition = partitionDevice(disk, primary_partnum) xelogging.log("Restoring to partition %s." % restore_partition) boot_part = tool.getPartition(boot_partnum) boot_device = partitionDevice(disk, boot_partnum) if boot_part else None efi_boot = boot_part and boot_part['id'] == GPTPartitionTool.ID_EFI_BOOT # determine current location of bootloader current_location = 'unknown' try: root_fs = util.TempMount(restore_partition, 'root-', options=['ro'], boot_device=boot_device) try: boot_config = bootloader.Bootloader.loadExisting( root_fs.mount_point) current_location = boot_config.location xelogging.log("Bootloader currently in %s" % current_location) finally: root_fs.unmount() except: pass # mount the backup fs backup_fs = util.TempMount(backup_partition, 'restore-backup-', options=['ro']) try: # extract the bootloader config boot_config = bootloader.Bootloader.loadExisting(backup_fs.mount_point) if boot_config.src_fmt == 'grub': raise RuntimeError, "Backup uses grub bootloader which is no longer supported - " + \ "to restore please use a version of the installer that matches the backup partition" # format the restore partition(s): try: util.mkfs(constants.rootfs_type, restore_partition) except Exception as e: raise RuntimeError("Failed to create root filesystem: %s" % e) if efi_boot: try: util.mkfs('vfat', boot_device) except Exception as e: raise RuntimeError("Failed to create boot filesystem: %s" % e) # mount restore partition: dest_fs = util.TempMount(restore_partition, 'restore-dest-') try: # copy files from the backup partition to the restore partition: objs = filter( lambda x: x not in ['lost+found', '.xen-backup-partition', '.xen-gpt.bin'], os.listdir(backup_fs.mount_point)) for i in range(len(objs)): obj = objs[i] xelogging.log("Restoring subtree %s..." % obj) progress((i * 100) / len(objs)) # Use 'cp' here because Python's copying tools are useless and # get stuck in an infinite loop when copying e.g. /dev/null. if util.runCmd2([ 'cp', '-a', os.path.join(backup_fs.mount_point, obj), dest_fs.mount_point ]) != 0: raise RuntimeError, "Failed to restore %s directory" % obj xelogging.log( "Data restoration complete. About to re-install bootloader.") location = boot_config.location m = re.search(r'root=LABEL=(\S+)', boot_config.menu[boot_config.default].kernel_args) if m: label = m.group(1) if location == constants.BOOT_LOCATION_PARTITION and current_location == constants.BOOT_LOCATION_MBR: # if bootloader in the MBR it's probably not safe to restore with it # on the partition xelogging.log( "Bootloader is currently installed to MBR, restoring to MBR instead of partition" ) location = constants.BOOT_LOCATION_MBR with open(os.path.join(backup_fs.mount_point, 'etc', 'fstab'), 'r') as fstab: for line in fstab: m = re.match(r'LABEL=(\S+)\s+/boot/efi\s', line) if m: bootlabel = m.group(1) mounts = { 'root': dest_fs.mount_point, 'boot': os.path.join(dest_fs.mount_point, 'boot') } # prepare extra mounts for installing bootloader: util.bindMount("/dev", "%s/dev" % dest_fs.mount_point) util.bindMount("/sys", "%s/sys" % dest_fs.mount_point) util.bindMount("/proc", "%s/proc" % dest_fs.mount_point) if boot_config.src_fmt == 'grub2': if efi_boot: branding = util.readKeyValueFile( os.path.join(backup_fs.mount_point, constants.INVENTORY_FILE)) branding['product-brand'] = branding['PRODUCT_BRAND'] backend.setEfiBootEntry(mounts, disk, boot_partnum, branding) else: if location == constants.BOOT_LOCATION_MBR: backend.installGrub2(mounts, disk, False) else: backend.installGrub2(mounts, restore_partition, True) else: backend.installExtLinux(mounts, disk, probePartitioningScheme(disk), location) # restore bootloader configuration dst_file = boot_config.src_file.replace(backup_fs.mount_point, dest_fs.mount_point, 1) util.assertDir(os.path.dirname(dst_file)) boot_config.commit(dst_file) finally: util.umount("%s/proc" % dest_fs.mount_point) util.umount("%s/sys" % dest_fs.mount_point) util.umount("%s/dev" % dest_fs.mount_point) dest_fs.unmount() finally: backup_fs.unmount() if not label: raise RuntimeError, "Failed to find label required for root filesystem." if efi_boot and not bootlabel: raise RuntimeError( "Failed to find label required for boot filesystem.") if util.runCmd2(['e2label', restore_partition, label]) != 0: raise RuntimeError, "Failed to label root partition" if bootlabel: if util.runCmd2(['fatlabel', boot_device, bootlabel]) != 0: raise RuntimeError, "Failed to label boot partition" if 'LOG' in backup_partition_layout: # From 7.x (new layout) to 7.x (new layout) tool.commitActivePartitiontoDisk(boot_partnum) rdm_label = label.split("-")[1] logs_part = partitionDevice(disk, logs_partnum) swap_part = partitionDevice(disk, swap_partnum) if util.runCmd2( ['e2label', logs_part, constants.logsfs_label % rdm_label]) != 0: raise RuntimeError, "Failed to label logs partition" if util.runCmd2([ 'swaplabel', '-L', constants.swap_label % rdm_label, swap_part ]) != 0: raise RuntimeError, "Failed to label swap partition"
def doRestore(backup, progress, backup_partition_layout, has_logs_partition): backup_partition = backup.partition backup_version = backup.version disk = backup.root_disk tool = PartitionTool(disk) _, boot_partnum, primary_partnum, backup_partnum, logs_partnum, swap_partnum, _ = backend.inspectTargetDisk( disk, None, [], constants.PRESERVE_IF_UTILITY, True, True) limit_version = product.THIS_PLATFORM_VERSION logs_partition = tool.getPartition(logs_partnum) boot_partition = tool.getPartition(boot_partnum) assert backup_partition.startswith('/dev/') assert disk.startswith('/dev/') label = None bootlabel = None if has_logs_partition and not backup_partition_layout: # From 7.x (new layout) to 6.x restore_partition = partitionDevice(disk, logs_partnum) else: restore_partition = partitionDevice(disk, primary_partnum) xelogging.log("Restoring to partition %s." % restore_partition) tool = PartitionTool(disk) boot_part = tool.getPartition(boot_partnum) boot_device = partitionDevice(disk, boot_partnum) if boot_part else None efi_boot = boot_part and boot_part['id'] == GPTPartitionTool.ID_EFI_BOOT # determine current location of bootloader current_location = 'unknown' try: root_fs = util.TempMount(restore_partition, 'root-', options=['ro'], boot_device=boot_device) try: boot_config = bootloader.Bootloader.loadExisting( root_fs.mount_point) current_location = boot_config.location xelogging.log("Bootloader currently in %s" % current_location) finally: root_fs.unmount() except: pass # mount the backup fs backup_fs = util.TempMount(backup_partition, 'restore-backup-', options=['ro']) try: # extract the bootloader config boot_config = bootloader.Bootloader.loadExisting(backup_fs.mount_point) if boot_config.src_fmt == 'grub': raise RuntimeError, "Backup uses grub bootloader which is no longer supported - " + \ "to restore please use a version of the installer that matches the backup partition" # format the restore partition(s): if util.runCmd2(['mkfs.%s' % constants.rootfs_type, restore_partition ]) != 0: raise RuntimeError, "Failed to create root filesystem" if efi_boot: if util.runCmd2(['mkfs.vfat', boot_device]) != 0: raise RuntimeError, "Failed to create boot filesystem" # mount restore partition: dest_fs = util.TempMount(restore_partition, 'restore-dest-') try: # copy files from the backup partition to the restore partition: objs = filter( lambda x: x not in ['lost+found', '.xen-backup-partition', '.xen-gpt.bin'], os.listdir(backup_fs.mount_point)) for i in range(len(objs)): obj = objs[i] xelogging.log("Restoring subtree %s..." % obj) progress((i * 100) / len(objs)) # Use 'cp' here because Python's copying tools are useless and # get stuck in an infinite loop when copying e.g. /dev/null. if util.runCmd2([ 'cp', '-a', os.path.join(backup_fs.mount_point, obj), dest_fs.mount_point ]) != 0: raise RuntimeError, "Failed to restore %s directory" % obj xelogging.log( "Data restoration complete. About to re-install bootloader.") location = boot_config.location m = re.search(r'root=LABEL=(\S+)', boot_config.menu[boot_config.default].kernel_args) if m: label = m.group(1) if location == constants.BOOT_LOCATION_PARTITION and current_location == constants.BOOT_LOCATION_MBR: # if bootloader in the MBR it's probably not safe to restore with it # on the partition xelogging.log( "Bootloader is currently installed to MBR, restoring to MBR instead of partition" ) location = constants.BOOT_LOCATION_MBR with open(os.path.join(backup_fs.mount_point, 'etc', 'fstab'), 'r') as fstab: for line in fstab: m = re.match(r'LABEL=(\S+)\s+/boot/efi\s', line) if m: bootlabel = m.group(1) mounts = { 'root': dest_fs.mount_point, 'boot': os.path.join(dest_fs.mount_point, 'boot') } # prepare extra mounts for installing bootloader: util.bindMount("/dev", "%s/dev" % dest_fs.mount_point) util.bindMount("/sys", "%s/sys" % dest_fs.mount_point) util.bindMount("/proc", "%s/proc" % dest_fs.mount_point) if boot_config.src_fmt == 'grub2': if efi_boot: branding = util.readKeyValueFile( os.path.join(backup_fs.mount_point, constants.INVENTORY_FILE)) branding['product-brand'] = branding['PRODUCT_BRAND'] backend.setEfiBootEntry(mounts, disk, boot_partnum, branding) else: if location == constants.BOOT_LOCATION_MBR: backend.installGrub2(mounts, disk, False) else: backend.installGrub2(mounts, restore_partition, True) else: backend.installExtLinux(mounts, disk, probePartitioningScheme(disk), location) # restore bootloader configuration dst_file = boot_config.src_file.replace(backup_fs.mount_point, dest_fs.mount_point, 1) util.assertDir(os.path.dirname(dst_file)) boot_config.commit(dst_file) finally: util.umount("%s/proc" % dest_fs.mount_point) util.umount("%s/sys" % dest_fs.mount_point) util.umount("%s/dev" % dest_fs.mount_point) dest_fs.unmount() finally: backup_fs.unmount() if not label: raise RuntimeError, "Failed to find label required for root filesystem." if efi_boot and not bootlabel: raise RuntimeError( "Failed to find label required for boot filesystem.") if util.runCmd2(['e2label', restore_partition, label]) != 0: raise RuntimeError, "Failed to label root partition" if bootlabel: if util.runCmd2(['fatlabel', boot_device, bootlabel]) != 0: raise RuntimeError, "Failed to label boot partition" if has_logs_partition: if not backup_partition_layout: # From 7.x (new layout) to 6.x # Delete backup, dom0, Boot and swap partitions tool.deletePartition(backup_partnum) tool.deletePartition(primary_partnum) tool.deletePartition(boot_partnum) tool.deletePartition(swap_partnum) # Rename logs partition to be n.1 tool.renamePartition(srcNumber=logs_partnum, destNumber=primary_partnum, overwrite=False) # Create 4GB backup partition tool.createPartition( tool.ID_LINUX, sizeBytes=constants.backup_size_old * 2**20, startBytes=tool.partitionEnd(primary_partnum) + tool.sectorSize, number=backup_partnum) # Commit partition table and mark dom0 disk as bootable tool.commit(log=True) tool.commitActivePartitiontoDisk(primary_partnum) xelogging.log("Bootloader restoration complete.") xelogging.log("Restore successful.") backend.writeLog(disk, primary_partnum, logs_partnum) elif 'LOG' in backup_partition_layout: # From 7.x (new layout) to 7.x (new layout) tool.commitActivePartitiontoDisk(boot_partnum) rdm_label = label.split("-")[1] logs_part = partitionDevice(disk, logs_partnum) swap_part = partitionDevice(disk, swap_partnum) if util.runCmd2([ 'e2label', logs_part, constants.logsfs_label % rdm_label ]) != 0: raise RuntimeError, "Failed to label logs partition" if util.runCmd2([ 'swaplabel', '-L', constants.swap_label % rdm_label, swap_part ]) != 0: raise RuntimeError, "Failed to label swap partition"
def restoreWithoutRepartButUEFI(backup, progress): backup_partition = backup.partition disk = backup.root_disk assert backup_partition.startswith('/dev/') assert disk.startswith('/dev/') # Restore the partition layout backup_fs = util.TempMount(backup_partition, 'restore-backup-', options=['ro']) gpt_bin = None try: src_bin = os.path.join(backup_fs.mount_point, '.xen-gpt.bin') if os.path.exists(src_bin): gpt_bin = tempfile.mktemp() shutil.copyfile(src_bin, gpt_bin) finally: backup_fs.unmount() if gpt_bin: xelogging.log("Restoring partition layout") rc, err = util.runCmd2(["sgdisk", "-l", gpt_bin, disk], with_stderr=True) if rc != 0: raise RuntimeError, "Failed to restore partition layout: %s" % err label = None bootlabel = None _, boot_partnum, primary_partnum, backup_partnum, logs_partnum, swap_partnum, _ = backend.inspectTargetDisk( disk, None, [], constants.PRESERVE_IF_UTILITY, True, True) restore_partition = partitionDevice(disk, primary_partnum) xelogging.log("Restoring to partition %s." % restore_partition) tool = PartitionTool(disk) boot_part = tool.getPartition(boot_partnum) boot_device = partitionDevice(disk, boot_partnum) if boot_part else None efi_boot = boot_part and boot_part['id'] == GPTPartitionTool.ID_EFI_BOOT # determine current location of bootloader current_location = 'unknown' try: root_fs = util.TempMount(restore_partition, 'root-', options=['ro'], boot_device=boot_device) try: boot_config = bootloader.Bootloader.loadExisting( root_fs.mount_point) current_location = boot_config.location xelogging.log("Bootloader currently in %s" % current_location) finally: root_fs.unmount() except: pass # mount the backup fs backup_fs = util.TempMount(backup_partition, 'restore-backup-', options=['ro']) try: # extract the bootloader config boot_config = bootloader.Bootloader.loadExisting(backup_fs.mount_point) if boot_config.src_fmt == 'grub': raise RuntimeError, "Backup uses grub bootloader which is no longer supported - " + \ "to restore please use a version of the installer that matches the backup partition" # format the restore partition(s): if util.runCmd2(['mkfs.%s' % constants.rootfs_type, restore_partition ]) != 0: raise RuntimeError, "Failed to create root filesystem" if efi_boot: if util.runCmd2(['mkfs.vfat', boot_device]) != 0: raise RuntimeError, "Failed to create boot filesystem" # mount restore partition: dest_fs = util.TempMount(restore_partition, 'restore-dest-', boot_device=boot_device, boot_mount_point='/boot/efi') try: # copy files from the backup partition to the restore partition: objs = filter( lambda x: x not in ['lost+found', '.xen-backup-partition', '.xen-gpt.bin'], os.listdir(backup_fs.mount_point)) for i in range(len(objs)): obj = objs[i] xelogging.log("Restoring subtree %s..." % obj) progress((i * 100) / len(objs)) # Use 'cp' here because Python's copying tools are useless and # get stuck in an infinite loop when copying e.g. /dev/null. if util.runCmd2([ 'cp', '-a', os.path.join(backup_fs.mount_point, obj), dest_fs.mount_point ]) != 0: raise RuntimeError, "Failed to restore %s directory" % obj xelogging.log( "Data restoration complete. About to re-install bootloader.") location = boot_config.location m = re.search(r'root=LABEL=(\S+)', boot_config.menu[boot_config.default].kernel_args) if m: label = m.group(1) if location == constants.BOOT_LOCATION_PARTITION and current_location == constants.BOOT_LOCATION_MBR: # if bootloader in the MBR it's probably not safe to restore with it # on the partition xelogging.log( "Bootloader is currently installed to MBR, restoring to MBR instead of partition" ) location = constants.BOOT_LOCATION_MBR with open(os.path.join(backup_fs.mount_point, 'etc', 'fstab'), 'r') as fstab: for line in fstab: m = re.match(r'LABEL=(\S+)\s+/boot/efi\s', line) if m: bootlabel = m.group(1) mounts = { 'root': dest_fs.mount_point, 'boot': os.path.join(dest_fs.mount_point, 'boot') } # prepare extra mounts for installing bootloader: util.bindMount("/dev", "%s/dev" % dest_fs.mount_point) util.bindMount("/sys", "%s/sys" % dest_fs.mount_point) util.bindMount("/proc", "%s/proc" % dest_fs.mount_point) if boot_config.src_fmt == 'grub2': if efi_boot: branding = util.readKeyValueFile( os.path.join(backup_fs.mount_point, constants.INVENTORY_FILE)) branding['product-brand'] = branding['PRODUCT_BRAND'] backend.setEfiBootEntry(mounts, disk, boot_partnum, branding) else: if location == constants.BOOT_LOCATION_MBR: backend.installGrub2(mounts, disk, False) else: backend.installGrub2(mounts, restore_partition, True) else: backend.installExtLinux(mounts, disk, probePartitioningScheme(disk), location) # restore bootloader configuration dst_file = boot_config.src_file.replace(backup_fs.mount_point, dest_fs.mount_point, 1) util.assertDir(os.path.dirname(dst_file)) boot_config.commit(dst_file) finally: util.umount("%s/proc" % dest_fs.mount_point) util.umount("%s/sys" % dest_fs.mount_point) util.umount("%s/dev" % dest_fs.mount_point) dest_fs.unmount() finally: backup_fs.unmount() if not label: raise RuntimeError, "Failed to find label required for root filesystem." if efi_boot and not bootlabel: raise RuntimeError( "Failed to find label required for boot filesystem.") if util.runCmd2(['e2label', restore_partition, label]) != 0: raise RuntimeError, "Failed to label root partition" if bootlabel: if util.runCmd2(['fatlabel', boot_device, bootlabel]) != 0: raise RuntimeError, "Failed to label boot partition" xelogging.log("Bootloader restoration complete.") xelogging.log("Restore successful.") backend.writeLog(disk, primary_partnum, logs_partnum)
def restoreFromBackup(backup_partition, disk, progress=lambda x: ()): """ Restore files from backup_partition to the root partition on disk. Call progress with a value between 0 and 100. Re-install bootloader. Fails if backup is not same version as the CD in use.""" assert backup_partition.startswith("/dev/") assert disk.startswith("/dev/") label = None primary_partnum, _, __ = backend.inspectTargetDisk(disk, None, [], False, False) restore_partition = partitionDevice(disk, primary_partnum) xelogging.log("Restoring to partition %s." % restore_partition) # determine current location of bootloader current_location = "unknown" try: root_fs = util.TempMount(restore_partition, "root-", options=["ro"]) try: boot_config = bootloader.Bootloader.loadExisting(root_fs.mount_point) current_location = boot_config.location xelogging.log("Bootloader currently in %s" % current_location) finally: root_fs.unmount() except: pass # mount the backup fs backup_fs = util.TempMount(backup_partition, "restore-backup-", options=["ro"]) try: # extract the bootloader config boot_config = bootloader.Bootloader.loadExisting(backup_fs.mount_point) if boot_config.src_fmt == "grub": raise RuntimeError, "Backup uses grub bootloader which is no longer supported - " + "to restore please use a version of the installer that matches the backup partition" # format the restore partition: if util.runCmd2(["mkfs.ext3", restore_partition]) != 0: raise RuntimeError, "Failed to create filesystem" # mount restore partition: dest_fs = util.TempMount(restore_partition, "restore-dest-") try: # copy files from the backup partition to the restore partition: objs = filter(lambda x: x not in ["lost+found", ".xen-backup-partition"], os.listdir(backup_fs.mount_point)) for i in range(len(objs)): obj = objs[i] xelogging.log("Restoring subtree %s..." % obj) progress((i * 100) / len(objs)) # Use 'cp' here because Python's copying tools are useless and # get stuck in an infinite loop when copying e.g. /dev/null. if util.runCmd2(["cp", "-a", os.path.join(backup_fs.mount_point, obj), dest_fs.mount_point]) != 0: raise RuntimeError, "Failed to restore %s directory" % obj xelogging.log("Data restoration complete. About to re-install bootloader.") location = boot_config.location m = re.search(r"root=LABEL=(\S+)", boot_config.menu[boot_config.default].kernel_args) if m: label = m.group(1) if location == "partition" and current_location == "mbr": # if bootloader in the MBR it's probably not safe to restore with it # on the partition xelogging.log("Bootloader is currently installed to MBR, restoring to MBR instead of partition") location = "mbr" mounts = {"root": dest_fs.mount_point, "boot": os.path.join(dest_fs.mount_point, "boot")} backend.installBootLoader( mounts, disk, probePartitioningScheme(disk), primary_partnum, None, False, [], location ) # restore bootloader configuration dst_file = boot_config.src_file.replace(backup_fs.mount_point, dest_fs.mount_point, 1) util.assertDir(os.path.dirname(dst_file)) boot_config.commit(dst_file) finally: dest_fs.unmount() finally: backup_fs.unmount() if not label: raise RuntimeError, "Failed to find label required for root filesystem." if util.runCmd2(["e2label", restore_partition, label]) != 0: raise RuntimeError, "Failed to label partition" xelogging.log("Bootloader restoration complete.") xelogging.log("Restore successful.")