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)
Beispiel #2
0
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
Beispiel #3
0
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
Beispiel #4
0
    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)
                ])
Beispiel #5
0
 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)
                ])
Beispiel #7
0
    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"
Beispiel #9
0
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"
Beispiel #10
0
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)
Beispiel #11
0
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.")