class XendLocalStorageRepo(XendStorageRepository):
    """A backwards compatibility storage repository so that
    traditional file:/dir/file.img and phy:/dev/hdxx images can
    still be represented in terms of the Xen API.
    """
    def __init__(self,
                 sr_uuid,
                 sr_type='local',
                 name_label='Local',
                 name_description='Traditional Local Storage Repo'):
        """
        @ivar    images: mapping of all the images.
        @type    images: dictionary by image uuid.
        @ivar    lock:   lock to provide thread safety.
        """

        XendStorageRepository.__init__(self, sr_uuid, sr_type, name_label,
                                       name_description)

        self.state = XendStateStore(xendoptions().get_xend_state_path() +
                                    '/local_sr')

        stored_images = self.state.load_state('vdi')
        if stored_images:
            for image_uuid, image in stored_images.items():
                self.images[image_uuid] = XendLocalVDI(image)

    def create_vdi(self, vdi_struct):
        """ Creates a fake VDI image for a traditional image string.

        The image uri is stored in the attribute 'uri'
        """
        vdi_struct['uuid'] = uuid.createString()
        vdi_struct['SR'] = self.uuid
        new_image = XendLocalVDI(vdi_struct)
        self.images[new_image.uuid] = new_image
        self.save_state()
        return new_image.uuid

    def save_state(self):
        vdi_records = dict([(k, v.get_record(transient=False))
                            for k, v in self.images.items()])
        self.state.save_state('vdi', vdi_records)

    def destroy_vdi(self, vdi_uuid):
        if vdi_uuid in self.images:
            del self.images[vdi_uuid]

        self.save_state()
class XendLocalStorageRepo(XendStorageRepository):
    """A backwards compatibility storage repository so that
    traditional file:/dir/file.img and phy:/dev/hdxx images can
    still be represented in terms of the Xen API.
    """
    
    def __init__(self, sr_uuid, sr_type = 'local',
                 name_label = 'Local',
                 name_description = 'Traditional Local Storage Repo'):
        """
        @ivar    images: mapping of all the images.
        @type    images: dictionary by image uuid.
        @ivar    lock:   lock to provide thread safety.
        """

        XendStorageRepository.__init__(self, sr_uuid, sr_type,
                                       name_label, name_description)
        
        self.state = XendStateStore(xendoptions().get_xend_state_path()
                                    + '/local_sr')

        stored_images = self.state.load_state('vdi')
        if stored_images:
            for image_uuid, image in stored_images.items():
                self.images[image_uuid] = XendLocalVDI(image)

    def create_vdi(self, vdi_struct):
        """ Creates a fake VDI image for a traditional image string.

        The image uri is stored in the attribute 'uri'
        """
        vdi_struct['uuid'] = uuid.createString()
        vdi_struct['SR'] = self.uuid
        new_image =  XendLocalVDI(vdi_struct)
        self.images[new_image.uuid] = new_image
        self.save_state()
        return new_image.uuid

    def save_state(self):
        vdi_records = dict([(k, v.get_record(transient = False))
                            for k, v in self.images.items()])
        self.state.save_state('vdi', vdi_records)

    def destroy_vdi(self, vdi_uuid):
        if vdi_uuid in self.images:
            del self.images[vdi_uuid]

        self.save_state()
 def __init__(self, sr_uuid, sr_type='local_gpfs',
              name_label='local_gpfs',
              name_description='Traditional Local Storage Repo',
              other_config={'location':'/local_gpfs', 'auto-scan':'False'},
              content_type='vhd',
              shared=False,
              sm_config={}):
 
     XendGpfsStorageRepo.__init__(self, sr_uuid, sr_type,
                                    name_label, name_description)
     #log.debug(self.lock)
     #log.debug(self.uuid)
     self.type = sr_type
     self.name_label = name_label
     self.name_description = name_description
     self.other_config = other_config
     self.content_type = content_type
     self.shared = shared
     self.sm_config = sm_config
     
     self.location = other_config.get('location')
     encode_passwd = other_config.get('password')
     self.passwd = encoding.ansi_decode(encode_passwd)
     auto = other_config.get('auto-scan', False)
     self.gpfs_name = self._get_gpfs_location(self.location)
     
     self.state = XendStateStore(xendoptions().get_xend_state_path()
                                 + '/local_sr/%s' % self.uuid)
     stored_images = self.state.load_state('vdi')
     images_path = {}
     if stored_images:
         for image_uuid, image in stored_images.items():
             images_path[image['location'].replace(VDI_TYPE, '')] = image_uuid
             self.images[image_uuid] = XendGpfsVDI(image)
    def __init__(self,
                 sr_uuid,
                 sr_type='local',
                 name_label='Local',
                 name_description='Traditional Local Storage Repo'):
        """
        @ivar    images: mapping of all the images.
        @type    images: dictionary by image uuid.
        @ivar    lock:   lock to provide thread safety.
        """

        XendStorageRepository.__init__(self, sr_uuid, sr_type, name_label,
                                       name_description)

        self.state = XendStateStore(xendoptions().get_xend_state_path() +
                                    '/local_sr')

        stored_images = self.state.load_state('vdi')
        if stored_images:
            for image_uuid, image in stored_images.items():
                self.images[image_uuid] = XendLocalVDI(image)
    def __init__(self, sr_uuid, sr_type,
                 name_label, name_description, physical_size, other_config, content_type, shared, sm_config):
        """
        @ivar    images: mapping of all the images.
        @type    images: dictionary by image uuid.
        @ivar    lock:   lock to provide thread safety.
        """
        XendStorageRepository.__init__(self, sr_uuid, sr_type,
                                       name_label, name_description)
        #log.debug(self.lock)
        #log.debug(self.uuid)
        self.type = sr_type
        self.name_label = name_label
        self.name_description = name_description
        self.other_config = other_config
        self.content_type = content_type
        self.shared = shared
        self.sm_config = sm_config
#        location = other_config.get('location')
        encode_passwd = other_config.get('password')
        self.passwd = encoding.ansi_decode(encode_passwd)
        auto = other_config.get('auto-scan', True)
#        local = location.split(':')[1]
#        if cmp(int(storage_max())*KB, physical_size) > 0:
#            self.physical_size = physical_size
#        else:
        location = self.other_config.get('location')
        self.local_sr_dir = location
        self.location = location
        self.mount_point = self._get_mount_point(self.location)
#        s_max = storage_max(self.local_sr_dir)
#        if s_max:
#            self.physical_size = int(s_max)*KB
#        else:
#            self.physical_size = 0
#        s_util = storage_util(self.local_sr_dir)
#        if s_util:
#            self.physical_utilisation = int(s_util)*KB
#        else:
#            self.physical_utilisation = 0
#        d_util = dir_util(self.local_sr_dir)
#        if d_util:
#            self.virtual_allocation = int(d_util)*KB
#        else:
#            self.virtual_allocation = 0
        self.state = XendStateStore(xendoptions().get_xend_state_path()
                                    + '/gpfs_iso_sr/%s' % self.uuid)
        stored_images = self.state.load_state('vdi')
        images_path = {}
        if stored_images:
            for image_uuid, image in stored_images.items():
                images_path[image['location'].replace(VDI_TYPE, '')] = image_uuid
                self.images[image_uuid] = XendLocalVDI(image)
    def __init__(self, sr_uuid, sr_type='local',
                 name_label='local',
                 name_description='Traditional Local Storage Repo',
                 other_config={'location':'/home/local_sr', 'auto-scan':'False'},
                 content_type='vhd',
                 shared=False,
                 sm_config={}):
        """
        @ivar    images: mapping of all the images.
        @type    images: dictionary by image uuid.
        @ivar    lock:   lock to provide thread safety.
        """

        XendStorageRepository.__init__(self, sr_uuid, sr_type,
                                       name_label, name_description)
        
        self.type = sr_type
        self.name_label = name_label
        self.name_description = name_description
        self.other_config = other_config
        self.content_type = content_type
        self.shared = shared
        self.sm_config = sm_config
        self.local_sr_dir = self.other_config.get('location')
        self.location = self.local_sr_dir
#        self.local_sr_dir = os.path.join(self.location, self.uuid)
        if not os.path.exists(self.local_sr_dir): 
            os.makedirs(self.local_sr_dir)
#        s_max = storage_max(self.local_sr_dir)
#        if s_max:
#            self.physical_size = int(s_max)*KB
#        else:
#            self.physical_size = 0
#        s_util = storage_util(self.local_sr_dir)
#        if s_util:
#            self.physical_utilisation = int(s_util)*KB
#        else:
#            self.physical_utilisation = 0
#        d_util = dir_util(self.local_sr_dir)
#        if d_util:
#            self.virtual_allocation = int(d_util)*KB
#        else:
#            self.virtual_allocation = 0       
        
        self.state = XendStateStore(xendoptions().get_xend_state_path()
                                    + '/local_sr/%s' % self.uuid)

        stored_images = self.state.load_state('vdi')
        if stored_images:
            for image_uuid, image in stored_images.items():
                self.images[image_uuid] = XendLocalVDI(image)
    def __init__(self, sr_uuid, sr_type,
                 name_label, name_description, physical_size, other_config, content_type, shared, sm_config):
        """
        @ivar    images: mapping of all the images.
        @type    images: dictionary by image uuid.
        @ivar    lock:   lock to provide thread safety.
        """

        XendStorageRepository.__init__(self, sr_uuid, sr_type,
                                       name_label, name_description)
        #log.debug(self.lock)
        #log.debug(self.uuid)
        self.record_changed = True
        
        self.type = sr_type
        self.name_label = name_label
        self.name_description = name_description
        self.other_config = other_config
        self.content_type = content_type
        self.shared = shared
        self.sm_config = sm_config
        location = other_config.get('location')
        auto = other_config.get('auto-scan', True)
        self.local_sr_dir = DEFAULT_HA_PATH
#        encode_passwd = other_config.get('password')
#        self.passwd = encoding.ansi_decode(encode_passwd)
#        if cmp(int(storage_free())*KB, physical_size) > 0:
#            self.physical_size = physical_size
#        else:
#        s_max = storage_max()
#        if s_max:
#            self.physical_size = int(s_max)*KB
#        else:
#            self.physical_size = 0
#        s_util = storage_util()
#        if s_util:
#            self.physical_utilisation = int(s_util)*KB
#        else:
#            self.physical_utilisation = 0
#        self.virtual_allocation = self.physical_size
        self.state = XendStateStore(xendoptions().get_xend_state_path()
                                    + '/nfs_ha_sr/%s' % self.uuid)
        stored_images = self.state.load_state('vdi')
        images_path = {}
        if stored_images:
            for image_uuid, image in stored_images.items():
                images_path[image['location']] = image_uuid
                self.images[image_uuid] = XendLocalVDI(image)
    def __init__(self, sr_uuid, sr_type = 'local',
                 name_label = 'Local',
                 name_description = 'Traditional Local Storage Repo'):
        """
        @ivar    images: mapping of all the images.
        @type    images: dictionary by image uuid.
        @ivar    lock:   lock to provide thread safety.
        """

        XendStorageRepository.__init__(self, sr_uuid, sr_type,
                                       name_label, name_description)
        
        self.state = XendStateStore(xendoptions().get_xend_state_path()
                                    + '/local_sr')

        stored_images = self.state.load_state('vdi')
        if stored_images:
            for image_uuid, image in stored_images.items():
                self.images[image_uuid] = XendLocalVDI(image)
    def __init__(self, sr_uuid, sr_type,
                 name_label, name_description, physical_size, other_config, content_type, shared, sm_config):
        """
        @ivar    images: mapping of all the images.
        @type    images: dictionary by image uuid.
        @ivar    lock:   lock to provide thread safety.
        """

        XendStorageRepository.__init__(self, sr_uuid, sr_type,
                                       name_label, name_description)
        #log.debug(self.lock)
        #log.debug(self.uuid)
        self.type = sr_type
        self.name_label = name_label
        self.name_description = name_description
        self.other_config = other_config
        self.content_type = content_type
        self.shared = shared
        self.sm_config = sm_config
        location = other_config.get('location')
        auto = other_config.get('auto-scan', False)
        self.local_sr_dir = self.other_config.get('location')
        self.location = location
#        if cmp(int(storage_free())*KB, physical_size) > 0:
#            self.physical_size = physical_size
#        else:
#        self.physical_size = int(storage_max())*KB
#        self.physical_utilisation = int(storage_util())*KB
#        self.virtual_allocation = self.physical_size
        self.state = XendStateStore(xendoptions().get_xend_state_path()
                                    + '/iso_sr/%s' % self.uuid)
        stored_images = self.state.load_state('vdi')
        images_path = {}
        if stored_images:
            for image_uuid, image in stored_images.items():
                images_path[image['location'].replace(VDI_TYPE, '')] = image_uuid
                self.images[image_uuid] = XendLocalVDI(image)
Beispiel #10
0
    def __init__(self):
        """Initalises the state of all host specific objects such as

        * host
        * host_CPU
        * host_metrics
        * PIF
        * PIF_metrics
        * network
        * Storage Repository
        * PPCI
        """

        self.xc = xen.lowlevel.xc.xc()
        self.state_store = XendStateStore(xendoptions().get_xend_state_path())
        self.monitor = XendMonitor()
        self.monitor.start()

        # load host state from XML file
        saved_host = self.state_store.load_state('host')
        if saved_host and len(saved_host.keys()) == 1:
            self.uuid = saved_host.keys()[0]
            host = saved_host[self.uuid]
            self.name = host.get('name_label', socket.gethostname())
            self.desc = host.get('name_description', '')
            self.host_metrics_uuid = host.get('metrics_uuid',
                                              uuid.createString())
            try:
                self.other_config = eval(host['other_config'])
            except:
                self.other_config = {}
            self.cpus = {}
        else:
            self.uuid = uuid.createString()
            self.name = socket.gethostname()
            self.desc = ''
            self.other_config = {}
            self.cpus = {}
            self.host_metrics_uuid = uuid.createString()

        # put some arbitrary params in other_config as this
        # is directly exposed via XenAPI
        self.other_config["xen_pagesize"] = self.xeninfo_dict()["xen_pagesize"]
        self.other_config["platform_params"] = self.xeninfo_dict(
        )["platform_params"]

        # load CPU UUIDs
        saved_cpus = self.state_store.load_state('cpu')
        for cpu_uuid, cpu in saved_cpus.items():
            self.cpus[cpu_uuid] = cpu

        cpuinfo = osdep.get_cpuinfo()
        physinfo = self.physinfo_dict()
        cpu_count = physinfo['nr_cpus']
        cpu_features = physinfo['hw_caps']
        virt_caps = physinfo['virt_caps']

        # If the number of CPUs don't match, we should just reinitialise
        # the CPU UUIDs.
        if cpu_count != len(self.cpus):
            self.cpus = {}
            for i in range(cpu_count):
                u = uuid.createString()
                self.cpus[u] = {'uuid': u, 'number': i}

        for u in self.cpus.keys():
            number = self.cpus[u]['number']
            # We can run off the end of the cpuinfo list if domain0 does not
            # have #vcpus == #pcpus. In that case we just replicate one that's
            # in the hash table.
            if not cpuinfo.has_key(number):
                number = cpuinfo.keys()[0]
            if arch.type == "x86":
                self.cpus[u].update({
                    'host':
                    self.uuid,
                    'features':
                    cpu_features,
                    'virt_caps':
                    virt_caps,
                    'speed':
                    int(float(cpuinfo[number]['cpu MHz'])),
                    'vendor':
                    cpuinfo[number]['vendor_id'],
                    'modelname':
                    cpuinfo[number]['model name'],
                    'stepping':
                    cpuinfo[number]['stepping'],
                    'flags':
                    cpuinfo[number]['flags'],
                })
            elif arch.type == "ia64":
                self.cpus[u].update({
                    'host':
                    self.uuid,
                    'features':
                    cpu_features,
                    'speed':
                    int(float(cpuinfo[number]['cpu MHz'])),
                    'vendor':
                    cpuinfo[number]['vendor'],
                    'modelname':
                    cpuinfo[number]['family'],
                    'stepping':
                    cpuinfo[number]['model'],
                    'flags':
                    cpuinfo[number]['features'],
                })
            else:
                self.cpus[u].update({
                    'host': self.uuid,
                    'features': cpu_features,
                })

        self.srs = {}

        # Initialise networks
        # First configure ones off disk
        saved_networks = self.state_store.load_state('network')
        if saved_networks:
            for net_uuid, network in saved_networks.items():
                try:
                    XendNetwork.recreate(network, net_uuid)
                except CreateUnspecifiedAttributeError:
                    log.warn("Error recreating network %s", net_uuid)

        # Next discover any existing bridges and check
        # they are not already configured
        bridges = Brctl.get_state().keys()
        configured_bridges = [
            XendAPIStore.get(network_uuid, "network").get_name_label()
            for network_uuid in XendNetwork.get_all()
        ]
        unconfigured_bridges = [
            bridge for bridge in bridges if bridge not in configured_bridges
        ]
        for unconfigured_bridge in unconfigured_bridges:
            XendNetwork.create_phy(unconfigured_bridge)

        # Initialise PIFs
        # First configure ones off disk
        saved_pifs = self.state_store.load_state('pif')
        if saved_pifs:
            for pif_uuid, pif in saved_pifs.items():
                try:
                    XendPIF.recreate(pif, pif_uuid)
                except CreateUnspecifiedAttributeError:
                    log.warn("Error recreating PIF %s", pif_uuid)

        # Next discover any existing PIFs and check
        # they are not already configured
        configured_pifs = [
            XendAPIStore.get(pif_uuid, "PIF").get_interface_name()
            for pif_uuid in XendPIF.get_all()
        ]
        unconfigured_pifs = [(name, mtu, mac)
                             for name, mtu, mac in linux_get_phy_ifaces()
                             if name not in configured_pifs]

        # Get a mapping from interface to bridge
        if_to_br = dict([(i, b) for (b, ifs) in Brctl.get_state().items()
                         for i in ifs])

        for name, mtu, mac in unconfigured_pifs:
            # Check PIF is on bridge
            # if not, ignore
            bridge_name = if_to_br.get(name, None)
            if bridge_name is not None:
                # Translate bridge name to network uuid
                for network_uuid in XendNetwork.get_all():
                    network = XendAPIStore.get(network_uuid, 'network')
                    if network.get_name_label() == bridge_name:
                        XendPIF.create_phy(network_uuid, name, mac, mtu)
                        break
                else:
                    log.debug(
                        "Cannot find network for bridge %s "
                        "when configuring PIF %s", (bridge_name, name))

        # initialise storage
        saved_srs = self.state_store.load_state('sr')
        if saved_srs:
            for sr_uuid, sr_cfg in saved_srs.items():
                if sr_cfg['type'] == 'qcow_file':
                    self.srs[sr_uuid] = XendQCoWStorageRepo(sr_uuid)
                elif sr_cfg['type'] == 'local':
                    self.srs[sr_uuid] = XendLocalStorageRepo(sr_uuid)

        # Create missing SRs if they don't exist
        if not self.get_sr_by_type('local'):
            image_sr_uuid = uuid.createString()
            self.srs[image_sr_uuid] = XendLocalStorageRepo(image_sr_uuid)

        if not self.get_sr_by_type('qcow_file'):
            qcow_sr_uuid = uuid.createString()
            self.srs[qcow_sr_uuid] = XendQCoWStorageRepo(qcow_sr_uuid)

        saved_pbds = self.state_store.load_state('pbd')
        if saved_pbds:
            for pbd_uuid, pbd_cfg in saved_pbds.items():
                try:
                    XendPBD.recreate(pbd_uuid, pbd_cfg)
                except CreateUnspecifiedAttributeError:
                    log.warn("Error recreating PBD %s", pbd_uuid)

        # Initialise PPCIs
        saved_ppcis = self.state_store.load_state('ppci')
        saved_ppci_table = {}
        if saved_ppcis:
            for ppci_uuid, ppci_record in saved_ppcis.items():
                try:
                    saved_ppci_table[ppci_record['name']] = ppci_uuid
                except KeyError:
                    pass

        for pci_dev in PciUtil.get_all_pci_devices():
            ppci_record = {
                'domain': pci_dev.domain,
                'bus': pci_dev.bus,
                'slot': pci_dev.slot,
                'func': pci_dev.func,
                'vendor_id': pci_dev.vendor,
                'vendor_name': pci_dev.vendorname,
                'device_id': pci_dev.device,
                'device_name': pci_dev.devicename,
                'revision_id': pci_dev.revision,
                'class_code': pci_dev.classcode,
                'class_name': pci_dev.classname,
                'subsystem_vendor_id': pci_dev.subvendor,
                'subsystem_vendor_name': pci_dev.subvendorname,
                'subsystem_id': pci_dev.subdevice,
                'subsystem_name': pci_dev.subdevicename,
                'driver': pci_dev.driver
            }
            # If saved uuid exists, use it. Otherwise create one.
            ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
            XendPPCI(ppci_uuid, ppci_record)
class XendNFSHAStorageRepo(XendStorageRepository):
    """A backwards compatibility storage repository so that
    traditional file:/dir/file.img and phy:/dev/hdxx images can
    still be represented in terms of the Xen API.
    """
    
    def __init__(self, sr_uuid, sr_type,
                 name_label, name_description, physical_size, other_config, content_type, shared, sm_config):
        """
        @ivar    images: mapping of all the images.
        @type    images: dictionary by image uuid.
        @ivar    lock:   lock to provide thread safety.
        """

        XendStorageRepository.__init__(self, sr_uuid, sr_type,
                                       name_label, name_description)
        #log.debug(self.lock)
        #log.debug(self.uuid)
        self.record_changed = True
        
        self.type = sr_type
        self.name_label = name_label
        self.name_description = name_description
        self.other_config = other_config
        self.content_type = content_type
        self.shared = shared
        self.sm_config = sm_config
        location = other_config.get('location')
        auto = other_config.get('auto-scan', True)
        self.local_sr_dir = DEFAULT_HA_PATH
#        encode_passwd = other_config.get('password')
#        self.passwd = encoding.ansi_decode(encode_passwd)
#        if cmp(int(storage_free())*KB, physical_size) > 0:
#            self.physical_size = physical_size
#        else:
#        s_max = storage_max()
#        if s_max:
#            self.physical_size = int(s_max)*KB
#        else:
#            self.physical_size = 0
#        s_util = storage_util()
#        if s_util:
#            self.physical_utilisation = int(s_util)*KB
#        else:
#            self.physical_utilisation = 0
#        self.virtual_allocation = self.physical_size
        self.state = XendStateStore(xendoptions().get_xend_state_path()
                                    + '/nfs_ha_sr/%s' % self.uuid)
        stored_images = self.state.load_state('vdi')
        images_path = {}
        if stored_images:
            for image_uuid, image in stored_images.items():
                images_path[image['location']] = image_uuid
                self.images[image_uuid] = XendLocalVDI(image)
#        self.update(auto, False)
    
    def update(self, auto=True, del_vdi=True):
        location = self.other_config.get('location')
        local = os.path.join(location.split(':')[1], self.uuid)
        log.debug(local)
#        local = location.split(':')[1]
        stored_images = self.state.load_state('vdi')
        images_path = {}
        if stored_images:
            for image_uuid, image in stored_images.items():
                images_path[image['location']] = image_uuid
                self.images[image_uuid] = XendLocalVDI(image)
        if auto:
            sxps = sxp_files(local)
            log.debug(sxps)
            vdi_struct = {}
            if sxps:
                for sxp in sxps.keys():
                    if sxp not in images_path.keys():
                        vdi_struct['other_config'] = {'virtual_machine' : self.get_domain_name_by_sxp(sxp),\
                                                      'vm_uuid' : self.get_domain_uuid_by_sxp(sxp)}
                        log.debug(vdi_struct['other_config'])
                        vdi_struct['location'] = sxp
                        vdi_struct['type'] = 'system'
                        vdi_struct['physical_utilisation'] = sxps[sxp]
                        vdi_struct['VBDs'] = []
#                        dir_name = os.path.dirname(sxp)
                        vdi_struct['name_label'] = XendNode.instance().get_name()
                        #XendTask.log_progress(0, 100, self.create_vdi_append_state, vdi_struct)
        #                self.images[image_new] = XendLocalVDI(image)
                        self.create_vdi_append_state(vdi_struct)
        stored_images = self.state.load_state('vdi')
        images_path = {}
        if stored_images:
            for image_uuid, image in stored_images.items():
                images_path[image['location']] = image_uuid
                self.images[image_uuid] = XendLocalVDI(image)
        if del_vdi and images_path: 
            log.debug(images_path.items())
            for img,vdi_uuid in images_path.items():
                if img not in sxps.keys():
                    self.destroy_vdi(vdi_uuid)      
#            xmls = xml_files(local)
#            vdi_struct = {}
#            for xml in xmls.keys():
#                if xml not in images_path.keys():
#                    vdi_struct['other_config'] = {'location':xml}
#                    vdi_struct['type'] = 'system'
#                    vdi_struct['physical_utilisation'] = xmls[xml]
#                    vdi_struct['VBDs'] = []
##                    dir_name = os.path.dirname(xml)
#                    vdi_struct['name_label'] = xml   
                    
    def get_record(self, transient = True):
        if self.record_changed:
            self.cached_record = {'uuid': self.uuid,
                  'name_label': self.name_label,
                  'name_description': self.name_description,
                  'resident_on' : XendNode.instance().uuid,
                  'virtual_allocation': 0,
                  'physical_utilisation': self.get_physical_utilisation(),
                  'physical_size': self.get_physical_size(),
                  'type': self.type,
                  'content_type': self.content_type,
                  'VDIs': self.images.keys(),
                  'PBDs': XendPBD.get_by_SR(self.uuid),
                  'other_config': self.other_config,
                  'shared': self.shared,
                  'sm_config': self.sm_config,
                  'virtual_allocation': self.virtual_allocation}
            self.record_changed = False
        return self.cached_record
    
    def get_physical_utilisation(self):
        s_util = storage_util(self.local_sr_dir)
        if s_util:
            self.physical_utilisation = int(s_util)*KB
        else:
            self.physical_utilisation = 0
        return self.physical_utilisation
        
    def get_physical_size(self):
        s_max = storage_max(self.local_sr_dir)
        if s_max:
            self.physical_size = int(s_max)*KB
        else:
            self.physical_size = 0   
        return self.physical_size  

    def create_vdi_append_state(self, vdi_struct, transient = True):
        """ Creates a fake VDI image for a traditional image string.

        The image uri is stored in the attribute 'uri'
        """
        f = open("/opt/xen/bug", "a")
        
#        if not vdi_struct.get('uuid') or vdi_struct.get('uuid') == '':
        vdi_struct['uuid'] = uuid.createString()
        vdi_struct['SR'] = self.uuid
        new_image = XendLocalVDI(vdi_struct)
#        if vdi_struct.get('type') == 'user':            
##            self.create_img_file(vdi_struct)
#            self.create_logical_volume(vdi_struct)    
        self.images[new_image.uuid] = new_image
        self.append_state(new_image, transient)
        f.write("go to here\n")
        f.close()
        return new_image.uuid
    
    def del_img_file_from_ssh(self, vdi_uuid):
#        location = self.other_config['location']
#        host_url = location.split(':')[0]
#        local = location.split(':')[1]
        location = self.images[vdi_uuid].location
#        file = '%s/%s' %(local, vdi_name)
        cmd = 'rm -f %s' % location
        (rc, stdout, stderr) = doexec(cmd)
        if rc != 0:
            err = stderr.read();
            out = stdout.read();
            stdout.close();
            stderr.close();
            raise Exception, 'Failed to execute rm -f %s.%s' %(location, err);
        stdout.close();
        stderr.close();  
            
    def get_domain_name_by_sxp(self, path):
        try:
            sxp_obj = sxp.parse(open(path, 'r'))
            sxp_obj = sxp_obj[0]
        except IOError, e:
            raise XendConfigError("Unable to read file: %s" % path)
        return sxp.child_value(sxp_obj, 'name_label', 'UNKNOWN')
Beispiel #12
0
class XendNode:
    """XendNode - Represents a Domain 0 Host."""
    
    def __init__(self):
        """Initalises the state of all host specific objects such as

        * host
        * host_CPU
        * host_metrics
        * PIF
        * PIF_metrics
        * network
        * Storage Repository
        * PPCI
        * PSCSI
        """
        
        self.xc = xen.lowlevel.xc.xc()
        self.state_store = XendStateStore(xendoptions().get_xend_state_path())
        self.monitor = XendMonitor()
        self.monitor.start()

        # load host state from XML file
        saved_host = self.state_store.load_state('host')
        if saved_host and len(saved_host.keys()) == 1:
            self.uuid = saved_host.keys()[0]
            host = saved_host[self.uuid]
            self.name = host.get('name_label', socket.gethostname())
            self.desc = host.get('name_description', '')
            self.host_metrics_uuid = host.get('metrics_uuid',
                                              uuid.createString())
            try:
                self.other_config = eval(host['other_config'])
            except:
                self.other_config = {}
            self.cpus = {}
        else:
            self.uuid = uuid.createString()
            self.name = socket.gethostname()
            self.desc = ''
            self.other_config = {}
            self.cpus = {}
            self.host_metrics_uuid = uuid.createString()

        # put some arbitrary params in other_config as this
        # is directly exposed via XenAPI
        self.other_config["xen_pagesize"] = self.xeninfo_dict()["xen_pagesize"]
        self.other_config["platform_params"] = self.xeninfo_dict()["platform_params"]
        self.other_config["xen_commandline"] = self.xeninfo_dict()["xen_commandline"]
            
        # load CPU UUIDs
        saved_cpus = self.state_store.load_state('cpu')
        for cpu_uuid, cpu in saved_cpus.items():
            self.cpus[cpu_uuid] = cpu

        cpuinfo = osdep.get_cpuinfo()
        physinfo = self.physinfo_dict()
        cpu_count = physinfo['nr_cpus']
        cpu_features = physinfo['hw_caps']
        virt_caps = physinfo['virt_caps']

        # If the number of CPUs don't match, we should just reinitialise 
        # the CPU UUIDs.
        if cpu_count != len(self.cpus):
            self.cpus = {}
            for i in range(cpu_count):
                u = uuid.createString()
                self.cpus[u] = {'uuid': u, 'number': i }

        for u in self.cpus.keys():
            number = self.cpus[u]['number']
            # We can run off the end of the cpuinfo list if domain0 does not
            # have #vcpus == #pcpus. In that case we just replicate one that's
            # in the hash table.
            if not cpuinfo.has_key(number):
                number = cpuinfo.keys()[0]
            if arch.type == "x86":
                self.cpus[u].update(
                    { 'host'     : self.uuid,
                      'features' : cpu_features,
                      'virt_caps': virt_caps,
                      'speed'    : int(float(cpuinfo[number]['cpu MHz'])),
                      'vendor'   : cpuinfo[number]['vendor_id'],
                      'modelname': cpuinfo[number]['model name'],
                      'stepping' : cpuinfo[number]['stepping'],
                      'flags'    : cpuinfo[number]['flags'],
                    })
            elif arch.type == "ia64":
                self.cpus[u].update(
                    { 'host'     : self.uuid,
                      'features' : cpu_features,
                      'speed'    : int(float(cpuinfo[number]['cpu MHz'])),
                      'vendor'   : cpuinfo[number]['vendor'],
                      'modelname': cpuinfo[number]['family'],
                      'stepping' : cpuinfo[number]['model'],
                      'flags'    : cpuinfo[number]['features'],
                    })
            else:
                self.cpus[u].update(
                    { 'host'     : self.uuid,
                      'features' : cpu_features,
                    })

        self.srs = {}

        self._init_networks()
        self._init_PIFs()

        self._init_SRs()
        self._init_PBDs()

        self._init_PPCIs()

        self._init_PSCSIs()

        self._init_cpu_pools()


    def _init_networks(self):
        # Initialise networks
        # First configure ones off disk
        saved_networks = self.state_store.load_state('network')
        if saved_networks:
            for net_uuid, network in saved_networks.items():
                try:
                    XendNetwork.recreate(network, net_uuid)
                except CreateUnspecifiedAttributeError:
                    log.warn("Error recreating network %s", net_uuid)
                
        # Next discover any existing bridges and check
        # they are not already configured

        # 'tmpbridge' is a temporary bridge created by network-bridge script.
        # Wait a couple of seconds for it to be renamed.
        for i in xrange(20):
            bridges = Brctl.get_state().keys()
            if 'tmpbridge' in bridges:
                time.sleep(0.1)
            else:
                break
            
        configured_bridges = [XendAPIStore.get(
                                  network_uuid, "network")
                                      .get_name_label()
                              for network_uuid in XendNetwork.get_all()]
        unconfigured_bridges = [bridge
                                for bridge in bridges
                                if bridge not in configured_bridges]
        for unconfigured_bridge in unconfigured_bridges:
            if unconfigured_bridge != 'tmpbridge':
                XendNetwork.create_phy(unconfigured_bridge)

    def _init_PIFs(self):
        # Initialise PIFs
        # First configure ones off disk
        saved_pifs = self.state_store.load_state('pif')
        if saved_pifs:
            for pif_uuid, pif in saved_pifs.items():
                try:
                    XendPIF.recreate(pif, pif_uuid)
                except CreateUnspecifiedAttributeError:
                    log.warn("Error recreating PIF %s", pif_uuid)
        
        # Next discover any existing PIFs and check
        # they are not already configured
        configured_pifs = [XendAPIStore.get(
                               pif_uuid, "PIF")
                                   .get_interface_name()
                           for pif_uuid in XendPIF.get_all()]
        unconfigured_pifs = [(name, mtu, mac)
                             for name, mtu, mac in linux_get_phy_ifaces()
                             if name not in configured_pifs]

        # Get a mapping from interface to bridge          
        if_to_br = dict([(i,b)
                         for (b,ifs) in Brctl.get_state().items()
                             for i in ifs])

        for name, mtu, mac in unconfigured_pifs:
            # Check PIF is on bridge
            # if not, ignore
            bridge_name = if_to_br.get(name, None)
            if bridge_name is not None:
                # Translate bridge name to network uuid
                for network_uuid in XendNetwork.get_all():
                    network = XendAPIStore.get(
                        network_uuid, 'network')
                    if network.get_name_label() == bridge_name:
                        XendPIF.create_phy(network_uuid, name,
                                           mac, mtu)
                        break
                else:
                    log.debug("Cannot find network for bridge %s "
                              "when configuring PIF %s",
                              (bridge_name, name))     

    def _init_SRs(self):
        # initialise storage
        saved_srs = self.state_store.load_state('sr')
        if saved_srs:
            for sr_uuid, sr_cfg in saved_srs.items():
                if sr_cfg['type'] == 'qcow_file':
                    self.srs[sr_uuid] = XendQCoWStorageRepo(sr_uuid)
                elif sr_cfg['type'] == 'local':
                    self.srs[sr_uuid] = XendLocalStorageRepo(sr_uuid)

        # Create missing SRs if they don't exist
        if not self.get_sr_by_type('local'):
            image_sr_uuid = uuid.createString()
            self.srs[image_sr_uuid] = XendLocalStorageRepo(image_sr_uuid)
            
        if not self.get_sr_by_type('qcow_file'):
            qcow_sr_uuid = uuid.createString()
            self.srs[qcow_sr_uuid] = XendQCoWStorageRepo(qcow_sr_uuid)

    def _init_PBDs(self):
        saved_pbds = self.state_store.load_state('pbd')
        if saved_pbds:
            for pbd_uuid, pbd_cfg in saved_pbds.items():
                try:
                    XendPBD.recreate(pbd_uuid, pbd_cfg)
                except CreateUnspecifiedAttributeError:
                    log.warn("Error recreating PBD %s", pbd_uuid) 

    def _init_PPCIs(self):
        saved_ppcis = self.state_store.load_state('ppci')
        saved_ppci_table = {}
        if saved_ppcis:
            for ppci_uuid, ppci_record in saved_ppcis.items():
                try:
                    saved_ppci_table[ppci_record['name']] = ppci_uuid
                except KeyError:
                    pass

        for pci_dev in PciUtil.get_all_pci_devices():
            ppci_record = {
                'domain':                   pci_dev.domain,
                'bus':                      pci_dev.bus,
                'slot':                     pci_dev.slot,
                'func':                     pci_dev.func,
                'vendor_id':                pci_dev.vendor,
                'vendor_name':              pci_dev.vendorname,
                'device_id':                pci_dev.device,
                'device_name':              pci_dev.devicename,
                'revision_id':              pci_dev.revision,
                'class_code':               pci_dev.classcode,
                'class_name':               pci_dev.classname,
                'subsystem_vendor_id':      pci_dev.subvendor,
                'subsystem_vendor_name':    pci_dev.subvendorname,
                'subsystem_id':             pci_dev.subdevice,
                'subsystem_name':           pci_dev.subdevicename,
                'driver':                   pci_dev.driver
                }
            # If saved uuid exists, use it. Otherwise create one.
            ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
            XendPPCI(ppci_uuid, ppci_record)

    def _init_PSCSIs(self):
        # Initialise PSCSIs and PSCSI_HBAs
        saved_pscsis = self.state_store.load_state('pscsi')
        saved_pscsi_table = {}
        if saved_pscsis:
            for pscsi_uuid, pscsi_record in saved_pscsis.items():
                try:
                    saved_pscsi_table[pscsi_record['scsi_id']] = pscsi_uuid
                except KeyError:
                    pass

        saved_pscsi_HBAs = self.state_store.load_state('pscsi_HBA')
        saved_pscsi_HBA_table = {}
        if saved_pscsi_HBAs:
            for pscsi_HBA_uuid, pscsi_HBA_record in saved_pscsi_HBAs.items():
                try:
                    physical_host = int(pscsi_HBA_record['physical_host'])
                    saved_pscsi_HBA_table[physical_host] = pscsi_HBA_uuid
                except (KeyError, ValueError):
                    pass

        pscsi_table = {}
        pscsi_HBA_table = {}

        pscsi_records = []
        for pscsi_mask in xendoptions().get_pscsi_device_mask():
            pscsi_records += vscsi_util.get_all_scsi_devices(pscsi_mask)
        log.debug("pscsi record count: %s" % len(pscsi_records))

        for pscsi_record in pscsi_records:
            scsi_id = pscsi_record['scsi_id']
            if scsi_id:
                saved_HBA_uuid = None

                pscsi_uuid = saved_pscsi_table.get(scsi_id, None)
                if pscsi_uuid is None:
                    pscsi_uuid = uuid.createString()
                    saved_pscsi_table[scsi_id] = pscsi_uuid
                else:
                    try:
                        saved_HBA_uuid = saved_pscsis[pscsi_uuid].get('HBA', None)
                    except KeyError:
                        log.warn("Multi-path SCSI devices are not supported for XenAPI")
                        return

                physical_host = int(pscsi_record['physical_HCTL'].split(':')[0])
                if pscsi_HBA_table.has_key(physical_host):
                    pscsi_HBA_uuid = pscsi_HBA_table[physical_host]
                elif saved_pscsi_HBA_table.has_key(physical_host):
                    pscsi_HBA_uuid = saved_pscsi_HBA_table[physical_host]
                    pscsi_HBA_table[physical_host] = pscsi_HBA_uuid
                else:
                    pscsi_HBA_uuid = uuid.createString()
                    pscsi_HBA_table[physical_host] = pscsi_HBA_uuid

                if saved_HBA_uuid is not None and \
                   saved_HBA_uuid != pscsi_HBA_uuid:
                    log.debug('The PSCSI(%s) host number was changed', scsi_id)
                pscsi_record['HBA'] = pscsi_HBA_uuid
                pscsi_table[pscsi_uuid] = pscsi_record

        for pscsi_uuid, pscsi_record in pscsi_table.items():
            XendPSCSI(pscsi_uuid, pscsi_record)

        for physical_host, pscsi_HBA_uuid in pscsi_HBA_table.items():
            XendPSCSI_HBA(pscsi_HBA_uuid, {'physical_host': physical_host})

    def _init_cpu_pools(self):
        # Initialise cpu_pools
        saved_cpu_pools = self.state_store.load_state(XendCPUPool.getClass())
        if saved_cpu_pools:
            for cpu_pool_uuid, cpu_pool in saved_cpu_pools.items():
                try:
                    XendCPUPool.recreate(cpu_pool, cpu_pool_uuid)
                except CreateUnspecifiedAttributeError:
                    log.warn("Error recreating %s %s",
                             (XendCPUPool.getClass(), cpu_pool_uuid))
        XendCPUPool.recreate_active_pools()


    def add_network(self, interface):
        # TODO
        log.debug("add_network(): Not implemented.")


    def remove_network(self, interface):
        # TODO
        log.debug("remove_network(): Not implemented.")


    def add_PPCI(self, pci_name):
        # Update lspci info
        PciUtil.create_lspci_info()

        # Initialise the PPCI
        saved_ppcis = self.state_store.load_state('ppci')
        saved_ppci_table = {}
        if saved_ppcis:
            for ppci_uuid, ppci_record in saved_ppcis.items():
                try:
                    saved_ppci_table[ppci_record['name']] = ppci_uuid
                except KeyError:
                    pass

        pci_dev = PciUtil.PciDevice(PciUtil.parse_pci_name(pci_name))
        ppci_record = {
            'domain':                   pci_dev.domain,
            'bus':                      pci_dev.bus,
            'slot':                     pci_dev.slot,
            'func':                     pci_dev.func,
            'vendor_id':                pci_dev.vendor,
            'vendor_name':              pci_dev.vendorname,
            'device_id':                pci_dev.device,
            'device_name':              pci_dev.devicename,
            'revision_id':              pci_dev.revision,
            'class_code':               pci_dev.classcode,
            'class_name':               pci_dev.classname,
            'subsystem_vendor_id':      pci_dev.subvendor,
            'subsystem_vendor_name':    pci_dev.subvendorname,
            'subsystem_id':             pci_dev.subdevice,
            'subsystem_name':           pci_dev.subdevicename,
            'driver':                   pci_dev.driver
            }
        # If saved uuid exists, use it. Otherwise create one.
        ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
        XendPPCI(ppci_uuid, ppci_record)

        self.save_PPCIs()


    def remove_PPCI(self, pci_name):
        # Update lspci info
        PciUtil.create_lspci_info()

        # Remove the PPCI
        (domain, bus, slot, func) = PciUtil.parse_pci_name(pci_name)
        ppci_ref = XendPPCI.get_by_sbdf(domain, bus, slot, func)
        XendAPIStore.get(ppci_ref, "PPCI").destroy()

        self.save_PPCIs()


    def add_PSCSI(self, add_HCTL):
        saved_pscsis = self.state_store.load_state('pscsi')
        saved_pscsi_table = {}
        if saved_pscsis:
            for saved_uuid, saved_record in saved_pscsis.items():
                try:
                    saved_pscsi_table[saved_record['scsi_id']] = saved_uuid
                except KeyError:
                    pass

        saved_pscsi_HBAs = self.state_store.load_state('pscsi_HBA')
        saved_pscsi_HBA_table = {}
        if saved_pscsi_HBAs:
            for saved_HBA_uuid, saved_HBA_record in saved_pscsi_HBAs.items():
                try:
                    physical_host = int(saved_HBA_record['physical_host'])
                    saved_pscsi_HBA_table[physical_host] = saved_HBA_uuid
                except (KeyError, ValueError):
                    pass

        # Initialise the PSCSI and the PSCSI_HBA
        pscsi_record = vscsi_util.get_scsi_device(add_HCTL)
        if pscsi_record and pscsi_record['scsi_id']:
            pscsi_uuid = saved_pscsi_table.get(pscsi_record['scsi_id'], None)
            if pscsi_uuid is None:
                physical_host = int(add_HCTL.split(':')[0])
                pscsi_HBA_uuid = saved_pscsi_HBA_table.get(physical_host, None)
                if pscsi_HBA_uuid is None:
                    pscsi_HBA_uuid = uuid.createString()
                    XendPSCSI_HBA(pscsi_HBA_uuid, {'physical_host': physical_host})
                pscsi_record['HBA'] = pscsi_HBA_uuid

                pscsi_uuid = uuid.createString()
                XendPSCSI(pscsi_uuid, pscsi_record)
                self.save_PSCSIs()
                self.save_PSCSI_HBAs()


    def remove_PSCSI(self, rem_HCTL):
        saved_pscsis = self.state_store.load_state('pscsi')
        if not saved_pscsis:
            return

        # Remove the PSCSI
        for pscsi_record in saved_pscsis.values():
            if rem_HCTL == pscsi_record['physical_HCTL']:
                pscsi_ref = XendPSCSI.get_by_HCTL(rem_HCTL)
                XendAPIStore.get(pscsi_ref, "PSCSI").destroy()
                self.save_PSCSIs()

                physical_host = int(rem_HCTL.split(':')[0])
                pscsi_HBA_ref = XendPSCSI_HBA.get_by_physical_host(physical_host)
                if pscsi_HBA_ref:
                    if not XendAPIStore.get(pscsi_HBA_ref, 'PSCSI_HBA').get_PSCSIs():
                        XendAPIStore.get(pscsi_HBA_ref, 'PSCSI_HBA').destroy()
                self.save_PSCSI_HBAs()

                return

    def add_usbdev(self, busid):
        # if the adding usb device should be owned by usbback
        # and is probed by other usb drivers, seize it!
        bus, intf = busid.split(':')
        buses = vusb_util.get_assigned_buses()
        if str(bus) in buses:
            if not vusb_util.usb_intf_is_binded(busid):
                log.debug("add_usb(): %s is binded to other driver" % busid)
                vusb_util.unbind_usb_device(bus)
                vusb_util.bind_usb_device(bus)
        return

    def remove_usbdev(self, busid):
        log.debug("remove_usbdev(): Not implemented.")

##    def network_destroy(self, net_uuid):
 ##       del self.networks[net_uuid]
  ##      self.save_networks()


    def get_PIF_refs(self):
        log.debug(XendPIF.get_all())
        return XendPIF.get_all()

##   def _PIF_create(self, name, mtu, vlan, mac, network, persist = True,
##                     pif_uuid = None, metrics_uuid = None):
##         for pif in self.pifs.values():
##             if pif.network == network:
##                 raise NetworkAlreadyConnected(pif.uuid)

##         if pif_uuid is None:
##             pif_uuid = uuid.createString()
##         if metrics_uuid is None:
##             metrics_uuid = uuid.createString()

##         metrics = XendPIFMetrics(metrics_uuid)
##         pif = XendPIF(pif_uuid, metrics, name, mtu, vlan, mac, network, self)
##         metrics.set_PIF(pif)

##         self.pif_metrics[metrics_uuid] = metrics
##         self.pifs[pif_uuid] = pif

##         if persist:
##             self.save_PIFs()
##             self.refreshBridges()
##         return pif_uuid

##     def PIF_destroy(self, pif_uuid):
##         pif = self.pifs[pif_uuid]

##         if pif.vlan == -1:
##             raise PIFIsPhysical()

##         del self.pifs[pif_uuid]
##         self.save_PIFs()


    def get_PPCI_refs(self):
        return XendPPCI.get_all()

    def get_ppci_by_uuid(self, ppci_uuid):
        if ppci_uuid in self.get_PPCI_refs():
            return ppci_uuid
        return None


    def get_PSCSI_refs(self):
        return XendPSCSI.get_all()

    def get_pscsi_by_uuid(self, pscsi_uuid):
        if pscsi_uuid in self.get_PSCSI_refs():
            return pscsi_uuid
        return None

    def get_PSCSI_HBA_refs(self):
        return XendPSCSI_HBA.get_all()

    def get_pscsi_HBA_by_uuid(self, pscsi_HBA_uuid):
        if pscsi_HBA_uuid in self.get_PSCSI_HBA_refs():
            return pscsi_HBA_uuid
        return None


    def save(self):
        # save state
        host_record = {self.uuid: {'name_label':self.name,
                                   'name_description':self.desc,
                                   'metrics_uuid': self.host_metrics_uuid,
                                   'other_config': self.other_config}}
        self.state_store.save_state('host',host_record)
        self.state_store.save_state('cpu', self.cpus)
        self.save_PIFs()
        self.save_networks()
        self.save_PBDs()
        self.save_SRs()
        self.save_PPCIs()
        self.save_PSCSIs()
        self.save_PSCSI_HBAs()
        self.save_cpu_pools()

    def save_PIFs(self):
        pif_records = dict([(pif_uuid, XendAPIStore.get(
                                 pif_uuid, "PIF").get_record())
                            for pif_uuid in XendPIF.get_all()])
        self.state_store.save_state('pif', pif_records)

    def save_networks(self):
        net_records = dict([(network_uuid, XendAPIStore.get(
                                 network_uuid, "network").get_record())
                            for network_uuid in XendNetwork.get_all()])
        self.state_store.save_state('network', net_records)

    def save_PBDs(self):
        pbd_records = dict([(pbd_uuid, XendAPIStore.get(
                                 pbd_uuid, "PBD").get_record())
                            for pbd_uuid in XendPBD.get_all()])
        self.state_store.save_state('pbd', pbd_records)

    def save_SRs(self):
        sr_records = dict([(k, v.get_record(transient = False))
                            for k, v in self.srs.items()])
        self.state_store.save_state('sr', sr_records)

    def save_PPCIs(self):
        ppci_records = dict([(ppci_uuid, XendAPIStore.get(
                                 ppci_uuid, "PPCI").get_record())
                            for ppci_uuid in XendPPCI.get_all()])
        self.state_store.save_state('ppci', ppci_records)

    def save_PSCSIs(self):
        pscsi_records = dict([(pscsi_uuid, XendAPIStore.get(
                                  pscsi_uuid, "PSCSI").get_record())
                            for pscsi_uuid in XendPSCSI.get_all()])
        self.state_store.save_state('pscsi', pscsi_records)

    def save_PSCSI_HBAs(self):
        pscsi_HBA_records = dict([(pscsi_HBA_uuid, XendAPIStore.get(
                                      pscsi_HBA_uuid, "PSCSI_HBA").get_record())
                                for pscsi_HBA_uuid in XendPSCSI_HBA.get_all()])
        self.state_store.save_state('pscsi_HBA', pscsi_HBA_records)

    def save_cpu_pools(self):
        cpu_pool_records = dict([(cpu_pool_uuid, XendAPIStore.get(
                    cpu_pool_uuid, XendCPUPool.getClass()).get_record())
                    for cpu_pool_uuid in XendCPUPool.get_all_managed()])
        self.state_store.save_state(XendCPUPool.getClass(), cpu_pool_records)

    def shutdown(self):
        return 0

    def reboot(self):
        return 0

    def notify(self, _):
        return 0
        
    #
    # Ref validation
    #
    
    def is_valid_host(self, host_ref):
        return (host_ref == self.uuid)

    def is_valid_cpu(self, cpu_ref):
        return (cpu_ref in self.cpus)

    def is_valid_sr(self, sr_ref):
        return (sr_ref in self.srs)

    def is_valid_vdi(self, vdi_ref):
        for sr in self.srs.values():
            if sr.is_valid_vdi(vdi_ref):
                return True
        return False

    #
    # Storage Repositories
    #

    def get_sr(self, sr_uuid):
        return self.srs.get(sr_uuid)

    def get_sr_by_type(self, sr_type):
        return [sr.uuid for sr in self.srs.values() if sr.type == sr_type]

    def get_sr_by_name(self, name):
        return [sr.uuid for sr in self.srs.values() if sr.name_label == name]

    def get_all_sr_uuid(self):
        return self.srs.keys()

    def get_vdi_by_uuid(self, vdi_uuid):
        for sr in self.srs.values():
            if sr.is_valid_vdi(vdi_uuid):
                return sr.get_vdi_by_uuid(vdi_uuid)
        return None

    def get_vdi_by_name_label(self, name):
        for sr in self.srs.values():
            vdi = sr.get_vdi_by_name_label(name)
            if vdi:
                return vdi
        return None

    def get_sr_containing_vdi(self, vdi_uuid):
        for sr in self.srs.values():
            if sr.is_valid_vdi(vdi_uuid):
                return sr
        return None
    

    #
    # Host Functions
    #

    def xen_version(self):
        info = self.xc.xeninfo()

        info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info}

        # Add xend_config_format
        info.update(self.xendinfo_dict())

        # Add version info about machine
        info.update(self.nodeinfo_dict())

        # Add specific xen version info
        xeninfo_dict = self.xeninfo_dict()

        info.update({
            "xen_major":         xeninfo_dict["xen_major"],
            "xen_minor":         xeninfo_dict["xen_minor"],
            "xen_extra":         xeninfo_dict["xen_extra"],
            "cc_compiler":       xeninfo_dict["cc_compiler"],
            "cc_compile_by":     xeninfo_dict["cc_compile_by"],
            "cc_compile_domain": xeninfo_dict["cc_compile_domain"],
            "cc_compile_date":   xeninfo_dict["cc_compile_date"],
            "xen_changeset":     xeninfo_dict["xen_changeset"],
            "xen_commandline":   xeninfo_dict["xen_commandline"]
            })
        
        return info

    def get_name(self):
        return self.name

    def set_name(self, new_name):
        self.name = new_name

    def get_description(self):
        return self.desc

    def set_description(self, new_desc):
        self.desc = new_desc

    def get_uuid(self):
        return self.uuid

    def get_capabilities(self):
        return self.xc.xeninfo()['xen_caps'].split(" ")

    #
    # Host CPU Functions
    #

    def get_host_cpu_by_uuid(self, host_cpu_uuid):
        if host_cpu_uuid in self.cpus:
            return host_cpu_uuid
        raise XendError('Invalid CPU UUID')

    def get_host_cpu_refs(self):
        return self.cpus.keys()

    def get_host_cpu_uuid(self, host_cpu_ref):
        if host_cpu_ref in self.cpus:
            return host_cpu_ref
        else:
            raise XendError('Invalid CPU Reference')

    def get_host_cpu_field(self, ref, field):
        try:
            return self.cpus[ref][field]
        except KeyError:
            raise XendError('Invalid CPU Reference')

    def get_host_cpu_load(self, host_cpu_ref):
        host_cpu = self.cpus.get(host_cpu_ref)
        if not host_cpu:
            return 0.0

        vcpu = int(host_cpu['number'])
        cpu_loads = self.monitor.get_domain_vcpus_util()
        if 0 in cpu_loads and vcpu in cpu_loads[0]:
            return cpu_loads[0][vcpu]

        return 0.0

    def get_vcpus_policy(self):
        sched_id = self.xc.sched_id_get()
        if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
            return 'sedf'
        elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
            return 'credit'
        elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT2:
            return 'credit2'
        elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_RTGLOBAL:
            return 'rtglobal'
        elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_RTPARTITION:
            return 'rtpartition'
        
        else:
            return 'unknown'

    def get_cpu_configuration(self):
        phys_info = self.physinfo_dict()

        cpu_info = {
            "nr_nodes":         phys_info["nr_nodes"],
            "nr_cpus":          phys_info["nr_cpus"],
            "cores_per_socket": phys_info["cores_per_socket"],
            "threads_per_core": phys_info["threads_per_core"]
            }

        return cpu_info
    
    #
    # Network Functions
    #
    
    def bridge_to_network(self, bridge):
        """
        Determine which network a particular bridge is attached to.

        @param bridge The name of the bridge.  If empty, the default bridge
        will be used instead (the first one in the list returned by brctl
        show); this is the behaviour of the vif-bridge script.
        @return The XendNetwork instance to which this bridge is attached.
        @raise Exception if the interface is not connected to a network.
        """
        if not bridge:
            rc, bridge = commands.getstatusoutput(
                'brctl show | cut -d "\n" -f 2 | cut -f 1')
            if rc != 0 or not bridge:
                raise Exception(
                    'Could not find default bridge, and none was specified')

        for network_uuid in XendNetwork.get_all():
            network = XendAPIStore.get(network_uuid, "network")
            if network.get_name_label() == bridge:
                return network
        else:
            raise Exception('Cannot find network for bridge %s' % bridge)

    #
    # Debug keys.
    #

    def send_debug_keys(self, keys):
        return self.xc.send_debug_keys(keys)

    #
    # Getting host information.
    #

    def info(self, show_numa = 1):
        return (self.nodeinfo() + self.physinfo(show_numa) + self.xeninfo() +
                self.xendinfo())

    def nodeinfo(self):
        (sys, host, rel, ver, mch) = os.uname()
        return [['system',  sys],
                ['host',    host],
                ['release', rel],
                ['version', ver],
                ['machine', mch]]

    def list_to_rangepairs(self,cmap):
            cmap.sort()
            pairs = []
            x = y = 0
            for i in range(0,len(cmap)):
                try:
                    if ((cmap[y+1] - cmap[i]) > 1):
                        pairs.append((cmap[x],cmap[y]))
                        x = y = i+1
                    else:
                        y = y + 1
                # if we go off the end, then just add x to y
                except IndexError:
                    pairs.append((cmap[x],cmap[y]))

            return pairs

    def format_pairs(self,pairs):
            if not pairs:
                return "no cpus"
            out = ""
            for f,s in pairs:
                if (f==s):
                    out += '%d'%f
                else:
                    out += '%d-%d'%(f,s)
                out += ','
            # trim trailing ','
            return out[:-1]

    def list_to_strrange(self,list):
        return self.format_pairs(self.list_to_rangepairs(list))

    def format_cpu_to_core_socket_node(self, tinfo):
        max_cpu_index=tinfo['max_cpu_index']
        str='\ncpu:    core    socket     node\n'
        for i in range(0, max_cpu_index+1):
            try:
                str+='%3d:%8d %8d %8d\n' % (i, 
                                            tinfo['cpu_to_core'][i],
                                            tinfo['cpu_to_socket'][i],
                                            tinfo['cpu_to_node'][i])
            except:
                pass
        return str[:-1];

    def format_numa_info(self, ninfo):
        try:
            max_node_index=ninfo['max_node_index']
            str='\nnode: TotalMemory FreeMemory dma32Memory NodeDist:'
            for i in range(0, max_node_index+1):
                str+='%4d ' % i
            str+='\n'
            for i in range(0, max_node_index+1):
                str+='%4d:  %8dMB %8dMB  %8dMB         :' % (i, 
                                      ninfo['node_memsize'][i],
                                      ninfo['node_memfree'][i],
                                      ninfo['node_to_dma32_mem'][i])
                for j in range(0, nr_nodes):
                    try:
                        str+='%4d ' % ninfo['node_to_node_dist'][i][j]
                    except:
                        str+='-    '
                str+='\n'
        except:
            str='none\n'
        return str[:-1];

    def physinfo(self, show_numa):
        info = self.xc.physinfo()
        tinfo = self.xc.topologyinfo()
        ninfo = self.xc.numainfo()

        info['cpu_mhz'] = info['cpu_khz'] / 1000
        
        # physinfo is in KiB, need it in MiB
        info['total_memory'] = info['total_memory'] / 1024
        info['free_memory']  = info['free_memory'] / 1024
        info['free_cpus'] = len(XendCPUPool.unbound_cpus())

        ITEM_ORDER = ['nr_cpus',
                      'nr_nodes',
                      'cores_per_socket',
                      'threads_per_core',
                      'cpu_mhz',
                      'hw_caps',
                      'virt_caps',
                      'total_memory',
                      'free_memory',
                      'free_cpus',
                      ]

        if show_numa != 0:
            info['cpu_topology']  = \
                 self.format_cpu_to_core_socket_node(tinfo)

            info['numa_info']  = \
                 self.format_numa_info(ninfo)

            ITEM_ORDER += [ 'cpu_topology', 'numa_info' ]

        return [[k, info[k]] for k in ITEM_ORDER]

    def pciinfo(self):
        from xen.xend.server.pciif import get_all_assigned_pci_devices
        assigned_devs = get_all_assigned_pci_devices()

        # Each element of dev_list is a PciDevice
        dev_list = PciUtil.find_all_assignable_devices()
        if dev_list is None:
            return None
 
        # Each element of devs_list is a list of PciDevice
        devs_list = PciUtil.check_FLR_capability(dev_list)
 
        devs_list = PciUtil.check_mmio_bar(devs_list)
 
        # Check if the devices have been assigned to guests.
        final_devs_list = []
        for dev_list in devs_list:
            available = True
            for d in dev_list:
                if d.name in assigned_devs:
                    available = False
                    break
            if available:
                final_devs_list = final_devs_list + [dev_list]

        pci_sxp_list = []
        for dev_list in final_devs_list:
            for d in dev_list:
                pci_sxp = ['dev', ['domain', '0x%04x' % d.domain],
                                  ['bus', '0x%02x' % d.bus],
                                  ['slot', '0x%02x' % d.slot],
                                  ['func', '0x%x' % d.func]]
                pci_sxp_list.append(pci_sxp)

        return pci_sxp_list
 

    def xenschedinfo(self):
        sched_id = self.xc.sched_id_get()
        if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
            return 'sedf'
        elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
            return 'credit'
        elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT2:
            return 'credit2'
        elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_RTGLOBAL:
            return 'rtglobal'
        elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_RTPARTITION:
            return 'rtpartition'
        else:
            return 'unknown'

    def xeninfo(self):
        info = self.xc.xeninfo()
        info['xen_scheduler'] = self.xenschedinfo()

        ITEM_ORDER = ['xen_major',
                      'xen_minor',
                      'xen_extra',
                      'xen_caps',
                      'xen_scheduler',
                      'xen_pagesize',
                      'platform_params',
                      'xen_changeset',
                      'xen_commandline',
                      'cc_compiler',
                      'cc_compile_by',
                      'cc_compile_domain',
                      'cc_compile_date',
                      ]

        return [[k, info[k]] for k in ITEM_ORDER]

    def xendinfo(self):
        return [['xend_config_format', 4]]

    #
    # utilisation tracking
    #

    def get_vcpu_util(self, domid, vcpuid):
        cpu_loads = self.monitor.get_domain_vcpus_util()
        if domid in cpu_loads:
            return cpu_loads[domid].get(vcpuid, 0.0)
        return 0.0

    def get_vif_util(self, domid, vifid):
        vif_loads = self.monitor.get_domain_vifs_util()
        if domid in vif_loads:
            return vif_loads[domid].get(vifid, (0.0, 0.0))
        return (0.0, 0.0)

    def get_vif_stat(self, domid, vifid):
        vif_loads = self.monitor.get_domain_vifs_stat()
        if domid in vif_loads:
            return vif_loads[domid].get(vifid, (0.0, 0.0))
        return (0.0, 0.0)

    def get_vbd_util(self, domid, vbdid):
        vbd_loads = self.monitor.get_domain_vbds_util()
        if domid in vbd_loads:
            return vbd_loads[domid].get(vbdid, (0.0, 0.0))
        return (0.0, 0.0)

    # dictionary version of *info() functions to get rid of
    # SXPisms.
    def nodeinfo_dict(self):
        return dict(self.nodeinfo())
    def xendinfo_dict(self):
        return dict(self.xendinfo())
    def xeninfo_dict(self):
        return dict(self.xeninfo())
    def physinfo_dict(self):
        return dict(self.physinfo(1))
    def info_dict(self):
        return dict(self.info())

    # tmem
    def tmem_list(self, cli_id, use_long):
        pool_id = -1
        subop = TMEMC_LIST
        arg1 = 32768
        arg2 = use_long
        arg3 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)

    def tmem_thaw(self, cli_id):
        pool_id = -1
        subop = TMEMC_THAW
        arg1 = 0
        arg2 = 0
        arg3 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)

    def tmem_freeze(self, cli_id):
        pool_id = -1
        subop = TMEMC_FREEZE
        arg1 = 0
        arg2 = 0
        arg3 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)

    def tmem_flush(self, cli_id, pages):
        pool_id = -1
        subop = TMEMC_FLUSH
        arg1 = pages
        arg2 = 0
        arg3 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)

    def tmem_destroy(self, cli_id):
        pool_id = -1
        subop = TMEMC_DESTROY
        arg1 = 0
        arg2 = 0
        arg3 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)

    def tmem_set_weight(self, cli_id, arg1):
        pool_id = -1
        subop = TMEMC_SET_WEIGHT
        arg2 = 0
        arg3 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)

    def tmem_set_cap(self, cli_id, arg1):
        pool_id = -1
        subop = TMEMC_SET_CAP
        arg2 = 0
        arg3 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)

    def tmem_set_compress(self, cli_id, arg1):
        pool_id = -1
        subop = TMEMC_SET_COMPRESS
        arg2 = 0
        arg3 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)

    def tmem_query_freeable_mb(self):
        pool_id = -1
        cli_id = -1
        subop = TMEMC_QUERY_FREEABLE_MB
        arg1 = 0
        arg2 = 0
        arg3 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf)

    def tmem_shared_auth(self, cli_id, uuid_str, auth):
        return self.xc.tmem_auth(cli_id, uuid_str, auth)
class XendNode:
    """XendNode - Represents a Domain 0 Host."""
    
    def __init__(self):
        """Initalises the state of all host specific objects such as

        * host
        * host_CPU
        * host_metrics
        * PIF
        * PIF_metrics
        * network
        * Storage Repository
        """
        
        self.xc = xen.lowlevel.xc.xc()
        self.state_store = XendStateStore(xendoptions().get_xend_state_path())
        self.monitor = XendMonitor()
        self.monitor.start()

        # load host state from XML file
        saved_host = self.state_store.load_state('host')
        if saved_host and len(saved_host.keys()) == 1:
            self.uuid = saved_host.keys()[0]
            host = saved_host[self.uuid]
            self.name = host.get('name_label', socket.gethostname())
            self.desc = host.get('name_description', '')
            self.host_metrics_uuid = host.get('metrics_uuid',
                                              uuid.createString())
            try:
                self.other_config = eval(host['other_config'])
            except:
                self.other_config = {}
            self.cpus = {}
        else:
            self.uuid = uuid.createString()
            self.name = socket.gethostname()
            self.desc = ''
            self.other_config = {}
            self.cpus = {}
            self.host_metrics_uuid = uuid.createString()

        # put some arbitrary params in other_config as this
        # is directly exposed via XenAPI
        self.other_config["xen_pagesize"] = self.xeninfo_dict()["xen_pagesize"]
        self.other_config["platform_params"] = self.xeninfo_dict()["platform_params"]
            
        # load CPU UUIDs
        saved_cpus = self.state_store.load_state('cpu')
        for cpu_uuid, cpu in saved_cpus.items():
            self.cpus[cpu_uuid] = cpu

        cpuinfo = parse_proc_cpuinfo()
        physinfo = self.physinfo_dict()
        cpu_count = physinfo['nr_cpus']
        cpu_features = physinfo['hw_caps']

        # If the number of CPUs don't match, we should just reinitialise 
        # the CPU UUIDs.
        if cpu_count != len(self.cpus):
            self.cpus = {}
            for i in range(cpu_count):
                u = uuid.createString()
                self.cpus[u] = {'uuid': u, 'number': i }

        for u in self.cpus.keys():
            number = self.cpus[u]['number']
            # We can run off the end of the cpuinfo list if domain0 does not
            # have #vcpus == #pcpus. In that case we just replicate one that's
            # in the hash table.
            if not cpuinfo.has_key(number):
                number = cpuinfo.keys()[0]
            if arch.type == "x86":
                self.cpus[u].update(
                    { 'host'     : self.uuid,
                      'features' : cpu_features,
                      'speed'    : int(float(cpuinfo[number]['cpu MHz'])),
                      'vendor'   : cpuinfo[number]['vendor_id'],
                      'modelname': cpuinfo[number]['model name'],
                      'stepping' : cpuinfo[number]['stepping'],
                      'flags'    : cpuinfo[number]['flags'],
                    })
            elif arch.type == "ia64":
                self.cpus[u].update(
                    { 'host'     : self.uuid,
                      'features' : cpu_features,
                      'speed'    : int(float(cpuinfo[number]['cpu MHz'])),
                      'vendor'   : cpuinfo[number]['vendor'],
                      'modelname': cpuinfo[number]['family'],
                      'stepping' : cpuinfo[number]['model'],
                      'flags'    : cpuinfo[number]['features'],
                    })
            else:
                self.cpus[u].update(
                    { 'host'     : self.uuid,
                      'features' : cpu_features,
                    })

        self.srs = {}

        # Initialise networks
        # First configure ones off disk
        saved_networks = self.state_store.load_state('network')
        if saved_networks:
            for net_uuid, network in saved_networks.items():
                try:
                    XendNetwork.recreate(network, net_uuid)
                except CreateUnspecifiedAttributeError:
                    log.warn("Error recreating network %s", net_uuid)
                
        # Next discover any existing bridges and check
        # they are not already configured
        bridges = Brctl.get_state().keys()
        configured_bridges = [XendAPIStore.get(
                                  network_uuid, "network")
                                      .get_name_label()
                              for network_uuid in XendNetwork.get_all()]
        unconfigured_bridges = [bridge
                                for bridge in bridges
                                if bridge not in configured_bridges]
        for unconfigured_bridge in unconfigured_bridges:
            XendNetwork.create_phy(unconfigured_bridge)

        # Initialise PIFs
        # First configure ones off disk
        saved_pifs = self.state_store.load_state('pif')
        if saved_pifs:
            for pif_uuid, pif in saved_pifs.items():
                try:
                    XendPIF.recreate(pif, pif_uuid)
                except CreateUnspecifiedAttributeError:
                    log.warn("Error recreating PIF %s", pif_uuid)
        
        # Next discover any existing PIFs and check
        # they are not already configured
        configured_pifs = [XendAPIStore.get(
                               pif_uuid, "PIF")
                                   .get_interface_name()
                           for pif_uuid in XendPIF.get_all()]
        unconfigured_pifs = [(name, mtu, mac)
                             for name, mtu, mac in linux_get_phy_ifaces()
                             if name not in configured_pifs]

        # Get a mapping from interface to bridge          
        if_to_br = dict([(i,b)
                         for (b,ifs) in Brctl.get_state().items()
                             for i in ifs])

        for name, mtu, mac in unconfigured_pifs:
            # Check PIF is on bridge
            # if not, ignore
            bridge_name = if_to_br.get(name, None)
            if bridge_name is not None:
                # Translate bridge name to network uuid
                for network_uuid in XendNetwork.get_all():
                    network = XendAPIStore.get(
                        network_uuid, 'network')
                    if network.get_name_label() == bridge_name:
                        XendPIF.create_phy(network_uuid, name,
                                           mac, mtu)
                        break
                else:
                    log.debug("Cannot find network for bridge %s "
                              "when configuring PIF %s",
                              (bridge_name, name))     
        
        # initialise storage
        saved_srs = self.state_store.load_state('sr')
        if saved_srs:
            for sr_uuid, sr_cfg in saved_srs.items():
                if sr_cfg['type'] == 'qcow_file':
                    self.srs[sr_uuid] = XendQCoWStorageRepo(sr_uuid)
                elif sr_cfg['type'] == 'local':
                    self.srs[sr_uuid] = XendLocalStorageRepo(sr_uuid)

        # Create missing SRs if they don't exist
        if not self.get_sr_by_type('local'):
            image_sr_uuid = uuid.createString()
            self.srs[image_sr_uuid] = XendLocalStorageRepo(image_sr_uuid)
            
        if not self.get_sr_by_type('qcow_file'):
            qcow_sr_uuid = uuid.createString()
            self.srs[qcow_sr_uuid] = XendQCoWStorageRepo(qcow_sr_uuid)

        saved_pbds = self.state_store.load_state('pbd')
        if saved_pbds:
            for pbd_uuid, pbd_cfg in saved_pbds.items():
                try:
                    XendPBD.recreate(pbd_uuid, pbd_cfg)
                except CreateUnspecifiedAttributeError:
                    log.warn("Error recreating PBD %s", pbd_uuid) 

##    def network_destroy(self, net_uuid):
 ##       del self.networks[net_uuid]
  ##      self.save_networks()


    def get_PIF_refs(self):
        log.debug(XendPIF.get_all())
        return XendPIF.get_all()

##   def _PIF_create(self, name, mtu, vlan, mac, network, persist = True,
##                     pif_uuid = None, metrics_uuid = None):
##         for pif in self.pifs.values():
##             if pif.network == network:
##                 raise NetworkAlreadyConnected(pif.uuid)

##         if pif_uuid is None:
##             pif_uuid = uuid.createString()
##         if metrics_uuid is None:
##             metrics_uuid = uuid.createString()

##         metrics = XendPIFMetrics(metrics_uuid)
##         pif = XendPIF(pif_uuid, metrics, name, mtu, vlan, mac, network, self)
##         metrics.set_PIF(pif)

##         self.pif_metrics[metrics_uuid] = metrics
##         self.pifs[pif_uuid] = pif

##         if persist:
##             self.save_PIFs()
##             self.refreshBridges()
##         return pif_uuid

##     def PIF_destroy(self, pif_uuid):
##         pif = self.pifs[pif_uuid]

##         if pif.vlan == -1:
##             raise PIFIsPhysical()

##         del self.pifs[pif_uuid]
##         self.save_PIFs()


    def save(self):
        # save state
        host_record = {self.uuid: {'name_label':self.name,
                                   'name_description':self.desc,
                                   'metrics_uuid': self.host_metrics_uuid,
                                   'other_config': self.other_config}}
        self.state_store.save_state('host',host_record)
        self.state_store.save_state('cpu', self.cpus)
        self.save_PIFs()
        self.save_networks()
        self.save_PBDs()
        self.save_SRs()

    def save_PIFs(self):
        pif_records = dict([(pif_uuid, XendAPIStore.get(
                                 pif_uuid, "PIF").get_record())
                            for pif_uuid in XendPIF.get_all()])
        self.state_store.save_state('pif', pif_records)

    def save_networks(self):
        net_records = dict([(network_uuid, XendAPIStore.get(
                                 network_uuid, "network").get_record())
                            for network_uuid in XendNetwork.get_all()])
        self.state_store.save_state('network', net_records)

    def save_PBDs(self):
        pbd_records = dict([(pbd_uuid, XendAPIStore.get(
                                 pbd_uuid, "PBD").get_record())
                            for pbd_uuid in XendPBD.get_all()])
        self.state_store.save_state('pbd', pbd_records)

    def save_SRs(self):
        sr_records = dict([(k, v.get_record(transient = False))
                            for k, v in self.srs.items()])
        self.state_store.save_state('sr', sr_records)

    def shutdown(self):
        return 0

    def reboot(self):
        return 0

    def notify(self, _):
        return 0
        
    #
    # Ref validation
    #
    
    def is_valid_host(self, host_ref):
        return (host_ref == self.uuid)

    def is_valid_cpu(self, cpu_ref):
        return (cpu_ref in self.cpus)

    def is_valid_sr(self, sr_ref):
        return (sr_ref in self.srs)

    def is_valid_vdi(self, vdi_ref):
        for sr in self.srs.values():
            if sr.is_valid_vdi(vdi_ref):
                return True
        return False

    #
    # Storage Repositories
    #

    def get_sr(self, sr_uuid):
        return self.srs.get(sr_uuid)

    def get_sr_by_type(self, sr_type):
        return [sr.uuid for sr in self.srs.values() if sr.type == sr_type]

    def get_sr_by_name(self, name):
        return [sr.uuid for sr in self.srs.values() if sr.name_label == name]

    def get_all_sr_uuid(self):
        return self.srs.keys()

    def get_vdi_by_uuid(self, vdi_uuid):
        for sr in self.srs.values():
            if sr.is_valid_vdi(vdi_uuid):
                return sr.get_vdi_by_uuid(vdi_uuid)
        return None

    def get_vdi_by_name_label(self, name):
        for sr in self.srs.values():
            vdi = sr.get_vdi_by_name_label(name)
            if vdi:
                return vdi
        return None

    def get_sr_containing_vdi(self, vdi_uuid):
        for sr in self.srs.values():
            if sr.is_valid_vdi(vdi_uuid):
                return sr
        return None
    

    #
    # Host Functions
    #

    def xen_version(self):
        info = self.xc.xeninfo()

        try:
            from xen import VERSION
            info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info,
                    'Xend': VERSION}
        except (ImportError, AttributeError):
            info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info,
                    'Xend': '3.0.3'}

        # Add xend_config_format
        info.update(self.xendinfo_dict())

        # Add version info about machine
        info.update(self.nodeinfo_dict())

        # Add specific xen version info
        xeninfo_dict = self.xeninfo_dict()

        info.update({
            "xen_major":         xeninfo_dict["xen_major"],
            "xen_minor":         xeninfo_dict["xen_minor"],
            "xen_extra":         xeninfo_dict["xen_extra"],
            "cc_compiler":       xeninfo_dict["cc_compiler"],
            "cc_compile_by":     xeninfo_dict["cc_compile_by"],
            "cc_compile_domain": xeninfo_dict["cc_compile_domain"],
            "cc_compile_date":   xeninfo_dict["cc_compile_date"],
            "xen_changeset":     xeninfo_dict["xen_changeset"]
            })
        
        return info

    def get_name(self):
        return self.name

    def set_name(self, new_name):
        self.name = new_name

    def get_description(self):
        return self.desc

    def set_description(self, new_desc):
        self.desc = new_desc

    def get_uuid(self):
        return self.uuid

    def get_capabilities(self):
        return self.xc.xeninfo()['xen_caps'].split(" ")

    #
    # Host CPU Functions
    #

    def get_host_cpu_by_uuid(self, host_cpu_uuid):
        if host_cpu_uuid in self.cpus:
            return host_cpu_uuid
        raise XendError('Invalid CPU UUID')

    def get_host_cpu_refs(self):
        return self.cpus.keys()

    def get_host_cpu_uuid(self, host_cpu_ref):
        if host_cpu_ref in self.cpus:
            return host_cpu_ref
        else:
            raise XendError('Invalid CPU Reference')

    def get_host_cpu_field(self, ref, field):
        try:
            return self.cpus[ref][field]
        except KeyError:
            raise XendError('Invalid CPU Reference')

    def get_host_cpu_load(self, host_cpu_ref):
        host_cpu = self.cpus.get(host_cpu_ref)
        if not host_cpu:
            return 0.0

        vcpu = int(host_cpu['number'])
        cpu_loads = self.monitor.get_domain_vcpus_util()
        if 0 in cpu_loads and vcpu in cpu_loads[0]:
            return cpu_loads[0][vcpu]

        return 0.0

    def get_vcpus_policy(self):
        sched_id = self.xc.sched_id_get()
        if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
            return 'sedf'
        elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
            return 'credit'
        else:
            return 'unknown'

    def get_cpu_configuration(self):
        phys_info = self.physinfo_dict()

        cpu_info = {
            "nr_nodes":         phys_info["nr_nodes"],
            "nr_cpus":          phys_info["nr_cpus"],
            "cores_per_socket": phys_info["cores_per_socket"],
            "threads_per_core": phys_info["threads_per_core"]
            }

        return cpu_info
    
    #
    # Network Functions
    #
    
    def bridge_to_network(self, bridge):
        """
        Determine which network a particular bridge is attached to.

        @param bridge The name of the bridge.  If empty, the default bridge
        will be used instead (the first one in the list returned by brctl
        show); this is the behaviour of the vif-bridge script.
        @return The XendNetwork instance to which this bridge is attached.
        @raise Exception if the interface is not connected to a network.
        """
        if not bridge:
            rc, bridge = commands.getstatusoutput(
                'brctl show | cut -d "\n" -f 2 | cut -f 1')
            if rc != 0 or not bridge:
                raise Exception(
                    'Could not find default bridge, and none was specified')

        for network_uuid in XendNetwork.get_all():
            network = XendAPIStore.get(network_uuid, "network")
            if network.get_name_label() == bridge:
                return network
        else:
            raise Exception('Cannot find network for bridge %s' % bridge)

    #
    # Debug keys.
    #

    def send_debug_keys(self, keys):
        return self.xc.send_debug_keys(keys)

    #
    # Getting host information.
    #

    def info(self):
        return (self.nodeinfo() + self.physinfo() + self.xeninfo() +
                self.xendinfo())

    def nodeinfo(self):
        (sys, host, rel, ver, mch) = os.uname()
        return [['system',  sys],
                ['host',    host],
                ['release', rel],
                ['version', ver],
                ['machine', mch]]

    def list_to_rangepairs(self,cmap):
            cmap.sort()
            pairs = []
            x = y = 0
            for i in range(0,len(cmap)):
                try:
                    if ((cmap[y+1] - cmap[i]) > 1):
                        pairs.append((cmap[x],cmap[y]))
                        x = y = i+1
                    else:
                        y = y + 1
                # if we go off the end, then just add x to y
                except IndexError:
                    pairs.append((cmap[x],cmap[y]))

            return pairs

    def format_pairs(self,pairs):
            if not pairs:
                return "no cpus"
            out = ""
            for f,s in pairs:
                if (f==s):
                    out += '%d'%f
                else:
                    out += '%d-%d'%(f,s)
                out += ','
            # trim trailing ','
            return out[:-1]

    def list_to_strrange(self,list):
        return self.format_pairs(self.list_to_rangepairs(list))

    def format_node_to_cpu(self, pinfo):
        str=''
        whitespace=''
        try:
            node_to_cpu=pinfo['node_to_cpu']
            for i in range(0, pinfo['nr_nodes']):
                str+='%snode%d:%s\n' % (whitespace,
                                        i, 
                                      self.list_to_strrange(node_to_cpu[i]))
                whitespace='%25s' % ''        
        except:
            str='none\n'
        return str[:-1];

    def physinfo(self):
        info = self.xc.physinfo()

        info['cpu_mhz'] = info['cpu_khz'] / 1000
        
        # physinfo is in KiB, need it in MiB
        info['total_memory'] = info['total_memory'] / 1024
        info['free_memory']  = info['free_memory'] / 1024
        info['node_to_cpu']  = self.format_node_to_cpu(info)

        ITEM_ORDER = ['nr_cpus',
                      'nr_nodes',
                      'cores_per_socket',
                      'threads_per_core',
                      'cpu_mhz',
                      'hw_caps',
                      'total_memory',
                      'free_memory',
                      'node_to_cpu'
                      ]

        return [[k, info[k]] for k in ITEM_ORDER]

    def xenschedinfo(self):
        sched_id = self.xc.sched_id_get()
        if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
            return 'sedf'
        elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
            return 'credit'
        else:
            return 'unknown'

    def xeninfo(self):
        info = self.xc.xeninfo()
        info['xen_scheduler'] = self.xenschedinfo()

        ITEM_ORDER = ['xen_major',
                      'xen_minor',
                      'xen_extra',
                      'xen_caps',
                      'xen_scheduler',
                      'xen_pagesize',
                      'platform_params',
                      'xen_changeset',
                      'cc_compiler',
                      'cc_compile_by',
                      'cc_compile_domain',
                      'cc_compile_date',
                      ]

        return [[k, info[k]] for k in ITEM_ORDER]

    def xendinfo(self):
        return [['xend_config_format', 4]]

    #
    # utilisation tracking
    #

    def get_vcpu_util(self, domid, vcpuid):
        cpu_loads = self.monitor.get_domain_vcpus_util()
        if domid in cpu_loads:
            return cpu_loads[domid].get(vcpuid, 0.0)
        return 0.0

    def get_vif_util(self, domid, vifid):
        vif_loads = self.monitor.get_domain_vifs_util()
        if domid in vif_loads:
            return vif_loads[domid].get(vifid, (0.0, 0.0))
        return (0.0, 0.0)

    def get_vif_stat(self, domid, vifid):
        vif_loads = self.monitor.get_domain_vifs_stat()
        if domid in vif_loads:
            return vif_loads[domid].get(vifid, (0.0, 0.0))
        return (0.0, 0.0)

    def get_vbd_util(self, domid, vbdid):
        vbd_loads = self.monitor.get_domain_vbds_util()
        if domid in vbd_loads:
            return vbd_loads[domid].get(vbdid, (0.0, 0.0))
        return (0.0, 0.0)

    # dictionary version of *info() functions to get rid of
    # SXPisms.
    def nodeinfo_dict(self):
        return dict(self.nodeinfo())
    def xendinfo_dict(self):
        return dict(self.xendinfo())
    def xeninfo_dict(self):
        return dict(self.xeninfo())
    def physinfo_dict(self):
        return dict(self.physinfo())
    def info_dict(self):
        return dict(self.info())
class XendLocalStorageRepo(XendStorageRepository):
    """A backwards compatibility storage repository so that
    traditional file:/dir/file.img and phy:/dev/hdxx images can
    still be represented in terms of the Xen API.
    """
    
    def __init__(self, sr_uuid, sr_type='local',
                 name_label='local',
                 name_description='Traditional Local Storage Repo',
                 other_config={'location':'/home/local_sr', 'auto-scan':'False'},
                 content_type='vhd',
                 shared=False,
                 sm_config={}):
        """
        @ivar    images: mapping of all the images.
        @type    images: dictionary by image uuid.
        @ivar    lock:   lock to provide thread safety.
        """

        XendStorageRepository.__init__(self, sr_uuid, sr_type,
                                       name_label, name_description)
        
        self.type = sr_type
        self.name_label = name_label
        self.name_description = name_description
        self.other_config = other_config
        self.content_type = content_type
        self.shared = shared
        self.sm_config = sm_config
        self.local_sr_dir = self.other_config.get('location')
        self.location = self.local_sr_dir
#        self.local_sr_dir = os.path.join(self.location, self.uuid)
        if not os.path.exists(self.local_sr_dir): 
            os.makedirs(self.local_sr_dir)
#        s_max = storage_max(self.local_sr_dir)
#        if s_max:
#            self.physical_size = int(s_max)*KB
#        else:
#            self.physical_size = 0
#        s_util = storage_util(self.local_sr_dir)
#        if s_util:
#            self.physical_utilisation = int(s_util)*KB
#        else:
#            self.physical_utilisation = 0
#        d_util = dir_util(self.local_sr_dir)
#        if d_util:
#            self.virtual_allocation = int(d_util)*KB
#        else:
#            self.virtual_allocation = 0       
        
        self.state = XendStateStore(xendoptions().get_xend_state_path()
                                    + '/local_sr/%s' % self.uuid)

        stored_images = self.state.load_state('vdi')
        if stored_images:
            for image_uuid, image in stored_images.items():
                self.images[image_uuid] = XendLocalVDI(image)
                
    def update(self, auto=True):
        stored_images = self.state.load_state('vdi')
        images_path = []
        if stored_images:
            for image_uuid, image in stored_images.items():
                images_path.append(image['location'])
                self.images[image_uuid] = XendLocalVDI(image)
                
    def get_record(self, transient = True):
        retval = {'uuid': self.uuid,
                  'name_label': self.name_label,
                  'name_description': self.name_description,
                  'resident_on' : XendNode.instance().uuid,
                  'virtual_allocation': 0,
                  'physical_utilisation': self.get_physical_utilisation(),
                  'physical_size': self.get_physical_size(),
                  'type': self.type,
                  'content_type': self.content_type,
                  'VDIs': self.images.keys(),
                  'PBDs': XendPBD.get_by_SR(self.uuid),
                  'other_config': self.other_config,
                  'shared': self.shared,
                  'sm_config': self.sm_config,
                  }
        return retval
    
    def get_physical_utilisation(self):
        s_util = storage_util(self.local_sr_dir)
        if s_util:
            self.physical_utilisation = int(s_util)*KB
        else:
            self.physical_utilisation = 0
        return self.physical_utilisation
        
    def get_physical_size(self):
        s_max = storage_max(self.local_sr_dir)
        if s_max:
            self.physical_size = int(s_max)*KB
        else:
            self.physical_size = 0   
        return self.physical_size  
    
    def get_vdi_physical_utilisation(self, vdi_ref):
        vdi = self.images.get(vdi_ref)
        return vdi.get_physical_utilisation()
        
    def get_vdi_virtual_size(self, vdi_ref):
        vdi = self.images.get(vdi_ref)
        return vdi.get_virtual_size()

    def create_vdi(self, vdi_struct, transient = False, create_file=True):
        """ Creates a fake VDI image for a traditional image string.

        The image uri is stored in the attribute 'uri'
        """
        if not vdi_struct.get('uuid') or vdi_struct.get('uuid') == '':
            vdi_struct['uuid'] = uuid.createString()
        vdi_struct['SR'] = self.uuid
#        vdi_struct['name_label'] = vdi_struct['uuid']
        if vdi_struct.get('type') == 'user' and create_file:            
            self.create_img_file(vdi_struct)
        vdi_struct['physical_utilisation'] = int(vdi_struct['virtual_size']) * BYTE
        new_image = XendLocalVDI(vdi_struct)
#            self.create_logical_volume(vdi_struct)    
        self.images[new_image.uuid] = new_image
        self.save_state(transient)
        return new_image.uuid
    
    def copy_vdi(self, vdi_struct, p_vdi_uuid, transient = False, copy_file = False):
        """ Creates a fake VDI image for a traditional image string.

        The image uri is stored in the attribute 'uri'
        """
        if not vdi_struct.get('uuid') or vdi_struct.get('uuid') == '':
            vdi_struct['uuid'] = uuid.createString()
        vdi_struct['SR'] = self.uuid
        new_image = XendLocalVDI(vdi_struct)
        self.images[new_image.uuid] = new_image
        self.save_state(transient)
        if vdi_struct.get('type') == 'user' and copy_file:            
            self.copy_img_file(vdi_struct, p_vdi_uuid)
#            self.create_logical_volume(vdi_struct)    
        return new_image.uuid  
    
    def create_img_file(self, vdi_struct, path=None, size=None):
#        path = IMG_FILE_PATH + vdi_struct.get('uuid') + '.img'
        path = self.local_sr_dir
        file = '%s/%s.vhd' %(path, vdi_struct.get('uuid'))
        size = int(vdi_struct.get('virtual_size')) * KB
        if not os.path.exists(path):
            os.makedirs(path)
        import subprocess
        if not os.path.exists(file):
#            subprocess.Popen("vhd-util create -n %s -s %d" % (file, size), shell=True,
#                               stdout=subprocess.PIPE)
            p = subprocess.Popen("dd if=/dev/zero of=%s bs=1M count=0 seek=%d" % (file, size), shell=True,
                               stdout=subprocess.PIPE)
            
    def copy_img_file(self, vdi_struct, p_vdi_uuid, path=None, size=None):
#        location = self.other_config['location']
#        local = location.split(':')[1]
#        path =  '%s/%s' %(local,self.uuid)
        path = self.local_sr_dir
        file = '%s/%s.vhd' %(path, vdi_struct.get('uuid'))
        p_file = '%s/%s.vhd' %(path, p_vdi_uuid)
        cmd = 'cp %s %s' %(p_file, file)
        log.debug("copy img file: %s" % cmd)
        (rc, stdout, stderr) = doexec(cmd)
        if rc != 0:
            err = stderr.read();
            out = stdout.read();
            stdout.close();
            stderr.close();
            raise Exception, 'Failed to execute cp %s %s.%s' %(p_file, file, err);
        stdout.close();
        stderr.close();   
        
        
        time_out = 20
        i = 0
        while True:
            i += 1
            if os.path.exists(file):
                break
            elif cmp(i, time_out) > 0:
                raise Exception, 'Clone file %s, timeout!' % file;
            else:
                time.sleep(1)
        log.debug("Clone finished, cost: %i s." % i)

    def get_vg_name(self):
        cmd = [VG_BINARY, '--noheadings', '--nosuffix', '--options=vg_name']
        (rc, stdout, stderr) = doexec(cmd)
        if rc != 0:
            err = stderr.read();
            out = stdout.read();
            stdout.close();
            stderr.close();
            raise Exception, 'Failed to get VG name. Check that lvm installed in dom0.';
        vg_name = stdout.read()
        stdout.close()
        stderr.close()
        return vg_name
        
    def create_logical_volume(self, vdi_struct, lv_name=None, size=None, vg_name=None):
        lv_name = 'VHD-' + vdi_struct.get('uuid')
        size = int(vdi_struct.get('virtual_size')) * 1024
        vg_name = mytrim(self.get_vg_name())
        cmd = [LV_CREATE_BINARY, '%s' %vg_name, '-L', '%dM' %size, '-n', '%s' %lv_name]
        (rc, stdout, stderr) = doexec(cmd)
        if rc != 0:
            err = stderr.read();
            out = stdout.read();
            stdout.close();
            stderr.close();
            raise Exception, 'Failed to create logical volume: %s, lv_size: %d on VG: %s.\n%s' %(lv_name, size, vg_name, err);
        stdout.close()
        stderr.close()
        
    def del_img_file(self, vdi_uuid):
#        location = self.other_config['location']
#        local = location.split(':')[1]
#        path =  '%s/%s' %(local,self.uuid)
        path = self.local_sr_dir
        file = '%s/%s.vhd' %(path, vdi_uuid)
        cmd = 'rm -f %s' % file
        (rc, stdout, stderr) = doexec(cmd)
        if rc != 0:
            err = stderr.read();
            out = stdout.read();
            stdout.close();
            stderr.close();
            raise Exception, 'Failed to execute rm -f %s.%s' %(file, err);
        stdout.close();
        stderr.close();   
        
    def save_state(self, transient=False):
        vdi_records = dict([(k, v.get_record(transient))
                            for k, v in self.images.items()])
        self.state.save_state('vdi', vdi_records)

    def destroy_vdi(self, vdi_uuid, del_file=True, transient = False):
        if vdi_uuid in self.images:
            if del_file:
                log.debug('destroy_vdi')
                log.debug(self.images[vdi_uuid])
                self.del_img_file(vdi_uuid)
            del self.images[vdi_uuid]
        self.save_state(transient)
        XendNode.instance().save_local_SRs()
Beispiel #15
0
class XendNode:
    """XendNode - Represents a Domain 0 Host."""
    def __init__(self):
        """Initalises the state of all host specific objects such as

        * host
        * host_CPU
        * host_metrics
        * PIF
        * PIF_metrics
        * network
        * Storage Repository
        * PPCI
        * PSCSI
        """

        self.xc = xen.lowlevel.xc.xc()
        self.state_store = XendStateStore(xendoptions().get_xend_state_path())
        self.monitor = XendMonitor()
        self.monitor.start()

        # load host state from XML file
        saved_host = self.state_store.load_state('host')
        if saved_host and len(saved_host.keys()) == 1:
            self.uuid = saved_host.keys()[0]
            host = saved_host[self.uuid]
            self.name = host.get('name_label', socket.gethostname())
            self.desc = host.get('name_description', '')
            self.host_metrics_uuid = host.get('metrics_uuid',
                                              uuid.createString())
            try:
                self.other_config = eval(host['other_config'])
            except:
                self.other_config = {}
            self.cpus = {}
        else:
            self.uuid = uuid.createString()
            self.name = socket.gethostname()
            self.desc = ''
            self.other_config = {}
            self.cpus = {}
            self.host_metrics_uuid = uuid.createString()

        # put some arbitrary params in other_config as this
        # is directly exposed via XenAPI
        self.other_config["xen_pagesize"] = self.xeninfo_dict()["xen_pagesize"]
        self.other_config["platform_params"] = self.xeninfo_dict(
        )["platform_params"]
        self.other_config["xen_commandline"] = self.xeninfo_dict(
        )["xen_commandline"]

        # load CPU UUIDs
        saved_cpus = self.state_store.load_state('cpu')
        for cpu_uuid, cpu in saved_cpus.items():
            self.cpus[cpu_uuid] = cpu

        cpuinfo = osdep.get_cpuinfo()
        physinfo = self.physinfo_dict()
        cpu_count = physinfo['nr_cpus']
        cpu_features = physinfo['hw_caps']
        virt_caps = physinfo['virt_caps']

        # If the number of CPUs don't match, we should just reinitialise
        # the CPU UUIDs.
        if cpu_count != len(self.cpus):
            self.cpus = {}
            for i in range(cpu_count):
                u = uuid.createString()
                self.cpus[u] = {'uuid': u, 'number': i}

        for u in self.cpus.keys():
            number = self.cpus[u]['number']
            # We can run off the end of the cpuinfo list if domain0 does not
            # have #vcpus == #pcpus. In that case we just replicate one that's
            # in the hash table.
            if not cpuinfo.has_key(number):
                number = cpuinfo.keys()[0]
            if arch.type == "x86":
                self.cpus[u].update({
                    'host':
                    self.uuid,
                    'features':
                    cpu_features,
                    'virt_caps':
                    virt_caps,
                    'speed':
                    int(float(cpuinfo[number]['cpu MHz'])),
                    'vendor':
                    cpuinfo[number]['vendor_id'],
                    'modelname':
                    cpuinfo[number]['model name'],
                    'stepping':
                    cpuinfo[number]['stepping'],
                    'flags':
                    cpuinfo[number]['flags'],
                })
            elif arch.type == "ia64":
                self.cpus[u].update({
                    'host':
                    self.uuid,
                    'features':
                    cpu_features,
                    'speed':
                    int(float(cpuinfo[number]['cpu MHz'])),
                    'vendor':
                    cpuinfo[number]['vendor'],
                    'modelname':
                    cpuinfo[number]['family'],
                    'stepping':
                    cpuinfo[number]['model'],
                    'flags':
                    cpuinfo[number]['features'],
                })
            else:
                self.cpus[u].update({
                    'host': self.uuid,
                    'features': cpu_features,
                })

        self.srs = {}

        self._init_networks()
        self._init_PIFs()

        self._init_SRs()
        self._init_PBDs()

        self._init_PPCIs()

        self._init_PSCSIs()

    def _init_networks(self):
        # Initialise networks
        # First configure ones off disk
        saved_networks = self.state_store.load_state('network')
        if saved_networks:
            for net_uuid, network in saved_networks.items():
                try:
                    XendNetwork.recreate(network, net_uuid)
                except CreateUnspecifiedAttributeError:
                    log.warn("Error recreating network %s", net_uuid)

        # Next discover any existing bridges and check
        # they are not already configured

        # 'tmpbridge' is a temporary bridge created by network-bridge script.
        # Wait a couple of seconds for it to be renamed.
        for i in xrange(20):
            bridges = Brctl.get_state().keys()
            if 'tmpbridge' in bridges:
                time.sleep(0.1)
            else:
                break

        configured_bridges = [
            XendAPIStore.get(network_uuid, "network").get_name_label()
            for network_uuid in XendNetwork.get_all()
        ]
        unconfigured_bridges = [
            bridge for bridge in bridges if bridge not in configured_bridges
        ]
        for unconfigured_bridge in unconfigured_bridges:
            if unconfigured_bridge != 'tmpbridge':
                XendNetwork.create_phy(unconfigured_bridge)

    def _init_PIFs(self):
        # Initialise PIFs
        # First configure ones off disk
        saved_pifs = self.state_store.load_state('pif')
        if saved_pifs:
            for pif_uuid, pif in saved_pifs.items():
                try:
                    XendPIF.recreate(pif, pif_uuid)
                except CreateUnspecifiedAttributeError:
                    log.warn("Error recreating PIF %s", pif_uuid)

        # Next discover any existing PIFs and check
        # they are not already configured
        configured_pifs = [
            XendAPIStore.get(pif_uuid, "PIF").get_interface_name()
            for pif_uuid in XendPIF.get_all()
        ]
        unconfigured_pifs = [(name, mtu, mac)
                             for name, mtu, mac in linux_get_phy_ifaces()
                             if name not in configured_pifs]

        # Get a mapping from interface to bridge
        if_to_br = dict([(i, b) for (b, ifs) in Brctl.get_state().items()
                         for i in ifs])

        for name, mtu, mac in unconfigured_pifs:
            # Check PIF is on bridge
            # if not, ignore
            bridge_name = if_to_br.get(name, None)
            if bridge_name is not None:
                # Translate bridge name to network uuid
                for network_uuid in XendNetwork.get_all():
                    network = XendAPIStore.get(network_uuid, 'network')
                    if network.get_name_label() == bridge_name:
                        XendPIF.create_phy(network_uuid, name, mac, mtu)
                        break
                else:
                    log.debug(
                        "Cannot find network for bridge %s "
                        "when configuring PIF %s", (bridge_name, name))

    def _init_SRs(self):
        # initialise storage
        saved_srs = self.state_store.load_state('sr')
        if saved_srs:
            for sr_uuid, sr_cfg in saved_srs.items():
                if sr_cfg['type'] == 'qcow_file':
                    self.srs[sr_uuid] = XendQCoWStorageRepo(sr_uuid)
                elif sr_cfg['type'] == 'local':
                    self.srs[sr_uuid] = XendLocalStorageRepo(sr_uuid)

        # Create missing SRs if they don't exist
        if not self.get_sr_by_type('local'):
            image_sr_uuid = uuid.createString()
            self.srs[image_sr_uuid] = XendLocalStorageRepo(image_sr_uuid)

        if not self.get_sr_by_type('qcow_file'):
            qcow_sr_uuid = uuid.createString()
            self.srs[qcow_sr_uuid] = XendQCoWStorageRepo(qcow_sr_uuid)

    def _init_PBDs(self):
        saved_pbds = self.state_store.load_state('pbd')
        if saved_pbds:
            for pbd_uuid, pbd_cfg in saved_pbds.items():
                try:
                    XendPBD.recreate(pbd_uuid, pbd_cfg)
                except CreateUnspecifiedAttributeError:
                    log.warn("Error recreating PBD %s", pbd_uuid)

    def _init_PPCIs(self):
        saved_ppcis = self.state_store.load_state('ppci')
        saved_ppci_table = {}
        if saved_ppcis:
            for ppci_uuid, ppci_record in saved_ppcis.items():
                try:
                    saved_ppci_table[ppci_record['name']] = ppci_uuid
                except KeyError:
                    pass

        for pci_dev in PciUtil.get_all_pci_devices():
            ppci_record = {
                'domain': pci_dev.domain,
                'bus': pci_dev.bus,
                'slot': pci_dev.slot,
                'func': pci_dev.func,
                'vendor_id': pci_dev.vendor,
                'vendor_name': pci_dev.vendorname,
                'device_id': pci_dev.device,
                'device_name': pci_dev.devicename,
                'revision_id': pci_dev.revision,
                'class_code': pci_dev.classcode,
                'class_name': pci_dev.classname,
                'subsystem_vendor_id': pci_dev.subvendor,
                'subsystem_vendor_name': pci_dev.subvendorname,
                'subsystem_id': pci_dev.subdevice,
                'subsystem_name': pci_dev.subdevicename,
                'driver': pci_dev.driver
            }
            # If saved uuid exists, use it. Otherwise create one.
            ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
            XendPPCI(ppci_uuid, ppci_record)

    def _init_PSCSIs(self):
        # Initialise PSCSIs
        saved_pscsis = self.state_store.load_state('pscsi')
        saved_pscsi_table = {}
        if saved_pscsis:
            for pscsi_uuid, pscsi_record in saved_pscsis.items():
                try:
                    saved_pscsi_table[pscsi_record['scsi_id']] = pscsi_uuid
                except KeyError:
                    pass

        for pscsi_record in vscsi_util.get_all_scsi_devices():
            if pscsi_record['scsi_id']:
                # If saved uuid exists, use it. Otherwise create one.
                pscsi_uuid = saved_pscsi_table.get(pscsi_record['scsi_id'],
                                                   uuid.createString())
                XendPSCSI(pscsi_uuid, pscsi_record)

    def add_network(self, interface):
        # TODO
        log.debug("add_network(): Not implemented.")

    def remove_network(self, interface):
        # TODO
        log.debug("remove_network(): Not implemented.")

    def add_PPCI(self, pci_name):
        # Update lspci info
        PciUtil.create_lspci_info()

        # Initialise the PPCI
        saved_ppcis = self.state_store.load_state('ppci')
        saved_ppci_table = {}
        if saved_ppcis:
            for ppci_uuid, ppci_record in saved_ppcis.items():
                try:
                    saved_ppci_table[ppci_record['name']] = ppci_uuid
                except KeyError:
                    pass

        pci_dev = PciUtil.PciDevice(PciUtil.parse_pci_name(pci_name))
        ppci_record = {
            'domain': pci_dev.domain,
            'bus': pci_dev.bus,
            'slot': pci_dev.slot,
            'func': pci_dev.func,
            'vendor_id': pci_dev.vendor,
            'vendor_name': pci_dev.vendorname,
            'device_id': pci_dev.device,
            'device_name': pci_dev.devicename,
            'revision_id': pci_dev.revision,
            'class_code': pci_dev.classcode,
            'class_name': pci_dev.classname,
            'subsystem_vendor_id': pci_dev.subvendor,
            'subsystem_vendor_name': pci_dev.subvendorname,
            'subsystem_id': pci_dev.subdevice,
            'subsystem_name': pci_dev.subdevicename,
            'driver': pci_dev.driver
        }
        # If saved uuid exists, use it. Otherwise create one.
        ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
        XendPPCI(ppci_uuid, ppci_record)

        self.save_PPCIs()

    def remove_PPCI(self, pci_name):
        # Update lspci info
        PciUtil.create_lspci_info()

        # Remove the PPCI
        (domain, bus, slot, func) = PciUtil.parse_pci_name(pci_name)
        ppci_ref = XendPPCI.get_by_sbdf(domain, bus, slot, func)
        XendAPIStore.get(ppci_ref, "PPCI").destroy()

        self.save_PPCIs()

    def add_PSCSI(self, add_HCTL):
        saved_pscsis = self.state_store.load_state('pscsi')
        saved_pscsi_table = {}
        if saved_pscsis:
            for saved_uuid, saved_record in saved_pscsis.items():
                try:
                    saved_pscsi_table[saved_record['scsi_id']] = saved_uuid
                except KeyError:
                    pass

        # Initialise the PSCSI
        pscsi_record = vscsi_util.get_scsi_device(add_HCTL)
        if pscsi_record and pscsi_record['scsi_id']:
            pscsi_uuid = saved_pscsi_table.get(pscsi_record['scsi_id'], None)
            if pscsi_uuid is None:
                pscsi_uuid = uuid.createString()
                XendPSCSI(pscsi_uuid, pscsi_record)
                self.save_PSCSIs()

    def remove_PSCSI(self, rem_HCTL):
        saved_pscsis = self.state_store.load_state('pscsi')
        if not saved_pscsis:
            return

        # Remove the PSCSI
        for pscsi_record in saved_pscsis.values():
            if rem_HCTL == pscsi_record['physical_HCTL']:
                pscsi_ref = XendPSCSI.get_by_HCTL(rem_HCTL)
                XendAPIStore.get(pscsi_ref, "PSCSI").destroy()
                self.save_PSCSIs()
                return

##    def network_destroy(self, net_uuid):
##       del self.networks[net_uuid]
##      self.save_networks()

    def get_PIF_refs(self):
        log.debug(XendPIF.get_all())
        return XendPIF.get_all()


##   def _PIF_create(self, name, mtu, vlan, mac, network, persist = True,
##                     pif_uuid = None, metrics_uuid = None):
##         for pif in self.pifs.values():
##             if pif.network == network:
##                 raise NetworkAlreadyConnected(pif.uuid)

##         if pif_uuid is None:
##             pif_uuid = uuid.createString()
##         if metrics_uuid is None:
##             metrics_uuid = uuid.createString()

##         metrics = XendPIFMetrics(metrics_uuid)
##         pif = XendPIF(pif_uuid, metrics, name, mtu, vlan, mac, network, self)
##         metrics.set_PIF(pif)

##         self.pif_metrics[metrics_uuid] = metrics
##         self.pifs[pif_uuid] = pif

##         if persist:
##             self.save_PIFs()
##             self.refreshBridges()
##         return pif_uuid

##     def PIF_destroy(self, pif_uuid):
##         pif = self.pifs[pif_uuid]

##         if pif.vlan == -1:
##             raise PIFIsPhysical()

##         del self.pifs[pif_uuid]
##         self.save_PIFs()

    def get_PPCI_refs(self):
        return XendPPCI.get_all()

    def get_ppci_by_uuid(self, ppci_uuid):
        if ppci_uuid in self.get_PPCI_refs():
            return ppci_uuid
        return None

    def get_PSCSI_refs(self):
        return XendPSCSI.get_all()

    def get_pscsi_by_uuid(self, pscsi_uuid):
        if pscsi_uuid in self.get_PSCSI_refs():
            return pscsi_uuid
        return None

    def save(self):
        # save state
        host_record = {
            self.uuid: {
                'name_label': self.name,
                'name_description': self.desc,
                'metrics_uuid': self.host_metrics_uuid,
                'other_config': self.other_config
            }
        }
        self.state_store.save_state('host', host_record)
        self.state_store.save_state('cpu', self.cpus)
        self.save_PIFs()
        self.save_networks()
        self.save_PBDs()
        self.save_SRs()
        self.save_PPCIs()
        self.save_PSCSIs()

    def save_PIFs(self):
        pif_records = dict([(pif_uuid, XendAPIStore.get(pif_uuid,
                                                        "PIF").get_record())
                            for pif_uuid in XendPIF.get_all()])
        self.state_store.save_state('pif', pif_records)

    def save_networks(self):
        net_records = dict([(network_uuid,
                             XendAPIStore.get(network_uuid,
                                              "network").get_record())
                            for network_uuid in XendNetwork.get_all()])
        self.state_store.save_state('network', net_records)

    def save_PBDs(self):
        pbd_records = dict([(pbd_uuid, XendAPIStore.get(pbd_uuid,
                                                        "PBD").get_record())
                            for pbd_uuid in XendPBD.get_all()])
        self.state_store.save_state('pbd', pbd_records)

    def save_SRs(self):
        sr_records = dict([(k, v.get_record(transient=False))
                           for k, v in self.srs.items()])
        self.state_store.save_state('sr', sr_records)

    def save_PPCIs(self):
        ppci_records = dict([(ppci_uuid, XendAPIStore.get(ppci_uuid,
                                                          "PPCI").get_record())
                             for ppci_uuid in XendPPCI.get_all()])
        self.state_store.save_state('ppci', ppci_records)

    def save_PSCSIs(self):
        pscsi_records = dict([
            (pscsi_uuid, XendAPIStore.get(pscsi_uuid, "PSCSI").get_record())
            for pscsi_uuid in XendPSCSI.get_all()
        ])
        self.state_store.save_state('pscsi', pscsi_records)

    def shutdown(self):
        return 0

    def reboot(self):
        return 0

    def notify(self, _):
        return 0

    #
    # Ref validation
    #

    def is_valid_host(self, host_ref):
        return (host_ref == self.uuid)

    def is_valid_cpu(self, cpu_ref):
        return (cpu_ref in self.cpus)

    def is_valid_sr(self, sr_ref):
        return (sr_ref in self.srs)

    def is_valid_vdi(self, vdi_ref):
        for sr in self.srs.values():
            if sr.is_valid_vdi(vdi_ref):
                return True
        return False

    #
    # Storage Repositories
    #

    def get_sr(self, sr_uuid):
        return self.srs.get(sr_uuid)

    def get_sr_by_type(self, sr_type):
        return [sr.uuid for sr in self.srs.values() if sr.type == sr_type]

    def get_sr_by_name(self, name):
        return [sr.uuid for sr in self.srs.values() if sr.name_label == name]

    def get_all_sr_uuid(self):
        return self.srs.keys()

    def get_vdi_by_uuid(self, vdi_uuid):
        for sr in self.srs.values():
            if sr.is_valid_vdi(vdi_uuid):
                return sr.get_vdi_by_uuid(vdi_uuid)
        return None

    def get_vdi_by_name_label(self, name):
        for sr in self.srs.values():
            vdi = sr.get_vdi_by_name_label(name)
            if vdi:
                return vdi
        return None

    def get_sr_containing_vdi(self, vdi_uuid):
        for sr in self.srs.values():
            if sr.is_valid_vdi(vdi_uuid):
                return sr
        return None

    #
    # Host Functions
    #

    def xen_version(self):
        info = self.xc.xeninfo()

        info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info}

        # Add xend_config_format
        info.update(self.xendinfo_dict())

        # Add version info about machine
        info.update(self.nodeinfo_dict())

        # Add specific xen version info
        xeninfo_dict = self.xeninfo_dict()

        info.update({
            "xen_major": xeninfo_dict["xen_major"],
            "xen_minor": xeninfo_dict["xen_minor"],
            "xen_extra": xeninfo_dict["xen_extra"],
            "cc_compiler": xeninfo_dict["cc_compiler"],
            "cc_compile_by": xeninfo_dict["cc_compile_by"],
            "cc_compile_domain": xeninfo_dict["cc_compile_domain"],
            "cc_compile_date": xeninfo_dict["cc_compile_date"],
            "xen_changeset": xeninfo_dict["xen_changeset"],
            "xen_commandline": xeninfo_dict["xen_commandline"]
        })

        return info

    def get_name(self):
        return self.name

    def set_name(self, new_name):
        self.name = new_name

    def get_description(self):
        return self.desc

    def set_description(self, new_desc):
        self.desc = new_desc

    def get_uuid(self):
        return self.uuid

    def get_capabilities(self):
        return self.xc.xeninfo()['xen_caps'].split(" ")

    #
    # Host CPU Functions
    #

    def get_host_cpu_by_uuid(self, host_cpu_uuid):
        if host_cpu_uuid in self.cpus:
            return host_cpu_uuid
        raise XendError('Invalid CPU UUID')

    def get_host_cpu_refs(self):
        return self.cpus.keys()

    def get_host_cpu_uuid(self, host_cpu_ref):
        if host_cpu_ref in self.cpus:
            return host_cpu_ref
        else:
            raise XendError('Invalid CPU Reference')

    def get_host_cpu_field(self, ref, field):
        try:
            return self.cpus[ref][field]
        except KeyError:
            raise XendError('Invalid CPU Reference')

    def get_host_cpu_load(self, host_cpu_ref):
        host_cpu = self.cpus.get(host_cpu_ref)
        if not host_cpu:
            return 0.0

        vcpu = int(host_cpu['number'])
        cpu_loads = self.monitor.get_domain_vcpus_util()
        if 0 in cpu_loads and vcpu in cpu_loads[0]:
            return cpu_loads[0][vcpu]

        return 0.0

    def get_vcpus_policy(self):
        sched_id = self.xc.sched_id_get()
        if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
            return 'sedf'
        elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
            return 'credit'
        else:
            return 'unknown'

    def get_cpu_configuration(self):
        phys_info = self.physinfo_dict()

        cpu_info = {
            "nr_nodes": phys_info["nr_nodes"],
            "nr_cpus": phys_info["nr_cpus"],
            "cores_per_socket": phys_info["cores_per_socket"],
            "threads_per_core": phys_info["threads_per_core"]
        }

        return cpu_info

    #
    # Network Functions
    #

    def bridge_to_network(self, bridge):
        """
        Determine which network a particular bridge is attached to.

        @param bridge The name of the bridge.  If empty, the default bridge
        will be used instead (the first one in the list returned by brctl
        show); this is the behaviour of the vif-bridge script.
        @return The XendNetwork instance to which this bridge is attached.
        @raise Exception if the interface is not connected to a network.
        """
        if not bridge:
            rc, bridge = commands.getstatusoutput(
                'brctl show | cut -d "\n" -f 2 | cut -f 1')
            if rc != 0 or not bridge:
                raise Exception(
                    'Could not find default bridge, and none was specified')

        for network_uuid in XendNetwork.get_all():
            network = XendAPIStore.get(network_uuid, "network")
            if network.get_name_label() == bridge:
                return network
        else:
            raise Exception('Cannot find network for bridge %s' % bridge)

    #
    # Debug keys.
    #

    def send_debug_keys(self, keys):
        return self.xc.send_debug_keys(keys)

    #
    # Getting host information.
    #

    def info(self):
        return (self.nodeinfo() + self.physinfo() + self.xeninfo() +
                self.xendinfo())

    def nodeinfo(self):
        (sys, host, rel, ver, mch) = os.uname()
        return [['system', sys], ['host', host], ['release', rel],
                ['version', ver], ['machine', mch]]

    def list_to_rangepairs(self, cmap):
        cmap.sort()
        pairs = []
        x = y = 0
        for i in range(0, len(cmap)):
            try:
                if ((cmap[y + 1] - cmap[i]) > 1):
                    pairs.append((cmap[x], cmap[y]))
                    x = y = i + 1
                else:
                    y = y + 1
            # if we go off the end, then just add x to y
            except IndexError:
                pairs.append((cmap[x], cmap[y]))

        return pairs

    def format_pairs(self, pairs):
        if not pairs:
            return "no cpus"
        out = ""
        for f, s in pairs:
            if (f == s):
                out += '%d' % f
            else:
                out += '%d-%d' % (f, s)
            out += ','
        # trim trailing ','
        return out[:-1]

    def list_to_strrange(self, list):
        return self.format_pairs(self.list_to_rangepairs(list))

    def format_node_to_cpu(self, pinfo):
        str = ''
        whitespace = ''
        try:
            node_to_cpu = pinfo['node_to_cpu']
            for i in range(0, pinfo['nr_nodes']):
                str += '%snode%d:%s\n' % (
                    whitespace, i, self.list_to_strrange(node_to_cpu[i]))
                whitespace = '%25s' % ''
        except:
            str = 'none\n'
        return str[:-1]

    def format_node_to_memory(self, pinfo):
        str = ''
        whitespace = ''
        try:
            node_to_memory = pinfo['node_to_memory']
            for i in range(0, pinfo['nr_nodes']):
                str += '%snode%d:%d\n' % (whitespace, i,
                                          node_to_memory[i] / 1024)
                whitespace = '%25s' % ''
        except:
            str = 'none\n'
        return str[:-1]

    def physinfo(self):
        info = self.xc.physinfo()

        info['cpu_mhz'] = info['cpu_khz'] / 1000

        # physinfo is in KiB, need it in MiB
        info['total_memory'] = info['total_memory'] / 1024
        info['free_memory'] = info['free_memory'] / 1024
        info['node_to_cpu'] = self.format_node_to_cpu(info)
        info['node_to_memory'] = self.format_node_to_memory(info)

        ITEM_ORDER = [
            'nr_cpus', 'nr_nodes', 'cores_per_socket', 'threads_per_core',
            'cpu_mhz', 'hw_caps', 'virt_caps', 'total_memory', 'free_memory',
            'node_to_cpu', 'node_to_memory'
        ]

        return [[k, info[k]] for k in ITEM_ORDER]

    def pciinfo(self):
        # Each element of dev_list is a PciDevice
        dev_list = PciUtil.find_all_assignable_devices()

        # Each element of devs_list is a list of PciDevice
        devs_list = PciUtil.check_FLR_capability(dev_list)

        devs_list = PciUtil.check_mmio_bar(devs_list)

        # Check if the devices have been assigned to guests.
        final_devs_list = []
        for dev_list in devs_list:
            available = True
            for d in dev_list:
                pci_str = '0x%x,0x%x,0x%x,0x%x' % (d.domain, d.bus, d.slot,
                                                   d.func)
                # Xen doesn't care what the domid is, so we pass 0 here...
                domid = 0
                bdf = self.xc.test_assign_device(domid, pci_str)
                if bdf != 0:
                    available = False
                    break
            if available:
                final_devs_list = final_devs_list + [dev_list]

        pci_sxp_list = []
        for dev_list in final_devs_list:
            for d in dev_list:
                pci_sxp = [
                    'dev', ['domain', '0x%04x' % d.domain],
                    ['bus', '0x%02x' % d.bus], ['slot',
                                                '0x%02x' % d.slot],
                    ['func', '0x%x' % d.func]
                ]
                pci_sxp_list.append(pci_sxp)

        return pci_sxp_list

    def xenschedinfo(self):
        sched_id = self.xc.sched_id_get()
        if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
            return 'sedf'
        elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
            return 'credit'
        else:
            return 'unknown'

    def xeninfo(self):
        info = self.xc.xeninfo()
        info['xen_scheduler'] = self.xenschedinfo()

        ITEM_ORDER = [
            'xen_major',
            'xen_minor',
            'xen_extra',
            'xen_caps',
            'xen_scheduler',
            'xen_pagesize',
            'platform_params',
            'xen_changeset',
            'xen_commandline',
            'cc_compiler',
            'cc_compile_by',
            'cc_compile_domain',
            'cc_compile_date',
        ]

        return [[k, info[k]] for k in ITEM_ORDER]

    def xendinfo(self):
        return [['xend_config_format', 4]]

    #
    # utilisation tracking
    #

    def get_vcpu_util(self, domid, vcpuid):
        cpu_loads = self.monitor.get_domain_vcpus_util()
        if domid in cpu_loads:
            return cpu_loads[domid].get(vcpuid, 0.0)
        return 0.0

    def get_vif_util(self, domid, vifid):
        vif_loads = self.monitor.get_domain_vifs_util()
        if domid in vif_loads:
            return vif_loads[domid].get(vifid, (0.0, 0.0))
        return (0.0, 0.0)

    def get_vif_stat(self, domid, vifid):
        vif_loads = self.monitor.get_domain_vifs_stat()
        if domid in vif_loads:
            return vif_loads[domid].get(vifid, (0.0, 0.0))
        return (0.0, 0.0)

    def get_vbd_util(self, domid, vbdid):
        vbd_loads = self.monitor.get_domain_vbds_util()
        if domid in vbd_loads:
            return vbd_loads[domid].get(vbdid, (0.0, 0.0))
        return (0.0, 0.0)

    # dictionary version of *info() functions to get rid of
    # SXPisms.
    def nodeinfo_dict(self):
        return dict(self.nodeinfo())

    def xendinfo_dict(self):
        return dict(self.xendinfo())

    def xeninfo_dict(self):
        return dict(self.xeninfo())

    def physinfo_dict(self):
        return dict(self.physinfo())

    def info_dict(self):
        return dict(self.info())

    # tmem
    def tmem_list(self, cli_id, use_long):
        pool_id = -1
        subop = TMEMC_LIST
        arg1 = 32768
        arg2 = use_long
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)

    def tmem_thaw(self, cli_id):
        pool_id = -1
        subop = TMEMC_THAW
        arg1 = 0
        arg2 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)

    def tmem_freeze(self, cli_id):
        pool_id = -1
        subop = TMEMC_FREEZE
        arg1 = 0
        arg2 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)

    def tmem_flush(self, cli_id, pages):
        pool_id = -1
        subop = TMEMC_FLUSH
        arg1 = pages
        arg2 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)

    def tmem_destroy(self, cli_id):
        pool_id = -1
        subop = TMEMC_DESTROY
        arg1 = 0
        arg2 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)

    def tmem_set_weight(self, cli_id, arg1):
        pool_id = -1
        subop = TMEMC_SET_WEIGHT
        arg2 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)

    def tmem_set_cap(self, cli_id, arg1):
        pool_id = -1
        subop = TMEMC_SET_CAP
        arg2 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)

    def tmem_set_compress(self, cli_id, arg1):
        pool_id = -1
        subop = TMEMC_SET_COMPRESS
        arg2 = 0
        buf = ''
        return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
Beispiel #16
0
    def __init__(self):
        """Initalises the state of all host specific objects such as

        * host
        * host_CPU
        * host_metrics
        * PIF
        * PIF_metrics
        * network
        * Storage Repository
        * PPCI
        * PSCSI
        """

        self.xc = xen.lowlevel.xc.xc()
        self.state_store = XendStateStore(xendoptions().get_xend_state_path())
        self.monitor = XendMonitor()
        self.monitor.start()

        # load host state from XML file
        saved_host = self.state_store.load_state('host')
        if saved_host and len(saved_host.keys()) == 1:
            self.uuid = saved_host.keys()[0]
            host = saved_host[self.uuid]
            self.name = host.get('name_label', socket.gethostname())
            self.desc = host.get('name_description', '')
            self.host_metrics_uuid = host.get('metrics_uuid',
                                              uuid.createString())
            try:
                self.other_config = eval(host['other_config'])
            except:
                self.other_config = {}
            self.cpus = {}
        else:
            self.uuid = uuid.createString()
            self.name = socket.gethostname()
            self.desc = ''
            self.other_config = {}
            self.cpus = {}
            self.host_metrics_uuid = uuid.createString()

        # put some arbitrary params in other_config as this
        # is directly exposed via XenAPI
        self.other_config["xen_pagesize"] = self.xeninfo_dict()["xen_pagesize"]
        self.other_config["platform_params"] = self.xeninfo_dict(
        )["platform_params"]
        self.other_config["xen_commandline"] = self.xeninfo_dict(
        )["xen_commandline"]

        # load CPU UUIDs
        saved_cpus = self.state_store.load_state('cpu')
        for cpu_uuid, cpu in saved_cpus.items():
            self.cpus[cpu_uuid] = cpu

        cpuinfo = osdep.get_cpuinfo()
        physinfo = self.physinfo_dict()
        cpu_count = physinfo['nr_cpus']
        cpu_features = physinfo['hw_caps']
        virt_caps = physinfo['virt_caps']

        # If the number of CPUs don't match, we should just reinitialise
        # the CPU UUIDs.
        if cpu_count != len(self.cpus):
            self.cpus = {}
            for i in range(cpu_count):
                u = uuid.createString()
                self.cpus[u] = {'uuid': u, 'number': i}

        for u in self.cpus.keys():
            number = self.cpus[u]['number']
            # We can run off the end of the cpuinfo list if domain0 does not
            # have #vcpus == #pcpus. In that case we just replicate one that's
            # in the hash table.
            if not cpuinfo.has_key(number):
                number = cpuinfo.keys()[0]
            if arch.type == "x86":
                self.cpus[u].update({
                    'host':
                    self.uuid,
                    'features':
                    cpu_features,
                    'virt_caps':
                    virt_caps,
                    'speed':
                    int(float(cpuinfo[number]['cpu MHz'])),
                    'vendor':
                    cpuinfo[number]['vendor_id'],
                    'modelname':
                    cpuinfo[number]['model name'],
                    'stepping':
                    cpuinfo[number]['stepping'],
                    'flags':
                    cpuinfo[number]['flags'],
                })
            elif arch.type == "ia64":
                self.cpus[u].update({
                    'host':
                    self.uuid,
                    'features':
                    cpu_features,
                    'speed':
                    int(float(cpuinfo[number]['cpu MHz'])),
                    'vendor':
                    cpuinfo[number]['vendor'],
                    'modelname':
                    cpuinfo[number]['family'],
                    'stepping':
                    cpuinfo[number]['model'],
                    'flags':
                    cpuinfo[number]['features'],
                })
            else:
                self.cpus[u].update({
                    'host': self.uuid,
                    'features': cpu_features,
                })

        self.srs = {}

        self._init_networks()
        self._init_PIFs()

        self._init_SRs()
        self._init_PBDs()

        self._init_PPCIs()

        self._init_PSCSIs()
class XendGpfsIsoStorageRepo(XendStorageRepository):
    """A backwards compatibility storage repository so that
    traditional file:/dir/file.img and phy:/dev/hdxx images can
    still be represented in terms of the Xen API.
    """
    
    def __init__(self, sr_uuid, sr_type,
                 name_label, name_description, physical_size, other_config, content_type, shared, sm_config):
        """
        @ivar    images: mapping of all the images.
        @type    images: dictionary by image uuid.
        @ivar    lock:   lock to provide thread safety.
        """
        XendStorageRepository.__init__(self, sr_uuid, sr_type,
                                       name_label, name_description)
        #log.debug(self.lock)
        #log.debug(self.uuid)
        self.type = sr_type
        self.name_label = name_label
        self.name_description = name_description
        self.other_config = other_config
        self.content_type = content_type
        self.shared = shared
        self.sm_config = sm_config
#        location = other_config.get('location')
        encode_passwd = other_config.get('password')
        self.passwd = encoding.ansi_decode(encode_passwd)
        auto = other_config.get('auto-scan', True)
#        local = location.split(':')[1]
#        if cmp(int(storage_max())*KB, physical_size) > 0:
#            self.physical_size = physical_size
#        else:
        location = self.other_config.get('location')
        self.local_sr_dir = location
        self.location = location
        self.mount_point = self._get_mount_point(self.location)
#        s_max = storage_max(self.local_sr_dir)
#        if s_max:
#            self.physical_size = int(s_max)*KB
#        else:
#            self.physical_size = 0
#        s_util = storage_util(self.local_sr_dir)
#        if s_util:
#            self.physical_utilisation = int(s_util)*KB
#        else:
#            self.physical_utilisation = 0
#        d_util = dir_util(self.local_sr_dir)
#        if d_util:
#            self.virtual_allocation = int(d_util)*KB
#        else:
#            self.virtual_allocation = 0
        self.state = XendStateStore(xendoptions().get_xend_state_path()
                                    + '/gpfs_iso_sr/%s' % self.uuid)
        stored_images = self.state.load_state('vdi')
        images_path = {}
        if stored_images:
            for image_uuid, image in stored_images.items():
                images_path[image['location'].replace(VDI_TYPE, '')] = image_uuid
                self.images[image_uuid] = XendLocalVDI(image)
#        self.update(auto)
        #self.save_state(True)
        #XendNode.instance().test_obj = self
#        TestObj.obj = self
#        log.debug(self.__dict__)

    def update(self, auto=True):
#        location = self.other_config.get('location')
#        local = location.split(':')[1]
        local = self.local_sr_dir
        stored_images = self.state.load_state('vdi')
        images_path = {}
        if stored_images:
            for image_uuid, image in stored_images.items():
                images_path[image['location'].replace(VDI_TYPE, '')] = image_uuid
                self.images[image_uuid] = XendLocalVDI(image)
        if auto:
            isos = iso_files(local)
            log.debug(isos)
            vdi_struct = {}
            for iso in isos.keys():
                if iso not in images_path.keys():
                    vdi_struct['other_config'] = {}
                    vdi_struct['location'] = VDI_TYPE+iso
                    vdi_struct['type'] = 'system'
                    vdi_struct['physical_utilisation'] = isos[iso]
                    vdi_struct['VBDs'] = []
                    vdi_struct['name_label'] = os.path.basename(iso)
                    #XendTask.log_progress(0, 100, self.create_vdi_append_state, vdi_struct)
    #                self.images[image_new] = XendLocalVDI(image)
                    self.create_vdi_append_state(vdi_struct)
            cd_rom = 'phy:/dev/sr0'
            log.debug(images_path.keys())
            if cd_rom not in images_path.keys():
                log.debug('In cd-rom create.')
                vdi_struct['other_config'] = {}
                vdi_struct['location'] = cd_rom
                vdi_struct['type'] = 'system'
                vdi_struct['VBDs'] = []
                vdi_struct['name_label'] = 'cd-rom'  
                self.create_vdi_append_state(vdi_struct)    
            import copy
            image_now = copy.deepcopy(images_path)          
            for img,vdi_uuid in image_now.items():
                if img not in isos.keys() and cmp(img, cd_rom) != 0:
                    self.destroy_vdi(vdi_uuid)

    def get_record(self, transient = True):
        retval = {'uuid': self.uuid,
                  'name_label': self.name_label,
                  'name_description': self.name_description,
                  'resident_on' : XendNode.instance().uuid,
                  'virtual_allocation': 0,
                  'physical_utilisation': self.get_physical_utilisation(),
                  'physical_size': self.get_physical_size(),
                  'type': self.type,
                  'content_type': self.content_type,
                  'VDIs': self.images.keys(),
                  'PBDs': XendPBD.get_by_SR(self.uuid),
                  'other_config': self.other_config,
                  'shared': self.shared,
                  'mount_point': self.mount_point, 
                  'sm_config': self.sm_config,}
        return retval
    
    def get_physical_utilisation(self):
        s_util = storage_util(self.local_sr_dir)
        if s_util:
            self.physical_utilisation = int(s_util)*KB
        else:
            self.physical_utilisation = 0
        return self.physical_utilisation
        
    def get_physical_size(self):
        s_max = storage_max(self.local_sr_dir)
        if s_max:
            self.physical_size = int(s_max)*KB
        else:
            self.physical_size = 0   
        return self.physical_size       

    def _get_mount_point(self, location):
        tmp = location.rsplit('/', 1)
        return tmp[0]      

    def create_vdi(self, vdi_struct, transient = False):
        """ Creates a fake VDI image for a traditional image string.

        The image uri is stored in the attribute 'uri'
        """
        if not vdi_struct.get('uuid') or vdi_struct.get('uuid') == '':
            vdi_struct['uuid'] = uuid.createString()
        vdi_struct['SR'] = self.uuid
        new_image = XendLocalVDI(vdi_struct)
        if vdi_struct.get('type') == 'user':            
#            self.create_img_file(vdi_struct)
            self.create_logical_volume(vdi_struct)    
        self.images[new_image.uuid] = new_image
        self.save_state(transient)
        return new_image.uuid
    
    def create_vdi_append_state(self, vdi_struct, transient = True):
        """ Creates a fake VDI image for a traditional image string.

        The image uri is stored in the attribute 'uri'
        """
#        f = open("/opt/xen/bug", "a")
        
#        if not vdi_struct.get('uuid') or vdi_struct.get('uuid') == '':
        vdi_struct['uuid'] = uuid.createString()
        vdi_struct['SR'] = self.uuid
        new_image = XendLocalVDI(vdi_struct)
        if vdi_struct.get('type') == 'user':            
#            self.create_img_file(vdi_struct)
            self.create_logical_volume(vdi_struct)    
        self.images[new_image.uuid] = new_image
        self.append_state(new_image, transient)
#        f.write("go to here\n")
#        f.close()
        return new_image.uuid

    def create_img_file(self, vdi_struct, path=None, size=None):
        path = IMG_FILE_PATH + vdi_struct.get('uuid') + '.img'
        size = int(vdi_struct.get('virtual_size')) * KB
        subprocess.Popen("vhd-util create -n %s -s %d" % (path, size), shell=True,
                           stdout=subprocess.PIPE)
        p = subprocess.Popen("dd if=/dev/zero of=%s bs=1M count=0 seek=%d" % (path, size), shell=True,
                           stdout=subprocess.PIPE)
#        log.debug("dd if=/dev/zero of=%s bs=1M count=0 seek=%d" % (path, size))

    def change_vdi_name_label(self, vdi_uuid, new_name):
        location = self.images[vdi_uuid].location.replace(VDI_TYPE, '')
        old_name = self.images[vdi_uuid].name_label
        new_location = location.replace(old_name, new_name)
        cmd = "mv %s %s" % (location, new_location)
        result = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
        self.update()

    def del_img_file_from_ssh(self, vdi_uuid):
#        location = self.other_config['location']
#        host_url = location.split(':')[0]
#        local = location.split(':')[1]
#        vdi_name = self.images[vdi_uuid].name_label
#        file = '%s/%s' %(local, vdi_name)
        location = self.images[vdi_uuid].location.replace(VDI_TYPE, '')
        cmd = 'rm -f %s' % location
        result = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)

    def get_vg_name(self):
        cmd = [VG_BINARY, '--noheadings', '--nosuffix', '--options=vg_name']
        (rc, stdout, stderr) = doexec(cmd)
        if rc != 0:
            err = stderr.read();
            out = stdout.read();
            stdout.close();
            stderr.close();
            raise Exception, 'Failed to get VG name. Check that lvm installed in dom0.';
        vg_name = stdout.read()
        stdout.close()
        stderr.close()
        return vg_name
        
    def create_logical_volume(self, vdi_struct, lv_name=None, size=None, vg_name=None):
        lv_name = 'VHD-' + vdi_struct.get('uuid')
        size = int(vdi_struct.get('virtual_size')) * KB
        vg_name = mytrim(self.get_vg_name())
        cmd = [LV_CREATE_BINARY, '%s' %vg_name, '-L', '%dM' %size, '-n', '%s' %lv_name]
        (rc, stdout, stderr) = doexec(cmd)
        if rc != 0:
            err = stderr.read();
            out = stdout.read();
            stdout.close();
            stderr.close();
            raise Exception, 'Failed to create logical volume: %s, lv_size: %d on VG: %s.\n%s' %(lv_name, size, vg_name, err);
        stdout.close()
        stderr.close()

    def save_state(self, transient=False):
        vdi_records = dict([(k, v.get_record(transient))
                            for k, v in self.images.items()])
        self.state.save_state('vdi', vdi_records)

    def append_state(self, new_image, transient):
        vdi_records = dict([(new_image.uuid, new_image.get_record(transient))])
        self.state.append_state('vdi', vdi_records)

    def destroy_vdi(self, vdi_uuid, del_file=True, transient = False):
#        if vdi_name:
#            for vdi_ref, image in self.images.items():
#                if image.name_label == vdi_name:
#                    vdi_uuid = vdi_ref
        if vdi_uuid in self.images:
            tmp = self.other_config['location'].split(':')
            exists = os.path.exists(tmp[len(tmp)-1])
            log.debug("in images")
            if exists and del_file:
                self.del_img_file_from_ssh(vdi_uuid)
            del self.images[vdi_uuid]
        else:
            log.debug("error: must not be here")
        self.save_state(transient)
        XendNode.instance().save_SRs()
Beispiel #18
0
    def __init__(self):
        """Initalises the state of all host specific objects such as

        * host
        * host_CPU
        * host_metrics
        * PIF
        * PIF_metrics
        * network
        * Storage Repository
        * PPCI
        * PSCSI
        """
        
        self.xc = xen.lowlevel.xc.xc()
        self.state_store = XendStateStore(xendoptions().get_xend_state_path())
        self.monitor = XendMonitor()
        self.monitor.start()

        # load host state from XML file
        saved_host = self.state_store.load_state('host')
        if saved_host and len(saved_host.keys()) == 1:
            self.uuid = saved_host.keys()[0]
            host = saved_host[self.uuid]
            self.name = host.get('name_label', socket.gethostname())
            self.desc = host.get('name_description', '')
            self.host_metrics_uuid = host.get('metrics_uuid',
                                              uuid.createString())
            try:
                self.other_config = eval(host['other_config'])
            except:
                self.other_config = {}
            self.cpus = {}
        else:
            self.uuid = uuid.createString()
            self.name = socket.gethostname()
            self.desc = ''
            self.other_config = {}
            self.cpus = {}
            self.host_metrics_uuid = uuid.createString()

        # put some arbitrary params in other_config as this
        # is directly exposed via XenAPI
        self.other_config["xen_pagesize"] = self.xeninfo_dict()["xen_pagesize"]
        self.other_config["platform_params"] = self.xeninfo_dict()["platform_params"]
        self.other_config["xen_commandline"] = self.xeninfo_dict()["xen_commandline"]
            
        # load CPU UUIDs
        saved_cpus = self.state_store.load_state('cpu')
        for cpu_uuid, cpu in saved_cpus.items():
            self.cpus[cpu_uuid] = cpu

        cpuinfo = osdep.get_cpuinfo()
        physinfo = self.physinfo_dict()
        cpu_count = physinfo['nr_cpus']
        cpu_features = physinfo['hw_caps']
        virt_caps = physinfo['virt_caps']

        # If the number of CPUs don't match, we should just reinitialise 
        # the CPU UUIDs.
        if cpu_count != len(self.cpus):
            self.cpus = {}
            for i in range(cpu_count):
                u = uuid.createString()
                self.cpus[u] = {'uuid': u, 'number': i }

        for u in self.cpus.keys():
            number = self.cpus[u]['number']
            # We can run off the end of the cpuinfo list if domain0 does not
            # have #vcpus == #pcpus. In that case we just replicate one that's
            # in the hash table.
            if not cpuinfo.has_key(number):
                number = cpuinfo.keys()[0]
            if arch.type == "x86":
                self.cpus[u].update(
                    { 'host'     : self.uuid,
                      'features' : cpu_features,
                      'virt_caps': virt_caps,
                      'speed'    : int(float(cpuinfo[number]['cpu MHz'])),
                      'vendor'   : cpuinfo[number]['vendor_id'],
                      'modelname': cpuinfo[number]['model name'],
                      'stepping' : cpuinfo[number]['stepping'],
                      'flags'    : cpuinfo[number]['flags'],
                    })
            elif arch.type == "ia64":
                self.cpus[u].update(
                    { 'host'     : self.uuid,
                      'features' : cpu_features,
                      'speed'    : int(float(cpuinfo[number]['cpu MHz'])),
                      'vendor'   : cpuinfo[number]['vendor'],
                      'modelname': cpuinfo[number]['family'],
                      'stepping' : cpuinfo[number]['model'],
                      'flags'    : cpuinfo[number]['features'],
                    })
            else:
                self.cpus[u].update(
                    { 'host'     : self.uuid,
                      'features' : cpu_features,
                    })

        self.srs = {}

        self._init_networks()
        self._init_PIFs()

        self._init_SRs()
        self._init_PBDs()

        self._init_PPCIs()

        self._init_PSCSIs()

        self._init_cpu_pools()
class XendLocalOcfs2StorageRepo(XendStorageRepository):
    """A backwards compatibility storage repository so that
    traditional file:/dir/file.img and phy:/dev/hdxx images can
    still be represented in terms of the Xen API.
    """
    
    def __init__(self, sr_uuid, sr_type,
                 name_label, name_description, physical_size, other_config, content_type, shared, sm_config):
        """
        @ivar    images: mapping of all the images.
        @type    images: dictionary by image uuid.
        @ivar    lock:   lock to provide thread safety.
        """
        XendStorageRepository.__init__(self, sr_uuid, sr_type,
                                       name_label, name_description)
        #log.debug(self.lock)
        #log.debug(self.uuid)
        self.record_changed = True
        self.type = sr_type
        self.name_label = name_label
        self.name_description = name_description
        self.other_config = other_config
        self.content_type = content_type
        self.shared = shared
        self.sm_config = sm_config
        
        self.location = other_config.get('location')
        encode_passwd = other_config.get('password')
        self.passwd = encoding.ansi_decode(encode_passwd)
        auto = other_config.get('auto-scan', False)
#        local = location.split(':')[1]
#        if cmp(int(storage_max())*KB, physical_size) > 0:
#            self.physical_size = physical_size
#        else:
        self.mount_point = self._get_mount_point(self.location)
#        s_max = storage_max(self.location)
#        if s_max:
#            self.physical_size = int(s_max)*KB
#        else:
#            self.physical_size = 0
#        s_util = storage_util(self.location)
#        if s_util:
#            self.physical_utilisation = int(s_util)*KB
#        else:
#            self.physical_utilisation = 0
#        d_util = dir_util(self.location)
#        if d_util:
#            self.virtual_allocation = int(d_util)*KB
#        else:
#            self.virtual_allocation = 0
        self.state = XendStateStore(xendoptions().get_xend_state_path()
                                    + '/local_ocfs2/%s' % self.uuid)
        stored_images = self.state.load_state('vdi')
        images_path = {}
        if stored_images:
            for image_uuid, image in stored_images.items():
                images_path[image['location'].replace(VDI_TYPE, '')] = image_uuid
                self.images[image_uuid] = XendLocalOcfs2VDI(image)
#        self.update(auto)
        #self.save_state(True)
        #XendNode.instance().test_obj = self
#        TestObj.obj = self
#        log.debug(self.__dict__)

    def _unit_format(self, data):
        try:
            data_num = data[:len(data)-1]
            result = 0
            if data.endswith('K'):
                result = float(data_num) * KB
            elif data.endswith('M'):
                result = float(data_num) * MB
            elif data.endswith('G'):
                result = float(data_num) * GB
            elif data.endswith('T'):
                result = float(data_num) * TB
            elif data.endswith('P'):
                result = float(data_num) * PB
            elif data_num:
                result = float(data_num)
            if result:
                return int(result)
            else:
                return result
        except Exception ,exn:
            log.debug(exn)
            return result