[kupfer: 5/11] plugin.virtualbox: merge virtualbox and virtualbox_ose plugins



commit f68cbef345ccaf73d141c8613766ad89cdce704e
Author: Karol BÄ?dkowski <karol bedkowsk+gh gmail com>
Date:   Sat Oct 17 17:21:26 2009 +0200

    plugin.virtualbox: merge virtualbox and virtualbox_ose plugins
    
    - Create virtualbox_vboxapi_support.py for Sun VirtualBox, and
      virtualbox_ose_support.py for VirtualBox OSE.
    - Drop virtualbox_ose plugin

 kupfer/plugin/virtualbox.py                 |  130 +++++---------------
 kupfer/plugin/virtualbox_ose.py             |  176 ---------------------------
 kupfer/plugin/virtualbox_ose_support.py     |  121 ++++++++++++++++++
 kupfer/plugin/virtualbox_vboxapi_support.py |  128 +++++++++++++++++++
 4 files changed, 282 insertions(+), 273 deletions(-)
---
diff --git a/kupfer/plugin/virtualbox.py b/kupfer/plugin/virtualbox.py
index cb9e645..e23a243 100644
--- a/kupfer/plugin/virtualbox.py
+++ b/kupfer/plugin/virtualbox.py
@@ -1,6 +1,7 @@
 # -*- coding: UTF-8 -*-
 
 from kupfer.objects import Leaf, Action, Source, AppLeafContentMixin
+from kupfer.helplib import PicklingHelperMixin, FilesystemWatchMixin
 from kupfer import pretty, plugin_support
 
 __kupfer_name__ = _("VirtualBox")
@@ -12,87 +13,43 @@ __kupfer_settings__ = plugin_support.PluginSettings(
 		plugin_support.SETTING_PREFER_CATALOG,
 )
 
-import vboxapi
 
-
-VM_POWEROFF = 0
-VM_POWERON = 1
-VM_PAUSED = 2
-
-
-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)
-		vbox.vbox.openExistingSession(session, vm_uuid)
-	except Exception, err:
-		pretty.print_error(__name__, 'virtualbox: get session to %s error' %
-				vm_uuid, err)
-
-	return vbox, session
-
-def _check_machine_state(vbox, vbox_sess, machine_id):
-	''' check vms state (on/off/paused) '''
-	state = VM_POWERON
-	try:
-		vbox.vbox.openExistingSession(vbox_sess, machine_id)
-		machine_state = vbox_sess.machine.state
-		if machine_state == vbox.constants.MachineState_Paused:
-			state = VM_PAUSED
-		elif machine_state in (vbox.constants.MachineState_PoweredOff, vbox.constants.MachineState_Aborted,
-				vbox.constants.MachineState_Starting):
-			state = VM_POWEROFF
-	except Exception, err: # exception == machine is off (xpcom.Exception)
-		# silently set state to off
-		state = VM_POWEROFF
-
-	if vbox_sess.state == vbox.constants.SessionState_Open:
-		vbox_sess.close()
-
-	return state
+try:
+	import virtualbox_vboxapi_support as virtualbox_support
+	pretty.print_info(__name__, 'Using vboxapi...')
+except ImportError, err:
+	import virtualbox_ose_support as virtualbox_support
+	pretty.print_info(__name__, 'Using cli...', err)
 
 
 class VirtualMachine(Leaf):
-	def __init__(self, obj, name, state, description):
+	def __init__(self, obj, name, description):
 		Leaf.__init__(self, obj, name)
-		self.state = state
 		self.description = description
 
 	def get_description(self):
 		return self.description
 
 	def get_icon_name(self):
-		return "VBox"
+		return virtualbox_support.ICON
 
 	def get_actions(self):
-		# actions depend on machine state
-		if self.state == VM_POWEROFF:
+		state = virtualbox_support.get_machine_state(self.object)
+		if state == virtualbox_support.VM_POWEROFF:
 			yield StartVM(_('Power On'), 'system-run', 'gui')
 			yield StartVM(_('Power On Headless'), 'system-run', 'headless', -5)
-		elif self.state == VM_POWERON:
+		elif state == virtualbox_support.VM_POWERON:
 			yield StdVmAction(_('Send Power Off Signal'), 'system-shutdown', \
-					lambda c:c.powerButton(), -5)
-			yield StdVmAction(_('Pause'), 'pause', lambda c:c.pause())
-			yield StdVmAction(_('Reboot'), 'system-reboot', lambda c:c.reset(), -10)
+					virtualbox_support.machine_acpipoweroff, -5)
+			yield StdVmAction(_('Pause'), 'pause', virtualbox_support.machine_pause)
+			yield StdVmAction(_('Reboot'), 'system-reboot', virtualbox_support.machine_reboot, -10)
 		else: # VM_PAUSED
-			yield StdVmAction(_('Resume'), 'resume', lambda c:c.resume())
+			yield StdVmAction(_('Resume'), 'resume', virtualbox_support.machine_resume)
+
+		if state in (virtualbox_support.VM_POWERON, virtualbox_support.VM_PAUSED):
+			yield StdVmAction(_('Save State'), 'system-supsend', virtualbox_support.machine_save)
+			yield StdVmAction(_('Power Off'), 'system-shutdown', virtualbox_support.machine_poweroff, -10)
 
-		if self.state in (VM_POWERON, VM_PAUSED):
-			yield StdVmAction(_('Save State'), 'system-supsend', lambda c:c.saveState())
-			yield StdVmAction(_('Power Off'), 'system-shutdown', lambda c:c.powerDown(), -10)
 
 class _VMAction(Action):
 	def __init__(self, name, icon):
@@ -113,17 +70,7 @@ class StartVM(_VMAction):
 		self.rank_adjust = rank_adjust
 
 	def activate(self, leaf):
-		vbox, session = _get_object_session()
-		if session:
-			try:
-				remote_sess = vbox.vbox.openRemoteSession(session, leaf.object, self.mode, '')
-				remote_sess.waitForCompletion(-1)
-			except Exception, err: 
-				pretty.print_error(__name__, "StartVM:", self.name,
-						"vm:", leaf.name, "error", err)
-
-			if session.state == vbox.constants.SessionState_Open:
-				session.close()
+		virtualbox_support.machine_start(leaf.object, self.mode)
 
 
 class StdVmAction(_VMAction):
@@ -133,43 +80,32 @@ class StdVmAction(_VMAction):
 		self.command = command
 
 	def activate(self, leaf):
-		vbox, session = _get_existing_session(leaf.object)
-		if session:
-			try:
-				self.command(session.console)
-			except Exception, err: 
-				pretty.print_error(__name__, "StdVmAction:", self.name,
-						"vm:", leaf.name, "error", err)
-			if session.state == vbox.constants.SessionState_Open:
-				session.close()
+		self.command(leaf.object)
 
 
-class VBoxMachinesSource(AppLeafContentMixin, Source):
-	appleaf_content_id = 'Sun VirtualBox'
+class VBoxMachinesSource(AppLeafContentMixin, Source, PicklingHelperMixin, FilesystemWatchMixin):
+	appleaf_content_id = ('VirtualBox OSE', 'Sun VirtualBox')
 
 	def __init__(self, name=_("Sun VirtualBox Machines")):
 		Source.__init__(self, name)
+		self.unpickle_finish()
+
+	def unpickle_finish(self):
+		if virtualbox_support.MONITORED_DIRS:
+			self.monitor_token = self.monitor_directories(*virtualbox_support.MONITORED_DIRS)
 
 	def is_dynamic(self):
-		return True
+		return virtualbox_support.IS_DYNAMIC
 
 	def get_items(self):
-		vbox, vbox_sess = _get_object_session()
-		if vbox_sess is None:
-			return
-
-		machines = vbox.getArray(vbox.vbox, 'machines')
-		session = vbox.mgr.getSessionObject(vbox.vbox)
-		for machine in machines:
-			state = _check_machine_state(vbox, vbox_sess, machine.id)
-			description = machine.description or machine.OSTypeId
-			yield VirtualMachine(machine.id, machine.name, state, description)
+		for machine_id, machine_name, machine_desc in virtualbox_support.get_machines():
+			yield VirtualMachine(machine_id, machine_name, machine_desc)
 
 	def get_description(self):
 		return None
 
 	def get_icon_name(self):
-		return "VBox"
+		return virtualbox_support.ICON
 
 	def provides(self):
 		yield VirtualMachine
diff --git a/kupfer/plugin/virtualbox_ose_support.py b/kupfer/plugin/virtualbox_ose_support.py
new file mode 100644
index 0000000..03a84f7
--- /dev/null
+++ b/kupfer/plugin/virtualbox_ose_support.py
@@ -0,0 +1,121 @@
+# -*- coding: UTF-8 -*-
+'''
+virtualbox_ose_support.py
+
+Control VirtualBox via command-line interface.
+Support both Sun VirtualBox and VirtualBox OpenSource Edition.
+'''
+from __future__ import with_statement
+
+__revision__ = "0.1"
+__author__ = "Karol BÄ?dkowski <karol bedkowski gmail com>"
+
+import os
+from xml.dom import minidom
+
+from kupfer import pretty, utils
+
+VM_POWEROFF = 0
+VM_POWERON = 1
+VM_PAUSED = 2
+
+_VBOX_CONFIG_DIR = os.path.expanduser('~/.VirtualBox/')
+_VBOX_CONFIG_FILE = os.path.join(_VBOX_CONFIG_DIR, 'VirtualBox.xml')
+
+MONITORED_DIRS = (_VBOX_CONFIG_DIR, )
+IS_DYNAMIC = False
+ICON = "virtualbox-ose"
+
+
+def get_machine_state(vm_uuid):
+	''' check vms state (on/off/paused) '''
+	state = VM_POWEROFF
+	try:
+		str_state = 'poweroff'
+		with os.popen('VBoxManage showvminfo %s --machinereadable' % vm_uuid) \
+				as pinfo:
+			for line in pinfo:
+				if line.startswith('VMState="'):
+					str_state = line.strip()[9:-1]
+					break
+		if str_state == 'paused':
+			state = VM_PAUSED
+		elif str_state == 'running':
+			state = VM_POWERON
+
+	except IOError, err:
+		pretty.print_error(__name__, 'get_machine_state error ' + vm_uuid, err)
+		state = VM_POWEROFF
+
+	return state
+
+
+def machine_start(vm_uuid, mode):
+	utils.launch_commandline('VBoxManage startvm ' + vm_uuid + ' --type ' + mode)
+
+def machine_poweroff(vm_uuid):
+	utils.launch_commandline('VBoxManage controlvm ' + vm_uuid+ ' poweroff')
+
+def machine_acpipoweroff(vm_uuid):
+	utils.launch_commandline('VBoxManage controlvm ' + vm_uuid+ ' acpipowerbutton')
+
+def machine_pause(vm_uuid):
+	utils.launch_commandline('VBoxManage controlvm ' + vm_uuid+ ' pause')
+
+def machine_reboot(vm_uuid):
+	utils.launch_commandline('VBoxManage controlvm ' + vm_uuid+ ' reset')
+
+def machine_resume(vm_uuid):
+	utils.launch_commandline('VBoxManage controlvm ' + vm_uuid+ ' resume')
+
+def machine_save(vm_uuid):
+	utils.launch_commandline('VBoxManage controlvm ' + vm_uuid+ ' savestate')
+
+
+def _get_virtual_machines(config_file):
+	try:
+		dtree = minidom.parse(config_file)
+		machine_registry = dtree.getElementsByTagName('MachineRegistry')[0]
+		for machine in machine_registry.getElementsByTagName('MachineEntry'):
+			yield (machine.getAttribute('uuid')[1:-1], machine.getAttribute('src'))
+
+	except StandardError, err:
+		pretty.print_error(__name__, '_get_virtual_machines error', err)
+
+
+def _get_machine_info(vm_uuid, config_file):
+	if not os.path.isfile(config_file):
+		return None, None
+
+	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 error ' + vm_uuid + ' ' + \
+				config_file, err)
+
+	return None, None
+
+
+def get_machines():
+	if os.path.isfile(_VBOX_CONFIG_FILE):
+		for vm_uuid, config in _get_virtual_machines(_VBOX_CONFIG_FILE):
+			name, description = _get_machine_info(vm_uuid, config)
+			if name:
+				yield (vm_uuid, name, description)
+
+
+
diff --git a/kupfer/plugin/virtualbox_vboxapi_support.py b/kupfer/plugin/virtualbox_vboxapi_support.py
new file mode 100644
index 0000000..170e705
--- /dev/null
+++ b/kupfer/plugin/virtualbox_vboxapi_support.py
@@ -0,0 +1,128 @@
+# -*- coding: UTF-8 -*-
+'''
+virtualbox_vboxapi_support.py
+
+Control VirtualBox via Python interface (vboxapi).
+Only (?) Sun VirtualBox (no OSE).
+'''
+__revision__ = "0.1"
+__author__ = "Karol BÄ?dkowski <karol bedkowski gmail com>"
+
+from kupfer import pretty 
+
+#raise ImportError()
+
+import vboxapi
+
+VM_POWEROFF = 0
+VM_POWERON = 1
+VM_PAUSED = 2
+
+MONITORED_DIRS = None
+IS_DYNAMIC = False
+ICON = "VBox"
+
+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)
+		vbox.vbox.openExistingSession(session, vm_uuid)
+	except Exception, err:
+		pretty.print_error(__name__, 'virtualbox: get session to %s error' %
+				vm_uuid, err)
+
+	return vbox, session
+
+def get_machine_state(machine_id):
+	''' check vms state (on/off/paused) '''
+	
+	vbox, vbox_sess = _get_object_session()
+	state = VM_POWERON
+	try:
+		vbox.vbox.openExistingSession(vbox_sess, machine_id)
+		machine_state = vbox_sess.machine.state
+		if machine_state == vbox.constants.MachineState_Paused:
+			state = VM_PAUSED
+		elif machine_state in (vbox.constants.MachineState_PoweredOff, 
+				vbox.constants.MachineState_Aborted,
+				vbox.constants.MachineState_Starting):
+			state = VM_POWEROFF
+	except Exception: # exception == machine is off (xpcom.Exception)
+		# silently set state to off
+		state = VM_POWEROFF
+
+	if vbox_sess.state == vbox.constants.SessionState_Open:
+		vbox_sess.close()
+
+	return state
+
+
+def machine_start(machine_uuid, mode):
+	vbox, session = _get_object_session()
+	if session:
+		try:
+			remote_sess = vbox.vbox.openRemoteSession(session, machine_uuid, mode, '')
+			remote_sess.waitForCompletion(-1)
+		except Exception, err: 
+			pretty.print_error(__name__, "StartVM:", machine_uuid, "error", err)
+
+		if session.state == vbox.constants.SessionState_Open:
+			session.close()
+
+
+def _execute_machine_action(machine_uuid, action):
+	vbox, session = _get_existing_session(machine_uuid)
+	try:
+		action(session.console)
+	except Exception, err: 
+		pretty.print_error(__name__, "_execute_machine_action:", repr(action),
+				" vm:", machine_uuid, "error", err)
+
+	if session.state == vbox.constants.SessionState_Open:
+		session.close()
+
+
+def machine_poweroff(machine_uuid):
+	_execute_machine_action(machine_uuid, lambda c:c.powerDown())
+
+def machine_acpipoweroff(machine_uuid):
+	_execute_machine_action(machine_uuid, lambda c:c.powerButton())
+
+def machine_pause(machine_uuid):
+	_execute_machine_action(machine_uuid, lambda c:c.pause())
+
+def machine_reboot(machine_uuid):
+	_execute_machine_action(machine_uuid, lambda c:c.reset())
+
+def machine_resume(machine_uuid):
+	_execute_machine_action(machine_uuid, lambda c:c.resume())
+
+def machine_save(machine_uuid):
+	_execute_machine_action(machine_uuid, lambda c:c.saveState())
+
+
+def get_machines():
+	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)
+
+
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]