[kupfer: 1/3] virtualbox: update plugin; support vbox4
- From: Ulrik Sverdrup <usverdrup src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [kupfer: 1/3] virtualbox: update plugin; support vbox4
- Date: Sat, 5 Mar 2011 21:13:23 +0000 (UTC)
commit e2441ab787d5b6a8b8701cb62894e6abaa836cba
Author: Karol BÄ?dkowski <karol bedkowski gmail com>
Date: Thu Jan 20 17:09:57 2011 +0100
virtualbox: update plugin; support vbox4
+ support virtualbox 4 api
+ new options "Force use cli interface".
Configuration option - allow to force use cli interface for access to
virtual machines even vboxapi is available.
This should be useful for some broken system or future version of
VirtualBox.
+ more logging/debug messages
+ catch exception when closing vboxapi sessions
+ fix problems with incorrect handling "saved" state of vm
kupfer/plugin/virtualbox/__init__.py | 49 +++++++--
kupfer/plugin/virtualbox/constants.py | 3 +-
kupfer/plugin/virtualbox/ose_support.py | 20 +---
kupfer/plugin/virtualbox/vboxapi4_support.py | 154 ++++++++++++++++++++++++++
kupfer/plugin/virtualbox/vboxapi_support.py | 83 ++++++++------
5 files changed, 248 insertions(+), 61 deletions(-)
---
diff --git a/kupfer/plugin/virtualbox/__init__.py b/kupfer/plugin/virtualbox/__init__.py
index 75a503a..16c1e2f 100644
--- a/kupfer/plugin/virtualbox/__init__.py
+++ b/kupfer/plugin/virtualbox/__init__.py
@@ -8,19 +8,46 @@ __version__ = "0.3"
__author__ = "Karol BÄ?dkowski <karol bedkowski gmail com>"
from kupfer.objects import Leaf, Action, Source
-from kupfer import pretty, plugin_support
+from kupfer import pretty
+from kupfer import plugin_support
from kupfer.obj.apps import ApplicationSource
try:
- from kupfer.plugin.virtualbox import vboxapi_support as vbox_support
- pretty.print_info(__name__, 'Using vboxapi...')
+ try:
+ from kupfer.plugin.virtualbox import vboxapi4_support as vboxapi_support
+ pretty.print_info(__name__, 'Using vboxapi4...')
+ except ImportError, err:
+ from kupfer.plugin.virtualbox import vboxapi_support
+ pretty.print_info(__name__, 'Using vboxapi...')
except ImportError, err:
- from kupfer.plugin.virtualbox import ose_support as vbox_support
- pretty.print_info(__name__, 'Using cli...', err)
+ pretty.print_info(__name__, 'vboxapi not available...', err)
+ vboxapi_support = None
+from kupfer.plugin.virtualbox import ose_support
from kupfer.plugin.virtualbox import constants as vbox_const
+__kupfer_settings__ = plugin_support.PluginSettings(
+ {
+ "key": "force_cli",
+ "label": _("Force use CLI interface"),
+ "type": bool,
+ "value": False,
+ },
+)
+
+
+class _VBoxSupportProxy:
+ def __getattr__(self, attr):
+ vbox = ose_support
+ if vboxapi_support and not __kupfer_settings__['force_cli']:
+ vbox = vboxapi_support
+ return getattr(vbox, attr)
+
+
+vbox_support = _VBoxSupportProxy()
+
+
class VirtualMachine(Leaf):
def __init__(self, obj, name, description):
Leaf.__init__(self, obj, name)
@@ -43,9 +70,14 @@ class VirtualMachine(Leaf):
yield VMAction(_('Send Power Off Signal'), 'system-shutdown',
vbox_const.VM_ACPI_POWEROFF, -5)
yield VMAction(_('Pause'), 'pause', vbox_const.VM_PAUSE)
- yield VMAction(_('Reboot'), 'system-reboot',
+ yield VMAction(_('Reboot'), 'system-reboot',
vbox_const.VM_REBOOT, -10)
- else: # VM_STATE_PAUSED
+ elif state == vbox_const.VM_STATE_SAVED:
+ yield VMAction(_('Power On'), 'system-run',
+ vbox_const.VM_START_NORMAL)
+ yield VMAction(_('Power On Headless'), 'system-run',
+ vbox_const.VM_START_HEADLESS, -5)
+ else: # VM_STATE_PAUSED
yield VMAction(_('Resume'), 'resume', vbox_const.VM_RESUME)
if state in (vbox_const.VM_STATE_POWERON, vbox_const.VM_STATE_PAUSED):
@@ -98,6 +130,3 @@ class VBoxMachinesSource(ApplicationSource):
def provides(self):
yield VirtualMachine
-
-
-
diff --git a/kupfer/plugin/virtualbox/constants.py b/kupfer/plugin/virtualbox/constants.py
index 5f85c6b..b32cc4d 100644
--- a/kupfer/plugin/virtualbox/constants.py
+++ b/kupfer/plugin/virtualbox/constants.py
@@ -11,6 +11,7 @@ __version__ = '0.3'
VM_STATE_POWEROFF = 0
VM_STATE_POWERON = 1
VM_STATE_PAUSED = 2
+VM_STATE_SAVED = 3
# virtual machine actions
VM_START_NORMAL = 1
@@ -21,5 +22,3 @@ VM_ACPI_POWEROFF = 5
VM_REBOOT = 6
VM_RESUME = 7
VM_SAVE = 8
-
-
diff --git a/kupfer/plugin/virtualbox/ose_support.py b/kupfer/plugin/virtualbox/ose_support.py
index 2c74658..cdaf696 100644
--- a/kupfer/plugin/virtualbox/ose_support.py
+++ b/kupfer/plugin/virtualbox/ose_support.py
@@ -31,7 +31,7 @@ _ACTIONS = {
vbox_const.VM_PAUSE: 'pause',
vbox_const.VM_REBOOT: 'reset',
vbox_const.VM_RESUME: 'resume',
- vbox_const.VM_SAVE: 'savestate'
+ vbox_const.VM_SAVE: 'savestate',
}
@@ -50,7 +50,8 @@ def get_machine_state(vm_uuid):
state = vbox_const.VM_STATE_PAUSED
elif str_state == 'running':
state = vbox_const.VM_STATE_POWERON
-
+ elif str_state == 'saved':
+ state = vbox_const.VM_STATE_SAVED
except IOError, err:
pretty.print_error(__name__, 'get_machine_state', vm_uuid, 'error', err)
state = vbox_const.VM_STATE_POWEROFF
@@ -76,7 +77,7 @@ def vm_action(action, vm_uuid):
def _get_virtual_machines(config_file):
- ''' load (virtual machine uuid, path to vm config) from virtualbox
+ ''' load (virtual machine uuid, path to vm config) from virtualbox
configuration.
@param config_file - path to VirtualBox.xml file
'''
@@ -84,11 +85,10 @@ def _get_virtual_machines(config_file):
dtree = minidom.parse(config_file)
machine_registry = dtree.getElementsByTagName('MachineRegistry')[0]
for machine in machine_registry.getElementsByTagName('MachineEntry'):
- yield (machine.getAttribute('uuid')[1:-1],
+ yield (machine.getAttribute('uuid')[1:-1],
machine.getAttribute('src'))
-
except StandardError, err:
- pretty.print_error(__name__, '_get_virtual_machines', config_file,
+ pretty.print_error(__name__, '_get_virtual_machines', config_file,
'error', err)
@@ -103,23 +103,18 @@ def _get_machine_info(vm_uuid, config_file):
try:
dtree = minidom.parse(config_file)
machine_registry = dtree.getElementsByTagName('Machine')[0]
-
os_type = machine_registry.getAttribute('OSType')
name = machine_registry.getAttribute('name')
-
description = None
for machine_registry_child in machine_registry.childNodes:
if machine_registry_child.nodeName == 'Description':
if machine_registry_child.hasChildNodes():
description = machine_registry_child.firstChild.nodeValue
break
-
return (name, description or os_type)
-
except StandardError, err:
pretty.print_error(__name__, '_get_machine_info', vm_uuid, 'error' + \
config_file, err)
-
return None, None
@@ -131,6 +126,3 @@ def get_machines():
name, description = _get_machine_info(vm_uuid, config)
if name:
yield (vm_uuid, name, description)
-
-
-
diff --git a/kupfer/plugin/virtualbox/vboxapi4_support.py b/kupfer/plugin/virtualbox/vboxapi4_support.py
new file mode 100644
index 0000000..85c4a92
--- /dev/null
+++ b/kupfer/plugin/virtualbox/vboxapi4_support.py
@@ -0,0 +1,154 @@
+# -*- coding: UTF-8 -*-
+'''
+virtualbox_vboxapi_support.py
+
+Control VirtualBox via Python interface (vboxapi).
+Only (?) Sun VirtualBox (no OSE).
+'''
+__author__ = "Karol BÄ?dkowski <karol bedkowski gmail com>"
+__version__ = "0.3"
+
+from kupfer import pretty
+
+#raise ImportError()
+
+import vboxapi
+
+# check api
+try:
+ vboxapi.VirtualBoxReflectionInfo(None).SessionState_Locked
+except AttributeError:
+ raise ImportError()
+
+from kupfer.plugin.virtualbox import constants as vbox_const
+
+MONITORED_DIRS = None
+IS_DYNAMIC = False
+ICON = "VBox"
+APP_ID = "virtualbox"
+
+
+_ACTIONS = {
+ vbox_const.VM_POWEROFF: lambda c: c.powerDown(),
+ vbox_const.VM_ACPI_POWEROFF: lambda c: c.powerButton(),
+ vbox_const.VM_PAUSE: lambda c: c.pause(),
+ vbox_const.VM_REBOOT: lambda c: c.reset(),
+ vbox_const.VM_RESUME: lambda c: c.resume(),
+ vbox_const.VM_SAVE: lambda c: c.saveState(),
+}
+
+
+def _get_object_session():
+ ''' get new session to vm '''
+ vbox, session = None, None
+ try:
+ vbox = vboxapi.VirtualBoxManager(None, None)
+ session = vbox.mgr.getSessionObject(vbox.vbox)
+ except Exception, err:
+ pretty.print_error(__name__, 'virtualbox: get session error ', err)
+ return vbox, session
+
+
+def _get_existing_session(vm_uuid):
+ ''' get existing session by machine uuid '''
+ vbox, session = None, None
+ try:
+ vbox = vboxapi.VirtualBoxManager(None, None)
+ session = vbox.mgr.getSessionObject(vbox.vbox)
+ except Exception, err:
+ pretty.print_error(__name__, 'virtualbox: get session error', vm_uuid,
+ err)
+ return vbox, session
+
+
+def get_machine_by_id(vbox, mid):
+ try:
+ mach = vbox.getMachine(mid)
+ except:
+ mach = vbox.findMachine(mid)
+ return mach
+
+
+def get_machine_state(machine_id):
+ ''' check vms state (on/off/paused) '''
+ vbox, vbox_sess = _get_object_session()
+ if vbox_sess is None:
+ return vbox_const.VM_STATE_POWEROFF
+ state = vbox_const.VM_STATE_POWERON
+ try:
+ machine = get_machine_by_id(vbox.vbox, machine_id)
+ machine_state = machine.state
+ if machine_state == vbox.constants.MachineState_Paused:
+ state = vbox_const.VM_STATE_PAUSED
+ elif machine_state in (vbox.constants.MachineState_PoweredOff,
+ vbox.constants.MachineState_Aborted,
+ vbox.constants.MachineState_Starting):
+ state = vbox_const.VM_STATE_POWEROFF
+ elif machine_state == vbox.constants.MachineState_Saved:
+ state = vbox_const.VM_STATE_SAVED
+ except Exception, err: # exception == machine is off (xpcom.Exception)
+ pretty.print_debug(__name__, 'get_machine_state', machine_state, err)
+ # silently set state to off
+ state = vbox_const.VM_STATE_POWEROFF
+ return state
+
+
+def _machine_start(vm_uuid, mode):
+ ''' Start virtual machine
+ @param vm_uuid - uuid of virtual machine
+ @param mode - mode: gui, headless
+ '''
+ vbox, session = _get_object_session()
+ if session:
+ try:
+ mach = get_machine_by_id(vbox.vbox, vm_uuid)
+ remote_sess = mach.launchVMProcess(session, mode, '')
+ remote_sess.waitForCompletion(-1)
+ session.unlockMachine()
+ except Exception, err:
+ pretty.print_error(__name__, "StartVM:", vm_uuid, "Mode ", mode,
+ "error", err)
+
+
+def _execute_machine_action(vm_uuid, action):
+ ''' Start virtual machine
+ @param vm_uuid - uuid of virtual machine
+ @param action - function called on vbox session
+ '''
+ vbox, session = _get_existing_session(vm_uuid)
+ try:
+ mach = get_machine_by_id(vbox.vbox, vm_uuid)
+ mach.lockMachine(session, vbox.constants.LockType_Shared)
+ action(session.console)
+ session.unlockMachine()
+ except Exception, err:
+ pretty.print_error(__name__, "_execute_machine_action:", repr(action),
+ " vm:", vm_uuid, "error", err)
+
+
+def vm_action(action, vm_uuid):
+ ''' change state of the virtual machine
+ @param action - one of the const VM_*
+ @param vm_uuid - virtual machine uuid
+ '''
+ if action == vbox_const.VM_START_NORMAL:
+ _machine_start(vm_uuid, 'gui')
+ elif action == vbox_const.VM_START_HEADLESS:
+ _machine_start(vm_uuid, 'headless')
+ else:
+ command = _ACTIONS[action]
+ _execute_machine_action(vm_uuid, command)
+
+
+def get_machines():
+ ''' Get generator of items:
+ (machine uuid, machine name, machine description)
+ '''
+ vbox, vbox_sess = _get_object_session()
+ if vbox_sess is None:
+ return
+
+ machines = vbox.getArray(vbox.vbox, 'machines')
+ for machine in machines:
+ description = machine.description or machine.OSTypeId
+ yield (machine.id, machine.name, description)
diff --git a/kupfer/plugin/virtualbox/vboxapi_support.py b/kupfer/plugin/virtualbox/vboxapi_support.py
index c9f8d63..abea025 100644
--- a/kupfer/plugin/virtualbox/vboxapi_support.py
+++ b/kupfer/plugin/virtualbox/vboxapi_support.py
@@ -6,9 +6,9 @@ Control VirtualBox via Python interface (vboxapi).
Only (?) Sun VirtualBox (no OSE).
'''
__author__ = "Karol BÄ?dkowski <karol bedkowski gmail com>"
-__version__ = "0.3"
+__version__ = "2011-01-20"
-from kupfer import pretty
+from kupfer import pretty
#raise ImportError()
@@ -21,30 +21,32 @@ IS_DYNAMIC = False
ICON = "VBox"
APP_ID = "virtualbox"
-
_ACTIONS = {
- vbox_const.VM_POWEROFF: lambda c:c.powerDown(),
- vbox_const.VM_ACPI_POWEROFF: lambda c:c.powerButton(),
- vbox_const.VM_PAUSE: lambda c:c.pause(),
- vbox_const.VM_REBOOT: lambda c:c.reset(),
- vbox_const.VM_RESUME: lambda c:c.resume(),
- vbox_const.VM_SAVE: lambda c:c.saveState()
+ vbox_const.VM_POWEROFF: lambda c: c.powerDown(),
+ vbox_const.VM_ACPI_POWEROFF: lambda c: c.powerButton(),
+ vbox_const.VM_PAUSE: lambda c: c.pause(),
+ vbox_const.VM_REBOOT: lambda c: c.reset(),
+ vbox_const.VM_RESUME: lambda c: c.resume(),
+ vbox_const.VM_SAVE: lambda c: c.saveState(),
}
def _get_object_session():
''' get new session to vm '''
+ pretty.print_debug(__name__, '_get_object_session start')
vbox, session = None, None
try:
vbox = vboxapi.VirtualBoxManager(None, None)
session = vbox.mgr.getSessionObject(vbox.vbox)
except Exception, err:
pretty.print_error(__name__, 'virtualbox: get session error ', err)
-
+ pretty.print_debug(__name__, '_get_object_session finished', vbox, session)
return vbox, session
+
def _get_existing_session(vm_uuid):
''' get existing session by machine uuid '''
+ pretty.print_debug(__name__, '_get_existing_session start')
vbox, session = None, None
try:
vbox = vboxapi.VirtualBoxManager(None, None)
@@ -53,73 +55,82 @@ def _get_existing_session(vm_uuid):
except Exception, err:
pretty.print_error(__name__, 'virtualbox: get session error', vm_uuid,
err)
-
+ pretty.print_debug(__name__, '_get_existing_session finished', vbox, session)
return vbox, session
+
def get_machine_state(machine_id):
''' check vms state (on/off/paused) '''
-
+ pretty.print_debug(__name__, 'get_machine_state', machine_id)
vbox, vbox_sess = _get_object_session()
if vbox_sess is None:
return vbox_const.VM_STATE_POWEROFF
-
state = vbox_const.VM_STATE_POWERON
try:
vbox.vbox.openExistingSession(vbox_sess, machine_id)
machine_state = vbox_sess.machine.state
if machine_state == vbox.constants.MachineState_Paused:
state = vbox_const.VM_STATE_PAUSED
- elif machine_state in (vbox.constants.MachineState_PoweredOff,
+ elif machine_state in (vbox.constants.MachineState_PoweredOff,
vbox.constants.MachineState_Aborted,
vbox.constants.MachineState_Starting):
state = vbox_const.VM_STATE_POWEROFF
- except Exception: # exception == machine is off (xpcom.Exception)
+ elif machine_state == vbox.constants.MachineState_Saved:
+ state = vbox_const.VM_STATE_SAVED
+ except Exception: # exception == machine is off (xpcom.Exception)
# silently set state to off
state = vbox_const.VM_STATE_POWEROFF
-
- if vbox_sess.state == vbox.constants.SessionState_Open:
- vbox_sess.close()
-
+ pretty.print_debug(__name__, 'get_machine_state error', err)
+ try:
+ if vbox_sess.state == vbox.constants.SessionState_Open:
+ vbox_sess.close()
+ except Exception: # varoius errors (xpcom.Exception)
+ pass
+ pretty.print_debug(__name__, 'get_machine_state finish', machine_id, state)
return state
def _machine_start(vm_uuid, mode):
- ''' Start virtual machine
+ ''' Start virtual machine
@param vm_uuid - uuid of virtual machine
@param mode - mode: gui, headless
'''
vbox, session = _get_object_session()
if session:
try:
- remote_sess = vbox.vbox.openRemoteSession(session, vm_uuid, mode,
+ remote_sess = vbox.vbox.openRemoteSession(session, vm_uuid, mode,
'')
remote_sess.waitForCompletion(-1)
- except Exception, err:
- pretty.print_error(__name__, "StartVM:", vm_uuid, "Mode ", mode,
+ except Exception, err:
+ pretty.print_error(__name__, "StartVM:", vm_uuid, "Mode ", mode,
"error", err)
-
- if session.state == vbox.constants.SessionState_Open:
- session.close()
+ try:
+ if session.state == vbox.constants.SessionState_Open:
+ session.close()
+ except Exception: # varoius errors (xpcom.Exception)
+ pass
def _execute_machine_action(vm_uuid, action):
- ''' Start virtual machine
+ ''' Start virtual machine
@param vm_uuid - uuid of virtual machine
@param action - function called on vbox session
'''
vbox, session = _get_existing_session(vm_uuid)
try:
action(session.console)
- except Exception, err:
+ except Exception, err:
pretty.print_error(__name__, "_execute_machine_action:", repr(action),
" vm:", vm_uuid, "error", err)
-
- if session.state == vbox.constants.SessionState_Open:
- session.close()
+ try:
+ if session.state == vbox.constants.SessionState_Open:
+ session.close()
+ except Exception: # varoius errors (xpcom.Exception)
+ pass
def vm_action(action, vm_uuid):
- ''' change state of the virtual machine
+ ''' change state of the virtual machine
@param action - one of the const VM_*
@param vm_uuid - virtual machine uuid
'''
@@ -133,15 +144,17 @@ def vm_action(action, vm_uuid):
def get_machines():
- ''' Get generator of items:
+ ''' Get generator of items:
(machine uuid, machine name, machine description)
'''
+ pretty.print_debug(__name__, 'get_machines start')
vbox, vbox_sess = _get_object_session()
if vbox_sess is None:
return
-
machines = vbox.getArray(vbox.vbox, 'machines')
for machine in machines:
+ pretty.print_debug(__name__, 'get_machines; found machine',
+ machine.id, machine.name)
description = machine.description or machine.OSTypeId
yield (machine.id, machine.name, description)
-
+ pretty.print_debug(__name__, 'get_machines finished')
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]