Add initial version of autoserv



git-svn-id: http://test.kernel.org/svn/autotest/trunk@557 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/server/autoserv b/server/autoserv
new file mode 100755
index 0000000..ae81de3
--- /dev/null
+++ b/server/autoserv
@@ -0,0 +1,54 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""Run an autoserv control file
+
+TODO(poirier): add a singleton logger
+TODO(poirier): maybe change the name "get_file" to "receive_file" ?
+"""
+
+__author__ = "[email protected] (Benjamin Poirier)"
+
+
+import sys
+import optparse
+
+
+usage = "usage: %prog <control file>"
+parser = optparse.OptionParser(usage)
+
+
+def parse_args():
+	global parser
+	
+	(options, arg)= parser.parse_args()
+	return (options, arg)
+
+
+def run(control_file):
+	namespace = {}
+	
+	str = ("import os\n"
+	       "import sys\n"
+	       "\n"
+	       "import errors\n"
+	       "import hosts\n"
+	       "import autotest\n"
+	       "import source_kernel\n"
+	       "import rpm_kernel\n"
+	       "import deb_kernel\n"
+	       "import kvm\n"
+	       "\n"
+	       "from utils import run, get_tmp_dir\n")
+	exec(str, namespace, namespace)
+	execfile(sys.argv[1], namespace, namespace)
+
+
+if __name__ == "__main__":
+	(options, args) = parse_args()
+	if len(args) != 1:
+		parser.error("program takes one argument")
+		sys.exit(1)
+	control_file= args[0]
+	run(control_file)
diff --git a/server/autotest.py b/server/autotest.py
new file mode 100644
index 0000000..c1c4f4a
--- /dev/null
+++ b/server/autotest.py
@@ -0,0 +1,255 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the Autotest class
+
+	Autotest: software to run tests automatically
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+import re
+import os
+import sys
+import subprocess
+import urllib
+import tempfile
+import shutil
+
+import installable_object
+import errors
+import utils
+
+
+AUTOTEST_SVN  = 'svn://test.kernel.org/autotest/trunk/client'
+AUTOTEST_HTTP = 'http://test.kernel.org/svn/autotest/trunk/client'
+
+# Timeouts for powering down and up respectively
+HALT_TIME = 300
+BOOT_TIME = 300
+
+
+class AutotestRunError(errors.AutoservRunError):
+	pass
+
+
+class Autotest(installable_object.InstallableObject):
+	"""This class represents the Autotest program.
+
+	Autotest is used to run tests automatically and collect the results.
+	It also supports profilers.
+
+	Implementation details:
+	This is a leaf class in an abstract class hierarchy, it must
+	implement the unimplemented methods in parent classes.
+	"""
+	def __init__(self):
+		super(Autotest, self).__init__()
+	
+	def get_from_file(self, filename):
+		"""Specify a tarball on the local filesystem from which
+		autotest will be installed.
+		
+		Args:
+			filename: a str specifying the path to the tarball
+		
+		Raises:
+			AutoservError: if filename does not exist
+		"""
+		if os.path.exists(filename):
+			self.__filename = filename
+		else:
+			raise errors.AutoservError('%s not found' % filename)
+	
+	def get_from_url(self, url):
+		"""Specify a url to a tarball from which autotest will be
+		installed.
+		
+		Args:
+			url: a str specifying the url to the tarball
+		"""
+		self.__filename = utils.get(url)
+	
+	def install(self, host):
+		"""Install autotest from the specified tarball (either
+		via get_from_file or get_from_url).  If neither were
+		called an attempt will be made to install from the
+		autotest svn repository.
+		
+		Args:
+			host: a Host instance on which autotest will be
+				installed
+		
+		Raises:
+			AutoservError: if a tarball was not specified and
+				the target host does not have svn installed in its path
+		"""
+		# try to install from file or directory
+		try:
+			if os.path.isdir(self.__filename):
+				# Copy autotest recursively
+				autodir = _get_autodir(host)
+				host.run('mkdir -p %s' %
+					 utils.scp_remote_escape(autodir))
+				host.send_file(self.__filename + '/',
+					       autodir)
+			else:
+				# Copy autotest via tarball
+				raise "Not yet implemented!"
+			return
+		except AttributeError, e:
+			pass
+
+		# if that fails try to install using svn
+		if utils.run('which svn').exit_status:
+			raise AutoservError('svn not found in path on \
+			target machine: %s' % host.name)
+		try:
+			host.run('svn checkout %s %s' %
+				 (AUTOTEST_SVN, _get_autodir(host)))
+		except errors.AutoservRunError, e:
+			host.run('svn checkout %s %s' %
+				 (AUTOTEST_HTTP, _get_autodir(host)))
+
+
+	def run(self, control_file, results_dir, host):
+		"""
+		Run an autotest job on the remote machine.
+
+		Args:
+			control_file: an open file-like-obj of the control file
+			results_dir: a str path where the results should be stored
+				on the local filesystem
+			host: a Host instance on which the control file should
+				be run
+		
+		Raises:
+			AutotestRunError: if there is a problem executing
+				the control file
+		"""
+		atrun = _Run(host, results_dir)
+		atrun.verify_machine()
+		debug = os.path.join(results_dir, 'debug')
+		if not os.path.exists(debug):
+			os.makedirs(debug)
+
+		# Ready .... Aim ....
+		host.run('rm -f ' + atrun.remote_control_file)
+		host.run('rm -f ' + atrun.remote_control_file + '.state')
+
+		# Copy control_file to remote_control_file on the host
+		tmppath = utils.get(control_file)
+		host.send_file(tmppath, atrun.remote_control_file)
+		os.remove(tmppath)
+
+		atrun.execute_control()
+
+		# retrive results
+		results = os.path.join(atrun.autodir, 'results', 'default')
+		# Copy all dirs in default to results_dir
+		host.get_file(results + '/', results_dir)
+
+
+class _Run(object):
+	"""
+	Represents a run of autotest control file.  This class maintains
+	all the state necessary as an autotest control file is executed.
+
+	It is not intended to be used directly, rather control files
+	should be run using the run method in Autotest.
+	"""
+	def __init__(self, host, results_dir):
+		self.host = host
+		self.results_dir = results_dir
+
+		self.autodir = _get_autodir(self.host)
+		self.remote_control_file = os.path.join(self.autodir, 'control')
+
+
+	def verify_machine(self):
+		binary = os.path.join(self.autodir, 'bin/autotest')
+		self.host.run('ls ' + binary)
+
+
+	def __execute_section(self, section):
+		print "Executing %s/bin/autotest %s/control phase %d" % \
+					(self.autodir, self.autodir,
+					 section)
+		logfile = "%s/debug/client.log.%d" % (self.results_dir,
+						      section)
+		client_log = open(logfile, 'w')
+		if section > 0:
+			cont = '-c'
+		else:
+			cont = ''
+		client = os.path.join(self.autodir, 'bin/autotest_client')
+		ssh = "ssh -q %s@%s" % (self.host.user, self.host.hostname)
+		cmd = "%s %s %s" % (client, cont, self.remote_control_file)
+		print "%s '%s'" % (ssh, cmd)
+		# Use Popen here, not m.ssh, as we want it in the background
+		p = subprocess.Popen("%s '%s'" % (ssh, cmd), shell=True, \
+				stdout=client_log, stderr=subprocess.PIPE)
+		line = None
+		for line in iter(p.stderr.readline, ''):
+			print line,
+			sys.stdout.flush()
+		if not line:
+			raise AutotestRunError("execute_section: %s '%s' \
+			failed to return anything" % (ssh, cmd))
+		return line
+
+
+	def execute_control(self):
+		section = 0
+		while True:
+			last = self.__execute_section(section)
+			section += 1
+			if re.match('DONE', last):
+				print "Client complete"
+				return
+			elif re.match('REBOOT', last):
+				print "Client is rebooting"
+				print "Waiting for client to halt"
+				if not self.host.wait_down(HALT_TIME):
+					raise AutotestRunError("%s \
+					failed to shutdown after %ds" %
+						       (self.host.hostname,
+							HALT_TIME))
+				print "Client down, waiting for restart"
+				if not self.host.wait_up(BOOT_TIME):
+					# since reboot failed
+					# hardreset the machine once if possible
+					# before failing this control file
+					if hasattr(self.host, 'hardreset'):
+						print "Hardresetting %s" % self.hostname
+						self.host.hardreset()
+					raise AutotestRunError("%s \
+					failed to boot after %ds" %
+						       (self.host.hostname,
+							BOOT_TIME))
+				continue
+			raise AutotestRunError("Aborting - unknown \
+			return code: %s\n" % last)
+
+
+def _get_autodir(host):
+	try:
+		atdir = host.run(
+			'grep autodir= /etc/autotest.conf').stdout.strip(" \n")
+		if atdir:
+			m = re.search(r'autodir *= *[\'"]?([^\'"]*)[\'"]?',
+				      atdir)
+			return m.group(1)
+	except errors.AutoservRunError:
+		pass
+	for path in ['/usr/local/autotest', '/home/autotest']:
+		try:
+			host.run('ls ' + path)
+			return path
+		except errors.AutoservRunError:
+			pass
+	raise AutotestRunError("Cannot figure out autotest directory")
diff --git a/server/deb_kernel.py b/server/deb_kernel.py
new file mode 100644
index 0000000..07d0cf4
--- /dev/null
+++ b/server/deb_kernel.py
@@ -0,0 +1,67 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the Kernel class
+
+	Kernel: an os kernel
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+import os
+import os.path
+import time
+import urllib
+
+import kernel
+import errors
+import utils
+
+
+class DEBKernel(kernel.Kernel):
+	"""This class represents a .deb pre-built kernel.
+
+	It is used to obtain a built kernel and install it on a Host.
+
+	Implementation details:
+	This is a leaf class in an abstract class hierarchy, it must
+	implement the unimplemented methods in parent classes.
+	"""
+	def __init__(self):
+		super(DEBKernel, self).__init__()
+
+
+	def get_from_file(self, filename):
+		if os.path.exists(filename):
+			self.__filename = filename
+		else:
+			raise errors.AutoservError('%s not found' % filename)
+
+
+	def get_from_url(self, url):
+		tmpdir = utils.get_tmp_dir()
+		tmpfile = os.path.join(tmpdir, os.path.basename(url))
+		urllib.urlretrieve(url, tmpfile)
+		self.__filename = tmpfile
+
+
+	def install(self, host):
+		# this directory will get cleaned up for us automatically
+		remote_tmpdir = host.get_tmp_dir()
+		basename = os.path.basename(self.__filename)
+		remote_filename = os.path.join(remote_tmpdir, basename)
+		host.send_file(self.__filename, remote_filename)
+		try:
+			result = host.run('dpkg -i %s'
+					  % remote_filename)
+			if result.exit_status:
+				raise AutoservError('dpkg failed \
+				installing %s:\n\n%s'% (remote_filename,
+							result.stderr))
+		except NameError, e:
+			raise AutoservError('A kernel must first be \
+			specified via get_from_file or get_from_url')
diff --git a/server/doc/class diagram - new.xmi b/server/doc/class diagram - new.xmi
new file mode 100644
index 0000000..c3a422e
--- /dev/null
+++ b/server/doc/class diagram - new.xmi
@@ -0,0 +1,1208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XMI xmlns:UML="http://schema.omg.org/spec/UML/1.3" verified="false" timestamp="2007-07-02T14:35:11" xmi.version="1.2" >
+ <XMI.header>
+  <XMI.documentation>
+   <XMI.exporter>umbrello uml modeller http://uml.sf.net</XMI.exporter>
+   <XMI.exporterVersion>1.5.2</XMI.exporterVersion>
+   <XMI.exporterEncoding>UnicodeUTF8</XMI.exporterEncoding>
+  </XMI.documentation>
+  <XMI.metamodel xmi.name="UML" href="UML.xml" xmi.version="1.3" />
+ </XMI.header>
+ <XMI.content>
+  <UML:Model isSpecification="false" isLeaf="false" isRoot="false" xmi.id="m1" isAbstract="false" name="UML Model" >
+   <UML:Namespace.ownedElement>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="2" isRoot="false" isAbstract="false" name="Host" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="4" />
+     </UML:GeneralizableElement.generalization>
+     <UML:Classifier.feature>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="7" isRoot="false" isAbstract="false" isQuery="false" name="run" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16818" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="9" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="11" value="" type="8" name="command" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="12" isRoot="false" isAbstract="false" isQuery="false" name="reboot" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16819" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="13" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="14" isRoot="false" isAbstract="false" isQuery="false" name="get_file" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16820" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="15" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="16" value="" type="8" name="source" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="17" value="" type="8" name="dest" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="18" isRoot="false" isAbstract="false" isQuery="false" name="send_file" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16821" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="19" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="20" value="" type="8" name="source" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="21" value="" type="8" name="dest" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="22" isRoot="false" isAbstract="false" isQuery="false" name="get_tmp_dir" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16822" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="23" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="24" isRoot="false" isAbstract="false" isQuery="false" name="is_up" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16823" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="25" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="26" isRoot="false" isAbstract="false" isQuery="false" name="wait_up" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16824" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="27" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="28" value="" type="8" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="29" isRoot="false" isAbstract="false" isQuery="false" name="wait_down" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16825" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="30" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="31" value="" type="8" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="32" isRoot="false" isAbstract="false" isQuery="false" name="install" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16826" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="33" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="34" value="" type="8" name="installableObject" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="3" isRoot="false" isAbstract="false" name="object" />
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="8" isRoot="false" isAbstract="false" name="string" />
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="10" isRoot="false" isAbstract="false" name="int" />
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="35" isRoot="false" isAbstract="false" name="RemoteHost" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="37" />
+      <UML:Generalization xmi.idref="3230" />
+     </UML:GeneralizableElement.generalization>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="36" isRoot="false" isAbstract="false" name="SiteHost" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="159" />
+      <UML:Generalization xmi.idref="3713" />
+     </UML:GeneralizableElement.generalization>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="40" isRoot="false" isAbstract="false" name="Guest" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="41" />
+      <UML:Generalization xmi.idref="11832" />
+     </UML:GeneralizableElement.generalization>
+     <UML:Classifier.feature>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="44" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16827" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="45" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="46" value="" type="8" name="controllingVMM" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="47" isRoot="false" isAbstract="false" isQuery="false" name="__del__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16828" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="48" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="49" isRoot="false" isAbstract="false" isQuery="false" name="run" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16829" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="50" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="51" value="" type="8" name="command" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="52" isRoot="false" isAbstract="false" isQuery="false" name="reboot" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16830" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="53" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="54" isRoot="false" isAbstract="false" isQuery="false" name="get_file" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16831" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="55" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="56" value="" type="8" name="source" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="57" value="" type="8" name="dest" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="58" isRoot="false" isAbstract="false" isQuery="false" name="send_file" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16832" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="59" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="60" value="" type="8" name="source" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="61" value="" type="8" name="dest" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="62" isRoot="false" isAbstract="false" isQuery="false" name="get_tmp_dir" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16833" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="63" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="64" isRoot="false" isAbstract="false" isQuery="false" name="is_up" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16834" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="65" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="66" isRoot="false" isAbstract="false" isQuery="false" name="wait_up" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16835" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="67" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="68" value="" type="8" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="69" isRoot="false" isAbstract="false" isQuery="false" name="wait_down" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16836" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="70" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="71" value="" type="8" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="72" isRoot="false" isAbstract="false" name="CmdResult" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="73" />
+     </UML:GeneralizableElement.generalization>
+     <UML:Classifier.feature>
+      <UML:Operation comment="Command execution result.
+
+Modified from the original Autoserv code, local_cmd.py:
+Copyright [email protected] (Jonathan Mayer),
[email protected]   (Martin J. Bligh)
+Released under the GPL, v2
+
+command: String containing the command line itself
+exit_status: Integer exit code of the process
+stdout: String containing stdout of the process
+stderr: String containing stderr of the process
+duration: Elapsed wall clock time running the process
+aborted: Signal that caused the command to terminate (0 if none)" isSpecification="false" isLeaf="false" visibility="public" xmi.id="76" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16837" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="77" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="78" isRoot="false" isAbstract="false" isQuery="false" name="__repr__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16838" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="79" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="80" isRoot="false" isAbstract="false" name="ConsoleRemoteHost" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="83" />
+      <UML:Generalization xmi.idref="4202" />
+     </UML:GeneralizableElement.generalization>
+     <UML:Classifier.feature>
+      <UML:Operation comment="This class represents a remote machine controlled through a serial
+console on which you can run programs. It is not the machine autoserv 
+is running on.
+
+For a machine controlled in this way, it may be possible to support 
+hard reset, boot strap monitoring or other operations not possible 
+on a machine controlled through ssh, telnet, .." isSpecification="false" isLeaf="false" visibility="public" xmi.id="86" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16839" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="87" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="88" value="" type="8" name="tty" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="89" isRoot="false" isAbstract="false" isQuery="false" name="run" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16840" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="90" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="91" value="" type="8" name="command" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="92" isRoot="false" isAbstract="false" isQuery="false" name="reboot" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16841" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="93" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="94" isRoot="false" isAbstract="false" isQuery="false" name="get_file" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16842" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="95" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="96" value="" type="8" name="source" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="97" value="" type="8" name="dest" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="98" isRoot="false" isAbstract="false" isQuery="false" name="send_file" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16843" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="99" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="100" value="" type="8" name="source" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="101" value="" type="8" name="dest" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="102" isRoot="false" isAbstract="false" isQuery="false" name="is_up" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16844" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="103" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="104" isRoot="false" isAbstract="false" isQuery="false" name="wait_up" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16845" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="105" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="106" value="" type="8" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="107" isRoot="false" isAbstract="false" isQuery="false" name="wait_down" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16846" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="108" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="109" value="" type="8" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Package isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="81" isRoot="false" isAbstract="false" name="base_classes" >
+     <UML:Namespace.ownedElement>
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="81" xmi.id="82" isRoot="false" isAbstract="false" name="RemoteHost" />
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="81" xmi.id="117" isRoot="false" isAbstract="false" name="Guest" />
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="81" xmi.id="126" isRoot="false" isAbstract="false" name="SiteHost" />
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="81" xmi.id="158" isRoot="false" isAbstract="false" name="Host" />
+     </UML:Namespace.ownedElement>
+    </UML:Package>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="110" isRoot="false" isAbstract="false" name="Grub" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="113" />
+     </UML:GeneralizableElement.generalization>
+    </UML:Class>
+    <UML:Package isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="111" isRoot="false" isAbstract="false" name="bootloader" >
+     <UML:Namespace.ownedElement>
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="111" xmi.id="112" isRoot="false" isAbstract="false" name="Bootloader" />
+     </UML:Namespace.ownedElement>
+    </UML:Package>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="116" isRoot="false" isAbstract="false" name="KVMGuest" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="118" />
+      <UML:Generalization xmi.idref="11189" />
+      <UML:Generalization xmi.idref="11995" />
+     </UML:GeneralizableElement.generalization>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="121" isRoot="false" isAbstract="false" name="Lilo" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="122" />
+     </UML:GeneralizableElement.generalization>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="125" isRoot="false" isAbstract="false" name="LocalHost" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="127" />
+      <UML:Generalization xmi.idref="3067" />
+      <UML:Generalization xmi.idref="3876" />
+     </UML:GeneralizableElement.generalization>
+     <UML:Classifier.feature>
+      <UML:Operation comment="A Host object for the machine Autoserv is running on
+
+This is the Host object for the machine Autoserv is running on.
+
+Implementation details:
+This is a leaf class in an abstract class hierarchy, it must 
+implement the unimplemented methods in parent classes." isSpecification="false" isLeaf="false" visibility="public" xmi.id="130" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16847" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="131" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="132" isRoot="false" isAbstract="false" isQuery="false" name="__del__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16848" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="133" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="134" isRoot="false" isAbstract="false" isQuery="false" name="run" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16849" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="135" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="136" value="" type="8" name="command" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="137" value="" type="8" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="138" isRoot="false" isAbstract="false" isQuery="false" name="reboot" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16850" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="139" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="140" isRoot="false" isAbstract="false" isQuery="false" name="get_file" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16851" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="141" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="142" value="" type="8" name="source" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="143" value="" type="8" name="dest" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="144" isRoot="false" isAbstract="false" isQuery="false" name="send_file" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16852" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="145" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="146" value="" type="8" name="source" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="147" value="" type="8" name="dest" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="148" isRoot="false" isAbstract="false" isQuery="false" name="get_tmp_dir" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16853" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="149" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="150" isRoot="false" isAbstract="false" isQuery="false" name="is_up" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16854" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="151" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="152" isRoot="false" isAbstract="false" isQuery="false" name="wait_up" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16855" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="153" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="154" value="" type="8" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="155" isRoot="false" isAbstract="false" isQuery="false" name="wait_down" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16856" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="156" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="157" value="" type="8" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="162" isRoot="false" isAbstract="false" name="SSHRemoteHost" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="163" />
+      <UML:Generalization xmi.idref="4039" />
+     </UML:GeneralizableElement.generalization>
+     <UML:Classifier.feature>
+      <UML:Operation comment="This class represents a remote machine controlled through an ssh
+session on which you can run programs.
+
+It is not the machine autoserv is running on. The machine must be 
+configured for password-less login, for example through public key 
+authentication.
+
+Implementation details:
+This is a leaf class in an abstract class hierarchy, it must 
+implement the unimplemented methods in parent classes." isSpecification="false" isLeaf="false" visibility="public" xmi.id="166" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16857" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="167" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="168" value="" type="8" name="hostname" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="169" value="" type="8" name="user" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="170" isRoot="false" isAbstract="false" isQuery="false" name="__del__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16858" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="171" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="172" isRoot="false" isAbstract="false" isQuery="false" name="run" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16859" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="173" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="174" value="" type="8" name="command" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="175" value="" type="8" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="176" isRoot="false" isAbstract="false" isQuery="false" name="reboot" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16860" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="177" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="178" isRoot="false" isAbstract="false" isQuery="false" name="get_file" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16861" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="179" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="180" value="" type="8" name="source" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="181" value="" type="8" name="dest" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="182" isRoot="false" isAbstract="false" isQuery="false" name="send_file" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16862" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="183" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="184" value="" type="8" name="source" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="185" value="" type="8" name="dest" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="186" isRoot="false" isAbstract="false" isQuery="false" name="get_tmp_dir" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16863" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="187" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="188" isRoot="false" isAbstract="false" isQuery="false" name="is_up" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16864" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="189" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="190" isRoot="false" isAbstract="false" isQuery="false" name="wait_up" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16865" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="191" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="192" value="" type="8" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="193" isRoot="false" isAbstract="false" isQuery="false" name="wait_down" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16866" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="194" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="195" value="" type="8" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="196" isRoot="false" isAbstract="false" name="AutotestRunError" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="199" />
+      <UML:Generalization xmi.idref="2904" />
+     </UML:GeneralizableElement.generalization>
+    </UML:Class>
+    <UML:Package isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="197" isRoot="false" isAbstract="false" name="errors" >
+     <UML:Namespace.ownedElement>
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="197" xmi.id="198" isRoot="false" isAbstract="false" name="AutoservRunError" />
+     </UML:Namespace.ownedElement>
+    </UML:Package>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="202" isRoot="false" isAbstract="false" name="Autotest" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="205" />
+      <UML:Generalization xmi.idref="9097" />
+     </UML:GeneralizableElement.generalization>
+     <UML:Classifier.feature>
+      <UML:Operation comment="This class represents the Autotest program.
+Autotest is used to run tests automatically and collect the results.
+It also supports profilers.
+Implementation details:
+This is a leaf class in an abstract class hierarchy, it must
+implement the unimplemented methods in parent classes." isSpecification="false" isLeaf="false" visibility="public" xmi.id="208" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16867" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="209" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="210" isRoot="false" isAbstract="false" isQuery="false" name="get_from_file" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16868" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="211" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="212" value="" type="8" name="filename" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="213" isRoot="false" isAbstract="false" isQuery="false" name="get_from_url" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16869" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="214" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="215" value="" type="8" name="url" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="216" isRoot="false" isAbstract="false" isQuery="false" name="__del__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16870" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="217" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="218" isRoot="false" isAbstract="false" isQuery="false" name="install" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16871" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="219" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="220" value="" type="8" name="host" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Package isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="203" isRoot="false" isAbstract="false" name="installable_object" >
+     <UML:Namespace.ownedElement>
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="203" xmi.id="204" isRoot="false" isAbstract="false" name="InstallableObject" />
+     </UML:Namespace.ownedElement>
+    </UML:Package>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="221" isRoot="false" isAbstract="false" name="_Run" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="222" />
+     </UML:GeneralizableElement.generalization>
+     <UML:Classifier.feature>
+      <UML:Operation comment="Represents a run of autotest control file.  This class maintains
+all the state necessary as an autotest control file is executed.
+It is not intended to be used directly, rather control files
+should be run using the run method in Autotest." isSpecification="false" isLeaf="false" visibility="public" xmi.id="225" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16872" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="226" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="227" value="" type="8" name="host" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="228" value="" type="8" name="results_dir" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="229" isRoot="false" isAbstract="false" isQuery="false" name="__get_autodir" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16873" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="230" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="231" isRoot="false" isAbstract="false" isQuery="false" name="verify_machine" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16874" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="232" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="233" isRoot="false" isAbstract="false" isQuery="false" name="__execute_section" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16875" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="234" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="235" value="" type="8" name="section" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="236" isRoot="false" isAbstract="false" isQuery="false" name="execute_control" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16876" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="237" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="238" isRoot="false" isAbstract="false" name="DEBKernel" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="241" />
+      <UML:Generalization xmi.idref="6451" />
+     </UML:GeneralizableElement.generalization>
+     <UML:Classifier.feature>
+      <UML:Operation comment="This class represents a .deb pre-built kernel.
+It is used to obtain a built kernel and install it on a Host.
+Implementation details:
+This is a leaf class in an abstract class hierarchy, it must
+implement the unimplemented methods in parent classes." isSpecification="false" isLeaf="false" visibility="public" xmi.id="244" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16877" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="245" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="246" isRoot="false" isAbstract="false" isQuery="false" name="get_from_file" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16878" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="247" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="248" value="" type="8" name="filename" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="249" isRoot="false" isAbstract="false" isQuery="false" name="get_from_url" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16879" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="250" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="251" value="" type="8" name="url" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="252" isRoot="false" isAbstract="false" isQuery="false" name="install" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16880" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="253" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="254" value="" type="8" name="host" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Package isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="239" isRoot="false" isAbstract="false" name="kernel" >
+     <UML:Namespace.ownedElement>
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="239" xmi.id="240" isRoot="false" isAbstract="false" name="Kernel" />
+     </UML:Namespace.ownedElement>
+    </UML:Package>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="255" isRoot="false" isAbstract="false" name="AutoservRunError" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="257" />
+     </UML:GeneralizableElement.generalization>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="256" isRoot="false" isAbstract="false" name="AutoservError" />
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="260" isRoot="false" isAbstract="false" name="InstallableObject" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="261" />
+     </UML:GeneralizableElement.generalization>
+     <UML:Classifier.feature>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="264" isRoot="false" isAbstract="false" isQuery="false" name="get" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16881" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="265" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="266" value="" type="8" name="location" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="267" isRoot="false" isAbstract="false" isQuery="false" name="install" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16882" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="268" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="269" value="" type="8" name="host" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="270" isRoot="false" isAbstract="false" name="Kernel" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="271" />
+      <UML:Generalization xmi.idref="6614" />
+     </UML:GeneralizableElement.generalization>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="274" isRoot="false" isAbstract="false" name="KVM" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="277" />
+      <UML:Generalization xmi.idref="12958" />
+     </UML:GeneralizableElement.generalization>
+     <UML:Classifier.feature>
+      <UML:Operation comment="This class represents a KVM virtual machine monitor.
+
+Implementation details:
+This is a leaf class in an abstract class hierarchy, it must 
+implement the unimplemented methods in parent classes." isSpecification="false" isLeaf="false" visibility="public" xmi.id="280" isRoot="false" isAbstract="false" isQuery="false" name="install" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16883" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="281" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="282" value="" type="8" name="host" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Package isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="275" isRoot="false" isAbstract="false" name="vmm" >
+     <UML:Namespace.ownedElement>
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="275" xmi.id="276" isRoot="false" isAbstract="false" name="VMM" />
+     </UML:Namespace.ownedElement>
+    </UML:Package>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="283" isRoot="false" isAbstract="false" name="RPMKernel" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="284" />
+      <UML:Generalization xmi.idref="6288" />
+     </UML:GeneralizableElement.generalization>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="287" isRoot="false" isAbstract="false" name="SourceKernel" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="288" />
+      <UML:Generalization xmi.idref="6125" />
+     </UML:GeneralizableElement.generalization>
+     <UML:Classifier.feature>
+      <UML:Operation comment="This class represents a linux kernel built from source.
+
+It is used to obtain a built kernel or create one from source and 
+install it on a Host.
+
+Implementation details:
+This is a leaf class in an abstract class hierarchy, it must 
+implement the unimplemented methods in parent classes." isSpecification="false" isLeaf="false" visibility="public" xmi.id="291" isRoot="false" isAbstract="false" isQuery="false" name="configure" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16884" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="292" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="293" value="" type="8" name="configFile" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="294" isRoot="false" isAbstract="false" isQuery="false" name="patch" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16885" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="295" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="296" value="" type="8" name="patchFile" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="297" isRoot="false" isAbstract="false" isQuery="false" name="build" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16886" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="298" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="299" value="" type="8" name="host" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="300" isRoot="false" isAbstract="false" name="VMM" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="301" />
+      <UML:Generalization xmi.idref="13121" />
+     </UML:GeneralizableElement.generalization>
+     <UML:Classifier.feature>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="304" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16887" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="305" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="306" value="" type="8" name="host" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="307" isRoot="false" isAbstract="false" isQuery="false" name="install" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16888" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="308" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="309" value="" type="8" name="host" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="310" isRoot="false" isAbstract="false" isQuery="false" name="new_guest" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16889" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="311" value="" type="8" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="312" isRoot="false" isAbstract="false" isQuery="false" name="delete_guest" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16890" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="313" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="314" value="" type="8" name="name" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="315" isRoot="false" isAbstract="false" isQuery="false" name="run_on_guest" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16891" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="316" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="317" value="" type="8" name="guest_name" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="318" value="" type="8" name="command" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="319" isRoot="false" isAbstract="false" isQuery="false" name="reboot_guest" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16892" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="320" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="321" value="" type="8" name="guest_name" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="322" isRoot="false" isAbstract="false" isQuery="false" name="get_file_from_guest" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16893" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="323" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="324" value="" type="8" name="guest_name" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="325" value="" type="8" name="source" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="326" value="" type="8" name="dest" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="327" isRoot="false" isAbstract="false" isQuery="false" name="send_file_to_guest" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16894" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="328" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="329" value="" type="8" name="guest_name" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="330" value="" type="8" name="source" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="331" value="" type="8" name="dest" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="332" isRoot="false" isAbstract="false" isQuery="false" name="is_guest_up" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16895" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="333" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="334" value="" type="8" name="guest_name" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="335" isRoot="false" isAbstract="false" isQuery="false" name="wait_guest_up" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16896" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="336" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="337" value="" type="8" name="guest_name" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="338" value="" type="8" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="339" isRoot="false" isAbstract="false" isQuery="false" name="wait_guest_down" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="16897" type="8" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="340" value="" type="8" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="341" value="" type="8" name="guest_name" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="342" value="" type="8" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Generalization isSpecification="false" child="2" visibility="public" namespace="m1" xmi.id="4" parent="3" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="35" visibility="public" namespace="m1" xmi.id="37" parent="36" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="40" visibility="public" namespace="m1" xmi.id="41" parent="36" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="72" visibility="public" namespace="m1" xmi.id="73" parent="3" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="80" visibility="public" namespace="m1" xmi.id="83" parent="82" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="110" visibility="public" namespace="m1" xmi.id="113" parent="112" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="116" visibility="public" namespace="m1" xmi.id="118" parent="117" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="121" visibility="public" namespace="m1" xmi.id="122" parent="112" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="125" visibility="public" namespace="m1" xmi.id="127" parent="126" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="36" visibility="public" namespace="m1" xmi.id="159" parent="158" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="162" visibility="public" namespace="m1" xmi.id="163" parent="82" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="196" visibility="public" namespace="m1" xmi.id="199" parent="198" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="202" visibility="public" namespace="m1" xmi.id="205" parent="204" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="221" visibility="public" namespace="m1" xmi.id="222" parent="3" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="238" visibility="public" namespace="m1" xmi.id="241" parent="240" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="255" visibility="public" namespace="m1" xmi.id="257" parent="256" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="260" visibility="public" namespace="m1" xmi.id="261" parent="3" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="270" visibility="public" namespace="m1" xmi.id="271" parent="204" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="274" visibility="public" namespace="m1" xmi.id="277" parent="276" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="283" visibility="public" namespace="m1" xmi.id="284" parent="240" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="287" visibility="public" namespace="m1" xmi.id="288" parent="240" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="300" visibility="public" namespace="m1" xmi.id="301" parent="204" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="196" visibility="public" namespace="m1" xmi.id="2904" parent="256" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="125" visibility="public" namespace="m1" xmi.id="3067" parent="2" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="35" visibility="public" namespace="m1" xmi.id="3230" parent="2" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="36" visibility="public" namespace="m1" xmi.id="3713" parent="2" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="125" visibility="public" namespace="m1" xmi.id="3876" parent="36" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="162" visibility="public" namespace="m1" xmi.id="4039" parent="35" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="80" visibility="public" namespace="m1" xmi.id="4202" parent="35" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="287" visibility="public" namespace="m1" xmi.id="6125" parent="270" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="283" visibility="public" namespace="m1" xmi.id="6288" parent="270" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="238" visibility="public" namespace="m1" xmi.id="6451" parent="270" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="270" visibility="public" namespace="m1" xmi.id="6614" parent="260" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="202" visibility="public" namespace="m1" xmi.id="9097" parent="260" discriminator="" name="" />
+    <UML:Association isSpecification="false" visibility="public" namespace="m1" xmi.id="9420" name="" >
+     <UML:Association.connection>
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="9421" aggregation="none" type="2" name="" />
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="9422" aggregation="none" type="72" name="" />
+     </UML:Association.connection>
+    </UML:Association>
+    <UML:Association isSpecification="false" visibility="public" namespace="m1" xmi.id="9663" name="" >
+     <UML:Association.connection>
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="9664" aggregation="composite" type="112" name="" />
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="9665" aggregation="none" type="2" name="" />
+     </UML:Association.connection>
+    </UML:Association>
+    <UML:Association isSpecification="false" visibility="public" namespace="m1" xmi.id="9906" name="" >
+     <UML:Association.connection>
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="9907" aggregation="composite" type="2" name="" />
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="9908" aggregation="none" type="112" name="" />
+     </UML:Association.connection>
+    </UML:Association>
+    <UML:Generalization isSpecification="false" child="116" visibility="public" namespace="m1" xmi.id="11189" parent="35" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="40" visibility="public" namespace="m1" xmi.id="11832" parent="35" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="116" visibility="public" namespace="m1" xmi.id="11995" parent="40" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="274" visibility="public" namespace="m1" xmi.id="12958" parent="300" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="300" visibility="public" namespace="m1" xmi.id="13121" parent="260" discriminator="" name="" />
+    <UML:Association isSpecification="false" visibility="public" namespace="m1" xmi.id="14486" name="" >
+     <UML:Association.connection>
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="14487" aggregation="composite" type="300" name="" />
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="14488" aggregation="none" type="40" name="" />
+     </UML:Association.connection>
+    </UML:Association>
+    <UML:Association isSpecification="false" visibility="public" namespace="m1" xmi.id="14571" name="" >
+     <UML:Association.connection>
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="14572" aggregation="aggregate" type="2" name="" />
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="14573" aggregation="none" type="300" name="" />
+     </UML:Association.connection>
+    </UML:Association>
+    <UML:Association isSpecification="false" visibility="public" namespace="m1" xmi.id="14814" name="" >
+     <UML:Association.connection>
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="14815" aggregation="aggregate" type="300" name="" />
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="14816" aggregation="none" type="2" name="" />
+     </UML:Association.connection>
+    </UML:Association>
+   </UML:Namespace.ownedElement>
+  </UML:Model>
+ </XMI.content>
+ <XMI.extensions xmi.extender="umbrello" >
+  <docsettings viewid="1" documentation="" uniqueid="16897" />
+  <diagrams>
+   <diagram snapgrid="0" showattsig="1" fillcolor="#ffffc0" linewidth="0" zoom="46" showgrid="0" showopsig="1" usefillcolor="1" snapx="10" canvaswidth="2153" snapy="10" showatts="1" xmi.id="1" documentation="" type="402" showops="1" showpackage="0" name="class diagram" localid="900000" showstereotype="0" showscope="1" snapcsgrid="0" font="DejaVu Sans,9,-1,5,50,0,0,0,0,0" linecolor="#ff0000" canvasheight="1283" >
+    <widgets>
+     <classwidget usesdiagramfillcolour="1" width="109" showattsigs="601" usesdiagramusefillcolour="1" x="368" y="913" showopsigs="601" linewidth="none" fillcolour="none" height="32" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="256" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="136" showattsigs="601" usesdiagramusefillcolour="1" x="268" y="1014" showopsigs="601" linewidth="none" fillcolour="none" height="32" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="255" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="135" showattsigs="601" usesdiagramusefillcolour="1" x="443" y="1015" showopsigs="601" linewidth="none" fillcolour="none" height="32" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="196" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="392" showattsigs="601" usesdiagramusefillcolour="1" x="279" y="43" showopsigs="601" linewidth="none" fillcolour="none" height="168" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="2" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="98" showattsigs="601" usesdiagramusefillcolour="1" x="439" y="447" showopsigs="601" linewidth="none" fillcolour="none" height="32" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="35" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="400" showattsigs="601" usesdiagramusefillcolour="1" x="505" y="625" showopsigs="601" linewidth="none" fillcolour="none" height="184" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="162" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="392" showattsigs="601" usesdiagramusefillcolour="1" x="68" y="638" showopsigs="601" linewidth="none" fillcolour="none" height="152" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="80" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="396" showattsigs="601" usesdiagramusefillcolour="1" x="17" y="387" showopsigs="601" linewidth="none" fillcolour="none" height="184" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="125" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="72" showattsigs="601" usesdiagramusefillcolour="1" x="457" y="265" showopsigs="601" linewidth="none" fillcolour="none" height="32" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="36" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="281" showattsigs="601" usesdiagramusefillcolour="1" x="1526" y="86" showopsigs="601" linewidth="none" fillcolour="none" height="56" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="260" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="57" showattsigs="601" usesdiagramusefillcolour="1" x="1628" y="861" showopsigs="601" linewidth="none" fillcolour="none" height="32" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="270" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="87" showattsigs="601" usesdiagramusefillcolour="1" x="1618" y="1015" showopsigs="601" linewidth="none" fillcolour="none" height="32" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="283" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="342" showattsigs="601" usesdiagramusefillcolour="1" x="1778" y="1012" showopsigs="601" linewidth="none" fillcolour="none" height="88" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="238" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="328" showattsigs="601" usesdiagramusefillcolour="1" x="1260" y="1019" showopsigs="601" linewidth="none" fillcolour="none" height="72" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="287" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="90" showattsigs="601" usesdiagramusefillcolour="1" x="1138" y="135" showopsigs="601" linewidth="none" fillcolour="none" height="32" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="112" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="36" showattsigs="601" usesdiagramusefillcolour="1" x="1079" y="220" showopsigs="601" linewidth="none" fillcolour="none" height="32" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="121" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="45" showattsigs="601" usesdiagramusefillcolour="1" x="1249" y="220" showopsigs="601" linewidth="none" fillcolour="none" height="32" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="110" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="342" showattsigs="601" usesdiagramusefillcolour="1" x="1730" y="367" showopsigs="601" linewidth="none" fillcolour="none" height="104" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="202" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="402" showattsigs="601" usesdiagramusefillcolour="1" x="1726" y="522" showopsigs="601" linewidth="none" fillcolour="none" height="104" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="221" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="204" showattsigs="601" usesdiagramusefillcolour="1" x="776" y="49" showopsigs="601" linewidth="none" fillcolour="none" height="56" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="72" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="591" showattsigs="601" usesdiagramusefillcolour="1" x="1024" y="316" showopsigs="601" linewidth="none" fillcolour="none" height="200" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="300" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="275" showattsigs="601" usesdiagramusefillcolour="1" x="1272" y="543" showopsigs="601" linewidth="none" fillcolour="none" height="40" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="274" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="83" showattsigs="601" usesdiagramusefillcolour="1" x="1082" y="888" showopsigs="601" linewidth="none" fillcolour="none" height="32" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="116" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="392" showattsigs="601" usesdiagramusefillcolour="1" x="959" y="628" showopsigs="601" linewidth="none" fillcolour="none" height="184" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="40" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+    </widgets>
+    <messages/>
+    <associations>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="1" linewidth="none" widgetbid="256" widgetaid="255" xmi.id="257" linecolor="none" >
+      <linepath>
+       <startpoint startx="384" starty="1014" />
+       <endpoint endx="384" endy="945" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="2" linewidth="none" widgetbid="256" widgetaid="196" xmi.id="2904" linecolor="none" >
+      <linepath>
+       <startpoint startx="460" starty="1015" />
+       <endpoint endx="460" endy="945" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="4" indexb="2" linewidth="none" widgetbid="36" widgetaid="35" xmi.id="37" linecolor="none" >
+      <linepath>
+       <startpoint startx="491" starty="447" />
+       <endpoint endx="491" endy="297" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="2" widgetaid="36" xmi.id="3713" linecolor="none" >
+      <linepath>
+       <startpoint startx="496" starty="265" />
+       <endpoint endx="496" endy="211" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="4" indexb="1" linewidth="none" widgetbid="36" widgetaid="125" xmi.id="3876" linecolor="none" >
+      <linepath>
+       <startpoint startx="413" starty="387" />
+       <endpoint endx="457" endy="297" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="2" linewidth="none" widgetbid="35" widgetaid="162" xmi.id="4039" linecolor="none" >
+      <linepath>
+       <startpoint startx="511" starty="625" />
+       <endpoint endx="511" endy="479" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="1" linewidth="none" widgetbid="35" widgetaid="80" xmi.id="4202" linecolor="none" >
+      <linepath>
+       <startpoint startx="460" starty="638" />
+       <endpoint endx="460" endy="479" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="4" indexb="1" linewidth="none" widgetbid="270" widgetaid="287" xmi.id="6125" linecolor="none" >
+      <linepath>
+       <startpoint startx="1588" starty="1019" />
+       <endpoint endx="1628" endy="893" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="4" indexb="2" linewidth="none" widgetbid="270" widgetaid="283" xmi.id="6288" linecolor="none" >
+      <linepath>
+       <startpoint startx="1658" starty="1015" />
+       <endpoint endx="1658" endy="893" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="4" indexb="3" linewidth="none" widgetbid="270" widgetaid="238" xmi.id="6451" linecolor="none" >
+      <linepath>
+       <startpoint startx="1778" starty="1012" />
+       <endpoint endx="1685" endy="893" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="4" indexb="2" linewidth="none" widgetbid="260" widgetaid="270" xmi.id="6614" linecolor="none" >
+      <linepath>
+       <startpoint startx="1658" starty="861" />
+       <endpoint endx="1658" endy="142" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="1" linewidth="none" widgetbid="112" widgetaid="121" xmi.id="122" linecolor="none" >
+      <linepath>
+       <startpoint startx="1115" starty="220" />
+       <endpoint endx="1138" endy="167" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="2" linewidth="none" widgetbid="112" widgetaid="110" xmi.id="113" linecolor="none" >
+      <linepath>
+       <startpoint startx="1249" starty="220" />
+       <endpoint endx="1228" endy="167" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="4" indexb="3" linewidth="none" widgetbid="260" widgetaid="202" xmi.id="9097" linecolor="none" >
+      <linepath>
+       <startpoint startx="1770" starty="367" />
+       <endpoint endx="1770" endy="142" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="112" widgetaid="2" xmi.id="9906" linecolor="none" >
+      <linepath>
+       <startpoint startx="671" starty="150" />
+       <endpoint endx="1138" endy="150" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="40" widgetaid="116" xmi.id="11995" linecolor="none" >
+      <linepath>
+       <startpoint startx="1125" starty="888" />
+       <endpoint endx="1125" endy="812" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="2" linewidth="none" widgetbid="300" widgetaid="274" xmi.id="12958" linecolor="none" >
+      <linepath>
+       <startpoint startx="1402" starty="543" />
+       <endpoint endx="1402" endy="516" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="2" totalcountb="4" indexb="1" linewidth="none" widgetbid="260" widgetaid="300" xmi.id="13121" linecolor="none" >
+      <linepath>
+       <startpoint startx="1583" starty="316" />
+       <endpoint endx="1583" endy="142" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="1" totalcountb="3" indexb="2" linewidth="none" widgetbid="40" widgetaid="300" xmi.id="14486" linecolor="none" >
+      <linepath>
+       <startpoint startx="1163" starty="516" />
+       <endpoint endx="1163" endy="628" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="1" totalcountb="3" indexb="2" linewidth="none" widgetbid="2" widgetaid="300" xmi.id="14814" linecolor="none" >
+      <linepath>
+       <startpoint startx="1024" starty="316" />
+       <endpoint endx="671" endy="211" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="1" totalcountb="4" indexb="3" linewidth="none" widgetbid="36" widgetaid="40" xmi.id="41" linecolor="none" >
+      <linepath>
+       <startpoint startx="959" starty="628" />
+       <endpoint endx="529" endy="297" />
+      </linepath>
+     </assocwidget>
+    </associations>
+   </diagram>
+  </diagrams>
+  <listview>
+   <listitem open="1" type="800" label="Views" >
+    <listitem open="1" type="801" label="Logical View" >
+     <listitem open="0" type="813" id="256" />
+     <listitem open="0" type="813" id="255" />
+     <listitem open="0" type="813" id="202" >
+      <listitem open="0" type="815" id="208" />
+      <listitem open="0" type="815" id="210" />
+      <listitem open="0" type="815" id="213" />
+      <listitem open="0" type="815" id="216" />
+      <listitem open="0" type="815" id="218" />
+     </listitem>
+     <listitem open="0" type="813" id="196" />
+     <listitem open="0" type="813" id="72" >
+      <listitem open="0" type="815" id="76" />
+      <listitem open="0" type="815" id="78" />
+     </listitem>
+     <listitem open="0" type="813" id="80" >
+      <listitem open="0" type="815" id="86" />
+      <listitem open="0" type="815" id="89" />
+      <listitem open="0" type="815" id="92" />
+      <listitem open="0" type="815" id="94" />
+      <listitem open="0" type="815" id="98" />
+      <listitem open="0" type="815" id="102" />
+      <listitem open="0" type="815" id="104" />
+      <listitem open="0" type="815" id="107" />
+     </listitem>
+     <listitem open="0" type="813" id="238" >
+      <listitem open="0" type="815" id="244" />
+      <listitem open="0" type="815" id="246" />
+      <listitem open="0" type="815" id="249" />
+      <listitem open="0" type="815" id="252" />
+     </listitem>
+     <listitem open="0" type="813" id="110" />
+     <listitem open="0" type="813" id="40" >
+      <listitem open="0" type="815" id="44" />
+      <listitem open="0" type="815" id="47" />
+      <listitem open="0" type="815" id="49" />
+      <listitem open="0" type="815" id="52" />
+      <listitem open="0" type="815" id="54" />
+      <listitem open="0" type="815" id="58" />
+      <listitem open="0" type="815" id="62" />
+      <listitem open="0" type="815" id="64" />
+      <listitem open="0" type="815" id="66" />
+      <listitem open="0" type="815" id="69" />
+     </listitem>
+     <listitem open="0" type="813" id="2" >
+      <listitem open="0" type="815" id="7" />
+      <listitem open="0" type="815" id="12" />
+      <listitem open="0" type="815" id="14" />
+      <listitem open="0" type="815" id="18" />
+      <listitem open="0" type="815" id="22" />
+      <listitem open="0" type="815" id="24" />
+      <listitem open="0" type="815" id="26" />
+      <listitem open="0" type="815" id="29" />
+      <listitem open="0" type="815" id="32" />
+     </listitem>
+     <listitem open="0" type="813" id="260" >
+      <listitem open="0" type="815" id="264" />
+      <listitem open="0" type="815" id="267" />
+     </listitem>
+     <listitem open="0" type="813" id="274" >
+      <listitem open="0" type="815" id="280" />
+     </listitem>
+     <listitem open="0" type="813" id="116" />
+     <listitem open="0" type="813" id="270" />
+     <listitem open="0" type="813" id="121" />
+     <listitem open="0" type="813" id="125" >
+      <listitem open="0" type="815" id="130" />
+      <listitem open="0" type="815" id="132" />
+      <listitem open="0" type="815" id="134" />
+      <listitem open="0" type="815" id="138" />
+      <listitem open="0" type="815" id="140" />
+      <listitem open="0" type="815" id="144" />
+      <listitem open="0" type="815" id="148" />
+      <listitem open="0" type="815" id="150" />
+      <listitem open="0" type="815" id="152" />
+      <listitem open="0" type="815" id="155" />
+     </listitem>
+     <listitem open="0" type="813" id="283" />
+     <listitem open="0" type="813" id="35" />
+     <listitem open="0" type="813" id="162" >
+      <listitem open="0" type="815" id="166" />
+      <listitem open="0" type="815" id="170" />
+      <listitem open="0" type="815" id="172" />
+      <listitem open="0" type="815" id="176" />
+      <listitem open="0" type="815" id="178" />
+      <listitem open="0" type="815" id="182" />
+      <listitem open="0" type="815" id="186" />
+      <listitem open="0" type="815" id="188" />
+      <listitem open="0" type="815" id="190" />
+      <listitem open="0" type="815" id="193" />
+     </listitem>
+     <listitem open="0" type="813" id="36" />
+     <listitem open="0" type="813" id="287" >
+      <listitem open="0" type="815" id="291" />
+      <listitem open="0" type="815" id="294" />
+      <listitem open="0" type="815" id="297" />
+     </listitem>
+     <listitem open="0" type="813" id="300" >
+      <listitem open="0" type="815" id="304" />
+      <listitem open="0" type="815" id="307" />
+      <listitem open="0" type="815" id="310" />
+      <listitem open="0" type="815" id="312" />
+      <listitem open="0" type="815" id="315" />
+      <listitem open="0" type="815" id="319" />
+      <listitem open="0" type="815" id="322" />
+      <listitem open="0" type="815" id="327" />
+      <listitem open="0" type="815" id="332" />
+      <listitem open="0" type="815" id="335" />
+      <listitem open="0" type="815" id="339" />
+     </listitem>
+     <listitem open="0" type="813" id="221" >
+      <listitem open="0" type="815" id="225" />
+      <listitem open="0" type="815" id="229" />
+      <listitem open="0" type="815" id="231" />
+      <listitem open="0" type="815" id="233" />
+      <listitem open="0" type="815" id="236" />
+     </listitem>
+     <listitem open="0" type="813" id="10" />
+     <listitem open="0" type="813" id="3" />
+     <listitem open="0" type="813" id="8" />
+     <listitem open="0" type="818" id="81" >
+      <listitem open="0" type="813" id="117" />
+      <listitem open="0" type="813" id="158" />
+      <listitem open="0" type="813" id="82" />
+      <listitem open="0" type="813" id="126" />
+     </listitem>
+     <listitem open="0" type="818" id="111" >
+      <listitem open="0" type="813" id="112" />
+     </listitem>
+     <listitem open="0" type="818" id="197" >
+      <listitem open="0" type="813" id="198" />
+     </listitem>
+     <listitem open="0" type="818" id="203" >
+      <listitem open="0" type="813" id="204" />
+     </listitem>
+     <listitem open="0" type="818" id="239" >
+      <listitem open="0" type="813" id="240" />
+     </listitem>
+     <listitem open="0" type="818" id="275" >
+      <listitem open="0" type="813" id="276" />
+     </listitem>
+     <listitem open="0" type="830" label="Datatypes" />
+    </listitem>
+    <listitem open="1" type="802" label="Use Case View" />
+    <listitem open="1" type="821" label="Component View" />
+    <listitem open="1" type="827" label="Deployment View" />
+    <listitem open="1" type="836" label="Entity Relationship Model" />
+   </listitem>
+  </listview>
+  <codegeneration>
+   <codegenerator language="Python" />
+  </codegeneration>
+ </XMI.extensions>
+</XMI>
diff --git a/server/doc/class diagram - original.xmi b/server/doc/class diagram - original.xmi
new file mode 100644
index 0000000..c46aa54
--- /dev/null
+++ b/server/doc/class diagram - original.xmi
@@ -0,0 +1,756 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XMI xmlns:UML="http://schema.omg.org/spec/UML/1.3" verified="false" timestamp="2007-06-14T11:23:28" xmi.version="1.2" >
+ <XMI.header>
+  <XMI.documentation>
+   <XMI.exporter>umbrello uml modeller http://uml.sf.net</XMI.exporter>
+   <XMI.exporterVersion>1.5.2</XMI.exporterVersion>
+   <XMI.exporterEncoding>UnicodeUTF8</XMI.exporterEncoding>
+  </XMI.documentation>
+  <XMI.metamodel xmi.name="UML" href="UML.xml" xmi.version="1.3" />
+ </XMI.header>
+ <XMI.content>
+  <UML:Model isSpecification="false" isLeaf="false" isRoot="false" xmi.id="m1" isAbstract="false" name="UML Model" >
+   <UML:Namespace.ownedElement>
+    <UML:Stereotype isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="3" isRoot="false" isAbstract="false" name="datatype" />
+    <UML:Stereotype isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="14" isRoot="false" isAbstract="false" name="constructor" />
+    <UML:Stereotype isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="15" isRoot="false" isAbstract="false" name="friend" />
+    <UML:Stereotype isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="16" isRoot="false" isAbstract="false" name="virtual" />
+    <UML:DataType stereotype="3" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="2" isRoot="false" isAbstract="false" name="int" />
+    <UML:DataType stereotype="3" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="4" isRoot="false" isAbstract="false" name="char" />
+    <UML:DataType stereotype="3" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="5" isRoot="false" isAbstract="false" name="bool" />
+    <UML:DataType stereotype="3" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="6" isRoot="false" isAbstract="false" name="float" />
+    <UML:DataType stereotype="3" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="7" isRoot="false" isAbstract="false" name="double" />
+    <UML:DataType stereotype="3" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="8" isRoot="false" isAbstract="false" name="short" />
+    <UML:DataType stereotype="3" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="9" isRoot="false" isAbstract="false" name="long" />
+    <UML:DataType stereotype="3" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="10" isRoot="false" isAbstract="false" name="unsigned int" />
+    <UML:DataType stereotype="3" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="11" isRoot="false" isAbstract="false" name="unsigned short" />
+    <UML:DataType stereotype="3" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="12" isRoot="false" isAbstract="false" name="unsigned long" />
+    <UML:DataType stereotype="3" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="13" isRoot="false" isAbstract="false" name="string" />
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="17" isRoot="false" isAbstract="false" name="bios" >
+     <UML:Classifier.feature>
+      <UML:Operation comment="Else we'll use the defaults in /home/mbligh/.bios_versions" isSpecification="false" isLeaf="false" visibility="public" xmi.id="71" isRoot="false" isAbstract="false" isQuery="false" name="get_info_from_biosrc" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12155" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="72" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="73" isRoot="false" isAbstract="false" isQuery="false" name="install_biosflash" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12156" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="74" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="75" value="" type="13" name="biosflash" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="76" isRoot="false" isAbstract="false" isQuery="false" name="verify_flash_module" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12157" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="77" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="78" isRoot="false" isAbstract="false" isQuery="false" name="flash_bios_unicorn" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12158" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="79" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="80" isRoot="false" isAbstract="false" isQuery="false" name="flash_bios_other" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12159" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="81" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="82" isRoot="false" isAbstract="false" isQuery="false" name="bios_init" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12160" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="83" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="84" value="" type="13" name="path" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="85" isRoot="false" isAbstract="false" isQuery="false" name="copy_bios" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12161" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="86" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="87" isRoot="false" isAbstract="false" isQuery="false" name="flash_bios" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12162" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="88" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="89" value="" type="13" name="path" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="90" isRoot="false" isAbstract="false" isQuery="false" name="get_bios_version" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12163" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="91" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="92" isRoot="false" isAbstract="false" isQuery="false" name="get_platform" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12164" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="93" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="94" value="" type="13" name="fullname" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+     <UML:Namespace.ownedElement>
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="17" xmi.id="160" isRoot="false" isAbstract="false" name="bios" />
+     </UML:Namespace.ownedElement>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="18" isRoot="false" isAbstract="false" name="burnin" >
+     <UML:Classifier.feature>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="95" isRoot="false" isAbstract="false" isQuery="false" name="burnin" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12165" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="96" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="97" value="" type="13" name="timeout_hours" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+     <UML:Namespace.ownedElement>
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="18" xmi.id="164" isRoot="false" isAbstract="false" name="burnin" />
+     </UML:Namespace.ownedElement>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="19" isRoot="false" isAbstract="false" name="installer" >
+     <UML:Classifier.feature>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="112" isRoot="false" isAbstract="false" isQuery="false" name="get_macaddr" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12166" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="113" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="114" isRoot="false" isAbstract="false" isQuery="false" name="lookup_machine" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12167" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="115" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="116" value="" type="13" name="installer" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="117" isRoot="false" isAbstract="false" isQuery="false" name="install" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12168" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="118" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="119" value="" type="13" name="installer" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+     <UML:Namespace.ownedElement>
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="19" xmi.id="168" isRoot="false" isAbstract="false" name="installer" />
+     </UML:Namespace.ownedElement>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="20" isRoot="false" isAbstract="false" name="remote_cmd" >
+     <UML:Classifier.feature>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="207" isRoot="false" isAbstract="false" isQuery="false" name="ping" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12169" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="208" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="209" isRoot="false" isAbstract="false" isQuery="false" name="ssh" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12170" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="210" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="211" value="" type="13" name="cmd" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="212" value="" type="13" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="213" isRoot="false" isAbstract="false" isQuery="false" name="ssh_output" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12171" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="214" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="215" value="" type="13" name="cmd" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="216" value="" type="13" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="217" isRoot="false" isAbstract="false" isQuery="false" name="scp_to" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12172" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="218" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="219" value="" type="13" name="src" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="220" value="" type="13" name="dest" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="221" value="" type="13" name="flags" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="222" isRoot="false" isAbstract="false" isQuery="false" name="rsync_to" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12173" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="223" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="224" value="" type="13" name="src" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="225" value="" type="13" name="dest" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="226" value="" type="13" name="flags" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="227" isRoot="false" isAbstract="false" isQuery="false" name="scp_from" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12174" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="228" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="229" value="" type="13" name="src" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="230" value="" type="13" name="dest" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="231" value="" type="13" name="flags" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="232" isRoot="false" isAbstract="false" isQuery="false" name="wait_for_ping" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12175" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="233" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="234" value="" type="13" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="235" isRoot="false" isAbstract="false" isQuery="false" name="wait_for_ssh" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12176" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="236" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="237" value="" type="13" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="238" isRoot="false" isAbstract="false" isQuery="false" name="wait_for_no_ssh" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12177" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="239" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="240" value="" type="13" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="241" isRoot="false" isAbstract="false" isQuery="false" name="ssh_and_monitor" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12178" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="242" value="" type="13" name="m" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="243" value="" type="13" name="cmd" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="244" value="" type="13" name="client_stdout" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="245" value="" type="13" name="client_stderr" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+     <UML:Namespace.ownedElement>
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="20" xmi.id="191" isRoot="false" isAbstract="false" name="remote_cmd" />
+     </UML:Namespace.ownedElement>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="21" isRoot="false" isAbstract="false" name="local" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="26" />
+      <UML:Generalization xmi.idref="29" />
+      <UML:Generalization xmi.idref="32" />
+      <UML:Generalization xmi.idref="161" />
+      <UML:Generalization xmi.idref="165" />
+      <UML:Generalization xmi.idref="169" />
+     </UML:GeneralizableElement.generalization>
+     <UML:Classifier.feature>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="172" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12179" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="173" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="174" isRoot="false" isAbstract="false" isQuery="false" name="local_init" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12180" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="175" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="176" value="" type="13" name="args_hash" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="177" isRoot="false" isAbstract="false" isQuery="false" name="disable_assimilator" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12181" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="178" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="179" value="" type="13" name="temporary" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+     <UML:Namespace.ownedElement>
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="21" xmi.id="183" isRoot="false" isAbstract="false" name="local" />
+     </UML:Namespace.ownedElement>
+    </UML:Class>
+    <UML:Class comment="This class deals with the installation of kernels, and rebooting" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="22" isRoot="false" isAbstract="false" name="kernel_boot" >
+     <UML:Classifier.feature>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="120" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12182" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="121" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="122" isRoot="false" isAbstract="false" isQuery="false" name="install_boottool" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12183" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="123" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="124" isRoot="false" isAbstract="false" isQuery="false" name="boottool" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12184" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="125" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="126" value="" type="13" name="cmd" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="127" value="" type="13" name="ignore_status" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="128" isRoot="false" isAbstract="false" isQuery="false" name="default_kernel" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12185" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="129" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="130" value="" type="13" name="arch" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="131" value="" type="13" name="version" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="132" isRoot="false" isAbstract="false" isQuery="false" name="install_kernel_url" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12186" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="133" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="134" value="" type="13" name="version" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="135" value="" type="13" name="label" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="136" value="" type="13" name="default" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="137" isRoot="false" isAbstract="false" isQuery="false" name="install_kernel_rpmdir" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12187" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="138" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="139" value="" type="13" name="rpmdir" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="140" value="" type="13" name="version" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="141" value="" type="13" name="label" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="142" value="" type="13" name="default" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="143" isRoot="false" isAbstract="false" isQuery="false" name="install_kernel" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12188" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="144" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="145" value="" type="13" name="rpm" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="146" value="" type="13" name="label" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="147" value="" type="13" name="default" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="148" isRoot="false" isAbstract="false" isQuery="false" name="get_lilo_default" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12189" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="149" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="150" isRoot="false" isAbstract="false" isQuery="false" name="reboot" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12190" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="151" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="152" value="" type="13" name="timeout" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="153" isRoot="false" isAbstract="false" isQuery="false" name="verify_reboot" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12191" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="154" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="155" value="" type="13" name="kernel_version" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="156" value="" type="13" name="lilo_label" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="157" value="" type="13" name="kernel_args" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="158" isRoot="false" isAbstract="false" isQuery="false" name="reset" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12192" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="159" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+     <UML:Namespace.ownedElement>
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="22" xmi.id="187" isRoot="false" isAbstract="false" name="kernel_boot" />
+     </UML:Namespace.ownedElement>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="23" isRoot="false" isAbstract="false" name="machine" >
+     <UML:GeneralizableElement.generalization>
+      <UML:Generalization xmi.idref="35" />
+      <UML:Generalization xmi.idref="38" />
+      <UML:Generalization xmi.idref="41" />
+      <UML:Generalization xmi.idref="184" />
+      <UML:Generalization xmi.idref="188" />
+      <UML:Generalization xmi.idref="192" />
+     </UML:GeneralizableElement.generalization>
+     <UML:Classifier.feature>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="195" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12193" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="196" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="197" value="" type="13" name="host" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="198" value="" type="13" name="*" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="199" isRoot="false" isAbstract="false" isQuery="false" name="check_uptime" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12194" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="200" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="201" isRoot="false" isAbstract="false" isQuery="false" name="get_arch" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12195" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="202" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="203" isRoot="false" isAbstract="false" isQuery="false" name="get_kernel_ver" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12196" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="204" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="205" isRoot="false" isAbstract="false" isQuery="false" name="get_cmdline" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12197" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="206" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="24" isRoot="false" isAbstract="false" name="autotest" >
+     <UML:Classifier.feature>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="50" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12198" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="51" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="52" value="" type="13" name="machine" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="53" value="" type="13" name="results_dir" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="54" isRoot="false" isAbstract="false" isQuery="false" name="install" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12199" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="55" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="56" isRoot="false" isAbstract="false" isQuery="false" name="get_dir" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12200" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="57" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="58" isRoot="false" isAbstract="false" isQuery="false" name="verify_machine" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12201" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="59" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="60" isRoot="false" isAbstract="false" isQuery="false" name="execute_section" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12202" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="61" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="62" value="" type="13" name="section" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="63" isRoot="false" isAbstract="false" isQuery="false" name="execute_control" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12203" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="64" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="65" value="" type="13" name="results_dir" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="66" isRoot="false" isAbstract="false" isQuery="false" name="run" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12204" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="67" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="68" value="" type="13" name="control_file" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="69" value="" type="13" name="results_dir" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="70" value="" type="13" name="type" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="25" isRoot="false" isAbstract="false" name="console" >
+     <UML:Classifier.feature>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="98" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12205" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="99" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="100" value="" type="13" name="console_name" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="101" value="" type="13" name="logfile" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="102" isRoot="false" isAbstract="false" isQuery="false" name="__del__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12206" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="103" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="104" isRoot="false" isAbstract="false" isQuery="false" name="send_cmd" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12207" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="105" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="106" value="" type="13" name="cmd" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="107" isRoot="false" isAbstract="false" isQuery="false" name="hardreset" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12208" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="108" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="109" isRoot="false" isAbstract="false" isQuery="false" name="console_log" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12209" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="110" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="111" value="" type="13" name="logfile" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="48" isRoot="false" isAbstract="false" name="subcommand" >
+     <UML:Classifier.feature>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="246" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12210" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="247" value="" type="13" name="self" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="248" value="" type="13" name="func" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="249" value="" type="13" name="args" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="250" value="" type="13" name="subdir" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="251" value="" type="13" name="tee" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="252" isRoot="false" isAbstract="false" isQuery="false" name="redirect_output" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12211" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="253" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="254" isRoot="false" isAbstract="false" isQuery="false" name="fork_start" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12212" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="255" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+      <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="256" isRoot="false" isAbstract="false" isQuery="false" name="fork_waitfor" >
+       <UML:BehavioralFeature.parameter>
+        <UML:Parameter kind="return" xmi.id="12213" type="13" />
+        <UML:Parameter isSpecification="false" visibility="private" xmi.id="257" value="" type="13" name="self" />
+       </UML:BehavioralFeature.parameter>
+      </UML:Operation>
+     </UML:Classifier.feature>
+    </UML:Class>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="7999" isRoot="false" isAbstract="false" name="asdf" />
+    <UML:Package isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="8723" isRoot="false" isAbstract="false" name="local_cmd" >
+     <UML:Namespace.ownedElement>
+      <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="8723" xmi.id="180" isRoot="false" isAbstract="false" name="cmd_result" >
+       <UML:Classifier.feature>
+        <UML:Operation comment="rc:		Integer exit code of the process
+stdout:		String containing stdout of the process
+stderr:		String containing stderr of the process
+duration:	Elapsed wall clock time running the process" isSpecification="false" isLeaf="false" visibility="public" xmi.id="181" isRoot="false" isAbstract="false" isQuery="false" name="__init__" >
+         <UML:BehavioralFeature.parameter>
+          <UML:Parameter kind="return" xmi.id="12214" type="13" />
+          <UML:Parameter isSpecification="false" visibility="private" xmi.id="182" value="" type="13" name="self" />
+         </UML:BehavioralFeature.parameter>
+        </UML:Operation>
+       </UML:Classifier.feature>
+      </UML:Class>
+     </UML:Namespace.ownedElement>
+    </UML:Package>
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="9745" isRoot="false" isAbstract="false" name="Host" />
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="9806" isRoot="false" isAbstract="false" name="RemoteHost" />
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="9867" isRoot="false" isAbstract="false" name="LocalHost" />
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="10468" isRoot="false" isAbstract="false" name="NormalRemoteHost" />
+    <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="10529" isRoot="false" isAbstract="false" name="VirtualRemoteHost" />
+    <UML:Generalization isSpecification="false" child="21" visibility="public" namespace="m1" xmi.id="26" parent="17" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="21" visibility="public" namespace="m1" xmi.id="29" parent="18" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="21" visibility="public" namespace="m1" xmi.id="32" parent="19" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="23" visibility="public" namespace="m1" xmi.id="35" parent="20" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="23" visibility="public" namespace="m1" xmi.id="38" parent="21" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="23" visibility="public" namespace="m1" xmi.id="41" parent="22" discriminator="" name="" />
+    <UML:Association isSpecification="false" visibility="public" namespace="m1" xmi.id="45" name="" >
+     <UML:Association.connection>
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="46" aggregation="aggregate" type="23" name="" />
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="47" aggregation="none" type="24" name="" />
+     </UML:Association.connection>
+    </UML:Association>
+    <UML:Generalization isSpecification="false" child="21" visibility="public" namespace="m1" xmi.id="161" parent="160" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="21" visibility="public" namespace="m1" xmi.id="165" parent="164" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="21" visibility="public" namespace="m1" xmi.id="169" parent="168" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="23" visibility="public" namespace="m1" xmi.id="184" parent="183" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="23" visibility="public" namespace="m1" xmi.id="188" parent="187" discriminator="" name="" />
+    <UML:Generalization isSpecification="false" child="23" visibility="public" namespace="m1" xmi.id="192" parent="191" discriminator="" name="" />
+    <UML:Association isSpecification="false" visibility="public" namespace="m1" xmi.id="11972" name="" >
+     <UML:Association.connection>
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="11973" aggregation="aggregate" type="24" name="" />
+      <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="11974" aggregation="none" type="23" name="" />
+     </UML:Association.connection>
+    </UML:Association>
+   </UML:Namespace.ownedElement>
+  </UML:Model>
+ </XMI.content>
+ <XMI.extensions xmi.extender="umbrello" >
+  <docsettings viewid="1" documentation="burnin(Host)" uniqueid="12214" />
+  <diagrams>
+   <diagram snapgrid="0" showattsig="1" fillcolor="#ffffc0" linewidth="0" zoom="50" showgrid="0" showopsig="1" usefillcolor="1" snapx="10" canvaswidth="2024" snapy="10" showatts="1" xmi.id="1" documentation="" type="402" showops="1" showpackage="0" name="original" localid="900000" showstereotype="0" showscope="1" snapcsgrid="0" font="DejaVu Sans,9,-1,5,50,0,0,0,0,0" linecolor="#ff0000" canvasheight="1206" >
+    <widgets>
+     <classwidget usesdiagramfillcolour="1" width="365" showattsigs="601" usesdiagramusefillcolour="1" x="273" y="140" showopsigs="601" linewidth="none" fillcolour="none" height="184" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="17" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="340" showattsigs="601" usesdiagramusefillcolour="1" x="807" y="118" showopsigs="601" linewidth="none" fillcolour="none" height="40" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="18" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="361" showattsigs="601" usesdiagramusefillcolour="1" x="1256" y="202" showopsigs="601" linewidth="none" fillcolour="none" height="72" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="19" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="602" showattsigs="601" usesdiagramusefillcolour="1" x="131" y="462" showopsigs="601" linewidth="none" fillcolour="none" height="184" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="20" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="393" showattsigs="601" usesdiagramusefillcolour="1" x="796" y="409" showopsigs="601" linewidth="none" fillcolour="none" height="72" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="21" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="665" showattsigs="601" usesdiagramusefillcolour="1" x="1226" y="446" showopsigs="601" linewidth="none" fillcolour="none" height="200" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="22" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="343" showattsigs="601" usesdiagramusefillcolour="1" x="817" y="762" showopsigs="601" linewidth="none" fillcolour="none" height="104" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="23" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="503" showattsigs="601" usesdiagramusefillcolour="1" x="1277" y="772" showopsigs="601" linewidth="none" fillcolour="none" height="136" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="24" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="436" showattsigs="601" usesdiagramusefillcolour="1" x="272" y="1074" showopsigs="601" linewidth="none" fillcolour="none" height="104" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="25" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+     <classwidget usesdiagramfillcolour="1" width="536" showattsigs="601" usesdiagramusefillcolour="1" x="216" y="919" showopsigs="601" linewidth="none" fillcolour="none" height="88" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="48" showoperations="1" showpackage="0" showscope="1" font="DejaVu Sans,9,-1,5,75,0,0,0,0,0" linecolor="none" />
+    </widgets>
+    <messages/>
+    <associations>
+     <assocwidget totalcounta="4" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="17" widgetaid="21" xmi.id="26" linecolor="none" >
+      <linepath>
+       <startpoint startx="796" starty="409" />
+       <endpoint endx="638" endy="324" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="4" indexa="2" totalcountb="2" indexb="1" linewidth="none" widgetbid="18" widgetaid="21" xmi.id="29" linecolor="none" >
+      <linepath>
+       <startpoint startx="962" starty="409" />
+       <endpoint endx="962" endy="158" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="4" indexa="3" totalcountb="2" indexb="1" linewidth="none" widgetbid="19" widgetaid="21" xmi.id="32" linecolor="none" >
+      <linepath>
+       <startpoint startx="1189" starty="409" />
+       <endpoint endx="1256" endy="274" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="4" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="20" widgetaid="23" xmi.id="35" linecolor="none" >
+      <linepath>
+       <startpoint startx="817" starty="762" />
+       <endpoint endx="733" endy="646" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="4" indexa="2" totalcountb="2" indexb="1" linewidth="none" widgetbid="21" widgetaid="23" xmi.id="38" linecolor="none" >
+      <linepath>
+       <startpoint startx="972" starty="762" />
+       <endpoint endx="972" endy="481" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="4" indexa="3" totalcountb="2" indexb="1" linewidth="none" widgetbid="22" widgetaid="23" xmi.id="41" linecolor="none" >
+      <linepath>
+       <startpoint startx="1160" starty="762" />
+       <endpoint endx="1226" endy="646" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="23" widgetaid="24" xmi.id="11972" linecolor="none" >
+      <linepath>
+       <startpoint startx="1277" starty="772" />
+       <endpoint endx="1160" endy="772" />
+      </linepath>
+     </assocwidget>
+    </associations>
+   </diagram>
+  </diagrams>
+  <listview>
+   <listitem open="1" type="800" label="Views" >
+    <listitem open="1" type="801" label="Logical View" >
+     <listitem open="1" type="813" id="9745" />
+     <listitem open="1" type="813" id="9867" />
+     <listitem open="1" type="813" id="10468" />
+     <listitem open="1" type="813" id="9806" />
+     <listitem open="1" type="813" id="10529" />
+     <listitem open="0" type="813" id="7999" />
+     <listitem open="1" type="813" id="24" >
+      <listitem open="0" type="815" id="50" />
+      <listitem open="0" type="815" id="54" />
+      <listitem open="0" type="815" id="56" />
+      <listitem open="0" type="815" id="58" />
+      <listitem open="0" type="815" id="60" />
+      <listitem open="0" type="815" id="63" />
+      <listitem open="0" type="815" id="66" />
+     </listitem>
+     <listitem open="1" type="813" id="17" >
+      <listitem open="0" type="813" id="160" />
+      <listitem open="0" type="815" id="71" />
+      <listitem open="0" type="815" id="73" />
+      <listitem open="0" type="815" id="76" />
+      <listitem open="0" type="815" id="78" />
+      <listitem open="0" type="815" id="80" />
+      <listitem open="0" type="815" id="82" />
+      <listitem open="0" type="815" id="85" />
+      <listitem open="0" type="815" id="87" />
+      <listitem open="0" type="815" id="90" />
+      <listitem open="0" type="815" id="92" />
+     </listitem>
+     <listitem open="1" type="813" id="18" >
+      <listitem open="0" type="813" id="164" />
+      <listitem open="0" type="815" id="95" />
+     </listitem>
+     <listitem open="1" type="813" id="25" >
+      <listitem open="0" type="815" id="98" />
+      <listitem open="0" type="815" id="102" />
+      <listitem open="0" type="815" id="104" />
+      <listitem open="0" type="815" id="107" />
+      <listitem open="0" type="815" id="109" />
+     </listitem>
+     <listitem open="1" type="813" id="19" >
+      <listitem open="0" type="813" id="168" />
+      <listitem open="0" type="815" id="112" />
+      <listitem open="0" type="815" id="114" />
+      <listitem open="0" type="815" id="117" />
+     </listitem>
+     <listitem open="1" type="813" id="22" >
+      <listitem open="0" type="813" id="187" />
+      <listitem open="0" type="815" id="120" />
+      <listitem open="0" type="815" id="122" />
+      <listitem open="0" type="815" id="124" />
+      <listitem open="0" type="815" id="128" />
+      <listitem open="0" type="815" id="132" />
+      <listitem open="0" type="815" id="137" />
+      <listitem open="0" type="815" id="143" />
+      <listitem open="0" type="815" id="148" />
+      <listitem open="0" type="815" id="150" />
+      <listitem open="0" type="815" id="153" />
+      <listitem open="0" type="815" id="158" />
+     </listitem>
+     <listitem open="1" type="813" id="21" >
+      <listitem open="0" type="813" id="183" />
+      <listitem open="0" type="815" id="172" />
+      <listitem open="0" type="815" id="174" />
+      <listitem open="0" type="815" id="177" />
+     </listitem>
+     <listitem open="1" type="813" id="23" >
+      <listitem open="0" type="815" id="195" />
+      <listitem open="0" type="815" id="199" />
+      <listitem open="0" type="815" id="201" />
+      <listitem open="0" type="815" id="203" />
+      <listitem open="0" type="815" id="205" />
+     </listitem>
+     <listitem open="1" type="813" id="20" >
+      <listitem open="0" type="813" id="191" />
+      <listitem open="0" type="815" id="207" />
+      <listitem open="0" type="815" id="209" />
+      <listitem open="0" type="815" id="213" />
+      <listitem open="0" type="815" id="217" />
+      <listitem open="0" type="815" id="222" />
+      <listitem open="0" type="815" id="227" />
+      <listitem open="0" type="815" id="232" />
+      <listitem open="0" type="815" id="235" />
+      <listitem open="0" type="815" id="238" />
+      <listitem open="0" type="815" id="241" />
+     </listitem>
+     <listitem open="1" type="813" id="48" >
+      <listitem open="0" type="815" id="246" />
+      <listitem open="0" type="815" id="252" />
+      <listitem open="0" type="815" id="254" />
+      <listitem open="0" type="815" id="256" />
+     </listitem>
+     <listitem open="1" type="818" id="8723" >
+      <listitem open="0" type="813" id="180" >
+       <listitem open="0" type="815" id="181" />
+      </listitem>
+     </listitem>
+     <listitem open="0" type="830" label="Datatypes" >
+      <listitem open="1" type="829" id="5" />
+      <listitem open="1" type="829" id="4" />
+      <listitem open="1" type="829" id="7" />
+      <listitem open="1" type="829" id="6" />
+      <listitem open="1" type="829" id="2" />
+      <listitem open="1" type="829" id="9" />
+      <listitem open="1" type="829" id="8" />
+      <listitem open="1" type="829" id="13" />
+      <listitem open="1" type="829" id="10" />
+      <listitem open="1" type="829" id="12" />
+      <listitem open="1" type="829" id="11" />
+     </listitem>
+    </listitem>
+    <listitem open="1" type="802" label="Use Case View" />
+    <listitem open="1" type="821" label="Component View" />
+    <listitem open="1" type="827" label="Deployment View" />
+    <listitem open="1" type="836" label="Entity Relationship Model" />
+   </listitem>
+  </listview>
+  <codegeneration>
+   <codegenerator language="Python" />
+  </codegeneration>
+ </XMI.extensions>
+</XMI>
diff --git a/server/errors.py b/server/errors.py
new file mode 100644
index 0000000..6f88cdf
--- /dev/null
+++ b/server/errors.py
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""Exceptions deliberatly thrown by autoserv
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+class AutoservError(Exception):
+	pass
+
+class AutoservRunError(AutoservError):
+	"""Errors raised by one of the run functions"""
+	pass
+
+class AutoservVirtError(AutoservError):
+	"""Vitualization related error"""
+	pass
diff --git a/server/hosts/__init__.py b/server/hosts/__init__.py
new file mode 100644
index 0000000..1b40526
--- /dev/null
+++ b/server/hosts/__init__.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This is a convenience module to import all available types of hosts.
+
+Implementation details:
+You should 'import hosts' instead of importing every available host module.
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+# host abstract classes
+from base_classes import Host
+from base_classes import SiteHost
+from base_classes import RemoteHost
+
+# host implementation classes
+from ssh_host import SSHHost
+from conmux_ssh_host import ConmuxSSHHost
+from guest import Guest
+from kvm_guest import KVMGuest
+
+# bootloader classes
+from bootloader import Bootloader
+from lilo import Lilo
+from grub import Grub
+
+# command result class
+from base_classes import CmdResult
diff --git a/server/hosts/base_classes.py b/server/hosts/base_classes.py
new file mode 100644
index 0000000..dac153a
--- /dev/null
+++ b/server/hosts/base_classes.py
@@ -0,0 +1,149 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the base classes for the Host hierarchy.
+
+Implementation details:
+You should import the "hosts" package instead of importing each type of host.
+
+	Host: a machine on which you can run programs
+	RemoteHost: a remote machine on which you can run programs
+	CmdResult: contain the results of a Host.run() command execution
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+import time
+import textwrap
+
+
+class Host(object):
+	"""This class represents a machine on which you can run programs.
+	
+	It may be a local machine, the one autoserv is running on, a remote 
+	machine or a virtual machine.
+	
+	Implementation details:
+	This is an abstract class, leaf subclasses must implement the methods
+	listed here. You must not instantiate this class but should 
+	instantiate one of those leaf subclasses."""
+	
+	bootloader = None
+	
+	def __init__(self):
+		super(Host, self).__init__()
+	
+	def run(self, command):
+		pass
+	
+	def reboot(self):
+		pass
+	
+	def get_file(self, source, dest):
+		pass
+	
+	def send_file(self, source, dest):
+		pass
+	
+	def get_tmp_dir(self):
+		pass
+	
+	def is_up(self):
+		pass
+	
+	def wait_up(self, timeout):
+		pass
+	
+	def wait_down(self, timeout):
+		pass
+	
+	def get_num_cpu(self):
+		pass
+	
+	def install(self, installableObject):
+		installableObject.install(self)
+
+
+# site_host.py may be non-existant or empty, make sure that an appropriate 
+# SiteHost class is created nevertheless
+try:
+	from site_host import SiteHost
+except ImportError:
+	pass
+
+if not "SiteHost" in dir():
+	class SiteHost(Host):
+		def __init__(self):
+			super(SiteHost, self).__init__()
+
+
+class RemoteHost(SiteHost):
+	"""This class represents a remote machine on which you can run 
+	programs.
+	
+	It may be accessed through a network, a serial line, ...
+	It is not the machine autoserv is running on.
+	
+	Implementation details:
+	This is an abstract class, leaf subclasses must implement the methods
+	listed here and in parent classes which have no implementation. They 
+	may reimplement methods which already have an implementation. You 
+	must not instantiate this class but should instantiate one of those 
+	leaf subclasses."""
+	
+	hostname= None
+	
+	def __init__(self):
+		super(RemoteHost, self).__init__()
+
+
+class CmdResult(object):
+	"""
+	Command execution result.
+	
+	Modified from the original Autoserv code, local_cmd.py:
+		Copyright [email protected] (Jonathan Mayer),
+		[email protected]   (Martin J. Bligh)
+		Released under the GPL, v2
+	
+	command: String containing the command line itself
+	exit_status: Integer exit code of the process
+	stdout: String containing stdout of the process
+	stderr: String containing stderr of the process
+	duration: Elapsed wall clock time running the process
+	aborted: Signal that caused the command to terminate (0 if none)
+	"""
+	
+	def __init__(self):
+		super(CmdResult, self).__init__()
+		self.command = ""
+		self.exit_status = None
+		self.stdout = ""
+		self.stderr = ""
+		self.duration = 0
+		self.aborted= False
+	
+	def __repr__(self):
+		wrapper= textwrap.TextWrapper(width=78, 
+			initial_indent="\n    ", subsequent_indent="    ")
+		
+		stdout= self.stdout.rstrip(" \n")
+		if stdout:
+			stdout= "\nStdout:\n%s" % (stdout,)
+		
+		stderr= self.stderr.rstrip(" \n")
+		if stderr:
+			stderr= "\nStderr:\n%s" % (stderr,)
+		
+		return ("* Command: %s\n"
+			"Exit status: %s\n"
+			"Duration: %s\n"
+			"Aborted: %s"
+			"%s"
+			"%s"
+			% (wrapper.fill(self.command), self.exit_status, 
+			self.duration, self.aborted, stdout, stderr))
diff --git a/server/hosts/bootloader.py b/server/hosts/bootloader.py
new file mode 100644
index 0000000..eeaa5fb
--- /dev/null
+++ b/server/hosts/bootloader.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the Bootloader class.
+
+	Bootloader: a program to boot Kernels on a Host.
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+class Bootloader(object):
+	"""This class represents a bootloader.
+	
+	It can be used to add a kernel to the list of kernels that can be 
+	booted by a bootloader. It can also make sure that this kernel will 
+	be the one chosen at next reboot.
+	
+	Implementation details:
+	This is an abstract class, leaf subclasses must implement the methods
+	listed here. You must not instantiate this class but should 
+	instantiate one of those leaf subclasses."""
+	
+	host = None
+	
+	def add_entry(self, name, image, initrd, root, options, default=True):
+		pass
+	
+	def remove_entry(self, name):
+		pass
diff --git a/server/hosts/conmux_ssh_host.py b/server/hosts/conmux_ssh_host.py
new file mode 100644
index 0000000..0cf1ad3
--- /dev/null
+++ b/server/hosts/conmux_ssh_host.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the ConmuxSSHHost
+
+Implementation details:
+You should import the "hosts" package instead of importing each type of host.
+
+	ConmuxSSHHost: a remote machine controlled through a serial console
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+import os
+import os.path
+import signal
+import subprocess
+
+import ssh_host
+
+class ConmuxSSHHost(ssh_host.SSHHost):
+	"""This class represents a remote machine controlled through a serial 
+	console on which you can run programs. It is not the machine autoserv 
+	is running on.
+	
+	For a machine controlled in this way, it may be possible to support 
+	hard reset, boot strap monitoring or other operations not possible 
+	on a machine controlled through ssh, telnet, ..."""
+	
+	def __init__(self,
+		     hostname,
+		     logfilename=None,
+		     server='localhost',
+		     attach='/usr/local/conmux/bin/conmux-attach'):
+		super(ConmuxSSHHost, self).__init__(hostname)
+		self.server = server
+		self.attach = attach
+		self.pid = None
+		self.__start_console_log(logfilename)
+
+	
+	def hardreset(self):
+		"""
+		Reach out and slap the box in the power switch
+		"""
+		self.__console_run(r"'~$hardreset'")
+
+
+	def __start_console_log(self, logfilename):
+		"""
+		Log the output of the console session to a specified file
+		"""
+		if not os.path.exists(self.attach):
+			return
+		cmd = [self.attach, '%s/%s' % (self.server, self.hostname), \
+						'cat - > %s' % logfilename ]
+		self.pid = subprocess.Popen(cmd).pid
+
+
+	def __console_run(self, cmd):
+		"""
+		Send a command to the conmux session
+		"""
+		cmd = '%s %s/%s echo %s' % (self.attach,
+					    self.server,
+					    self.hostname,
+					    cmd)
+		os.system(cmd)
+
+
+	def __del__(self):
+		if self.pid:
+			os.kill(self.pid, signal.SIGTERM)
+		super(ConmuxSSHHost, self).__del__()
+		
diff --git a/server/hosts/grub.py b/server/hosts/grub.py
new file mode 100644
index 0000000..39ab0dd
--- /dev/null
+++ b/server/hosts/grub.py
@@ -0,0 +1,34 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the Grub class.
+
+Implementation details:
+You should import the "hosts" package instead of importing this module directly.
+
+	Grub: a particular Bootloader
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+import bootloader
+
+
+class Grub(bootloader.Bootloader):
+	"""This class represents the GRUB bootloader.
+	
+	It can be used to add a kernel to the list of kernels that can be 
+	booted. It can also make sure that this kernel will be the one 
+	chosen at next reboot.
+	
+	Implementation details:
+	This is a leaf class in an abstract class hierarchy, it must 
+	implement the unimplemented methods in parent classes.
+	"""
+	
+	pass
+	
diff --git a/server/hosts/guest.py b/server/hosts/guest.py
new file mode 100644
index 0000000..9f4d89c
--- /dev/null
+++ b/server/hosts/guest.py
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the Guest class in the Host hierarchy.
+
+Implementation details:
+You should import the "hosts" package instead of importing each type of host.
+
+	Guest: a virtual machine on which you can run programs
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+import ssh_host
+
+
+class Guest(ssh_host.SSHHost):
+	"""This class represents a virtual machine on which you can run 
+	programs.
+	
+	It is not the machine autoserv is running on.
+	
+	Implementation details:
+	This is an abstract class, leaf subclasses must implement the methods
+	listed here and in parent classes which have no implementation. They 
+	may reimplement methods which already have an implementation. You 
+	must not instantiate this class but should instantiate one of those 
+	leaf subclasses."""
+	
+	controllingHypervisor = None
+	
+	def __init__(self, controllingHypervisor):
+		"""Construct a Guest object
+		
+		Args:
+			controllingHypervisor: Hypervisor object that is 
+				responsible for the creation and management of this 
+				guest
+			hostname: network hostname or address of virtual machine
+		"""
+		hostname= controllingHypervisor.new_guest()
+		super(Guest, self).__init__(hostname)
+		self.controllingHypervisor= controllingHypervisor
+	
+	def __del__(self):
+		"""Destroy a Guest object
+		"""
+		self.controllingHypervisor.delete_guest(self.hostname)
+	
+	def hardreset(self):
+		"""Perform a "hardreset" of the guest.
+		
+		It is restarted through the hypervisor. That will restart it 
+		even if the guest otherwise innaccessible through ssh.
+		"""
+		return self.controllingHypervisor.reset_guest(self.name)
+
diff --git a/server/hosts/kvm_guest.py b/server/hosts/kvm_guest.py
new file mode 100644
index 0000000..ca120f9
--- /dev/null
+++ b/server/hosts/kvm_guest.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the Host class.
+
+Implementation details:
+You should import the "hosts" package instead of importing each type of host.
+
+	KVMGuest: a KVM virtual machine on which you can run programs
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+import guest
+
+
+class KVMGuest(guest.Guest):
+	"""This class represents a KVM virtual machine on which you can run 
+	programs.
+	
+	Implementation details:
+	This is a leaf class in an abstract class hierarchy, it must 
+	implement the unimplemented methods in parent classes.
+	"""
+	
+	pass
diff --git a/server/hosts/lilo.py b/server/hosts/lilo.py
new file mode 100644
index 0000000..9560384
--- /dev/null
+++ b/server/hosts/lilo.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the Lilo class.
+
+Implementation details:
+You should import the "hosts" package instead of importing this module directly.
+
+	Lilo: a particular Bootloader
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+import bootloader
+
+
+class Lilo(bootloader.Bootloader):
+	"""This class represents the Lilo bootloader.
+	
+	It can be used to add a kernel to the list of kernels that can be 
+	booted. It can also make sure that this kernel will be the one 
+	chosen at next reboot.
+	
+	Implementation details:
+	This is a leaf class in an abstract class hierarchy, it must 
+	implement the unimplemented methods in parent classes.
+	"""
+	
+	pass
diff --git a/server/hosts/site_host.py b/server/hosts/site_host.py
new file mode 100644
index 0000000..d5ebfc7
--- /dev/null
+++ b/server/hosts/site_host.py
@@ -0,0 +1,35 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the SiteHost class.
+
+This file may be removed or left empty if no site customization is neccessary.
+base_classes.py contains logic to provision for this.
+
+Implementation details:
+You should import the "hosts" package instead of importing each type of host.
+
+	SiteHost: Host containing site-specific customizations.
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+import base_classes
+
+
+class SiteHost(base_classes.Host):
+	"""Custom host to containing site-specific methods or attributes.
+	"""
+	
+	def __init__(self):
+		super(SiteHost, self).__init__()
+	
+	#def get_platform(self):
+		#...
+	
+	#def get_bios_version(self):
+		#...
diff --git a/server/hosts/ssh_host.py b/server/hosts/ssh_host.py
new file mode 100644
index 0000000..eb4a301
--- /dev/null
+++ b/server/hosts/ssh_host.py
@@ -0,0 +1,301 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the SSHHost class.
+
+Implementation details:
+You should import the "hosts" package instead of importing each type of host.
+
+	SSHHost: a remote machine with a ssh access
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+import types
+import os
+import time
+
+import base_classes
+import utils
+import errors
+
+
+class SSHHost(base_classes.RemoteHost):
+	"""This class represents a remote machine controlled through an ssh 
+	session on which you can run programs.
+	
+	It is not the machine autoserv is running on. The machine must be 
+	configured for password-less login, for example through public key 
+	authentication.
+	
+	Implementation details:
+	This is a leaf class in an abstract class hierarchy, it must 
+	implement the unimplemented methods in parent classes.
+	"""
+	
+	def __init__(self, hostname, user="root", port=22):
+		"""Construct a SSHHost object
+		
+		Args:
+			hostname: network hostname or address of remote machine
+			user: user to log in as on the remote machine
+			port: port the ssh daemon is listening on on the remote 
+				machine
+		"""
+		super(SSHHost, self).__init__()
+		
+		self.hostname= hostname
+		self.user= user
+		self.port= port
+		self.tmp_dirs= []
+	
+	def __del__(self):
+		"""Destroy a SSHHost object
+		"""
+		for dir in self.tmp_dirs:
+			try:
+				self.run('rm -rf "%s"' % (utils.sh_escape(dir)))
+			except errors.AutoservRunError:
+				pass
+	
+	def run(self, command, timeout=None):
+		"""Run a command on the remote host.
+		
+		Args:
+			command: the command line string
+			timeout: time limit in seconds before attempting to 
+				kill the running process. The run() function
+				will take a few seconds longer than 'timeout'
+				to complete if it has to kill the process.
+		
+		Returns:
+			a hosts.base_classes.CmdResult object
+		
+		Raises:
+			AutoservRunError: the exit code of the command 
+				execution was not 0
+		"""
+		#~ print "running %s" % (command,)
+		result= utils.run(r'ssh -l %s -p %d %s "%s"' % (self.user, 
+			self.port, self.hostname, utils.sh_escape(command)), 
+			timeout)
+		return result
+	
+	def reboot(self):
+		"""Reboot the remote host.
+		
+		TODO(poirier): Should the function return only after having 
+			done a self.wait_down()? or should this be left to 
+			the control file?
+			pro: A common usage pattern would be reboot(), 
+			wait_down(), wait_up(), [more commands]. If wait_down() 
+			is not there, wait_up() is likely to return right away 
+			because the ssh daemon has not yet shutdown, so a 
+			control file expecting the host to have rebooted will 
+			run eronously. Doing the wait_down() in reboot 
+			eliminates the risk of confusion. Also, making the 
+			wait_down() external might lead to race conditions if 
+			the control file does a reboot() does some other things, 
+			then there's no way to know if it should wait_down() 
+			first or wait_up() right away.
+			con: wait_down() just after reboot will be mandatory, 
+			this might be undesirable if there are other operations 
+			that can be executed right after the reboot, for 
+			example many hosts have to be rebooted at the same 
+			time. The solution to this is to use multiple
+			threads of execution in the control file.
+		"""
+		self.run("reboot")
+		self.wait_down()
+	
+	def get_file(self, source, dest):
+		"""Copy files from the remote host to a local path.
+		
+		Directories will be copied recursively.
+		If a source component is a directory with a trailing slash, 
+		the content of the directory will be copied, otherwise, the 
+		directory itself and its content will be copied. This 
+		behavior is similar to that of the program 'rsync'.
+		
+		Args:
+			source: either
+				1) a single file or directory, as a string
+				2) a list of one or more (possibly mixed) 
+					files or directories
+			dest: a file or a directory (if source contains a 
+				directory or more than one element, you must 
+				supply a directory dest)
+		
+		Raises:
+			AutoservRunError: the scp command failed
+		"""
+		if isinstance(source, types.StringTypes):
+			source= [source]
+		
+		processed_source= []
+		for entry in source:
+			if entry.endswith('/'):
+				format_string= '%s@%s:"%s*"'
+			else:
+				format_string= '%s@%s:"%s"'
+			entry= format_string % (self.user, self.hostname, 
+				utils.scp_remote_escape(entry))
+			processed_source.append(entry)
+		
+		processed_dest= os.path.abspath(dest)
+		if os.path.isdir(dest):
+			processed_dest= "%s/" % (utils.sh_escape(processed_dest),)
+		else:
+			processed_dest= utils.sh_escape(processed_dest)
+		
+		utils.run('scp -rpq %s "%s"' % (
+			" ".join(processed_source), 
+			processed_dest))
+	
+	def send_file(self, source, dest):
+		"""Copy files from a local path to the remote host.
+		
+		Directories will be copied recursively.
+		If a source component is a directory with a trailing slash, 
+		the content of the directory will be copied, otherwise, the 
+		directory itself and its content will be copied. This 
+		behavior is similar to that of the program 'rsync'.
+		
+		Args:
+			source: either
+				1) a single file or directory, as a string
+				2) a list of one or more (possibly mixed) 
+					files or directories
+			dest: a file or a directory (if source contains a 
+				directory or more than one element, you must 
+				supply a directory dest)
+		
+		Raises:
+			AutoservRunError: the scp command failed
+		"""
+		if isinstance(source, types.StringTypes):
+			source= [source]
+		
+		processed_source= []
+		for entry in source:
+			if entry.endswith('/'):
+				format_string= '"%s/"*'
+			else:
+				format_string= '"%s"'
+			entry= format_string % (utils.sh_escape(os.path.abspath(entry)),)
+			processed_source.append(entry)
+		
+		utils.run('scp -rpq %s %s@%s:"%s"' % (
+			" ".join(processed_source), self.user, self.hostname, 
+			utils.scp_remote_escape(dest)))
+	
+	def get_tmp_dir(self):
+		"""Return the pathname of a directory on the host suitable 
+		for temporary file storage.
+		
+		The directory and its content will be deleted automatically
+		on the destruction of the Host object that was used to obtain
+		it.
+		"""
+		dir_name= self.run("mktemp -dt autoserv-XXXXXX").stdout.rstrip(" \n")
+		self.tmp_dirs.append(dir_name)
+		return dir_name
+	
+	def is_up(self):
+		"""Check if the remote host is up.
+		
+		Returns:
+			True if the remote host is up, False otherwise
+		"""
+		try:
+			result= self.run("true", timeout=10)
+		except errors.AutoservRunError:
+			return False
+		else:
+			if result.exit_status == 0:
+				return True
+			else:
+				return False
+	
+	def wait_up(self, timeout=None):
+		"""Wait until the remote host is up or the timeout expires.
+		
+		In fact, it will wait until an ssh connection to the remote 
+		host can be established.
+		
+		Args:
+			timeout: time limit in seconds before returning even
+				if the host is not up.
+		
+		Returns:
+			True if the host was found to be up, False otherwise
+		"""
+		if timeout:
+			end_time= time.time() + timeout
+		
+		while not timeout or time.time() < end_time:
+			try:
+				if timeout:
+					run_timeout= end_time - time.time()
+				else:
+					run_timeout= 10
+				result= self.run("true", timeout=run_timeout)
+			except errors.AutoservRunError:
+				pass
+			else:
+				if result.exit_status == 0:
+					return True
+			time.sleep(1)
+		
+		return False
+	
+	def wait_down(self, timeout=None):
+		"""Wait until the remote host is down or the timeout expires.
+		
+		In fact, it will wait until an ssh connection to the remote 
+		host fails.
+		
+		Args:
+			timeout: time limit in seconds before returning even
+				if the host is not up.
+		
+		Returns:
+			True if the host was found to be down, False otherwise
+		"""
+		if timeout:
+			end_time= time.time() + timeout
+		
+		while not timeout or time.time() < end_time:
+			try:
+				if timeout:
+					run_timeout= end_time - time.time()
+				else:
+					run_timeout= 10
+				result= self.run("true", timeout=run_timeout)
+			except errors.AutoservRunError:
+				return True
+			else:
+				if result.aborted:
+					return True
+			time.sleep(1)
+		
+		return False
+	
+	def get_num_cpu(self):
+		"""Get the number of CPUs in the host according to 
+		/proc/cpuinfo.
+		
+		Returns:
+			The number of CPUs
+		"""
+		
+		proc_cpuinfo= self.run("cat /proc/cpuinfo").stdout
+		cpus = 0
+		for line in proc_cpuinfo.splitlines():
+			if line.startswith('processor'):
+				cpus += 1
+		return cpus
diff --git a/server/hypervisor.py b/server/hypervisor.py
new file mode 100644
index 0000000..7e2beb8
--- /dev/null
+++ b/server/hypervisor.py
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the Hypervisor class
+
+	Hypervisor: a virtual machine monitor
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+import installable_object
+
+
+class Hypervisor(installable_object.InstallableObject):
+	"""This class represents a virtual machine monitor.
+	
+	Implementation details:
+	This is an abstract class, leaf subclasses must implement the methods
+	listed here and in parent classes which have no implementation. They 
+	may reimplement methods which already have an implementation. You 
+	must not instantiate this class but should instantiate one of those 
+	leaf subclasses."""
+	
+	host = None
+	guests = None
+	
+	def __init__(self, host):
+		super(Hypervisor, self).__init__()
+		self.host= host
+	
+	def new_guest(self):
+		pass
+	
+	def delete_guest(self, name):
+		pass
+	
+	def reset_guest(self, guest_name):
+		pass
diff --git a/server/installable_object.py b/server/installable_object.py
new file mode 100644
index 0000000..0874e4b
--- /dev/null
+++ b/server/installable_object.py
@@ -0,0 +1,47 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the InstallableObject class
+
+	InstallableObject: a software package that can be installed on a Host
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+import utils
+
+
+class InstallableObject(object):
+	"""This class represents a software package that can be installed on 
+	a Host.
+	
+	Implementation details:
+	This is an abstract class, leaf subclasses must implement the methods
+	listed here. You must not instantiate this class but should 
+	instantiate one of those leaf subclasses."""
+	
+	source_material= None
+	
+	def __init__(self):
+		super(InstallableObject, self).__init__()
+	
+	def get(self, location):
+		"""Get the source material required to install the object.
+		
+		Through the utils.get() function, the argument passed will be 
+		saved in a temporary location on the LocalHost. That location 
+		is saved in the source_material attribute.
+		
+		Args:
+			location: the path to the source material. This path
+				may be of any type that the utils.get() 
+				function will accept.
+		"""
+		self.source_material= utils.get(location)
+	
+	def install(self, host):
+		pass
diff --git a/server/kernel.py b/server/kernel.py
new file mode 100644
index 0000000..db6762a
--- /dev/null
+++ b/server/kernel.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the Kernel class
+
+	Kernel: an os kernel
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+import installable_object
+
+
+class Kernel(installable_object.InstallableObject):
+	"""This class represents a kernel.
+	
+	It is used to obtain a built kernel or create one from source and 
+	install it on a Host.
+	
+	Implementation details:
+	This is an abstract class, leaf subclasses must implement the methods
+	listed here and in parent classes which have no implementation. They 
+	may reimplement methods which already have an implementation. You 
+	must not instantiate this class but should instantiate one of those 
+	leaf subclasses."""
+	
+	pass
diff --git a/server/kvm.py b/server/kvm.py
new file mode 100644
index 0000000..24d452b
--- /dev/null
+++ b/server/kvm.py
@@ -0,0 +1,296 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the KVM class
+
+	KVM: a KVM virtual machine monitor
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+import os
+
+import hypervisor
+import errors
+import utils
+import hosts
+
+
+class KVM(hypervisor.Hypervisor):
+	"""This class represents a KVM virtual machine monitor.
+	
+	Implementation details:
+	This is a leaf class in an abstract class hierarchy, it must 
+	implement the unimplemented methods in parent classes.
+	"""
+	
+	build_dir= None
+	pid_dir= None
+	support_dir= None
+	addresses= []
+	qemu_ifup_script= (
+		"#!/bin/sh\n"
+		"# $1 is the name of the new qemu tap interface\n"
+		"\n"
+		"ifconfig $1 0.0.0.0 promisc up\n"
+		"brctl addif br0 $1\n")
+	check_process_script= (
+		'if [ -f "%(pid_file_name)s" ]\n'
+		'then\n'
+		'	pid=$(cat "%(pid_file_name)s")\n'
+		'	if [ -L /proc/$pid/exe ] && stat /proc/$pid/exe | \n'
+		'		grep -q --  "-> \`%(qemu_binary)s\'\$"\n'
+		'	then\n'
+		'		echo "process present"\n'
+		'	else\n'
+		'		rm "%(pid_file_name)s"\n'
+		'	fi\n'
+		'fi')
+	
+	def __del__(self):
+		"""Destroy a KVM object.
+		
+		Guests managed by this hypervisor that are still running will 
+		be killed.
+		"""
+		self.deinitialize()
+
+	def install(self, addresses):
+		"""Compile the kvm software on the host that the object was 
+		initialized with.
+		
+		The kvm kernel modules are compiled, for this, the kernel
+		sources must be available. A custom qemu is also compiled.
+		Note that 'make install' is not run, the kernel modules and 
+		qemu are run from where they were built, therefore not 
+		conflicting with what might already be installed.
+		
+		Args:
+			addresses: a list of dict entries of the form 
+				{"mac" : "xx:xx:xx:xx:xx:xx", 
+				"ip" : "yyy.yyy.yyy.yyy"} where x and y 
+				are replaced with sensible values. The ip 
+				address may be a hostname or an IPv6 instead.
+				
+				When a new virtual machine is created, the 
+				first available entry in that list will be 
+				used. The network card in the virtual machine 
+				will be assigned the specified mac address and
+				autoserv will use the specified ip address to 
+				connect to the virtual host via ssh. The virtual
+				machine os must therefore be configured to 
+				configure its network with the ip corresponding 
+				to the mac.
+		
+		TODO(poirier): check dependencies before building
+		kvm needs:
+		libasound2-dev
+		libsdl1.2-dev (or configure qemu with --disable-gfx-check, how?)
+		"""
+		self.addresses= [
+			{"mac" : address["mac"], 
+			"ip" : address["ip"],
+			"is_used" : False} for address in addresses]
+		
+		self.build_dir = self.host.get_tmp_dir()
+		self.support_dir= self.host.get_tmp_dir()
+		
+		self.host.run('echo "%s" > "%s"' % (
+			utils.sh_escape(self.qemu_ifup_script),
+			utils.sh_escape(os.path.join(self.support_dir, 
+				"qemu-ifup.sh")),))
+		self.host.run('chmod a+x "%s"' % (
+			utils.sh_escape(os.path.join(self.support_dir, 
+				"qemu-ifup.sh")),))
+		
+		self.host.send_file(self.source_material, self.build_dir)
+		source_material= os.path.join(self.build_dir, 
+				os.path.basename(self.source_material))
+		
+		# uncompress
+		if (source_material.endswith(".gz") or 
+			source_material.endswith(".gzip")):
+			self.host.run('gunzip "%s"' % (utils.sh_escape(
+				source_material)))
+			source_material= ".".join(
+				source_material.split(".")[:-1])
+		elif source_material.endswith("bz2"):
+			self.host.run('bunzip2 "%s"' % (utils.sh_escape(
+				source_material)))
+			source_material= ".".join(
+				source_material.split(".")[:-1])
+		
+		# untar
+		if source_material.endswith(".tar"):
+			result= self.host.run('tar -xvf "%s" | head -1' % (
+				utils.sh_escape(source_material)))
+			source_material += result.stdout.strip("\n")
+			self.build_dir= source_material
+		
+		# build
+		try:
+			self.host.run('make -C "%s" clean' % (
+				utils.sh_escape(self.build_dir),))
+		except errors.AutoservRunError:
+			pass
+		self.host.run('cd "%s" && ./configure' % (
+			utils.sh_escape(self.build_dir),))
+		self.host.run('make -j%d -C "%s"' % (
+			self.host.get_num_cpu() * 2, 
+			utils.sh_escape(self.build_dir),))
+		
+		self.initialize()
+	
+	def initialize(self):
+		"""Initialize the hypervisor.
+		
+		Loads needed kernel modules and creates temporary directories.
+		The logic is that you could compile once and 
+		initialize - deinitialize many times. But why you would do that
+		has yet to be figured.
+		
+		TODO(poirier): check processor type and support for vm 
+			extensions before loading kvm-intel
+		"""
+		self.pid_dir= self.host.get_tmp_dir()
+		
+		self.host.run('if ! $(grep -q "^kvm " /proc/modules); '
+			'then insmod "%s"; fi' % (utils.sh_escape(
+			os.path.join(self.build_dir, "kernel/kvm.ko")),))
+		self.host.run('if ! $(grep -q "^kvm_intel " /proc/modules); '
+			'then insmod "%s"; fi' % (utils.sh_escape(
+			os.path.join(self.build_dir, "kernel/kvm-intel.ko")),))
+	
+	def deinitialize(self):
+		"""Terminate the hypervisor.
+		
+		Kill all the virtual machines that are still running and
+		unload the kernel modules.
+		"""
+		self.refresh_guests()
+		for address in self.addresses:
+			if address["is_used"]:
+				self.delete_guest(address["is_used"])
+		self.pid_dir= None
+		
+		self.host.run(
+			'if $(grep -q "^kvm_intel [[:digit:]]+ 0" '
+				'/proc/modules)\n'
+			'then\n'
+			'	rmmod kvm-intel\n'
+			'fi')
+		self.host.run(
+			'if $(grep -q "^kvm [[:digit:]]+ 0" /proc/modules)\n'
+			'then\n'
+			'	rmmod kvm\n'
+			'fi')
+	
+	def new_guest(self):
+		"""Start a new guest ("virtual machine").
+		
+		Returns:
+			The ip that was picked from the list supplied to 
+			install() and assigned to this guest.
+		
+		Raises:
+			AutoservVirtError: no more addresses are available.
+		"""
+		for address in self.addresses:
+			if not address["is_used"]:
+				break
+		else:
+			raise errors.AutoservVirtError(
+				"No more addresses available")
+		
+		# TODO(poirier): uses start-stop-daemon until qemu -pidfile 
+		# and -daemonize can work together
+		retval= self.host.run(
+			'start-stop-daemon -S --exec "%s" --pidfile "%s" -b -- '
+			# this is the line of options that can be modified
+			'-m 256 -hda /var/local/vdisk.img -snapshot '
+			'-pidfile "%s" -nographic '
+			#~ '-serial telnet::4444,server '
+			#~ '-monitor telnet::4445,server '
+			'-net nic,macaddr="%s" -net tap,script="%s" ' % (
+			utils.sh_escape(os.path.join(
+				self.build_dir, 
+				"qemu/x86_64-softmmu/qemu-system-x86_64")),
+			utils.sh_escape(os.path.join(
+				self.pid_dir, 
+				"vhost%s_pid" % (address["ip"],))), 
+			utils.sh_escape(os.path.join(
+				self.pid_dir, 
+				"vhost%s_pid" % (address["ip"],))), 
+			utils.sh_escape(address["mac"]),
+			utils.sh_escape(os.path.join(
+				self.support_dir, 
+				"qemu-ifup.sh")),))
+		
+		address["is_used"]= True
+		return address["ip"]
+	
+	def refresh_guests(self):
+		"""Refresh the list of guests addresses.
+		
+		The is_used status will be updated according to the presence
+		of the process specified in the pid file that was written when
+		the virtual machine was started.
+		
+		TODO(poirier): there are a lot of race conditions in this code
+		because the process might terminate on its own anywhere in 
+		between
+		"""
+		for address in self.addresses:
+			if address["is_used"]:
+				pid_file_name= utils.sh_escape(os.path.join(
+					self.pid_dir, 
+					"vhost%s_pid" % (address["ip"],)))
+				retval= self.host.run(
+					self.check_process_script % {
+					"pid_file_name" : pid_file_name, 
+					"qemu_binary" : utils.sh_escape(
+					os.path.join(self.build_dir, 
+					"qemu/x86_64-softmmu/qemu-system-x86_64"
+					)),})
+				if (retval.stdout.strip(" \n") != 
+					"process present"):
+					address["is_used"]= False
+	
+	def delete_guest(self, guest_hostname):
+		"""Terminate a virtual machine.
+		
+		Args:
+			guest_hostname: the ip (as it was specified in the 
+				address list given to install()) of the guest 
+				to terminate.
+		
+		TODO(poirier): is there a difference in qemu between 
+		sending SIGTEM or quitting from the monitor?
+		TODO(poirier): there are a lot of race conditions in this code
+		because the process might terminate on its own anywhere in 
+		between
+		"""
+		for address in self.addresses:
+			if address["ip"] is guest_hostname:
+				break
+		else:
+			return None
+		
+		pid_file_name= utils.sh_escape(os.path.join(self.pid_dir, 
+			"vhost%s_pid" % (address["ip"],)))
+		
+		retval= self.host.run(
+			self.check_process_script % {
+			"pid_file_name" : pid_file_name, 
+			"qemu_binary" : utils.sh_escape(os.path.join(
+			self.build_dir, 
+			"qemu/x86_64-softmmu/qemu-system-x86_64")),})
+		if retval.stdout.strip(" \n") == "process present":
+			self.host.run('kill $(cat "%s")' %(
+				pid_file_name,))
+			self.host.run('rm "%s"' %(
+				pid_file_name,))
+		address["is_used"]= False
diff --git a/server/rpm_kernel.py b/server/rpm_kernel.py
new file mode 100644
index 0000000..7227e20
--- /dev/null
+++ b/server/rpm_kernel.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the Kernel class
+
+	Kernel: an os kernel
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+import kernel
+
+
+class RPMKernel(kernel.Kernel):
+	"""This class represents a .rpm pre-built kernel.
+	
+	It is used to obtain a built kernel and install it on a Host.
+	
+	Implementation details:
+	This is a leaf class in an abstract class hierarchy, it must 
+	implement the unimplemented methods in parent classes.
+	"""
+	
+	pass
diff --git a/server/source_kernel.py b/server/source_kernel.py
new file mode 100644
index 0000000..e64fcc6
--- /dev/null
+++ b/server/source_kernel.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the SourceKernel class
+
+	SourceKernel: an linux kernel built from source
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+import kernel
+
+
+
+class SourceKernel(kernel.Kernel):
+	"""This class represents a linux kernel built from source.
+	
+	It is used to obtain a built kernel or create one from source and 
+	install it on a Host.
+	
+	Implementation details:
+	This is a leaf class in an abstract class hierarchy, it must 
+	implement the unimplemented methods in parent classes.
+	"""
+	def __init__(self):
+		super(kernel.Kernel, self).__init__()
+		self.__patch_list = []
+		self.__config_file = None
+	
+	def configure(self, configFile):
+		self.__config_file = configFile
+	
+	def patch(self, patchFile):
+		self.__patch_list.append(patchFile)
+	
+	def build(self, host):
+		at = autotest.Autotest()
+		at.install(host)
+		ctlfile = self.control_file(self.__kernel, self.__patch_list,
+					    self.__config_file)
+		at.run(ctlfile, host.get_tmp_dir(), host)
+
+	def __control_file(self, kernel, patch_list, config):
+		ctl = ("def step_init():\n"
+		       "\tjob.next_step([step_test])\n"
+		       "\ttestkernel = job.kernel('%s')\n" % kernel)
+
+		if len(patch_list):
+			 patches = ', '.join(["'%s'" % x for x in patch_list])
+			 ctl += "\ttestkernel.patch(%s)" % patches
+
+		if config:
+			ctl += "\ttestkernel.config('%s')" % config
+		else:
+			ctl += "\ttestkernel.config('', None, True)"
+
+		ctl += "\ttestkernel.build()"
+
+		# copy back to server
+
+		return ctl
diff --git a/server/tests/alltests_suite.py b/server/tests/alltests_suite.py
new file mode 100644
index 0000000..14ffc1d
--- /dev/null
+++ b/server/tests/alltests_suite.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module provides a means to run all the unittests for autoserv
+"""
+
+__author__ = """[email protected] (Ryan Stutsman)"""
+
+import os, sys
+
+# Adjust the path so Python can find the autoserv modules
+src = os.path.abspath("%s/.." % (os.path.dirname(sys.argv[0]),))
+if src not in sys.path:
+	sys.path.insert(1, src)
+
+import unittest
+
+
+import autotest_test
+import utils_test
+
+
+def suite():
+	return unittest.TestSuite([autotest_test.suite(),
+                                   utils_test.suite()])
+
+
+if __name__ == '__main__':
+	unittest.TextTestRunner(verbosity=2).run(suite())
diff --git a/server/tests/autotest_test.py b/server/tests/autotest_test.py
new file mode 100644
index 0000000..46507dd
--- /dev/null
+++ b/server/tests/autotest_test.py
@@ -0,0 +1,139 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the unittests for the Autotest class
+"""
+
+__author__ = """[email protected] (Ryan Stutsman)"""
+
+import os
+import sys
+import unittest
+
+# Adjust the path so Python can find the autoserv modules
+src = os.path.abspath("%s/.." % (os.path.dirname(sys.argv[0]),))
+if src not in sys.path:
+	sys.path.insert(1, src)
+
+import utils
+import autotest
+import hosts
+
+
+class AutotestTestCase(unittest.TestCase):
+	def setUp(self):
+		self.autotest = autotest.Autotest()
+	
+	def tearDown(self):
+		pass
+
+
+	def testGetAutoDir(self):
+		class MockInstallHost:
+			def __init__(self):
+				self.commands = []
+				self.result = "autodir='/stuff/autotest'\n"
+			
+			def run(self, command):
+				if command == "grep autodir= /etc/autotest.conf":
+					result = hosts.CmdResult()
+					result.stdout = self.result
+					return result
+				else:
+					self.commands.append(command)
+		
+		host = MockInstallHost()
+		self.assertEqual('/stuff/autotest',
+				 autotest._get_autodir(host))
+		host.result = "autodir=/stuff/autotest\n"
+		self.assertEqual('/stuff/autotest',
+				 autotest._get_autodir(host))
+		host.result = 'autodir="/stuff/auto test"\n'
+		self.assertEqual('/stuff/auto test',
+				 autotest._get_autodir(host))
+
+
+	def testInstallFromDir(self):
+		class MockInstallHost:
+			def __init__(self):
+				self.commands = []
+			
+			def run(self, command):
+				if command == "grep autodir= /etc/autotest.conf":
+					result= hosts.CmdResult()
+					result.stdout = "autodir=/usr/local/autotest\n"
+					return result
+				else:
+					self.commands.append(command)
+
+			def send_file(self, src, dst):
+				self.commands.append("send_file: %s %s" % (src,
+									   dst))
+				
+		host = MockInstallHost()
+		tmpdir = utils.get_tmp_dir()
+		self.autotest.get_from_file(tmpdir)
+		self.autotest.install(host)
+		self.assertEqual(host.commands,
+				 ['mkdir -p /usr/local/autotest',
+				  'send_file: %s/ %s' % (tmpdir,
+							'/usr/local/autotest')])
+
+		
+
+	
+	def testInstallFromSVN(self):
+		class MockInstallHost:
+			def __init__(self):
+				self.commands = []
+			
+			def run(self, command):
+				if command == "grep autodir= /etc/autotest.conf":
+					result= hosts.CmdResult()
+					result.stdout = "autodir=/usr/local/autotest\n"
+					return result
+				else:
+					self.commands.append(command)
+		
+		host = MockInstallHost()
+		self.autotest.install(host)
+		self.assertEqual(host.commands,
+				 ['svn checkout '
+				  + autotest.AUTOTEST_SVN + ' '
+				  + "/usr/local/autotest"])
+
+	
+	def testFirstInstallFromSVNFails(self):
+		class MockFirstInstallFailsHost:
+			def __init__(self):
+				self.commands = []
+			
+			def run(self, command):
+				if command == "grep autodir= /etc/autotest.conf":
+					result= hosts.CmdResult()
+					result.stdout = "autodir=/usr/local/autotest\n"
+					return result
+				else:
+					self.commands.append(command)
+					first = ('svn checkout ' +
+					    autotest.AUTOTEST_SVN + ' ' +
+					    "/usr/local/autotest")
+					if (command == first):
+						raise autotest.errors.AutoservRunError(
+							"svn not found")
+		
+		host = MockFirstInstallFailsHost()
+		self.autotest.install(host)
+		self.assertEqual(host.commands,
+				 ['svn checkout ' + autotest.AUTOTEST_SVN +
+				  ' ' + "/usr/local/autotest",
+				  'svn checkout ' + autotest.AUTOTEST_HTTP +
+				  ' ' + "/usr/local/autotest"])
+
+
+def suite():
+	return unittest.TestLoader().loadTestsFromTestCase(AutotestTestCase)
+
+if __name__ == '__main__':
+	unittest.TextTestRunner(verbosity=2).run(suite())
diff --git a/server/tests/utils_test.py b/server/tests/utils_test.py
new file mode 100644
index 0000000..0978752
--- /dev/null
+++ b/server/tests/utils_test.py
@@ -0,0 +1,76 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""This module defines the unittests for the utils
+"""
+
+__author__ = """[email protected] (Ryan Stutsman)"""
+
+import os
+import sys
+import os.path
+import unittest
+
+# Adjust the path so Python can find the autoserv modules
+src = os.path.abspath("%s/.." % (os.path.dirname(sys.argv[0]),))
+if src not in sys.path:
+	sys.path.insert(1, src)
+
+import utils
+
+
+
+class UtilsTestCase(unittest.TestCase):
+	def setUp(self):
+		pass
+
+
+	def tearDown(self):
+		pass
+
+
+	def testGetWithOpenFile(self):
+		tmpdir = utils.get_tmp_dir()
+		tmppath = os.path.join(tmpdir, 'testfile')
+		tmpfile = file(tmppath, 'w')
+		print >> tmpfile, 'Test string'
+		tmpfile.close()
+		tmpfile = file(tmppath)
+		newtmppath = utils.get(tmpfile)
+		self.assertEqual(file(newtmppath).read(), 'Test string\n')
+
+
+	def testGetWithHTTP(self):
+		# Yeah, this test is a bad idea, oh well
+		url = 'http://www.kernel.org/pub/linux/kernel/README'
+		tmppath = utils.get(url)
+		f = file(tmppath)
+		f.readline()
+		self.assertTrue('Linux' in f.readline().split())
+
+
+	def testGetWithPath(self):
+		path = utils.get('/proc/cpuinfo')
+		self.assertTrue(file(path).readline().startswith('processor'))
+
+
+	def testGetWithString(self):
+		path = utils.get('/tmp loves rabbits!')
+		self.assertTrue(file(path).readline().startswith('/tmp loves'))
+
+
+	def testGetWithDir(self):
+		tmpdir = utils.get_tmp_dir()
+		origpath = os.path.join(tmpdir, 'testGetWithDir')
+		os.mkdir(origpath)
+		dstpath = utils.get(origpath)
+		self.assertTrue(dstpath.endswith('/'))
+		self.assertTrue(os.path.isdir(dstpath))
+
+
+def suite():
+	return unittest.TestLoader().loadTestsFromTestCase(UtilsTestCase)
+
+if __name__ == '__main__':
+	unittest.TextTestRunner(verbosity=2).run(suite())
diff --git a/server/utils.py b/server/utils.py
new file mode 100644
index 0000000..9ed6218
--- /dev/null
+++ b/server/utils.py
@@ -0,0 +1,248 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc. Released under the GPL v2
+
+"""Miscellaneous small functions.
+"""
+
+__author__ = """[email protected] (Martin J. Bligh),
[email protected] (Benjamin Poirier),
[email protected] (Ryan Stutsman)"""
+
+
+import atexit
+import os
+import os.path
+import select
+import shutil
+import signal
+import StringIO
+import subprocess
+import tempfile
+import time
+import types
+import urllib
+
+import hosts
+import errors
+
+
+__tmp_dirs= []
+
+
+def sh_escape(command):
+	"""Escape special characters from a command so that it can be passed 
+	as a double quoted (" ") string.
+	
+	Args:
+		command: the command string to escape. 
+	
+	Returns:
+		The escaped command string. The required englobing double 
+		quotes are NOT added and so should be added at some point by 
+		the caller.
+	
+	See also: http://www.tldp.org/LDP/abs/html/escapingsection.html
+	"""
+	command= command.replace("\\", "\\\\")
+	command= command.replace("$", r'\$')
+	command= command.replace('"', r'\"')
+	command= command.replace('`', r'\`')
+	return command
+
+
+def scp_remote_escape(filename):
+	"""Escape special characters from a filename so that it can be passed 
+	to scp (within double quotes) as a remote file.
+	
+	Bis-quoting has to be used with scp for remote files, "bis-quoting" 
+	as in quoting x 2
+	scp does not support a newline in the filename
+	
+	Args:
+		filename: the filename string to escape. 
+	
+	Returns:
+		The escaped filename string. The required englobing double 
+		quotes are NOT added and so should be added at some point by 
+		the caller.
+	"""
+	escape_chars= r' !"$&' "'" r'()*,:;<=>?[\]^`{|}'
+	
+	new_name= []
+	for char in filename:
+		if char in escape_chars:
+			new_name.append("\\%s" % (char,))
+		else:
+			new_name.append(char)
+	
+	return sh_escape("".join(new_name))
+
+
+def get(location):
+	"""Get a file or directory to a local temporary directory.
+	
+	Args:
+		location: the source of the material to get. This source may 
+			be one of:
+			* a local file or directory
+			* a URL (http or ftp)
+			* a python file-like object
+	
+	Returns:
+		The location of the file or directory where the requested
+		content was saved. This will be contained in a temporary 
+		directory on the local host.
+	"""
+	tmpdir = get_tmp_dir()
+	
+	# location is a file-like object
+	if hasattr(location, "read"):
+		tmpfile = os.path.join(tmpdir, "file")
+		tmpfileobj = file(tmpfile, 'w')
+		shutil.copyfileobj(location, tmpfileobj)
+		tmpfileobj.close()
+		return tmpfile
+	
+	if isinstance(location, types.StringTypes):
+		# location is a URL
+		if location.startswith('http') or location.startswith('ftp'):
+			tmpfile = os.path.join(tmpdir, os.path.basename(location))
+			urllib.urlretrieve(location, tmpfile)
+			return tmpfile
+		# location is a local path
+		elif os.path.exists(os.path.abspath(location)):
+			tmpfile = os.path.join(tmpdir, os.path.basename(location))
+			if os.path.isdir(location):
+				tmpfile += '/'
+				shutil.copytree(location, tmpfile, symlinks=True)
+				return tmpfile
+			shutil.copyfile(location, tmpfile)
+			return tmpfile
+		# location is just a string, dump it to a file
+		else:
+			tmpfd, tmpfile = tempfile.mkstemp(dir=tmpdir)
+			tmpfileobj = os.fdopen(tmpfd, 'w')
+			tmpfileobj.write(location)
+			tmpfileobj.close()
+			return tmpfile
+
+
+def run(command, timeout=None):
+	"""Run a command on the host.
+	
+	Args:
+		command: the command line string
+		timeout: time limit in seconds before attempting to 
+			kill the running process. The run() function
+			will take a few seconds longer than 'timeout'
+			to complete if it has to kill the process.
+	
+	Returns:
+		a hosts.CmdResult object
+	
+	Raises:
+		AutoservRunError: the exit code of the command 
+			execution was not 0
+	
+	TODO(poirier): Add a "tee" option to send the command's 
+		stdout and stderr to python's stdout and stderr? At 
+		the moment, there is no way to see the command's 
+		output as it is running.
+	TODO(poirier): Should a timeout raise an exception? Should
+		exceptions be raised at all?
+	"""
+	result= hosts.CmdResult()
+	result.command= command
+	sp= subprocess.Popen(command, stdout=subprocess.PIPE, 
+		stderr=subprocess.PIPE, close_fds=True, shell=True, 
+		executable="/bin/bash")
+	
+	start_time= time.time()
+	if timeout:
+		stop_time= start_time + timeout
+		time_left= stop_time - time.time()
+		while time_left > 0:
+			# select will return when stdout is ready 
+			# (including when it is EOF, that is the 
+			# process has terminated).
+			(retval, tmp, tmp) = select.select(
+				[sp.stdout], [], [], time_left)
+			if len(retval):
+				# os.read() has to be used instead of 
+				# sp.stdout.read() which will 
+				# otherwise block
+				result.stdout += os.read(
+					sp.stdout.fileno(), 1024)
+			
+			(pid, exit_status_indication) = os.waitpid(
+				sp.pid, os.WNOHANG)
+			if pid:
+				stop_time= time.time()
+			time_left= stop_time - time.time()
+		
+		# the process has not terminated within timeout, 
+		# kill it via an escalating series of signals.
+		if not pid:
+			signal_queue = [signal.SIGTERM, signal.SIGKILL]
+			for sig in signal_queue:
+				try:
+					os.kill(sp.pid, sig)
+				# handle race condition in which 
+				# process died before we could kill it.
+				except OSError:
+					pass
+				
+				for i in range(5):
+					(pid, exit_status_indication
+						) = os.waitpid(sp.pid, 
+						os.WNOHANG)
+					if pid:
+						break
+					else:
+						time.sleep(1)
+				if pid:
+					break
+	else:
+		exit_status_indication = os.waitpid(sp.pid, 0)[1]
+	
+	result.duration = time.time() - start_time
+	result.aborted = exit_status_indication & 127
+	if result.aborted:
+		result.exit_status= None
+	else:
+		result.exit_status=  exit_status_indication / 256
+	result.stdout += sp.stdout.read()
+	result.stderr = sp.stderr.read()
+	
+	if result.exit_status > 0:
+		raise errors.AutoservRunError("command execution error", 
+			result)
+	
+	return result
+
+
+def get_tmp_dir():
+	"""Return the pathname of a directory on the host suitable 
+	for temporary file storage.
+	
+	The directory and its content will be deleted automatically
+	at the end of the program execution if they are still present.
+	"""
+	global __tmp_dirs
+	
+	dir_name= tempfile.mkdtemp(prefix="autoserv-")
+	__tmp_dirs.append(dir_name)
+	return dir_name
+
+
[email protected]
+def __clean_tmp_dirs():
+	"""Erase temporary directories that were created by the get_tmp_dir() 
+	function and that are still present.
+	"""
+	global __tmp_dirs
+	
+	for dir in __tmp_dirs:
+		shutil.rmtree(dir)
+	__tmp_dirs= []