Commit b5af93d2 authored by Anael Beutot's avatar Anael Beutot
Browse files

Create volume and delete volume handlers.

parent c76efb7e
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -11,3 +11,7 @@ class PluginError(CCNodeError):

class UndefinedDomain(CCNodeError):
    pass


class PoolStorageError(CCNodeError):
    pass
+80 −6
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@ from ccnode.hypervisor.lib import (
    EventLoop as VirEventLoop,
)
from ccnode.hypervisor.domains import VirtualMachine
from ccnode.exc import UndefinedDomain
from ccnode.exc import UndefinedDomain, PoolStorageError


logger = logging.getLogger(__name__)
@@ -247,6 +247,22 @@ class Handler(HostHandler):
            logger.error(msg)
            raise UndefinedDomain(msg)

    def vol_create(self, pool, name, size):
        logger.debug('Volume create %s, pool %s, size %s', name, pool, size)
        try:
            self.hypervisor.storage.create_volume(pool, name, size)
        except Exception:
            logger.exception('Error while creating volume')
            raise

    def vol_delete(self, pool, name):
        logger.debug('Volume delete %s, pool %s', name, pool)
        try:
            self.hypervisor.storage.delete_volume(pool, name)
        except Exception:
            logger.exception('Error while deleting volume')
            raise


class Hypervisor(object):
    """Container for all hypervisor related state."""
@@ -415,8 +431,8 @@ class StorageIndex(object):
        )

        self.paths = dict(
            (v.path, v) for v in chain.from_iterable(map(
                lambda s: s.volumes,
            (v.path, v) for v in chain.from_iterable(imap(
                lambda s: s.volumes.itervalues(),
                self.storages.itervalues(),
            )),
        )
@@ -427,6 +443,62 @@ class StorageIndex(object):
    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."""
@@ -436,15 +508,16 @@ class Storage(object):
        """
        self.uuid = lv_storage.UUID()
        self.name = lv_storage.name()
        self.lv_storage = lv_storage

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

        self.volumes = map(
        self.volumes = dict((v.name, v) for v in imap(
            Volume,
            (lv_storage.storageVolLookupByName(n) for n in
             lv_storage.listVolumes()),
        )
        ))


class Volume(object):
@@ -457,3 +530,4 @@ class Volume(object):
        self.path = lv_volume.path()
        self.name = lv_volume.name()
        self.capacity, self.allocation = lv_volume.info()[1:]
        self.lv_volume = lv_volume