Example #1
0
    def readInventory(self):
        self.mount_root()
        try:
            self.inventory = util.readKeyValueFile(os.path.join(
                self.root_fs.mount_point, constants.INVENTORY_FILE),
                                                   strip_quotes=True)
            self.build = self.inventory['BUILD_NUMBER']
            self.version = Version.from_string(
                "%s-%s" % (self.inventory['PLATFORM_VERSION'], self.build))
            if 'PRODUCT_NAME' in self.inventory:
                self.name = self.inventory['PRODUCT_NAME']
                self.brand = self.inventory['PRODUCT_BRAND']
            else:
                self.name = self.inventory['PLATFORM_NAME']
                self.brand = self.inventory['PLATFORM_NAME']

            if 'OEM_BRAND' in self.inventory:
                self.oem_brand = self.inventory['OEM_BRAND']
                self.visual_brand = self.oem_brand
            else:
                self.visual_brand = self.brand
            if 'OEM_VERSION' in self.inventory:
                self.oem_version = self.inventory['OEM_VERSION']
                self.visual_version = "%s-%s" % (self.inventory['OEM_VERSION'],
                                                 self.build)
            else:
                if '/' in self.build:
                    self.visual_version = self.inventory['PRODUCT_VERSION']
                else:
                    self.visual_version = "%s-%s" % (
                        self.inventory['PRODUCT_VERSION'], self.build)
        finally:
            self.unmount_root()
Example #2
0
    def loadFromIfcfg(filename):
        def valOrNone(d, k):
            return d.has_key(k) and d[k] or None

        conf = util.readKeyValueFile(filename)
        mode = None
        if conf.has_key('BOOTPROTO'):
            if conf['BOOTPROTO'] == 'static' or conf.has_key('IPADDR'):
                mode = NetInterface.Static
            elif conf['BOOTPROTO'] == 'dhcp':
                mode = NetInterface.DHCP

        hwaddr = valOrNone(conf, 'HWADDR')
        if not hwaddr:
            hwaddr = valOrNone(conf, 'MACADDR')
        if not hwaddr:
            try:
                hwaddr = netutil.getHWAddr(conf['DEVICE'])
            except:
                pass
        dns = None
        n = 1
        while conf.has_key('DNS%d' % n):
            if not dns: dns = []
            dns.append(conf['DNS%d' % n])
            n += 1

        return NetInterface(mode, hwaddr, valOrNone(conf, 'IPADDR'), valOrNone(conf, 'NETMASK'),
                            valOrNone(conf, 'GATEWAY'), dns, valOrNone(conf, 'DOMAIN'))
Example #3
0
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."""

    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_version = backup.version
    limit_version = product.THIS_PLATFORM_VERSION
    logs_partition = tool.getPartition(logs_partnum)
    boot_partition = tool.getPartition(boot_partnum)
    root_partition = partitionDevice(disk, primary_partnum)

    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 = []
    if 'PARTITION_LAYOUT' in inventory:  # Present from XS 7.0
        backup_partition_layout = inventory['PARTITION_LAYOUT'].split(',')
    backup_fs.unmount()

    (boot, _, _, _, logs) = diskutil.probeDisk(disk)

    xelogging.log("BACKUP DISK PARTITION LAYOUT: %s" % backup_partition_layout)

    if not logs[0] and boot[
            0] and not backup_partition_layout:  # From 7.x (no new layout - yes Boot partition) to 6.x
        restoreWithoutRepartButUEFI(backup, progress)
    else:
        doRestore(backup, progress, backup_partition_layout, logs[0])
Example #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)
                ])
Example #5
0
 def __init__(self, part, mnt):
     self.partition = part
     self.inventory = util.readKeyValueFile(os.path.join(mnt, constants.INVENTORY_FILE), strip_quotes=True)
     self.name = self.inventory["PRODUCT_NAME"]
     self.brand = self.inventory["PRODUCT_BRAND"]
     self.version = Version.from_string(
         "%s-%s" % (self.inventory["PRODUCT_VERSION"], self.inventory["BUILD_NUMBER"])
     )
     self.build = self.inventory["BUILD_NUMBER"]
     self.root_disk = diskutil.partitionFromId(self.inventory["PRIMARY_DISK"])
Example #6
0
 def readInventory(self):
     self.mount_root()
     try:
         self.inventory = util.readKeyValueFile(
             os.path.join(self.root_fs.mount_point, constants.INVENTORY_FILE), strip_quotes=True
         )
         self.name = self.inventory["PRODUCT_NAME"]
         self.brand = self.inventory["PRODUCT_BRAND"]
         self.version = Version.from_string(
             "%s-%s" % (self.inventory["PRODUCT_VERSION"], self.inventory["BUILD_NUMBER"])
         )
         self.build = self.inventory["BUILD_NUMBER"]
     finally:
         self.unmount_root()
Example #7
0
    def __init__(self, source):
        Upgrader.__init__(self, source)
        primary_fs = util.TempMount(self.source.root_device, 'primary-', options=['ro'])
        safe2upgrade_path = os.path.join(primary_fs.mount_point, constants.SAFE_2_UPGRADE)
        default_storage_conf_path = os.path.join(primary_fs.mount_point, "etc/firstboot.d/data/default-storage.conf")

        self.safe2upgrade = os.path.isfile(safe2upgrade_path)
        self.vgs_output = None

        self.storage_type = None
        if os.path.exists(default_storage_conf_path):
            input_data = util.readKeyValueFile(default_storage_conf_path)
            self.storage_type = input_data['TYPE']

        primary_fs.unmount()
Example #8
0
    def __init__(self, part, mnt):
        self.partition = part
        self.inventory = util.readKeyValueFile(os.path.join(
            mnt, constants.INVENTORY_FILE),
                                               strip_quotes=True)
        self.build = self.inventory['BUILD_NUMBER']
        self.version = Version.from_string(
            "%s-%s" % (self.inventory['PLATFORM_VERSION'], self.build))
        if 'PRODUCT_NAME' in self.inventory:
            self.name = self.inventory['PRODUCT_NAME']
            self.brand = self.inventory['PRODUCT_BRAND']
        else:
            self.name = self.inventory['PLATFORM_NAME']
            self.brand = self.inventory['PLATFORM_NAME']

        if 'OEM_BRAND' in self.inventory:
            self.oem_brand = self.inventory['OEM_BRAND']
            self.visual_brand = self.oem_brand
        else:
            self.visual_brand = self.brand
        if 'OEM_VERSION' in self.inventory:
            self.oem_version = self.inventory['OEM_VERSION']
            self.visual_version = "%s-%s" % (self.inventory['OEM_VERSION'],
                                             self.build)
        else:
            if '/' in self.build:
                self.visual_version = self.inventory['PRODUCT_VERSION']
            else:
                self.visual_version = "%s-%s" % (
                    self.inventory['PRODUCT_VERSION'], self.build)

        if self.inventory['PRIMARY_DISK'].startswith('/dev/md_'):
            # Handle restoring an installation using a /dev/md_* path
            self.root_disk = os.path.realpath(
                self.inventory['PRIMARY_DISK'].replace('md_', 'md/') + '_0')
        else:
            self.root_disk = diskutil.partitionFromId(
                self.inventory['PRIMARY_DISK'])
            self.root_disk = getMpathMasterOrDisk(self.root_disk)
Example #9
0
    def loadFromIfcfg(filename):
        def valOrNone(d, k):
            return k in d and d[k] or None

        conf = util.readKeyValueFile(filename)
        mode = None
        if 'BOOTPROTO' in conf:
            if conf['BOOTPROTO'] == 'static' or 'IPADDR' in conf:
                mode = NetInterface.Static
            elif conf['BOOTPROTO'] == 'dhcp':
                mode = NetInterface.DHCP

        hwaddr = valOrNone(conf, 'HWADDR')
        if not hwaddr:
            hwaddr = valOrNone(conf, 'MACADDR')
        if not hwaddr:
            hwaddr = netutil.getHWAddr(conf['DEVICE'])
        dns = None
        n = 1
        while 'DNS%d' % n in conf:
            if not dns: dns = []
            dns.append(conf['DNS%d' % n])
            n += 1

        modev6 = None
        if 'DHCPV6C' in conf:
            modev6 = NetInterface.DHCP
        elif 'IPV6_AUTOCONF' in conf:
            modev6 = NetInterface.Autoconf
        elif 'IPV6INIT' in conf:
            modev6 = NetInterface.Static

        ni = NetInterface(mode, hwaddr, valOrNone(conf, 'IPADDR'),
                          valOrNone(conf, 'NETMASK'),
                          valOrNone(conf, 'GATEWAY'), dns,
                          valOrNone(conf, 'DOMAIN'))
        ni.addIPv6(modev6, valOrNone(conf, 'IPV6ADDR'),
                   valOrNone(conf, 'IPV6_DEFAULTGW'))
        return ni
Example #10
0
File: upgrade.py Project: xtha/pxe
    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'])
Example #11
0
def readInventoryFile(filename):
    return util.readKeyValueFile(filename, strip_quotes=True)
Example #12
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"
Example #13
0
    def _readSettings(self):
        """ Read settings from the installation, returns a results dictionary. """

        results = {'host-config': {}}

        self.mount_state()
        try:

            # timezone:
            tz = None
            clock_file = self.join_state_path('etc/localtime')
            if os.path.islink(clock_file):
                tzfile = os.path.realpath(clock_file)
                if '/usr/share/zoneinfo/' in tzfile:
                    _, tz = tzfile.split('/usr/share/zoneinfo/', 1)
            if not tz:
                # No timezone found:
                # Supply a default and for interactive installs prompt the user.
                xelogging.log('No timezone configuration found.')
                results['request-timezone'] = True
                tz = "Europe/London"
            results['timezone'] = tz

            # hostname.  We will assume one was set anyway and thus write
            # it back into the new filesystem.  If one wasn't set then this
            # will be localhost.localdomain, in which case the old behaviour
            # will persist anyway:
            fd = open(self.join_state_path('etc/sysconfig/network'), 'r')
            lines = fd.readlines()
            fd.close()
            for line in lines:
                if line.startswith('HOSTNAME='):
                    results['manual-hostname'] = (True, line[9:].strip())

            if os.path.exists(self.join_state_path('etc/hostname')):
                fd = open(self.join_state_path('etc/hostname'), 'r')
                line = fd.readline()
                results['manual-hostname'] = (True, line.strip())
                fd.close()

            if not results.has_key('manual-hostname'):
                results['manual-hostname'] = (False, None)

            # nameservers:
            domain = None
            if not os.path.exists(self.join_state_path('etc/resolv.conf')):
                results['manual-nameservers'] = (False, None)
            else:
                ns = []
                fd = open(self.join_state_path('etc/resolv.conf'), 'r')
                lines = fd.readlines()
                fd.close()
                for line in lines:
                    if line.startswith("nameserver "):
                        ns.append(line[11:].strip())
                    elif line.startswith("domain "):
                        domain = line[8:].strip()
                    elif line.startswith("search "):
                        domain = line.split()[1]
                results['manual-nameservers'] = (True, ns)

            # ntp servers:
            fd = open(self.join_state_path('etc/ntp.conf'), 'r')
            lines = fd.readlines()
            fd.close()
            ntps = []
            for line in lines:
                if line.startswith("server "):
                    ntps.append(line[7:].strip())
            results['ntp-servers'] = ntps

            # keyboard:
            keyboard_dict = {}
            keyboard_file = self.join_state_path('etc/sysconfig/keyboard')
            if os.path.exists(keyboard_file):
                keyboard_dict = util.readKeyValueFile(keyboard_file)
            keyboard_file = self.join_state_path('etc/vconsole.conf')
            if os.path.exists(keyboard_file):
                keyboard_dict.update(util.readKeyValueFile(keyboard_file))
            if 'KEYMAP' in keyboard_dict:
                results['keymap'] = keyboard_dict['KEYMAP']
            elif 'KEYTABLE' in keyboard_dict:
                results['keymap'] = keyboard_dict['KEYTABLE']
            # Do not error here if no keymap configuration is found.
            # This enables upgrade to still carry state on hosts without
            # keymap configured:
            # A default keymap is assigned in the backend of this installer.
            if not results.has_key('keymap'):
                xelogging.log('No existing keymap configuration found.')

            # root password:
            fd = open(self.join_state_path('etc/passwd'), 'r')
            root_pwd = None
            for line in fd:
                pwent = line.split(':')
                if pwent[0] == 'root':
                    root_pwd = pwent[1]
                    break
            fd.close()
            if len(root_pwd) == 1:
                root_pwd = None
                try:
                    fd = open(self.join_state_path('etc/shadow'), 'r')
                    for line in fd:
                        pwent = line.split(':')
                        if pwent[0] == 'root':
                            root_pwd = pwent[1]
                            break
                    fd.close()
                except:
                    pass

            if not root_pwd:
                raise SettingsNotAvailable, "no root password found"
            results['root-password'] = ('pwdhash', root_pwd)

            # don't care about this too much.
            results['time-config-method'] = 'ntp'

            # read network configuration.  We only care to find out what the
            # management interface is, and what its configuration was.
            # The dev -> MAC mapping for other devices will be preserved in the
            # database which is available in time for everything except the
            # management interface.
            mgmt_iface = self.getInventoryValue('MANAGEMENT_INTERFACE')

            networkdb_path = constants.NETWORK_DB
            if not os.path.exists(self.join_state_path(networkdb_path)):
                networkdb_path = constants.OLD_NETWORK_DB
            dbcache_path = constants.DBCACHE
            if not os.path.exists(self.join_state_path(dbcache_path)):
                dbcache_path = constants.OLD_DBCACHE

            if not mgmt_iface:
                xelogging.log('No existing management interface found.')
            elif os.path.exists(self.join_state_path(networkdb_path)):
                networkd_db = constants.NETWORKD_DB
                if not os.path.exists(self.join_state_path(networkd_db)):
                    networkd_db = constants.OLD_NETWORKD_DB
                xelogging.log(
                    'Checking %s for management interface configuration' %
                    networkd_db)

                def fetchIfaceInfoFromNetworkdbAsDict(bridge, iface=None):
                    args = [
                        'chroot', self.state_fs.mount_point, '/' + networkd_db,
                        '-bridge', bridge
                    ]
                    if iface:
                        args.extend(['-iface', iface])
                    rv, out = util.runCmd2(args, with_stdout=True)
                    d = {}
                    for line in (x.strip() for x in out.split('\n')
                                 if len(x.strip())):
                        for key_value in line.split(" "):
                            var = key_value.split('=', 1)
                            d[var[0]] = var[1]
                    return d

                d = fetchIfaceInfoFromNetworkdbAsDict(mgmt_iface, mgmt_iface)
                # For mgmt on tagged vlan, networkdb output has no value for
                # 'interfaces' but instead has 'parent' specified. We need
                # to fetch 'interfaces' of parent and use for mgmt bridge.
                if not d.get('interfaces') and 'parent' in d:
                    p = fetchIfaceInfoFromNetworkdbAsDict(d['parent'])
                    d['interfaces'] = p['interfaces']

                results['net-admin-bridge'] = mgmt_iface
                results['net-admin-interface'] = d.get('interfaces').split(
                    ',')[0]

                if_hwaddr = netutil.getHWAddr(results['net-admin-interface'])

                vlan = int(d['vlan']) if 'vlan' in d else None
                proto = d.get('mode')
                if proto == 'static':
                    ip = d.get('ipaddr')
                    netmask = d.get('netmask')
                    gateway = d.get('gateway')
                    dns = d.get('dns', '').split(',')
                    if ip and netmask:
                        results['net-admin-configuration'] = NetInterface(
                            NetInterface.Static,
                            if_hwaddr,
                            ip,
                            netmask,
                            gateway,
                            dns,
                            vlan=vlan)
                elif proto == 'dhcp':
                    results['net-admin-configuration'] = NetInterface(
                        NetInterface.DHCP, if_hwaddr, vlan=vlan)
                else:
                    results['net-admin-configuration'] = NetInterface(
                        None, if_hwaddr, vlan=vlan)

                protov6 = d.get('modev6')
                if protov6 == 'static':
                    ipv6 = d.get('ipaddrv6')
                    gatewayv6 = d.get('gatewayv6')
                    if ipv6:
                        results['net-admin-configuration'].addIPv6(
                            NetInterface.Static, ipv6, gatewayv6)
                elif protov6 == 'dhcp':
                    results['net-admin-configuration'].addIPv6(
                        NetInterface.DHCP)
                elif protov6 == 'autoconf':
                    results['net-admin-configuration'].addIPv6(
                        NetInterface.Autoconf)

            elif os.path.exists(self.join_state_path(dbcache_path)):
                xelogging.log(
                    'Checking %s for management network configuration' %
                    dbcache_path)

                def getText(nodelist):
                    rc = ""
                    for node in nodelist:
                        if node.nodeType == node.TEXT_NODE:
                            rc = rc + node.data
                    return rc.strip().encode()

                xmldoc = xml.dom.minidom.parse(
                    self.join_state_path(dbcache_path))

                pif_uid = None
                for node in xmldoc.documentElement.childNodes:
                    if node.nodeType == node.ELEMENT_NODE and node.tagName == 'network':
                        network = node
                    else:
                        continue
                    # CA-50971: handle renamed networks in MNR
                    if len(network.getElementsByTagName('bridge')) == 0 or \
                       len(network.getElementsByTagName('PIFs')) == 0 or \
                       len(network.getElementsByTagName('PIFs')[0].getElementsByTagName('PIF')) == 0:
                        continue

                    if getText(
                            network.getElementsByTagName('bridge')
                        [0].childNodes) == mgmt_iface:
                        pif_uid = getText(
                            network.getElementsByTagName('PIFs')
                            [0].getElementsByTagName('PIF')[0].childNodes)
                        break
                if pif_uid:
                    for node in xmldoc.documentElement.childNodes:
                        if node.nodeType == node.ELEMENT_NODE and node.tagName == 'pif':
                            pif = node
                        else:
                            continue
                        if pif.getAttribute('ref') == pif_uid:
                            results['net-admin-interface'] = getText(
                                pif.getElementsByTagName('device')
                                [0].childNodes)
                            results['net-admin-bridge'] = mgmt_iface
                            results[
                                'net-admin-configuration'] = NetInterface.loadFromPif(
                                    pif)
                            break
            else:
                xelogging.log(
                    'Checking ifcfg files for management network configuration'
                )
                for cfile in filter(lambda x: True in [x.startswith(y) for y in ['ifcfg-eth', 'ifcfg-bond']], \
                                   os.listdir(self.join_state_path(constants.NET_SCR_DIR))):
                    devcfg = util.readKeyValueFile(self.join_state_path(
                        constants.NET_SCR_DIR, cfile),
                                                   strip_quotes=False)
                    if devcfg.has_key('DEVICE') and devcfg.has_key(
                            'BRIDGE') and devcfg['BRIDGE'] == mgmt_iface:
                        brcfg = util.readKeyValueFile(self.join_state_path(
                            constants.NET_SCR_DIR,
                            'ifcfg-' + devcfg['BRIDGE']),
                                                      strip_quotes=False)
                        results['net-admin-interface'] = devcfg['DEVICE']
                        results['net-admin-bridge'] = devcfg['BRIDGE']

                        # get hardware address if it was recorded, otherwise look it up:
                        if devcfg.has_key('HWADDR'):
                            hwaddr = devcfg['HWADDR']
                        elif devcfg.has_key('MACADDR'):
                            # our bonds have a key called MACADDR instead
                            hwaddr = devcfg['MACADDR']
                        else:
                            hwaddr = netutil.getHWAddr(devcfg['DEVICE'])

                        ifcfg = NetInterface.loadFromIfcfg(
                            self.join_state_path(constants.NET_SCR_DIR,
                                                 'ifcfg-' + devcfg['BRIDGE']))
                        if not ifcfg.hwaddr:
                            ifcfg.hwaddr = hwaddr
                        if ifcfg.isStatic() and not ifcfg.domain and domain:
                            ifcfg.domain = domain
                        results['net-admin-configuration'] = ifcfg
                        break

            repo_list = []
            if os.path.exists(
                    self.join_state_path(constants.INSTALLED_REPOS_DIR)):
                try:
                    for repo_id in os.listdir(
                            self.join_state_path(
                                constants.INSTALLED_REPOS_DIR)):
                        try:
                            repo = repository.LegacyRepository(
                                repository.FilesystemAccessor(
                                    self.join_state_path(
                                        constants.INSTALLED_REPOS_DIR,
                                        repo_id)))
                            if repo.hidden() != "true":
                                repo_list.append(
                                    (repo.identifier(), repo.name(),
                                     (repo_id !=
                                      constants.MAIN_REPOSITORY_NAME)))
                        except repository.RepoFormatError:
                            # probably pre-XML format
                            repo = open(
                                self.join_state_path(
                                    constants.INSTALLED_REPOS_DIR, repo_id,
                                    repository.LegacyRepository.
                                    REPOSITORY_FILENAME))
                            repo_id = repo.readline().strip()
                            repo_name = repo.readline().strip()
                            repo.close()
                            repo_list.append(
                                (repo_id, repo_name,
                                 (repo_id != constants.MAIN_REPOSITORY_NAME)))
                except Exception, e:
                    xelogging.log('Scan for driver disks failed:')
                    xelogging.log_exception(e)

            results['repo-list'] = repo_list

            results['ha-armed'] = False
            try:
                db_path = "var/lib/xcp/local.db"
                if not os.path.exists(self.join_state_path(db_path)):
                    db_path = "var/xapi/local.db"
                db = open(self.join_state_path(db_path), 'r')
                if db.readline().find(
                        '<row key="ha.armed" value="true"') != -1:
                    results['ha-armed'] = True
                db.close()
            except:
                pass

            try:
                network_conf = open(
                    self.join_state_path("etc/xensource/network.conf"), 'r')
                network_backend = network_conf.readline().strip()
                network_conf.close()

                if network_backend == constants.NETWORK_BACKEND_BRIDGE:
                    results[
                        'network-backend'] = constants.NETWORK_BACKEND_BRIDGE
                elif network_backend in [
                        constants.NETWORK_BACKEND_VSWITCH,
                        constants.NETWORK_BACKEND_VSWITCH_ALT
                ]:
                    results[
                        'network-backend'] = constants.NETWORK_BACKEND_VSWITCH
                else:
                    raise SettingsNotAvailable, "unknown network backend %s" % network_backend
            except:
                pass

            results['master'] = None
            try:
                pt = open(self.join_state_path("etc/xensource/ptoken"), 'r')
                results['pool-token'] = pt.readline().strip()
                pt.close()
                pc = open(self.join_state_path("etc/xensource/pool.conf"), 'r')
                line = pc.readline().strip()
                if line.startswith('slave:'):
                    results['master'] = line[6:]
                pc.close()
            except:
                pass
Example #14
0
    def _readSettings(self):
        """ Read settings from the installation, returns a results dictionary. """

        results = {'host-config': {}}

        self.mount_state()
        try:

            # timezone:
            tz = None
            clock_file = self.join_state_path('etc/localtime')
            if os.path.islink(clock_file):
                tzfile = os.path.realpath(clock_file)
                if '/usr/share/zoneinfo/' in tzfile:
                    _, tz = tzfile.split('/usr/share/zoneinfo/', 1)
            if not tz:
                # No timezone found:
                # Supply a default and for interactive installs prompt the user.
                logger.log('No timezone configuration found.')
                results['request-timezone'] = True
                tz = "Europe/London"
            results['timezone'] = tz

            # hostname.  We will assume one was set anyway and thus write
            # it back into the new filesystem.  If one wasn't set then this
            # will be localhost.localdomain, in which case the old behaviour
            # will persist anyway:
            fd = open(self.join_state_path('etc/sysconfig/network'), 'r')
            lines = fd.readlines()
            fd.close()
            for line in lines:
                if line.startswith('HOSTNAME='):
                    results['manual-hostname'] = (True, line[9:].strip())

            if os.path.exists(self.join_state_path('etc/hostname')):
                fd = open(self.join_state_path('etc/hostname'), 'r')
                line = fd.readline()
                results['manual-hostname'] = (True, line.strip())
                fd.close()

            if 'manual-hostname' not in results:
                results['manual-hostname'] = (False, None)

            # nameservers:
            domain = None
            if not os.path.exists(self.join_state_path('etc/resolv.conf')):
                results['manual-nameservers'] = (False, None)
            else:
                ns = []
                fd = open(self.join_state_path('etc/resolv.conf'), 'r')
                lines = fd.readlines()
                fd.close()
                for line in lines:
                    if line.startswith("nameserver "):
                        ns.append(line[11:].strip())
                    elif line.startswith("domain "):
                        domain = line[8:].strip()
                    elif line.startswith("search "):
                        domain = line.split()[1]
                results['manual-nameservers'] = (True, ns)

            # ntp servers:
            if os.path.exists(self.join_state_path('etc/chrony.conf')):
                fd = open(self.join_state_path('etc/chrony.conf'), 'r')
            else:
                fd = open(self.join_state_path('etc/ntp.conf'), 'r')
            lines = fd.readlines()
            fd.close()
            ntps = []
            for line in lines:
                if line.startswith("server "):
                    ntps.append(line[7:].split()[0].strip())
            results['ntp-servers'] = ntps

            # keyboard:
            keyboard_dict = {}
            keyboard_file = self.join_state_path('etc/sysconfig/keyboard')
            if os.path.exists(keyboard_file):
                keyboard_dict = util.readKeyValueFile(keyboard_file)
            keyboard_file = self.join_state_path('etc/vconsole.conf')
            if os.path.exists(keyboard_file):
                keyboard_dict.update(util.readKeyValueFile(keyboard_file))
            if 'KEYMAP' in keyboard_dict:
                results['keymap'] = keyboard_dict['KEYMAP']
            elif 'KEYTABLE' in keyboard_dict:
                results['keymap'] = keyboard_dict['KEYTABLE']
            # Do not error here if no keymap configuration is found.
            # This enables upgrade to still carry state on hosts without
            # keymap configured:
            # A default keymap is assigned in the backend of this installer.
            if 'keymap' not in results:
                logger.log('No existing keymap configuration found.')

            # root password:
            fd = open(self.join_state_path('etc/passwd'), 'r')
            root_pwd = None
            for line in fd:
                pwent = line.split(':')
                if pwent[0] == 'root':
                    root_pwd = pwent[1]
                    break
            fd.close()
            if len(root_pwd) == 1:
                root_pwd = None
                try:
                    fd = open(self.join_state_path('etc/shadow'), 'r')
                    for line in fd:
                        pwent = line.split(':')
                        if pwent[0] == 'root':
                            root_pwd = pwent[1]
                            break
                    fd.close()
                except:
                    pass

            if not root_pwd:
                raise SettingsNotAvailable("no root password found")
            results['root-password'] = ('pwdhash', root_pwd)

            # don't care about this too much.
            results['time-config-method'] = 'ntp'

            # read network configuration.  We only care to find out what the
            # management interface is, and what its configuration was.
            # The dev -> MAC mapping for other devices will be preserved in the
            # database which is available in time for everything except the
            # management interface.
            mgmt_iface = self.getInventoryValue('MANAGEMENT_INTERFACE')

            if not mgmt_iface:
                logger.log('No existing management interface found.')
            elif os.path.exists(self.join_state_path(constants.NETWORK_DB)):
                logger.log(
                    'Checking %s for management interface configuration' %
                    constants.NETWORKD_DB)

                def fetchIfaceInfoFromNetworkdbAsDict(bridge, iface=None):
                    args = [
                        'chroot', self.state_fs.mount_point,
                        '/' + constants.NETWORKD_DB, '-bridge', bridge
                    ]
                    if iface:
                        args.extend(['-iface', iface])
                    rv, out = util.runCmd2(args, with_stdout=True)
                    d = {}
                    for line in (x.strip() for x in out.split('\n')
                                 if len(x.strip())):
                        for key_value in line.split(" "):
                            var = key_value.split('=', 1)
                            d[var[0]] = var[1]
                    return d

                d = fetchIfaceInfoFromNetworkdbAsDict(mgmt_iface, mgmt_iface)
                # For mgmt on tagged vlan, networkdb output has no value for
                # 'interfaces' but instead has 'parent' specified. We need
                # to fetch 'interfaces' of parent and use for mgmt bridge.
                if not d.get('interfaces') and 'parent' in d:
                    p = fetchIfaceInfoFromNetworkdbAsDict(d['parent'])
                    d['interfaces'] = p['interfaces']

                results['net-admin-bridge'] = mgmt_iface
                results['net-admin-interface'] = d.get('interfaces').split(
                    ',')[0]

                if_hwaddr = netutil.getHWAddr(results['net-admin-interface'])

                vlan = int(d['vlan']) if 'vlan' in d else None
                proto = d.get('mode')
                if proto == 'static':
                    ip = d.get('ipaddr')
                    netmask = d.get('netmask')
                    gateway = d.get('gateway')
                    dns = d.get('dns', '').split(',')
                    if ip and netmask:
                        results['net-admin-configuration'] = NetInterface(
                            NetInterface.Static,
                            if_hwaddr,
                            ip,
                            netmask,
                            gateway,
                            dns,
                            vlan=vlan)
                elif proto == 'dhcp':
                    results['net-admin-configuration'] = NetInterface(
                        NetInterface.DHCP, if_hwaddr, vlan=vlan)
                else:
                    results['net-admin-configuration'] = NetInterface(
                        None, if_hwaddr, vlan=vlan)

                protov6 = d.get('modev6')
                if protov6 == 'static':
                    ipv6 = d.get('ipaddrv6')
                    gatewayv6 = d.get('gatewayv6')
                    if ipv6:
                        results['net-admin-configuration'].addIPv6(
                            NetInterface.Static, ipv6, gatewayv6)
                elif protov6 == 'dhcp':
                    results['net-admin-configuration'].addIPv6(
                        NetInterface.DHCP)
                elif protov6 == 'autoconf':
                    results['net-admin-configuration'].addIPv6(
                        NetInterface.Autoconf)

            repo_list = []
            if os.path.exists(
                    self.join_state_path(constants.INSTALLED_REPOS_DIR)):
                try:
                    for repo_id in os.listdir(
                            self.join_state_path(
                                constants.INSTALLED_REPOS_DIR)):
                        try:
                            repo = repository.LegacyRepository(
                                repository.FilesystemAccessor(
                                    self.join_state_path(
                                        constants.INSTALLED_REPOS_DIR,
                                        repo_id)))
                            if repo.hidden() != "true":
                                repo_list.append(
                                    (repo.identifier(), repo.name(),
                                     (repo_id !=
                                      constants.MAIN_REPOSITORY_NAME)))
                        except repository.RepoFormatError:
                            # probably pre-XML format
                            repo = open(
                                self.join_state_path(
                                    constants.INSTALLED_REPOS_DIR, repo_id,
                                    repository.LegacyRepository.
                                    REPOSITORY_FILENAME))
                            repo_id = repo.readline().strip()
                            repo_name = repo.readline().strip()
                            repo.close()
                            repo_list.append(
                                (repo_id, repo_name,
                                 (repo_id != constants.MAIN_REPOSITORY_NAME)))
                except Exception as e:
                    logger.log('Scan for driver disks failed:')
                    logger.logException(e)

            results['repo-list'] = repo_list

            results['ha-armed'] = False
            try:
                db_path = "var/lib/xcp/local.db"
                if not os.path.exists(self.join_state_path(db_path)):
                    db_path = "var/xapi/local.db"
                db = open(self.join_state_path(db_path), 'r')
                if db.readline().find(
                        '<row key="ha.armed" value="true"') != -1:
                    results['ha-armed'] = True
                db.close()
            except:
                pass

            try:
                network_conf = open(
                    self.join_state_path("etc/xensource/network.conf"), 'r')
                network_backend = network_conf.readline().strip()
                network_conf.close()

                if network_backend == constants.NETWORK_BACKEND_BRIDGE:
                    results[
                        'network-backend'] = constants.NETWORK_BACKEND_BRIDGE
                elif network_backend in [
                        constants.NETWORK_BACKEND_VSWITCH,
                        constants.NETWORK_BACKEND_VSWITCH_ALT
                ]:
                    results[
                        'network-backend'] = constants.NETWORK_BACKEND_VSWITCH
                else:
                    raise SettingsNotAvailable("unknown network backend %s" %
                                               network_backend)
            except:
                pass

            results['master'] = None
            try:
                pt = open(self.join_state_path("etc/xensource/ptoken"), 'r')
                results['pool-token'] = pt.readline().strip()
                pt.close()
                pc = open(self.join_state_path("etc/xensource/pool.conf"), 'r')
                line = pc.readline().strip()
                if line.startswith('slave:'):
                    results['master'] = line[6:]
                pc.close()
            except:
                pass

        finally:
            self.unmount_state()

        # read bootloader config to extract various settings
        try:
            # Boot device
            self.mount_boot()
            boot_config = bootloader.Bootloader.loadExisting(
                self.boot_fs_mount)

            # Serial console
            try:
                xen_args = boot_config.menu['xe-serial'].getHypervisorArgs()
                com = [i for i in xen_args if re.match('com[0-9]+=.*', i)]
                results['serial-console'] = hardware.SerialPort.from_string(
                    com[0])
            except Exception:
                logger.log("Could not parse serial settings")

                if boot_config.serial:
                    results['serial-console'] = hardware.SerialPort(
                        boot_config.serial['port'],
                        baud=str(boot_config.serial['baud']))
            results['bootloader-location'] = boot_config.location
            if boot_config.default != 'upgrade':
                results['boot-serial'] = (boot_config.default == 'xe-serial')

            # Subset of hypervisor arguments
            xen_args = boot_config.menu[
                boot_config.default].getHypervisorArgs()

            #   - cpuid_mask
            results['host-config']['xen-cpuid-masks'] = filter(
                lambda x: x.startswith('cpuid_mask'), xen_args)

            #   - dom0_mem
            dom0_mem_arg = filter(lambda x: x.startswith('dom0_mem'), xen_args)
            (dom0_mem, dom0_mem_min,
             dom0_mem_max) = xcp.dom0.parse_mem(dom0_mem_arg[0])
            if dom0_mem:
                results['host-config']['dom0-mem'] = dom0_mem / 1024 / 1024
        except:
            pass
        self.unmount_boot()

        return results
Example #15
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)
Example #16
0
    def _readSettings(self):
        """ Read settings from the installation, returns a results dictionary. """

        results = {}
        if self.version < XENSERVER_5_6_0:
            raise SettingsNotAvailable, "version too old"

        self.mount_state()
        try:

            # timezone:
            tz = None
            clock_file = self.join_state_path("etc/sysconfig/clock")
            if os.path.exists(clock_file):
                fd = open(clock_file, "r")
                lines = fd.readlines()
                fd.close()
                for line in lines:
                    if line.startswith("ZONE="):
                        tz = line[5:].strip()
            if not tz:
                # No timezone found:
                # Supply a default and for interactive installs prompt the user.
                xelogging.log("No timezone configuration found.")
                results["request-timezone"] = True
                tz = "Europe/London"
            results["timezone"] = tz

            # hostname.  We will assume one was set anyway and thus write
            # it back into the new filesystem.  If one wasn't set then this
            # will be localhost.localdomain, in which case the old behaviour
            # will persist anyway:
            fd = open(self.join_state_path("etc/sysconfig/network"), "r")
            lines = fd.readlines()
            fd.close()
            for line in lines:
                if line.startswith("HOSTNAME="):
                    results["manual-hostname"] = (True, line[9:].strip())
            if not results.has_key("manual-hostname"):
                results["manual-hostname"] = (False, None)

            # nameservers:
            domain = None
            if not os.path.exists(self.join_state_path("etc/resolv.conf")):
                results["manual-nameservers"] = (False, None)
            else:
                ns = []
                fd = open(self.join_state_path("etc/resolv.conf"), "r")
                lines = fd.readlines()
                fd.close()
                for line in lines:
                    if line.startswith("nameserver "):
                        ns.append(line[11:].strip())
                    elif line.startswith("domain "):
                        domain = line[8:].strip()
                    elif line.startswith("search "):
                        domain = line.split()[1]
                results["manual-nameservers"] = (True, ns)

            # ntp servers:
            fd = open(self.join_state_path("etc/ntp.conf"), "r")
            lines = fd.readlines()
            fd.close()
            ntps = []
            for line in lines:
                if line.startswith("server "):
                    ntps.append(line[7:].strip())
            results["ntp-servers"] = ntps

            # keyboard:
            keyboard_file = self.join_state_path("etc/sysconfig/keyboard")
            if os.path.exists(keyboard_file):
                fd = open(keyboard_file, "r")
                lines = fd.readlines()
                fd.close()
                for line in lines:
                    if line.startswith("KEYTABLE="):
                        results["keymap"] = line[9:].strip()
            # Do not error here if no keymap configuration is found.
            # This enables upgrade to still carry state on hosts without
            # keymap configured:
            # A default keymap is assigned in the backend of this installer.
            if not results.has_key("keymap"):
                xelogging.log("No existing keymap configuration found.")

            # root password:
            fd = open(self.join_state_path("etc/passwd"), "r")
            root_pwd = None
            for line in fd:
                pwent = line.split(":")
                if pwent[0] == "root":
                    root_pwd = pwent[1]
                    break
            fd.close()

            if not root_pwd:
                raise SettingsNotAvailable, "no root password found"
            results["root-password"] = ("pwdhash", root_pwd)

            # don't care about this too much.
            results["time-config-method"] = "ntp"

            # read network configuration.  We only care to find out what the
            # management interface is, and what its configuration was.
            # The dev -> MAC mapping for other devices will be preserved in the
            # database which is available in time for everything except the
            # management interface.
            mgmt_iface = self.getInventoryValue("MANAGEMENT_INTERFACE")
            if os.path.exists(self.join_state_path(constants.DBCACHE)):

                def getText(nodelist):
                    rc = ""
                    for node in nodelist:
                        if node.nodeType == node.TEXT_NODE:
                            rc = rc + node.data
                    return rc.strip().encode()

                xmldoc = xml.dom.minidom.parse(self.join_state_path(constants.DBCACHE))

                pif_uid = None
                for node in xmldoc.documentElement.childNodes:
                    if node.nodeType == node.ELEMENT_NODE and node.tagName == "network":
                        network = node
                    else:
                        continue
                    # CA-50971: handle renamed networks in MNR
                    if (
                        len(network.getElementsByTagName("bridge")) == 0
                        or len(network.getElementsByTagName("PIFs")) == 0
                        or len(network.getElementsByTagName("PIFs")[0].getElementsByTagName("PIF")) == 0
                    ):
                        continue

                    if getText(network.getElementsByTagName("bridge")[0].childNodes) == mgmt_iface:
                        pif_uid = getText(
                            network.getElementsByTagName("PIFs")[0].getElementsByTagName("PIF")[0].childNodes
                        )
                        break
                if pif_uid:
                    for node in xmldoc.documentElement.childNodes:
                        if node.nodeType == node.ELEMENT_NODE and node.tagName == "pif":
                            pif = node
                        else:
                            continue
                        if pif.getAttribute("ref") == pif_uid:
                            results["net-admin-interface"] = getText(pif.getElementsByTagName("device")[0].childNodes)
                            results["net-admin-bridge"] = mgmt_iface
                            results["net-admin-configuration"] = NetInterface.loadFromPif(pif)
                            break
            else:
                for cfile in filter(
                    lambda x: True in [x.startswith(y) for y in ["ifcfg-eth", "ifcfg-bond"]],
                    os.listdir(self.join_state_path(constants.NET_SCR_DIR)),
                ):
                    devcfg = util.readKeyValueFile(
                        self.join_state_path(constants.NET_SCR_DIR, cfile), strip_quotes=False
                    )
                    if devcfg.has_key("DEVICE") and devcfg.has_key("BRIDGE") and devcfg["BRIDGE"] == mgmt_iface:
                        brcfg = util.readKeyValueFile(
                            self.join_state_path(constants.NET_SCR_DIR, "ifcfg-" + devcfg["BRIDGE"]), strip_quotes=False
                        )
                        results["net-admin-interface"] = devcfg["DEVICE"]
                        results["net-admin-bridge"] = devcfg["BRIDGE"]

                        # get hardware address if it was recorded, otherwise look it up:
                        if devcfg.has_key("HWADDR"):
                            hwaddr = devcfg["HWADDR"]
                        elif devcfg.has_key("MACADDR"):
                            # our bonds have a key called MACADDR instead
                            hwaddr = devcfg["MACADDR"]
                        else:
                            # XXX what if it's been renamed out of existence?
                            try:
                                hwaddr = netutil.getHWAddr(devcfg["DEVICE"])
                            except:
                                hwaddr = None

                        ifcfg = NetInterface.loadFromIfcfg(
                            self.join_state_path(constants.NET_SCR_DIR, "ifcfg-" + devcfg["BRIDGE"])
                        )
                        if not ifcfg.hwaddr:
                            ifcfg.hwaddr = hwaddr
                        if ifcfg.isStatic() and not ifcfg.domain and domain:
                            ifcfg.domain = domain
                        results["net-admin-configuration"] = ifcfg
                        break

            repo_list = []
            if os.path.exists(self.join_state_path(constants.INSTALLED_REPOS_DIR)):
                try:
                    for repo_id in os.listdir(self.join_state_path(constants.INSTALLED_REPOS_DIR)):
                        try:
                            repo = repository.Repository(
                                repository.FilesystemAccessor(
                                    self.join_state_path(constants.INSTALLED_REPOS_DIR, repo_id)
                                )
                            )
                            repo_list.append(
                                (repo.identifier(), repo.name(), (repo_id != constants.MAIN_REPOSITORY_NAME))
                            )
                        except repository.RepoFormatError:
                            # probably pre-XML format
                            repo = open(
                                self.join_state_path(
                                    constants.INSTALLED_REPOS_DIR, repo_id, repository.Repository.REPOSITORY_FILENAME
                                )
                            )
                            repo_id = repo.readline().strip()
                            repo_name = repo.readline().strip()
                            repo.close()
                            repo_list.append((repo_id, repo_name, (repo_id != constants.MAIN_REPOSITORY_NAME)))
                except Exception, e:
                    xelogging.log("Scan for driver disks failed:")
                    xelogging.log_exception(e)

            results["repo-list"] = repo_list

            results["ha-armed"] = False
            try:
                db = open(self.join_state_path("var/xapi/local.db"), "r")
                if db.readline().find('<row key="ha.armed" value="true"') != -1:
                    results["ha-armed"] = True
                db.close()
            except:
                pass

            results["master"] = None
            try:
                pt = open(self.join_state_path("etc/xensource/ptoken"), "r")
                results["pool-token"] = pt.readline().strip()
                pt.close()
                pc = open(self.join_state_path("etc/xensource/pool.conf"), "r")
                line = pc.readline().strip()
                if line.startswith("slave:"):
                    results["master"] = line[6:]
                pc.close()
            except:
                pass
Example #17
0
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"
Example #18
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/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)
                ])
Example #19
0
def readInventoryFile(filename):
    return util.readKeyValueFile(filename, strip_quotes=True)