Source code for mcvirt.virtual_machine.hard_drive.local

# Copyright (c) 2014 - I.T. Dev Ltd
#
# This file is part of MCVirt.
#
# MCVirt is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# MCVirt is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with MCVirt.  If not, see <http://www.gnu.org/licenses/>

import Pyro4
import libvirt
import os

from mcvirt.system import System
from mcvirt.exceptions import (VmAlreadyStartedException, VmIsCloneException,
                               ExternalStorageCommandErrorException,
                               DiskAlreadyExistsException,
                               CannotMigrateLocalDiskException,
                               MCVirtCommandException)
from mcvirt.virtual_machine.hard_drive.base import Base
from mcvirt.auth.auth import Auth
from mcvirt.auth.permissions import PERMISSIONS
from mcvirt.rpc.lock import locking_method


[docs]class Local(Base): """Provides operations to manage local hard drives, used by VMs""" MAXIMUM_DEVICES = 4 CACHE_MODE = 'directsync' def __init__(self, *args, **kwargs): """Sets member variables and obtains libvirt domain object""" super(Local, self).__init__(*args, **kwargs) @staticmethod
[docs] def isAvailable(pyro_object): """Determine if local storage is available on the node""" return pyro_object._get_registered_object('node').is_volume_group_set()
@Pyro4.expose() @locking_method() def increaseSize(self, increase_size): """Increases the size of a VM hard drive, given the size to increase the drive by""" self._get_registered_object('auth').assert_permission( PERMISSIONS.MODIFY_VM, self.vm_object ) # Ensure disk exists self._ensure_exists() # Ensure VM is stopped from mcvirt.virtual_machine.virtual_machine import PowerStates if (self.vm_object._getPowerState() is not PowerStates.STOPPED): raise VmAlreadyStartedException('VM must be stopped before increasing disk size') # Ensure that VM has not been cloned and is not a clone if (self.vm_object.getCloneParent() or self.vm_object.getCloneChildren()): raise VmIsCloneException('Cannot increase the disk of a cloned VM or a clone.') command_args = ('lvextend', '-L', '+%sM' % increase_size, self._getDiskPath()) try: System.runCommand(command_args) except MCVirtCommandException, e: raise ExternalStorageCommandErrorException( "Error whilst extending logical volume:\n" + str(e) ) def _check_exists(self): """Checks if a disk exists, which is required before any operations can be performed on the disk""" self._ensureLogicalVolumeExists( self._getDiskName()) return True def _removeStorage(self): """Removes the backing logical volume""" self._ensure_exists() self._removeLogicalVolume(self._getDiskName())
[docs] def getSize(self): """Gets the size of the disk (in MB)""" self._ensure_exists() return self._get_logical_volume_size(self._getDiskName())
[docs] def clone(self, destination_vm_object): """Clone a VM, using snapshotting, attaching it to the new VM object""" self._ensure_exists() new_disk = Local(vm_object=destination_vm_object, driver=self.driver, disk_id=self.disk_id) self._register_object(new_disk) new_logical_volume_name = new_disk._getDiskName() disk_size = self.getSize() # Perform a logical volume snapshot command_args = ('lvcreate', '-L', '%sM' % disk_size, '-s', '-n', new_logical_volume_name, self._getDiskPath()) try: System.runCommand(command_args) except MCVirtCommandException, e: raise ExternalStorageCommandErrorException( "Error whilst cloning disk logical volume:\n" + str(e) ) new_disk.addToVirtualMachine() return new_disk
[docs] def create(self, size): """Creates a new disk image, attaches the disk to the VM and records the disk in the VM configuration""" disk_path = self._getDiskPath() logical_volume_name = self._getDiskName() # Ensure the disk doesn't already exist if (os.path.lexists(disk_path)): raise DiskAlreadyExistsException('Disk already exists: %s' % disk_path) # Create the raw disk image self._createLogicalVolume(logical_volume_name, size) # Attach to VM and create disk object self.addToVirtualMachine()
[docs] def activateDisk(self): """Starts the disk logical volume""" self._ensure_exists() self._activateLogicalVolume(self._getDiskName())
[docs] def deactivateDisk(self): """Deactivates the disk loglcal volume""" self._ensure_exists()
[docs] def preMigrationChecks(self): """Perform pre-migration checks""" raise CannotMigrateLocalDiskException('VMs using local disks cannot be migrated')
def _getDiskPath(self): """Returns the path of the raw disk image""" return self._getLogicalVolumePath(self._getDiskName()) def _getDiskName(self): """Returns the name of a disk logical volume, for a given VM""" vm_name = self.vm_object.get_name() return 'mcvirt_vm-%s-disk-%s' % (vm_name, self.disk_id) def _getMCVirtConfig(self): """Returns the MCVirt hard drive configuration for the Local hard drive""" # There are no configurations for the disk stored by MCVirt return super(Local, self)._getMCVirtConfig() def _getBackupLogicalVolume(self): """Returns the storage device for the backup""" return self._getDiskName() def _getBackupSnapshotLogicalVolume(self): """Returns the logical volume name for the backup snapshot""" return self._getDiskName + self.SNAPSHOT_SUFFIX