diff options
author | Martin Gracik <mgracik@redhat.com> | 2009-03-24 11:05:40 +0100 |
---|---|---|
committer | Martin Gracik <mgracik@redhat.com> | 2009-03-24 14:41:55 +0100 |
commit | ac83df7815ff3db042875db51a43c107e982ee70 (patch) | |
tree | a8b67d04cf0b00ea92b6fa1d4c162123dc9fa0e3 /anate/vm.py | |
download | anate-master.tar.gz anate-master.tar.xz anate-master.zip |
Diffstat (limited to 'anate/vm.py')
-rw-r--r-- | anate/vm.py | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/anate/vm.py b/anate/vm.py new file mode 100644 index 0000000..71fcabc --- /dev/null +++ b/anate/vm.py @@ -0,0 +1,135 @@ +import logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger('anate.vm') + +import os +import devices + + +class VirtualDisk(devices.DMDevice): + + _LOOP_DEV_MAJOR = 7 + _AVAILABLE_MINORS = [0, 1, 2, 3, 4, 5, 6, 7] + + def getAvailableMinor(self): + return self._AVAILABLE_MINORS[0] + + def useMinor(self, minor): + self._AVAILABLE_MINORS.remove(minor) + + def freeMinor(self, minor): + self._AVAILABLE_MINORS.append(minor) + self._AVAILABLE_MINORS.sort() + + def __init__(self, name, size, usable_size=None): + if not usable_size: + usable_size = size + elif usable_size > size: + logger.error('usable_size cannot be greater than size') + return + + self._remove_node = False + self._loop_node = self._createLoopNode(name) + if not self._loop_node: + raise OSError, 'node error' + + self._loop_dev = self._createLoopDev(name, self._loop_node, usable_size) + + devices.DMDevice.__init__(self, name, self._loop_dev, size) + + def _createLoopNode(self, name): + loop_node = devices.BlockDeviceNode(os.path.join('/dev/', name), major=None, minor=None) + if loop_node.available: + logger.info('using existing node %s', loop_node.path) + loop_node.major, loop_node.minor = devices.getDeviceNumbers(loop_node.path) + if loop_node.major != self._LOOP_DEV_MAJOR: + logger.error('not a loop device node') + return + if loop_node.minor not in self._AVAILABLE_MINORS: + logger.error('node not available') + return + else: + logger.info('creating new node %s', loop_node.path) + loop_node.major = self._LOOP_DEV_MAJOR + loop_node.minor = self.getAvailableMinor() + loop_node.create() + self._remove_node = True + + self.useMinor(loop_node.minor) + logger.info('using minor %d', loop_node.minor) + logger.info('available minors: %s', self._AVAILABLE_MINORS) + + if not loop_node.available: + raise OSError, 'node error' + + return loop_node + + def _createLoopDev(self, name, loop_node, size): + loop_dev = devices.LoopDevice(name, loop_node, os.path.join('/tmp/', name), size) + loop_dev.initialize() + if not loop_dev.active: + raise OSError, 'loop device error' + + return loop_dev + + def create(self): + self.initialize() + if not self.active: + raise OSError, 'dm device error' + + def remove(self): + self.destroy() + if self.active: + raise OSError, 'dm device error' + + self._loop_dev.destroy() + if self._loop_dev.active: + raise OSError, 'loop device error' + + if self._remove_node: + logger.info('removing node %s', self._loop_node.path) + self._loop_node.unlink() + if self._loop_node.available: + raise OSError, 'node error' + + self.freeMinor(self._loop_node.minor) + logger.info('freeing minor %d', self._loop_node.minor) + logger.info('available minors: %s', self._AVAILABLE_MINORS) + + +class VM(object): + def __init__(self): + self._disks = {} + + def addDisk(self, name, size, usable_size=None): + if name in self.disks: + logger.error('disk %s already exists', name) + return + + disk = VirtualDisk(name, size=size, usable_size=usable_size) + disk.create() + self._disks[name] = disk + + def removeDisk(self, name): + if name not in self.disks: + logger.error('disk %s does not exist', name) + return + + disk = self.getDisk(name) + if disk.active: + disk.remove() + del self._disks[name] + + def halt(self): + for disk in self.disks.values(): + if disk.active: + disk.remove() + + self._disks = {} + + @property + def disks(self): + return self._disks + + def getDisk(self, name): + return self.disks.get(name, None) |