Skip to content
__init__.py 41.4 KiB
Newer Older
            chain(
                self.lv_con.listDefinedStoragePools(),
                self.lv_con.listStoragePools(),
            ),
        ):
            if lv_storage.name() in self.storages:
                # update
                self.storages[lv_storage.name()].update()
            else:
                # add storage pool
                s = Storage(lv_storage)
                self.storages[s.name] = s
                # add tags
                self.handler.tag_db.add_tags((
                    Tag('sto%s_state' % s.name, lambda: s.state, 5, 5),
                    Tag('sto%s_size' % s.name, lambda: s.capacity, 5, 5),
                    Tag('sto%s_free' % s.name, lambda: s.available, 5, 5),
                    Tag('sto%s_used' % s.name,
                        lambda: s.capacity - s.available, 5, 5),
                    Tag('sto%s_type' % s.name, lambda: s.type, 5, 5),
                ))

        self.update_path_index()

    def update_path_index(self):
        self.paths = dict(
            (v.path, v) for v in chain.from_iterable(imap(
                lambda s: s.volumes.itervalues(),
                self.storages.itervalues(),
            )),
        )

    def get_volume(self, path):
        return self.paths.get(path)

    def get_storage(self, name):
        return self.storages.get(name)
    def create_volume(self, pool_name, volume_name, capacity):
        """Create a new volume in the storage pool.

        :param str name: name for the volume
        :param int capacity: size for the volume
        """
        # get volume
        logger.debug('asked pool %s', pool_name)
        logger.debug('Pool state %s', self.storages)
        try:
            pool = self.storages[pool_name]
        except KeyError:
            raise PoolStorageError('Invalid pool name')
        if pool is None:
            raise Exception('Storage pool not found')
        try:
            new_volume = pool.lv_storage.createXML("""<volume>
                                        <name>%s</name>
                                        <capacity>%d</capacity>
                                      </volume>""" % (volume_name, capacity), 0)
        except libvirt.libvirtError:
            logger.exception('Error while creating volume')
            raise

        new_volume = Volume(new_volume)
        # if success add the volume to the index
        self.paths[new_volume.path] = new_volume
        # and also to its storage pool
        self.storages[new_volume.storage].volumes[new_volume.name] = new_volume

    def delete_volume(self, pool_name, volume_name):
        """Delete a volume in the givent storage pool.

        :param str pool_name: name for the storage pool
        :param str volume_name: name for the volume
        """
        # get volume
        try:
            pool = self.storages[pool_name]
        except KeyError:
            raise PoolStorageError('Invalid pool name')
        try:
            volume = pool.volumes[volume_name]
        except KeyError:
            raise PoolStorageError('Invalid volume name')
        # delete from index
        del self.paths[volume.path]
        del self.storages[pool_name].volumes[volume_name]

        # delete volume
        try:
            volume.lv_volume.delete(0)
        except libvirt.libvirtError:
            logger.exception('Error while deleting volume')
            raise


class Storage(object):
    """Storage abstraction."""
    def __init__(self, lv_storage):
        """
        :param lv_storage: Libvirt pool storage instance
        """
        self.uuid = lv_storage.UUID()
        self.name = lv_storage.name()
        self.lv_storage = lv_storage
        self.state, self.capacity = None, None
        self.allocation, self.available = None, None
        self.type = et.ElementTree().parse(
            StringIO(lv_storage.XMLDesc(0))).get('type')

        self.volumes = dict((v.name, v) for v in imap(
Anael Beutot's avatar
Anael Beutot committed
            Volume,
            (lv_storage.storageVolLookupByName(n) for n in
             lv_storage.listVolumes()),
        ))
        self.update_attr()

    def update(self):
        self.update_attr()

        # update volumes
        for vol_name in self.lv_storage.listVolumes():
            if vol_name in self.volumes:
                # update volume
                self.volumes[vol_name].update()
            else:
                # add volume
                v = Volume(self.lv_storage.storageVolLookupByName(vol_name))
                self.volumes[v.name] = v

    def update_attr(self):
        self.state, self.capacity, self.allocation, self.available = self.lv_storage.info()
        self.state = STORAGE_STATES[self.state]

        self.type = et.ElementTree().parse(
            StringIO(self.lv_storage.XMLDesc(0))).get('type')



class Volume(object):
    """Volume abstraction."""
Anael Beutot's avatar
Anael Beutot committed
    def __init__(self, lv_volume):
        """
        :param lv_volume: Libvirt volume instance
        """
        self.storage = lv_volume.storagePoolLookupByVolume().name()
        self.path = lv_volume.path()
        self.name = lv_volume.name()
        self.capacity, self.allocation = None, None
        self.lv_volume = lv_volume
        self.update()

    def update(self):
        self.capacity, self.allocation = self.lv_volume.info()[1:]