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= []