def __getattr__(self, attr): if self._wrappedInstance: if attr in self._passthruProperties: with VirtualBoxException.ExceptionHandler(): return getattr(self._wrappedInstance, attr) for prop, func in self._wrappedProperties: if prop == attr: with VirtualBoxException.ExceptionHandler(): value = getattr(self._wrappedInstance, attr) return func(value) if value else None raise AttributeError("Unrecognized attribute '%s'" % attr)
def create(cls, path, format=None): """Create a new hard disk at the given location.""" with VirtualBoxException.ExceptionHandler(): path = cls._canonicalizeMediumPath(path) if os.path.exists(path): # Todo: Better exception here raise VirtualBoxException.VirtualBoxException( "Cannot create %s - file already exists." % path) with VirtualBoxException.ExceptionHandler(): # Despire the name of this method it returns an IMedium # instance imedium = cls._getVBox().createHardDisk(format, path) return cls(imedium)
def waitForCompletion(self, timeout=None): """Waits until the task is done (including all sub-operations). Timeout is in milliseconds, specify None for an indefinite wait.""" if timeout is None: timeout = self.WaitIndefinite with VirtualBoxException.ExceptionHandler(): self._wrappedInstance.waitForCompletion(timeout) if (((not self.completed) and (timeout == self.WaitIndefinite)) or (self.completed and (self.resultCode != 0))): # TODO: This is not the right exception to return. raise VirtualBoxException.VirtualBoxException( "Task %s did not complete: %s (%d)" % (self.description, self.errorInfo.text, self.resultCode))
def powerOn(self, type="gui", env=""): """Spawns a new process that executes a virtual machine. This is spawning a "remote session" in VirtualBox terms.""" # TODO: Add a wait argument if not self.isRegistered(): raise VirtualBoxException.VirtualBoxInvalidVMStateException( "VM is not registered") with VirtualBoxException.ExceptionHandler(): iMachine = self.getIMachine() session = Session.create() iprogress = iMachine.launchVMProcess(session.getISession(), type, env) progress = Progress(iprogress) progress.waitForCompletion() session.unlockMachine()
def find(cls, path, deviceType): """Returns a medium that uses the given path or UUID to store medium data.""" with VirtualBoxException.ExceptionHandler(): if not UUID.isUUID(path): path = cls._canonicalizeMediumPath(path) medium = cls._getVBox().findMedium(path, deviceType) return Medium(medium)
def __delattr__(self, attr): if self._wrappedInstance and (attr in self._passthruProperties): with VirtualBoxException.ExceptionHandler(): raise AttributeError("Cannot delete attribute '%s'" % attr) del self.__dict__[attr]
def removeStorageController(self, name): """Removes a storage controller from the machine.""" with self.lock() as session: with VirtualBoxException.ExceptionHandler(): mutableMachine = session.getMachine() mutableMachine.getIMachine().removeStorageController(name) session.saveSettings()
def unlockMachine(self, wait=True): """Close any open session, unlocking the machine.""" if self.isLocked(): with VirtualBoxException.ExceptionHandler(): self._wrappedInstance.unlockMachine() if wait: while self.isLocked(): self._vbox.waitForEvent()
def isRegistered(cls, path): """Is a hard disk at the given path already registered?""" try: with VirtualBoxException.ExceptionHandler(): cls.find(path) except VirtualBoxException.VirtualBoxObjectNotFoundException: return False return True
def waitForEvents(self, timeout=None): """Wait for an event. Timeout is in miliseconds (I think).""" if timeout is None: # No timeout timeout = 0 with VirtualBoxException.ExceptionHandler(): vboxapi.VirtualBoxManager.waitForEvents(self, timeout)
def detachMedium(self, device): """Detach the medium from the machine.""" with self.lock() as session: with VirtualBoxException.ExceptionHandler(): attachment = self._findMediumAttachment(device) session.getIMachine().detachDevice(attachment.controller, attachment.port, attachment.device) session.saveSettings()
def delete(self): """Delete the VM. VM must be locked or unregistered""" with VirtualBoxException.ExceptionHandler(): iMachine = self.getIMachine() iprogress = iMachine.delete(None) progress = Progress(iprogress) progress.waitForCompletion()
def pause(self, wait=False): """Pause a running VM. If wait is True, then wait until machine is actually paused before returning.""" with self.lock() as session: with VirtualBoxException.ExceptionHandler(): session.console.pause() # XXX Note sure if we need a lock for this or not if wait: self.waitUntilPaused()
def getAttachedMediums(self): """Return array of attached Medium instances.""" with self.lock() as session: mediums = [] with VirtualBoxException.ExceptionHandler(): attachments = self._getMediumAttachments() attachments = filter(lambda a: a.medium is not None, attachments) mediums = [Medium(a.medium) for a in attachments] return mediums
def detachAllMediums(self): """Detach all mediums from the machine.""" with self.lock() as session: with VirtualBoxException.ExceptionHandler(): attachments = self._getMediumAttachments() for attachment in attachments: session.getIMachine().detachDevice(attachment.controller, attachment.port, attachment.device) session.saveSettings()
def powerOff(self, wait=False): """Power off a running VM. If wait is True, then wait for power down and session closureto complete.""" with self.lock() as session: with VirtualBoxException.ExceptionHandler(): session.console.powerDown() # XXX Not sure we need a lock for the following if wait: self.waitUntilDown() self.waitUntilUnlocked()
def open(cls, path): """Opens a virtual machine from the existing settings file. Note that calling open() on a VM that is already registered will throw a VirtualBoxFileNotFoundException except. Throws VirtualBoxFileNotFoundException if file not found.""" with VirtualBoxException.ExceptionHandler(): path = cls._canonicalizeVMPath(path) machine = cls._vbox.openMachine(path) return VirtualMachine(machine)
def createBaseStorage(self, size, variant=None, wait=True): """Create storage for the drive of the given size (in MB). Returns Progress instance. If wait is True, does not return until process completes.""" if variant is None: variant = Constants.MediumVariant_Standard with VirtualBoxException.ExceptionHandler(): progress = self.getIMedium().createBaseStorage(size, variant) progress = Progress(progress) if wait: progress.waitForCompletion() return progress
def lock(self, type=Constants.LockType_Shared): """Contextmanager yielding a session to a locked machine. Machine must be registered.""" session = Session.create() with VirtualBoxException.ExceptionHandler(): self.getIMachine().lockMachine(session.getISession(), type) try: session._setMachine(VirtualMachine(session.getIMachine())) yield session finally: session.unlockMachine(wait=True)
def _findMediumAttachment(self, device): """Given a device, find the IMediumAttachment object associated with its attachment on this machine.""" assert(device is not None) mediumAttachments = self._getMediumAttachments() for attachment in mediumAttachments: # medium can be Null for removable devices if attachment.medium is not None: if attachment.medium.id == device.id: return attachment raise VirtualBoxException.VirtualBoxPluggableDeviceManagerError( "No attachment for device \"%s\" on VM \"%s\" found" % (device, self))
def deleteSnapshot(self, snapshot, wait=True): """Deletes the specified snapshot. Returns Progress instance. If wait is True, does not return until process completes.""" assert(snapshot is not None) with self.lock() as session: with VirtualBoxException.ExceptionHandler(): iprogress = session.console.deleteSnapshot(snapshot.id) progress = Progress(iprogress) # XXX Not sure if we need a lock for this or not if wait: progress.waitForCompletion() return progress
def takeSnapshot(self, name, description=None, wait=True): """Saves the current execution state and all settings of the machine and creates differencing images for all normal (non-independent) media. Returns Progress instance. If wait is True, does not return until process completes.""" assert(name is not None) with self.lock() as session: with VirtualBoxException.ExceptionHandler(): iprogress = session.console.takeSnapshot(name, description) progress = Progress(iprogress) # XXX Not sure if we need a lock for this or not if wait: progress.waitForCompletion() return progress
def cloneTo(self, target, variant=None, parent=None, wait=True): """Clone to the target hard drive. Returns Progress instance. If wait is True, does not return until process completes.""" if variant is None: variant = Constants.MediumVariant_Standard with VirtualBoxException.ExceptionHandler(): progress = self.getIMedium().cloneTo(target.getIMedium(), variant, parent) progress = Progress(progress) if wait: progress.waitForCompletion() return progress
def open(cls, path, deviceType, accessMode = None, forceNewUuid=False): """Opens a medium from an existing location. Throws VirtualBoxFileError if file not found.""" with VirtualBoxException.ExceptionHandler(): if accessMode is None: accessMode = Constants.AccessMode_ReadWrite # path must be absolute path path = cls._canonicalizeMediumPath(path) medium = cls._getVBox().openMedium(path, deviceType, accessMode, forceNewUuid) return Medium(medium)
def addStorageController(self, type, name=None): """Add a storage controller to the virtual machine type should be the bus type of the new controller. Must be one of Constants.StorageBus_IDE, Constants.StorageBus_SATA, Constants.StorageBus_SCSI, or Constants.StorageBus_Floppy name should be the name of the storage controller. If None, a name will be assigned. Returns StorageController instance for new controller. """ if name is None: name = self._getNewStorageControllerName(type) with self.lock() as session: with VirtualBoxException.ExceptionHandler(): mutableMachine = session.getMachine() controller = mutableMachine.getIMachine().addStorageController(name, type) session.saveSettings() return StorageController(controller)
def attachDevice(self, device, medium=None): """Attaches a Device and optionally a Medium.""" imedium = medium.getIMedium() if medium else None with self.lock() as session: with VirtualBoxException.ExceptionHandler(): # XXX following code needs to be smarter and find appropriate # attachment point storageControllers = self._getStorageControllers() storageController = storageControllers[0] controllerPort = 0 deviceNum = 0 session.getIMachine().attachDevice(storageController.name, controllerPort, deviceNum, device.type, imedium) session.saveSettings()
def clone(self, path, newUUID=True, wait=True): """Create a clone of this medium at the given location. If wait is True, does not return until process completes. if newUUID is true, clone will have new UUID and will be registered, otherwise will have same UUID as source medium. Returns Progress instance.""" with VirtualBoxException.ExceptionHandler(): path = self._canonicalizeMediumPath(path) if newUUID: # If target doesn't have storage, new UUID is created. target= self.create(path) else: # If target does have storage, UUID is copied. target = self.createWithStorage(path, self.logicalSize) progress = self.cloneTo(target, wait=wait) if wait: progress.waitForCompletion() return progress
def create(cls, name, osTypeId, settingsFile=None, id=None, register=True, forceOverwrite=False): """Create a new virtual machine with the given name and osType. If settingsFile is not None, it should be a path to use instead of the default for the settings file. If id is not None, it will be used as the UUID of the machine. Otherwise one will be automatically generated. If register is True, register machine after creation.""" with VirtualBoxException.ExceptionHandler(): machine = cls._vbox.createMachine(settingsFile, name, osTypeId, id, forceOverwrite) vm = VirtualMachine(machine) vm.saveSettings() if register: vm.register() return vm
def resume(self): """Resume a paused VM.""" with self.lock() as session: with VirtualBoxException.ExceptionHandler(): session.console.resume()
def saveSettings(self): """Saves any changes to machine settings made since the session has been opened or a new machine has been created, or since the last call to saveSettings or discardSettings.""" with VirtualBoxException.ExceptionHandler(): self.getIMachine().saveSettings()