Commit a4c3bf31 authored by Thibault VINCENT's avatar Thibault VINCENT
Browse files

new disk and storage tags, helper methods

parent 7f87d0d6
Loading
Loading
Loading
Loading
+55 −24
Original line number Diff line number Diff line
@@ -96,12 +96,14 @@ class NodeHandler(RpcHandler):
        :param method: the method to be called
        :type method: :class:`str`
        '''
        logging.debug('called _call_hv_method(%s)' % method)
        return getattr(self.hv_handle, HV_TAG_WRAP_MAP[method])()
    
    def _call_hv_helper(self, method):
        logging.debug('called _call_hv_helper(%s)' % method)
        return getattr(self, "_helper_hv_" + method)()
    
    def _call_vm_method(self, vm, method):
    def _call_vm_method(self, vm_name, tag):
        '''
        Calls the given method in vm instance
        Returns the result of the method called
@@ -111,12 +113,17 @@ class NodeHandler(RpcHandler):
        :param method: the method to be called
        :type method: :class:`str`
        '''
        return getattr(vm, VM_TAG_WRAP_MAP[method])()
        logging.debug('called _call_vm_method(%s,%s)' % (vm_name, tag))
        vm_obj = self.hv_handle.get_vm(vm_name)
        return getattr(vm_obj, VM_TAG_WRAP_MAP[tag])()
    
    def _call_vm_helper(self, method):
        return getattr(self, "_helper_vm_" + method)()
    def _call_vm_helper(self, vm_name, helper):
        logging.debug('called _call_vm_helper(%s,%s)' % (vm_name, helper))
        vm_obj = self.hv_handle.get_vm(vm_name)
        return getattr(self, "_helper_vm_" + helper)(vm_obj)
    
    def _helper_hv_sto(self):
        logging.debug('called _helper_hv_sto()')
        result = {}
        hv = self.hv_handle
        # fetch pool list
@@ -124,29 +131,48 @@ class NodeHandler(RpcHandler):
        result['sto'] = " ".join(pools)
        # get pool info
        for pool in pools:
            # storage type
            result['sto%s_type' % pool] = hv.get_storage_type(pool)
            # path to the pool base
            result['sto%s_path' % pool] = hv.get_storage_path(pool)
            # pool size
            result['sto%s_size' % pool] = hv.get_storage_capacity(pool)
            result['sto%s_size' % pool] = str(hv.get_storage_capacity(pool))
            # pool used space
            result['sto%s_used' % pool] = hv.get_storage_used(pool)
            result['sto%s_used' % pool] = str(hv.get_storage_used(pool))
            # pool free space
            result['sto%s_free' % pool] = hv.get_storage_free(pool)
            result['sto%s_free' % pool] = str(hv.get_storage_free(pool))
            # pool volume list
            result['sto%s_vol' % pool] = hv.get_storage_volumes(pool)
        return result
    
    def _helper_hv_disk(self):
        return {}
        logging.debug('called _helper_hv_disk()')
        result = {}
        disks = self.hv_handle.get_disks()
        result['disk'] = " ".join(disks.keys())
        for disk, size in disks.iteritems():
            result['disk%s_size' % disk] = str(size)
        return result
    
    def _helper_vm_disk(self):
    def _helper_vm_disk(self, vm):
        logging.debug('called _helper_vm_disk(%s)' % vm.get_name())
        result = {}
        hv = self.hv_handle
        # fetch disk list
        disks = hv.get_vm_disks()
        result['disk'] = " ".join([d['name'] for d in disks])
        disks = vm.get_disks()
        logging.debug('_helper_vm_disk: disk list "%s"' % disks)
        if len(disks):
            result['disk'] = " ".join(str(id) for id in range(0, len(disks)))
            # add disk info
            for n, disk in enumerate(disks):
                # disk path to real storage
                result['disk%i_path' % n] = disk['path']
                # disk size
            result['disk%i_size' % n] = disk['size']
                result['disk%i_size' % n] = str(disk['size'])
                # disk pool
                result['disk%i_pool' % n] = disk['pool']
                # disk volume
                result['disk%i_vol' % n] = disk['vol']
        logging.debug('_helper_vm_disk returns "%s"' % result)
        return result
    
    @pure
@@ -159,23 +185,28 @@ class NodeHandler(RpcHandler):
        :type tags: :class:`list` 
        '''
        result = {}
        if tags is None:
            tags = HV_TAG_WRAP_MAP.keys()
        if tags is not None:
            tags = set(tags)
            tags |= set(('h', 'hv'))
        hv_tags = HV_TAG_WRAP_MAP.keys() if tags is None else tags
        # static tags
        result['version'] = str(__version__)
        # direct wrapping
        for tag in tags:
        for tag in hv_tags:
            try:
                result[tag] = self._call_hv_method(tag)
                result[tag] = str(self._call_hv_method(tag))
            except AttributeError:
                logging.warning(TAG_METHOD_ERROR % tag)
            except KeyError:
                logging.warning(TAG_NOT_FOUND_ERROR % tag)
            except NotImplementedError:
                logging.debug('get_tags: no mehod in hypervisor to handle %s' % tag)
                logging.debug('get_tags: no method in hypervisor to handle "%s"' % tag)
        # tag aggregations from wrapping helpers
        for helper in HV_TAG_HELPER_LIST:
            result.update(self._call_hv_helper(helper))
            htags = self._call_hv_helper(helper)
            for tag, val in htags.iteritems():
                if tags is None or tag in tags:
                    result.update({tag:val})
        return result

    @pure
+70 −8
Original line number Diff line number Diff line
@@ -157,19 +157,34 @@ class LibvirtVm(VM):
    
    def get_disks(self):
        result = []
        # we parse xml description of the vm to get this info
        # we parse xml description of the vm to get disk list
        xml_string = self._domain.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE)
        root = xml.dom.minidom.parseString(xml_string)
        domain = root.getElementsByTagName('domain').pop()
        devices = domain.getElementsByTagName('devices').pop()
        # iter on "disk" devices
        for disk in devices.getElementsByTagName('disk'):
            # skip weird disks
            if disk.getAttribute('device') == 'disk':
                d = {}
                if disk.getAttribute('type') == 'file':
                # get type
                dtype = disk.getAttribute('type')
                # get disk path
                if dtype == 'file':
                    d['path'] = disk.getElementsByTagName('source').pop().getAttribute('file')
                elif disk.getAttribute('type') == 'block':
                elif dtype == 'block':
                    d['path'] = disk.getElementsByTagName('source').pop().getAttribute('dev')
                results.append(d)
                # attributes only resolvable in the storage pool
                if dtype in ['file', 'block']:
                    sto = self._hypervisor._storage
                    for pool_name, pool in sto.get_pools().iteritems():
                        for vol_name in sto.get_volume_names(pool):
                            if sto.get_volume_path(pool, vol_name) == d['path']:
                                d['pool'] = pool_name
                                d['vol'] = vol_name
                                d['size'] = sto.get_volume_capacity(pool, vol_name)                    
                result.append(d)
        return result
        return result
    
    def get_status(self):
@@ -331,6 +346,20 @@ class LibvirtHypervisor(Hypervisor):
    def get_cpu_percent(self):
        return '%2.0f' % psutil.cpu_percent()
    
    def get_disks(self):
        result = {}
        try:
            re_pattern = re.compile(r'([sh]d[a-z]+)')
            found = [bd for bd in os.listdir('/sys/block/') if re_pattern.match(bd)]
            for disk in found:
                fullname = os.path.join('/sys/block', disk, 'size')
                size = int(open(fullname).read())
                if size > 0:
                    result[disk] = size * 512
        except:
            pass
        return result
    
    def get_storage_pools(self):
        return self._storage.get_pools().keys()
    
@@ -370,6 +399,38 @@ class LibvirtHypervisor(Hypervisor):
                                            self._storage.get_pools()[pool])
        return free
    
    def get_storage_type(self, pool_name):
        result = None
        try:
            pool = self._storage.get_pools()[pool_name]
            xroot = xml.dom.minidom.parseString(pool.XMLDesc(0))
            xpool = xroot.getElementsByTagName('pool').pop()
            result = xpool.getAttribute('type')
        except:
            pass
        return result
    
    def get_storage_path(self, pool_name):
        result = None
        try:
            pool = self._storage.get_pools()[pool_name]
            xroot = xml.dom.minidom.parseString(pool.XMLDesc(0))
            xpool = xroot.getElementsByTagName('pool').pop()
            xtarget = xpool.getElementsByTagName('target').pop()
            xpath = xtarget.getElementsByTagName('path').pop()
            result = xpath.firstChild.nodeValue
        except:
            pass
        return result
    
    def get_storage_volumes(self, pool_name):
        result = None
        try:
            pool = self._storage.get_pools()[pool_name]
            result = " ".join(self._storage.get_volume_names(pool))
        except:
            pass

    def get_status(self):
        raise NotImplementedError()
   
@@ -508,9 +569,6 @@ class LibvirtHypervisor(Hypervisor):
    def get_network_conf(self):
        raise NotImplementedError
    
    def get_storage_conf(self):
        raise NotImplementedError
    
    def get_storage_stats(self):
        raise NotImplementedError

@@ -544,7 +602,11 @@ class LibvirtHVStorage(HVStorage):
        '''
        Returns a dict of storage pools bound to the host
        '''
        return self._pools
        pools = {}
        for pool_name, pool in self._pools.iteritems():
            if pool.isActive():
                pools[pool_name] = pool
        return pools

    def get_volume_names(self, pool=None):
        '''