Upstream Autotest merge.

As titled, a merge up to 93fc426ca133e775eb495f34d138fc57d92fb55e.

- Removes a bunch of deprecated code.
- Moves several private utilities into the private repo.
- Couple changes ported upstream and resynced.

BUG=None
TEST=In progress... will spin up new Autotest server and use
run_remote_tests for bvt, regression, smoke.

Change-Id: Id3e2ad529bb7b05f148e5d98aea46bb9ea828200
Reviewed-on: http://gerrit.chromium.org/gerrit/3350
Tested-by: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
diff --git a/utils/autotest-rh.init b/utils/autotest-rh.init
new file mode 100755
index 0000000..e5618a0
--- /dev/null
+++ b/utils/autotest-rh.init
@@ -0,0 +1,135 @@
+#!/bin/bash
+#
+# autotestd       Start up the autotest scheduler daemon
+#
+# Copyright 2009 Red Hat, Inc.
+#
+# This software may be freely redistributed under the terms of the GNU
+# general public license.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# chkconfig: - 65 25
+# description: Autotest is a framework for fully automated testing.
+# processname: monitor_db.py
+# pidfile: /var/run/autotest/monitor_db_babysitter.pid
+#
+### BEGIN INIT INFO
+# Provides: autotest
+# Required-Start: $syslog $local_fs
+# Required-Stop: $syslog $local_fs
+# Default-Stop: 0 1 6
+# Short-Description: Start the autotest scheduler daemon
+# Description: Autotest is a framework for fully automated testing.
+### END INIT INFO
+
+# source function library
+. /etc/rc.d/init.d/functions
+
+# pull in sysconfig settings
+[ -f /etc/sysconfig/autotest ] && . /etc/sysconfig/autotest
+
+PROG="autotest"
+BECOME_USER=$PROG
+LOCKFILE=/var/lock/subsys/$PROG
+
+# Autotest paths
+AUTOTEST_DIR="/usr/local/$PROG"
+BABYSITTER="$AUTOTEST_DIR/scheduler/monitor_db_babysitter"
+SCHEDULER="$AUTOTEST_DIR/scheduler/monitor_db.py"
+
+# Scheduler options
+OPTIONS="--background"
+
+# Where to locate PID files
+PID_PATH="$AUTOTEST_DIR" # "/var/run/$PROG"
+BABYSITTER_PIDFILE="$PID_PATH/monitor_db_babysitter.pid"
+SCHEDULER_PIDFILE="$PID_PATH/monitor_db.pid"
+
+# Assume pass
+RETVAL=0
+
+start()
+{
+    [ -f $BABYSITTER ] || exit 5
+
+    echo -n $"Starting $PROG: "
+    daemon --user $BECOME_USER --check $PROG $BABYSITTER $OPTIONS
+    RETVAL=$?
+    echo
+    [ "$RETVAL" = 0 ] && touch $LOCKFILE
+    return $RETVAL
+}
+
+stop()
+{
+    echo -n $"Stopping $PROG: "
+
+    killproc $BABYSITTER
+
+    RETVAL=$?
+    echo
+    if [ "$RETVAL" = 0 ]; then
+         rm -f $LOCKFILE
+         rm -f $BABYSITTER_PIDFILE
+         rm -f $SCHEDULER_PIDFILE
+    fi
+    return $RETVAL
+}
+
+reload()
+{
+    echo -n $"Reloading $PROG: "
+    killproc -p $BABYSITTER_PIDFILE $PROG -HUP
+    RETVAL=$?
+    echo
+    return $RETVAL
+}
+
+restart() {
+    stop
+    start
+}
+
+force_reload() {
+    restart
+}
+
+case "$1" in
+    start)
+        start
+        ;;
+    stop)
+        stop
+        ;;
+    restart)
+        restart
+        ;;
+    reload)
+        reload
+        ;;
+    condrestart|try-restart)
+        if [ -f $LOCKFILE ] ; then
+            if [ "$RETVAL" = 0 ] ; then
+                stop
+                # avoid race
+                sleep 3
+                start
+            else
+                RETVAL=6
+            fi
+        fi
+        ;;
+    status)
+        # status -p $PIDFILE $PROG
+        status $BABYSITTER
+        status $SCHEDULER
+        RETVAL=$?
+        ;;
+    *)
+        echo $"Usage: $0 {start|stop|restart|reload|condrestart|try-restart|status}"
+        RETVAL=2
+esac
+exit $RETVAL
diff --git a/utils/autotestd.service b/utils/autotestd.service
new file mode 100644
index 0000000..0152ec2
--- /dev/null
+++ b/utils/autotestd.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Autotest scheduler
+
+[Service]
+ExecStart=/usr/local/autotest/scheduler/monitor_db_babysitter
+User=autotest
+Group=autotest
+Restart=on-abort
+
+[Install]
+WantedBy=multi-user.target
diff --git a/utils/compile_gwt_clients.py b/utils/compile_gwt_clients.py
index 67108bc..e9aa86a 100755
--- a/utils/compile_gwt_clients.py
+++ b/utils/compile_gwt_clients.py
@@ -15,9 +15,9 @@
 
 _COMPILE_LINE = ('java  -Xmx512M '
                  '-cp "%(app_dir)s/src:%(app_dir)s/bin:%(gwt_dir)s/gwt-user.jar'
-                 ':%(gwt_dir)s/gwt-dev.jar:%(gwt_dir)s/gwt-incubator.jar" '
-                 '-Djava.awt.headless=true com.google.gwt.dev.Compiler '
-                 '-war "%(compile_dir)s" %(extra_args)s %(project_client)s')
+                 ':%(gwt_dir)s/gwt-dev.jar" -Djava.awt.headless=true '
+                 'com.google.gwt.dev.Compiler -war "%(compile_dir)s" '
+                 '%(extra_args)s %(project_client)s')
 
 class CompileClientsLoggingConfig(logging_config.LoggingConfig):
     def configure_logging(self, results_dir=None, verbose=False):
diff --git a/utils/docgen/CreateDocs.py b/utils/docgen/CreateDocs.py
deleted file mode 100755
index c2873ea..0000000
--- a/utils/docgen/CreateDocs.py
+++ /dev/null
@@ -1,703 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2010 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-""" Parse suite control files and make HTML documentation from included tests.
-
-This program will create a list of test cases found in suite files by parsing
-through each suite control file and making a list of all of the jobs called from
-it. Once it has a list of tests, it will parse the AutoTest control file for
-each test and grab the doc strings. These doc strings, along with any
-constraints in the suite control file, will be added to the original test
-script. These new scripts will be placed in a stand alone directory. Doxygen
-will then use these files for the sole purpose of producing HTML documentation
-for all of the tests. Once HTML docs are created some post processing will be
-done against the docs to change a few strings.
-
-If this script is executed without a --src argument, it will assume it is being
-executed from <ChromeOS>/src/third_party/autotest/files/utils/docgen/ directory.
-
-Classes:
-
-  DocCreator
-    This class is responsible for all processing. It requires the following:
-      - Absolute path of suite control files.
-      - Absolute path of where to place temporary files it constructs from the
-        control files and test scripts.
-    This class makes the following assumptions:
-      - Each master suite has a README.txt file with general instructions on
-        test preparation and usage.
-      - The control file for each test has doc strings with labels of:
-        - PURPOSE: one line description of why this test exists.
-        - CRITERIA: Pass/Failure conditions.
-        - DOC: additional test details.
-  ReadNode
-    This class parses a node from a control file into a key/value pair. In this
-    context, a node represents a syntactic construct of an abstract syntax tree.
-    The root of the tree is the module object (in this case a control file). If
-    suite=True, it will assume the node is from a suite control file.
-
-Doxygen should already be configured with a configuration file called:
-doxygen.conf. This file should live in the same directory with this program.
-If you haven't installed doxygen, you'll need to install this program before
-this script is executed. This program will automatically update the doxygen.conf
-file to match self.src_tests and self.html.
-
-TODO: (kdlucas@google.com) Update ReadNode class to use the replacement module
-for the compiler module, as that has been deprecated.
-"""
-
-__author__ = 'kdlucas@google.com (Kelly Lucas)'
-__version__ = '0.9.0'
-
-import compiler
-import fileinput
-import glob
-import logging
-import optparse
-import os
-import re
-import shutil
-import subprocess
-import sys
-
-
-class DocCreator(object):
-    """Process suite control files to combine docstrings and create HTML docs.
-
-    The DocCreator class is designed to parse AutoTest suite control files to
-    find all of the tests referenced, and build HTML documentation based on the
-    docstrings in those files. It will cross reference the test control file
-    and any parameters passed through the suite file, with the original test
-    case. DocCreator relies on doxygen to actually generate the HTML documents.
-
-    The workflow is as follows:
-        - Parse the suite file(s) and generate a test list.
-        - Locate the test source, and grab the docstrings from the associated
-          AutoTest control file.
-        - Combine the docstring from the control file with any parameters passed
-          in from the suite control file, with the original test case.
-        - Write a new test file with the combined docstrings to src_tests.
-        - Create HTML documentation by running doxygen against the tests stored
-          in self.src_tests.
-
-    Implements the following methods:
-        - SetLogger() - Gets a logger and sets the formatting.
-        - GetTests() - Parse suite control files, create a dictionary of tests.
-        - ParseControlFiles() - Runs through all tests and parses control files
-        - _CleanDir() - Remove any files in a direcory and create an empty one.
-        - _GetDoctString() - Parses docstrings and joins it with constraints.
-        - _CreateTest() - Add docstrings and constraints to existing test script
-          to form a new test script.
-        - CreateMainPage() - Create a mainpage.txt file based on contents of the
-          suite README file.
-        - _ConfigDoxygen - Updates doxygen.conf to match some attributes this
-          script was run with.
-        - RunDoxygen() - Executes the doxygen program.
-        - CleanDocs() - Changes some text in the HTML files to conform to our
-          naming conventions and style.
-
-    Depends upon class ReadNode.
-    """
-    def __init__(self):
-        """Parse command line arguments and set some initial variables."""
-
-        desc="""%prog will scan AutoTest suite control files to build a list of
-        test cases called in the suite, and build HTML documentation based on
-        the docstrings it finds in the tests, control files, and suite control
-        files.
-        """
-
-        self.runpath = os.path.abspath('.')
-        autotest_root = os.path.join(self.runpath, '../../')
-
-        parser = optparse.OptionParser(description=desc,
-                                       prog='CreateDocs',
-                                       version=__version__,
-                                       usage='%prog')
-        parser.add_option('--autotest_dir',
-                          help='path to autotest root directory'
-                               ' [default: %default]',
-                          default=autotest_root,
-                          dest='autotest_dir')
-        parser.add_option('--debug',
-                          help='Debug level [default: %default]',
-                          default='debug',
-                          dest='debug')
-        parser.add_option('--docversion',
-                          help='Specify a version for the documentation'
-                               '[default: %default]',
-                          default=None,
-                          dest='docversion')
-        parser.add_option('--doxy',
-                          help='doxygen configuration file [default: %default]',
-                          default='doxygen.conf',
-                          dest='doxyconf')
-        parser.add_option('--html',
-                          help='path to store html docs [default: %default]',
-                          default='html',
-                          dest='html')
-        parser.add_option('--latex',
-                          help='path to store latex docs [default: %default]',
-                          default='latex',
-                          dest='latex')
-        parser.add_option('--layout',
-                          help='doxygen layout file [default: %default]',
-                          default='doxygenLayout.xml',
-                          dest='layout')
-        parser.add_option('--log',
-                          help='Logfile for program output [default: %default]',
-                          default='docCreator.log',
-                          dest='logfile')
-        parser.add_option('--readme',
-                          help='filename of suite documentation'
-                               '[default: %default]',
-                          default='README.txt',
-                          dest='readme')
-        #TODO(kdlucas): add an all option that will parse all suites.
-        parser.add_option('--suite',
-                          help='Directory name of suite [default: %default]',
-                          type='choice',
-                          default='suite_HWQual',
-                          choices = [
-                                     'suite_Factory',
-                                     'suite_HWConfig',
-                                     'suite_HWQual',
-                                    ],
-                          dest='suite')
-        parser.add_option('--tests',
-                          help='Absolute path of temporary test files'
-                               ' [default: %default]',
-                          default='testsource',
-                          dest='src_tests')
-
-        self.options, self.args = parser.parse_args()
-
-
-        # Make parameters a little shorter by making the following assignments.
-        self.autotest_root = self.options.autotest_dir
-        self.debug = self.options.debug
-        self.docversion = self.options.docversion
-        self.doxyconf = self.options.doxyconf
-        self.html = self.options.html
-        self.latex = self.options.latex
-        self.layout = self.options.layout
-        self.logfile = self.options.logfile
-        self.readme = self.options.readme
-        self.src_tests = self.options.src_tests
-        self.suite = self.options.suite
-
-        self.testcase = {}
-
-        self.site_dir = os.path.join(self.autotest_root, 'client', 'site_tests')
-        self.test_dir = os.path.join(self.autotest_root, 'client', 'tests')
-        self.suite_dir = os.path.join(self.site_dir, self.suite)
-
-        self.logger = self.SetLogger('docCreator')
-        self.logger.debug('Executing with debug level: %s', self.debug)
-        self.logger.debug('Writing to logfile: %s', self.logfile)
-        self.logger.debug('New test directory: %s', self.src_tests)
-        self.logger.debug('Test suite: %s', self.suite)
-
-        self.suitename = {
-                          'suite_Factory': 'Factory Testing',
-                          'suite_HWConfig': 'Hardware Configuration',
-                          'suite_HWQual': 'Hardware Qualification',
-                         }
-
-    def SetLogger(self, namespace):
-        """Create a logger with some good formatting options.
-
-        Args:
-            namespace: string, name associated with this logger.
-        Returns:
-            Logger object.
-        This method assumes self.logfile and self.debug are already set.
-        This logger will write to stdout as well as a log file.
-        """
-
-        loglevel = {'debug': logging.DEBUG,
-                    'info': logging.INFO,
-                    'warning': logging.WARNING,
-                    'error': logging.ERROR,
-                    'critical': logging.CRITICAL,
-                   }
-
-        logger = logging.getLogger(namespace)
-        c = logging.StreamHandler()
-        h = logging.FileHandler(os.path.join(self.runpath, self.logfile))
-        hf = logging.Formatter(
-            '%(asctime)s %(process)d %(levelname)s: %(message)s')
-        cf = logging.Formatter('%(levelname)s: %(message)s')
-        logger.addHandler(h)
-        logger.addHandler(c)
-        h.setFormatter(hf)
-        c.setFormatter(cf)
-
-        logger.setLevel(loglevel.get(self.debug, logging.INFO))
-
-        return logger
-
-
-    def GetTests(self):
-        """Create dictionary of tests based on suite control file contents."""
-
-        suite_search = os.path.join(self.suite_dir, 'control.*')
-        for suitefile in glob.glob(suite_search):
-            self.logger.debug('Scanning %s for tests', suitefile)
-            if os.path.isfile(suitefile):
-                try:
-                    suite = compiler.parseFile(suitefile)
-                except SyntaxError, e:
-                    self.logger.error('Error parsing: %s\n%s', (suitefile, e))
-                    raise SystemExit
-
-            # Walk through each node found in the control file, which in our
-            # case will be a call to a test. compiler.walk() will walk through
-            # each component node, and call the appropriate function in class
-            # ReadNode. The returned key should be a string, and the name of a
-            # test. visitor.value should be any extra arguments found in the
-            # suite file that are used with that test case.
-            for n in suite.node.nodes:
-                visitor = ReadNode(suite=True)
-                compiler.walk(n, visitor)
-                if len(visitor.key) > 1:
-                    self.logger.debug('Found test %s', visitor.key)
-                    filtered_input = ''
-                    # Lines in value should start with '  -' for bullet item.
-                    if visitor.value:
-                        lines = visitor.value.split('\n')
-                        for line in lines:
-                            if line.startswith('  -'):
-                                filtered_input += line + '\n'
-                    # A test could be called multiple times, so see if the key
-                    # already exists, and if so append the new value.
-                    if visitor.key in self.testcase:
-                        s = self.testcase[visitor.key] + filtered_input
-                        self.testcase[visitor.key] = s
-                    else:
-                        self.testcase[visitor.key] = filtered_input
-
-
-    def _CleanDir(self, directory):
-        """Ensure the directory is available and empty.
-
-        Args:
-            directory: string, path of directory
-        """
-
-        if os.path.isdir(directory):
-            try:
-                shutil.rmtree(directory)
-            except IOError, err:
-                self.logger.error('Error cleaning %s\n%s', (directory, err))
-        try:
-            os.makedirs(directory)
-        except IOError, err:
-            self.logger.error('Error creating %s\n%s', (directory, err))
-            self.logger.error('Check your permissions of %s', directory)
-            raise SystemExit
-
-
-    def ParseControlFiles(self):
-        """Get docstrings from control files and add them to new test scripts.
-
-        This method will cycle through all of the tests and attempt to find
-        their control file. If found, it will parse the docstring from the
-        control file, add this to any parameters found in the suite file, and
-        add this combined docstring to the original test. These new tests will
-        be written in the self.src_tests directory.
-        """
-        # Clean some target directories.
-        for d in [self.src_tests, self.html]:
-            self._CleanDir(d)
-
-        for test in self.testcase:
-            testdir = os.path.join(self.site_dir, test)
-            if not os.path.isdir(testdir):
-                testdir = os.path.join(self.test_dir, test)
-
-            if os.path.isdir(testdir):
-                control_file = os.path.join(testdir, 'control')
-                test_file = os.path.join(testdir, test + '.py')
-                docstring = self._GetDocString(control_file, test)
-                self._CreateTest(test_file, docstring, test)
-            else:
-                self.logger.warning('Cannot find test: %s', test)
-
-    def _GetDocString(self, control_file, test):
-        """Get the docstrings from control file and join to suite file params.
-
-        Args:
-            control_file: string, absolute path to test control file.
-            test: string, name of test.
-        Returns:
-            string: combined docstring with needed markup language for doxygen.
-        """
-
-        # Doxygen needs the @package marker.
-        package_doc = '## @package '
-        # To allow doxygen to use special commands, we must use # for comments.
-        comment = '# '
-        endlist = '  .\n'
-        control_dict = {}
-        output = []
-        temp = []
-        tempstring = ''
-        docstring = ''
-        keys = ['\\brief\n', '<H3>Pass/Fail Criteria:</H3>\n',
-                '<H3>Author</H3>\n', '<H3>Test Duration</H3>\n',
-                '<H3>Category</H3>\n', '<H3>Test Type</H3>\n',
-                '<H3>Test Class</H3>\n', '<H3>Notest</H3>\n',
-               ]
-
-        try:
-            control = compiler.parseFile(control_file)
-        except SyntaxError, e:
-            self.logger.error('Error parsing: %s\n%s', (control_file, e))
-            return None
-
-        for n in control.node.nodes:
-            visitor = ReadNode()
-            compiler.walk(n, visitor)
-            control_dict[visitor.key] = visitor.value
-
-        for k in keys:
-            if k in control_dict:
-                if len(control_dict[k]) > 1:
-                    if k != test:
-                        temp.append(k)
-                    temp.append(control_dict[k])
-                    if control_dict[k]:
-                        temp.append(endlist)
-                    # Add constraints and extra args after the Criteria section.
-                    if 'Criteria:' in k:
-                        if self.testcase[test]:
-                            temp.append('<H3>Arguments:</H3>\n')
-                            temp.append(self.testcase[test])
-                            # '.' character at the same level as the '-' tells
-                            # doxygen this is the end of the list.
-                            temp.append(endlist)
-
-        output.append(package_doc + test + '\n')
-        tempstring = "".join(temp)
-        lines = tempstring.split('\n')
-        for line in lines:
-            # Doxygen requires a '#' character to add special doxygen commands.
-            comment_line = comment + line + '\n'
-            output.append(comment_line)
-
-        docstring = "".join(output)
-
-        return docstring
-
-
-    def _CreateTest(self, test_file, docstring, test):
-        """Create a new test with the combined docstrings from multiple sources.
-
-        Args:
-            test_file: string, file name of new test to write.
-            docstring: string, the docstring to add to the existing test.
-            test: string, name of the test.
-
-        This method is used to create a temporary copy of a new test, that will
-        be a combination of the original test plus the docstrings from the
-        control file, and any constraints from the suite control file.
-        """
-
-        class_def = 'class ' + test
-        pathname = os.path.join(self.src_tests, test + '.py')
-
-        # Open the test and write out new test with added docstrings
-        try:
-            f = open(test_file, 'r')
-        except IOError, err:
-            self.logger.error('Error while reading %s\n%s', (test_file, err))
-            return
-        lines = f.readlines()
-        f.close()
-
-        try:
-            f = open(pathname, 'w')
-        except IOError, err:
-            self.logger.error('Error creating %s\n%s', (pathname, err))
-            return
-
-        for line in lines:
-            if class_def in line and docstring:
-                f.write(docstring)
-                f.write('\n')
-            f.write(line)
-        f.close()
-
-    def CreateMainPage(self):
-        """Create a main page to provide content for index.html.
-
-        This method assumes a file named README.txt is located in your suite
-        directory with general instructions on setting up and using the suite.
-        If your README file is in another file, ensure you pass a --readme
-        option with the correct filename. To produce a better looking
-        landing page, use the '-' character for list items. This method assumes
-        os commands start with '$'.
-        """
-
-        # Define some strings that Doxygen uses for specific formatting.
-        cstart = '/**'
-        cend = '**/'
-        mp = '@mainpage'
-        section_begin = '@section '
-        vstart = '@verbatim '
-        vend = ' @endverbatim\n'
-
-        # Define some characters we expect to delineate sections in the README.
-        sec_char = '=========='
-        command_prompt = '$ '
-        crosh_prompt = 'crosh>'
-        command_cont = '\\'
-
-        command = False
-        comment = False
-        section = False
-        sec_ctr = 0
-
-        readme_file = os.path.join(self.suite_dir, self.readme)
-        mainpage_file = os.path.join(self.src_tests, 'mainpage.txt')
-
-        try:
-            f = open(readme_file, 'r')
-        except IOError, err:
-            self.logger.error('Error opening %s\n%s', (readme_file, err))
-            return
-        try:
-            fw = open(mainpage_file, 'w')
-        except IOError, err:
-            self.logger.error('Error opening %s\n%s', (mainpage_file, err))
-            return
-
-        lines = f.readlines()
-        f.close()
-
-        fw.write(cstart)
-        fw.write('\n')
-        fw.write(mp)
-        fw.write('\n')
-
-        for line in lines:
-            if sec_char in line:
-                comment = True
-                section = not section
-            elif section:
-                sec_ctr += 1
-                section_name = ' section%d ' % sec_ctr
-                fw.write(section_begin + section_name + line)
-            else:
-                # comment is used to denote when we should start recording text
-                # from the README file. Some of the initial text is not needed.
-                if comment:
-                    if command_prompt in line or crosh_prompt in line:
-                        line = line.rstrip()
-                        if line[-1] == command_cont:
-                            fw.write(vstart + line[:-1])
-                            command = True
-                        else:
-                            fw.write(vstart + line + vend)
-                    elif command:
-                        line = line.strip()
-                        if line[-1] == command_cont:
-                          fw.write(line)
-                        else:
-                          fw.write(line + vend)
-                          command = False
-                    else:
-                        fw.write(line)
-
-        fw.write('\n')
-        fw.write(cend)
-        fw.close()
-
-    def _ConfigDoxygen(self):
-        """Set Doxygen configuration to match our options."""
-
-        doxy_config = {
-                       'ALPHABETICAL_INDEX': 'YES',
-                       'EXTRACT_ALL': 'YES',
-                       'EXTRACT_LOCAL_METHODS': 'YES',
-                       'EXTRACT_PRIVATE': 'YES',
-                       'EXTRACT_STATIC': 'YES',
-                       'FILE_PATTERNS': '*.py *.txt',
-                       'FULL_PATH_NAMES ': 'YES',
-                       'GENERATE_TREEVIEW': 'YES',
-                       'HTML_DYNAMIC_SECTIONS': 'YES',
-                       'HTML_FOOTER': 'footer.html',
-                       'HTML_HEADER': 'header.html',
-                       'HTML_OUTPUT ': self.html,
-                       'INLINE_SOURCES': 'YES',
-                       'INPUT ': self.src_tests,
-                       'JAVADOC_AUTOBRIEF': 'YES',
-                       'LATEX_OUTPUT ': self.latex,
-                       'LAYOUT_FILE ': self.layout,
-                       'OPTIMIZE_OUTPUT_JAVA': 'YES',
-                       'PROJECT_NAME ': self.suitename[self.suite],
-                       'PROJECT_NUMBER': self.docversion,
-                       'SOURCE_BROWSER': 'YES',
-                       'STRIP_CODE_COMMENTS': 'NO',
-                       'TAB_SIZE': '4',
-                       'USE_INLINE_TREES': 'YES',
-                      }
-
-        doxy_layout = {
-                       'tab type="mainpage"': 'title="%s"' %
-                         self.suitename[self.suite],
-                       'tab type="namespaces"': 'title="Tests"',
-                       'tab type="namespacemembers"': 'title="Test Functions"',
-                      }
-
-        for line in fileinput.input(self.doxyconf, inplace=1):
-            for k in doxy_config:
-                if line.startswith(k):
-                    line = '%s = %s\n' % (k, doxy_config[k])
-            print line,
-
-        for line in fileinput.input('header.html', inplace=1):
-            if line.startswith('<H2>'):
-                line = '<H2>%s</H2>\n' % self.suitename[self.suite]
-            print line,
-
-        for line in fileinput.input(self.layout, inplace=1):
-            for k in doxy_layout:
-                if line.find(k) != -1:
-                    line = line.replace('title=""', doxy_layout[k])
-            print line,
-
-
-    def RunDoxygen(self, doxyargs):
-        """Execute Doxygen on the files in the self.src_tests directory.
-
-        Args:
-          doxyargs: string, any command line args to be passed to doxygen.
-        """
-
-        doxycmd = 'doxygen %s' % doxyargs
-
-        p = subprocess.Popen(doxycmd, shell=True, stdout=subprocess.PIPE,
-                             stderr=subprocess.PIPE)
-        p.wait()
-        cmdoutput = p.stdout.read()
-
-        if p.returncode:
-            self.logger.error('Error while running %s', doxycmd)
-            self.logger.error(cmdoutput)
-        else:
-            self.logger.info('%s successfully ran', doxycmd)
-
-
-    def CreateDocs(self):
-        """Configure and execute Doxygen to create HTML docuements."""
-
-        # First run doxygen with args to create default configuration files.
-        # Create layout xml file.
-        doxyargs = '-l %s' % self.layout
-        self.RunDoxygen(doxyargs)
-
-        # Create doxygen configuration file.
-        doxyargs = '-g %s' % self.doxyconf
-        self.RunDoxygen(doxyargs)
-
-        # Edit the configuration files to match our options.
-        self._ConfigDoxygen()
-
-        # Run doxygen with configuration file as argument.
-        self.RunDoxygen(self.doxyconf)
-
-
-    def CleanDocs(self):
-        """Run some post processing on the newly created docs."""
-
-        logo_image = 'customLogo.gif'
-
-        # Key = original string, value = replacement string.
-        replace = {
-                   '>Package': '>Test',
-                  }
-
-        docpages = os.path.join(self.html, '*.html')
-        files = glob.glob(docpages)
-        for file in files:
-            for line in fileinput.input(file, inplace=1):
-                for k in replace:
-                    if line.find(k) != -1:
-                        line = line.replace(k, replace[k])
-                print line,
-
-        shutil.copy(logo_image, self.html)
-
-        self.logger.info('Sanitized documentation completed.')
-
-
-class ReadNode(object):
-    """Parse a compiler node object from a control file.
-
-    Args:
-        suite: boolean, set to True if parsing nodes from a suite control file.
-    """
-
-    def __init__(self, suite=False):
-        self.key = ''
-        self.value = ''
-        self.testdef = False
-        self.suite = suite
-        self.bullet = '  - '
-
-    def visitName(self, n):
-        if n.name == 'job':
-            self.testdef = True
-
-    def visitConst(self, n):
-        if self.testdef:
-            self.key = str(n.value)
-            self.testdef = False
-        else:
-            self.value += str(n.value) + '\n'
-
-    def visitKeyword(self, n):
-        if n.name != 'constraints':
-            self.value += self.bullet + n.name + ': '
-        for item in n.expr:
-            if isinstance(item, compiler.ast.Const):
-                for i in item:
-                    self.value += self.bullet + str(i) + '\n'
-                self.value += '  .\n'
-            else:
-                self.value += str(item) + '\n'
-
-
-    def visitAssName(self, n):
-        # To remove section from appearing in the documentation, set value = ''.
-        sections = {
-                    'AUTHOR': '',
-                    'CRITERIA': '<H3>Pass/Fail Criteria:</H3>\n',
-                    'DOC': '<H3>Notes</H3>\n',
-                    'NAME': '',
-                    'PURPOSE': '\\brief\n',
-                    'TIME': '<H3>Test Duration</H3>\n',
-                    'TEST_CATEGORY': '<H3>Category</H3>\n',
-                    'TEST_CLASS': '<H3>Test Class</H3>\n',
-                    'TEST_TYPE': '<H3>Test Type</H3>\n',
-                   }
-
-        if not self.suite:
-            self.key = sections.get(n.name, n.name)
-
-
-def main():
-    doc = DocCreator()
-    doc.GetTests()
-    doc.ParseControlFiles()
-    doc.CreateMainPage()
-    doc.CreateDocs()
-    doc.CleanDocs()
-
-
-if __name__ == '__main__':
-    main()
diff --git a/utils/docgen/customLogo.gif b/utils/docgen/customLogo.gif
deleted file mode 100644
index 4336a6d..0000000
--- a/utils/docgen/customLogo.gif
+++ /dev/null
Binary files differ
diff --git a/utils/docgen/footer.html b/utils/docgen/footer.html
deleted file mode 100644
index b881cfb..0000000
--- a/utils/docgen/footer.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<hr size="1"><address style="text-align: right;"><small>
-Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
-
-For complete testing documentation see:
-<a href="http://www.chromium.org/chromium-os/testing">Chromium OS Testing</a>
-
-For additional help, send email to
-<a href="mailto:chromium-os-dev@chromium.org">Developer Mail List</a>
-
-<p>Generated on $datetime for $projectname by&nbsp;<a href="http://www.doxygen.org/index.html"><img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> $doxygenversion</small></address>
-</body>
-</html>
diff --git a/utils/docgen/header.html b/utils/docgen/header.html
deleted file mode 100644
index 0ff5033..0000000
--- a/utils/docgen/header.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<!-- Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file. -->
-<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
-<title>$projectname</title>
-<img src="customLogo.gif" alt="The Chromium OS Project" title="Chromium Logo" />
-<H1>Chromium OS</H1>
-<H2>Hardware Qualification</H2>
-<link href="$relpath$doxygen.css" rel="stylesheet" type="text/css">
-<link href="$relpath$tabs.css" rel="stylesheet" type="text/css">
-</head><body>
diff --git a/utils/external_packages.py b/utils/external_packages.py
old mode 100755
new mode 100644
index d32d9bc..0b8cb56
--- a/utils/external_packages.py
+++ b/utils/external_packages.py
@@ -1,5 +1,3 @@
-#!/usr/bin/python
-#
 # Please keep this code python 2.4 compatible and stand alone.
 
 import logging, os, shutil, sys, tempfile, time, urllib2
@@ -111,7 +109,10 @@
         self.installed_version = self._get_installed_version_from_module(module)
         logging.info('imported %s version %s.', self.module_name,
                      self.installed_version)
-        return self.version > self.installed_version
+        if hasattr(self, 'minimum_version'):
+            return self.minimum_version > self.installed_version
+        else:
+            return self.version > self.installed_version
 
 
     def _get_installed_version_from_module(self, module):
@@ -478,6 +479,9 @@
     # For all known setuptools releases a string compare works for the
     # version string.  Hopefully they never release a 0.10.  (Their own
     # version comparison code would break if they did.)
+    # Any system with setuptools > 0.6 is fine. If none installed, then
+    # try to install the latest found on the upstream.
+    minimum_version = '0.6'
     version = '0.6c11'
     urls = ('http://pypi.python.org/packages/source/s/setuptools/'
             'setuptools-%s.tar.gz' % (version,),)
@@ -552,10 +556,10 @@
 
 
 class DjangoPackage(ExternalPackage):
-    version = '1.1.1'
+    version = '1.3'
     local_filename = 'Django-%s.tar.gz' % version
     urls = ('http://www.djangoproject.com/download/%s/tarball/' % version,)
-    hex_sum = '441c54f0e90730bf4a55432b64519169b1e6ef20'
+    hex_sum = 'f8814d5e1412bb932318db5130260da5bf053ff7'
 
     _build_and_install = ExternalPackage._build_and_install_from_package
     _build_and_install_current_dir = (
@@ -680,10 +684,10 @@
 class GwtPackage(ExternalPackage):
     """Fetch and extract a local copy of GWT used to build the frontend."""
 
-    version = '2.0.3'
+    version = '2.3.0'
     local_filename = 'gwt-%s.zip' % version
     urls = ('http://google-web-toolkit.googlecode.com/files/' + local_filename,)
-    hex_sum = '1dabd25a02b9299f6fa84c51c97210a3373a663e'
+    hex_sum = 'd51fce9166e6b31349659ffca89baf93e39bc84b'
     name = 'gwt'
     about_filename = 'about.txt'
     module_name = None  # Not a Python module.
@@ -721,35 +725,6 @@
         return True
 
 
-# This requires GWT to already be installed, so it must be declared after
-# GwtPackage
-class GwtIncubatorPackage(ExternalPackage):
-    version = '20100204-r1747'
-    local_filename = 'gwt-incubator-%s.jar' % version
-    symlink_name = 'gwt-incubator.jar'
-    urls = ('http://google-web-toolkit-incubator.googlecode.com/files/'
-            + local_filename,)
-    hex_sum = '0c9495634f0627d0b4de0d78a50a3aefebf67f8c'
-    module_name = None  # Not a Python module
-
-
-    def is_needed(self, install_dir):
-        gwt_dir = os.path.join(install_dir, GwtPackage.name)
-        return not os.path.exists(os.path.join(gwt_dir, self.local_filename))
-
-
-    def _build_and_install(self, install_dir):
-        dest = os.path.join(install_dir, GwtPackage.name, self.local_filename)
-        shutil.copyfile(self.verified_package, dest)
-
-        symlink_path = os.path.join(
-                install_dir, GwtPackage.name, self.symlink_name)
-        if os.path.exists(symlink_path):
-            os.remove(symlink_path)
-        os.symlink(dest, symlink_path)
-        return True
-
-
 class GVizAPIPackage(ExternalPackage):
     version = '1.7.0'
     url_filename = 'gviz_api_py-%s.tar.gz' % version
@@ -761,7 +736,3 @@
     _build_and_install = ExternalPackage._build_and_install_from_package
     _build_and_install_current_dir = (
                         ExternalPackage._build_and_install_current_dir_noegg)
-
-
-if __name__ == '__main__':
-    sys.exit(main())
diff --git a/utils/monitor.py b/utils/monitor.py
deleted file mode 100755
index e6d6d2e..0000000
--- a/utils/monitor.py
+++ /dev/null
@@ -1,1895 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2010 The Chromium OS Authors. All Rights Reserved.
-# Use of this souce code is governed by a BSD-sytle license that can be
-# found in the LICENSE file.
-
-"""System Monitor.
-
-This program monitors the health of Chrome OS devices in the AutoTest testbed.
-
-    Classes:
-
-    Monitor - The Monitor is responsible for managing the overall process of
-    keeping an updated status of each host available to AutoTest.
-
-    MonitorThread - a very small threaded class that gets hosts from a queue and
-    will create a RemoteWorker object for each thread.
-
-    RemoteWorker - responsible for SSHing to remote hosts to gather resources.
-
-    Resource - maintains all of the resources that are monitored, and methods to
-    parse their data for consumption by RRDTool.
-
-    RRD - maintains all interfaces to RRDTool, including graph definitions, and
-    methods to create, update, and graph resources.
-
-    TestBed - a global class used to hold configuration data and data collected
-    from each remote host. Additionally, formatted data for RRD will be kept
-    associated with each host, and some general information about the update
-    process of each remote host.
-
-    TBQueue - a subclass of Queue.Queue(), in order to override method join(),
-    since we need a timeout in case one of the paramiko ssh sessions hangs.
-
-
-Usage:
-    The following options are supported:
-    --debug: set the debug level. Requires one of the following parameters:
-        debug
-        info (default)
-        warning
-        error
-        critical
-    --gclient: the source directory for ChromeOS source code.
-    --graph: boolean, if True, it will create new graphs for resources.
-    --home: the top level directory for systemhealth files to be placed.
-    --html: boolean, if set to True it will build html pages.
-    --logfile: set the file name of the log file. Default: monitor.log
-    --update: boolean, if True, it will collect new data from all monitored
-      hosts, and update the RRD databases with the newly collected data.
-    --url: string, the base URL for the landing page.
-
-    Arguments should be space separated.
-"""
-
-__author__ = 'kdlucas@gmail.com (Kelly Lucas)'
-__version__ = '2.02'
-
-import logging, logging.handlers, optparse, os, paramiko, Queue, shutil
-import subprocess, sys, threading
-
-from IPy import IP
-from time import *
-
-TIMEOUT = 5  # Timeout for accessing remote hosts.
-RUNTIME = 240  # Total time to allow the host queue to finish all tasks.
-AUTOTEST_BIN = '/home/build/static/projects/chromeos/autotest'
-
-def SetLogger(namespace, logfile, loglevel, log_to_stdout=False):
-    """Create a log handler and set log level.
-
-    Args:
-        namespace: name of the logger.
-        logfile: log file name.
-        loglevel: debug level of logger.
-        log_to_stdout: boolean, True = send msgs to stdout and logfile,
-                                False = send msgs to log file only.
-    Returns:
-        Logger object.
-    We use RotatingFileHandler to handle rotating the log files when they reach
-    MAXSIZE in bytes.
-    """
-    # The logs are linked to the landing page, so we don't want to allow them to
-    # grow too large.
-    MAXSIZE = 1024000  # Max size to grow log files, in bytes.
-
-    levels = {'debug': logging.DEBUG,
-              'info': logging.INFO,
-              'warning': logging.WARNING,
-              'error': logging.ERROR,
-              'critical': logging.CRITICAL,
-             }
-
-    logger = logging.getLogger(namespace)
-    c = logging.StreamHandler()
-    h = logging.handlers.RotatingFileHandler(logfile, maxBytes=MAXSIZE,
-                                             backupCount=10)
-    hf = logging.Formatter('%(asctime)s %(process)d %(levelname)s: %(message)s')
-    cf = logging.Formatter('%(levelname)s: %(message)s')
-    logger.addHandler(h)
-    h.setFormatter(hf)
-    if log_to_stdout:
-        logger.addHandler(c)
-        c.setFormatter(cf)
-
-    logger.setLevel(levels.get(loglevel, logging.INFO))
-
-    return logger
-
-
-class MonitorThread(threading.Thread):
-    """Get AutoTest hosts from queue and create remote host monitors."""
-
-    def __init__(self):
-        threading.Thread.__init__(self)
-        self.tb = TB  # In case the thread outlives the main program.
-
-
-    def run(self):
-        host = self.tb.q.get()
-        worker = RemoteWorker(host)
-        try:
-            worker.run()
-        except Exception, e:
-            self.tb.logger.error('Error on remote host: %s\n%s', host, e)
-        # Notify Queue that process is finished.
-        self.tb.logger.debug('Releasing host %s from queue', host)
-        self.tb.q.task_done()
-
-
-class RemoteWorker(object):
-    """SSH into remote hosts to obtain resource data."""
-
-    def __init__(self, hostname):
-        """
-        Args:
-            hostname: string, hostname of AutoTest host.
-        """
-        self.h = hostname
-        self.client = paramiko.SSHClient()
-        self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-        self.tb = TB  # In case the thread outlives the main program.
-        # Send paramiko messages to it's own log file.
-        # paramiko.util.log_to_file() will overwrite the log file each time you
-        # call it, therefore do not send paramiko messages to the update log.
-        self.logger = SetLogger('SSH', self.tb.sshlog, self.tb.loglevel)
-        paramiko.util.log_to_file(self.tb.sshlog, level=30)
-
-
-    def run(self):
-        try:
-            self.client.connect(self.h, username='root',
-                                key_filename=self.tb.privkey, timeout=TIMEOUT)
-            self.tb.hosts[self.h]['status'] = True
-        except Exception, e:
-            self.logger.error('Host %s: %s', self.h, e)
-            self.tb.hosts[self.h]['status'] = False
-        finally:
-            if self.tb.hosts[self.h]['status']:
-                try:
-                    self.ReadRelease()  # Must be done before UpdateRelease().
-                    self.ReadFirmware()
-                except Exception, e:
-                    self.logger.error('Error on : %s\n%s', self.h, e)
-            self.UpdateRelease()  # Must be done before ReadResources().
-            if self.tb.hosts[self.h]['status']:
-                try:
-                    self.ReadResources()
-                except Exception, e:
-                    self.tb.logger.error('Error on: %s\n%s', self.h, e)
-            self.tb.logger.debug('Closing client for %s', self.h)
-            self.client.close()
-        self.tb.hosts[self.h]['time'] = strftime(
-            '%d%b%Y %H:%M:%S', localtime())
-
-
-    def ReadRelease(self):
-        """Get the Chrome OS Release version."""
-        # The PTR key will mark the current version.
-
-        cmd = 'cat /etc/lsb-release'
-        try:
-            stdin, stdout, stderr = self.client.exec_command(cmd)
-            for line in stdout:
-                if 'CHROMEOS_RELEASE_DESCRIPTION' in line:
-                    release = line.split('=')
-                    self.tb.hosts[self.h]['release']['PTR'] = release[1].strip()
-        except Exception, e:
-            self.tb.logger.error('Error getting release version on host %s\n%s',
-                            self.h, e)
-
-
-    def ReadFirmware(self):
-        """Get the Firmware versions."""
-        # The PTR key will mark the current versions.
-        cmd = '/usr/sbin/mosys -k smbios info bios'
-        try:
-            stdin, stdout, stderr = self.client.exec_command(cmd)
-            for line in stdout:
-                lines = line.split('" ')
-                for item in lines:
-                    if 'ec_version' in item:
-                        fields = item.split('=')
-                        # We must sanitize the string for RRDTool.
-                        val = fields[1].strip('\n" ')
-                        self.tb.hosts[self.h]['ec_firmware']['PTR'] = val
-                    elif 'version' in item:
-                        fields = item.split('=')
-                        val = fields[1].strip('\n" ')
-                        self.tb.hosts[self.h]['firmware']['PTR'] = val
-        except Exception, e:
-            self.tb.logger.error('Error getting firmware versions on %s\n%s',
-                            self.h, e)
-
-
-    def UpdateRelease(self):
-        """Update Release info with most current release versions.
-
-        The PTR key points to the most recent released version. This will also
-        preserve the last known release version in case the host is down.
-        """
-        rrd_dir = os.path.join(self.tb.home, 'hosts', self.h, 'rrd')
-        for v in self.tb.version:
-            update_file = False
-            relfile = os.path.join(rrd_dir, v)
-            tmpfile = os.path.join(rrd_dir, v + '.tmp')
-            if os.path.isfile(relfile):
-                try:
-                    rf = open(relfile, 'r')
-                    lines = rf.readlines()
-                except IOError, e:
-                    self.tb.logger.error('Error parsing release file %s\n%s',
-                                    relfile, e)
-                finally:
-                    rf.close()
-
-                for line in lines:
-                    fields = line.split('=')
-                    # The correct format will have two strings separated by =.
-                    if len(fields) == 2:
-                        if fields[0] == 'PTR':
-                            if self.tb.hosts[self.h][v]['PTR']:
-                                if self.tb.hosts[self.h][v]['PTR'] != fields[1]:
-                                    # Most recent version has changed.
-                                    update_file = True
-                                    lines.pop(lines.index(line))
-                                    self.tb.hosts[self.h][v][self.tb.time] = (
-                                        self.tb.hosts[self.h][v]['PTR'])
-                            else:
-                                # Host is down so use last known value.
-                                self.tb.hosts[self.h][v]['PTR'] = (
-                                    fields[1].strip())
-                        else:
-                            self.tb.hosts[self.h][v][fields[0]] = (
-                                fields[1].strip())
-                    elif len(line) > 3:
-                        # This means the release file has the wrong format, so
-                        # we'll just write a new one with current values.
-                        update_file = True
-                        lines.pop(lines.index(line))
-                    else:
-                        # If we get here than it's probably a blank line.
-                        update_file = True
-                        lines.pop(lines.index(line))
-
-                if update_file:
-                    self.tb.logger.debug('Updating %s', relfile)
-                    shutil.move(relfile, tmpfile)
-                    # Put the most recent update in the new file, and make the
-                    # PTR key to point to it.
-                    lines.append('%s=%s\n' % (self.tb.time,
-                                 self.tb.hosts[self.h][v]['PTR']))
-                    lines.append('PTR=%s' % self.tb.hosts[self.h][v]['PTR'])
-                    try:
-                        rf = open(relfile, 'w')
-                        for line in lines:
-                            rf.write(line)
-                    except IOError, e:
-                        self.tb.logger.error('Error writing %s\n%s', relfile, e)
-                    finally:
-                        rf.close()
-            else:
-                # Create a new release file, as it does not exist.
-                if self.tb.hosts[self.h][v]['PTR']:
-                    self.tb.logger.info('Creating new %s', relfile)
-                    try:
-                        rf = open(relfile, 'w')
-                        rf.write('%s=%s\n' % (
-                            self.tb.time,self.tb.hosts[self.h][v]['PTR']))
-                        rf.write('PTR=%s' % self.tb.hosts[self.h][v]['PTR'])
-                    except IOError, e:
-                        self.tb.logger.error('Error writing %s\n%s', relfile, e)
-                    finally:
-                        rf.close()
-
-                    self.tb.hosts[self.h][v][self.tb.time] = (
-                        self.tb.hosts[self.h][v]['PTR'])
-
-
-    def ReadResources(self):
-        """Get resources that we are monitoring on the host."""
-
-        advisor = Resource()
-        if self.tb.update == True:
-            self.tb.logger.debug('Collecting data on %s', self.h)
-            cmd = advisor.GetCommands()
-            for r in advisor.resources:
-                output = []
-                try:
-                    stdin, stdout, stderr = self.client.exec_command(cmd[r])
-                    for line in stdout:
-                        output.append(line)
-                except Exception, e:
-                    self.tb.logger.error('Cannot read %s from %s', r, self.h)
-                self.tb.hosts[self.h]['data'][r] = "".join(output)
-            self.tb.logger.debug('Formatting data for %s', self.h)
-            advisor.FormatData(self.h)
-        advisor.ProcessRRD(self.h)
-        if self.tb.html:
-            self.tb.logger.debug('Building HTML files for %s', self.h)
-            advisor.BuildHTML(self.h)
-
-
-class TestBed(object):
-    """Used to hold all of the testbed machine data and some global varibles.
-
-    This class will be instantiated as a global object so that all of the other
-    classes in this module will have read/write access to it's variables. It
-    will also hold some general configuration data as well as all remote hosts
-    raw and formatted data that was collected.
-    """
-
-    def __init__(self, logfile, log_to_stdout, debug, graph, home, html, src,
-                 update, url):
-        """
-        Args:
-            logfile: string, name of logfile.
-            log_to_stdout: boolean, True = send log msgs to stdout.
-            debug: string, the debug log level.
-            graph: boolean, flag to create graphs.
-            home: string, pathname of root directory of monitor files.
-            html: boolean, flag to build html files.
-            src: pathname of Chrome OS src directory.
-            update: boolean, flag to get update data from remote hosts.
-            url: string, base URL of system health monitor.
-        """
-        self.version = ['ec_firmware', 'firmware', 'release']
-        start_time = strftime('%H:%M:%S', localtime())
-        self.time = int(time())
-        rundir = '/var/run/systemhealth'
-        if not os.path.isdir(rundir):
-            os.mkdir(rundir)
-        self.update_runfile = os.path.join(rundir, 'update.running')
-        self.graph_runfile = os.path.join(rundir, 'graph.running')
-        self.logfile = logfile
-        self.sshlog = os.path.join(home, 'ssh.log')
-        self.logger = SetLogger('SystemMonitor', logfile, debug,
-                                log_to_stdout=log_to_stdout)
-        self.logger.info('=================================================')
-        self.logger.info('=====================Run Start===================')
-        self.logger.info('=================================================')
-        self.logger.info('Script started at: %s', start_time)
-        self.loglevel = debug
-        self.graph = graph
-        self.home = home
-        self.html = html
-        self.rrdtimes = ['-1hours', '-4hours', '-24hours', '-1week', '-1month',
-                         '-1year']
-        self.update = update
-        self.url = url
-        self.hosts = {}  # Dictionary to hold data from each host.
-
-        # Create a queue for checking resources on remote hosts.
-        self.q = TBQueue()
-        cros_keys = 'scripts/mod_for_test_scripts/ssh_keys'
-        self.privkey = os.path.join(src, cros_keys, 'testing_rsa')
-
-
-class Monitor(object):
-    """Main class used to manage the monitoring of remote hosts.
-
-    This class is used to determine the current status of hosts in the AutoTest
-    testbed. AutoTest will be queried to populate self.rhosts. It will populate
-    a Queue and start a threaded operation using the MonitorThread class, to
-    access each host in the AutoTest testbed and get resource data.
-    """
-
-    def __init__(self):
-        """Monitor will use config data from TestBed."""
-        self.afe_hosts = self.LoadHosts()
-        self.threads = []
-
-    def LoadHosts(self):
-        """Get a list of hosnames from the AutoTest server."""
-        # We only want AclGroup acl_cros_test, and depend on the atest tool to
-        # get the hosts from the AutoTest server.
-        # We'll return a dictionary keyed by hostname/ip address.
-        afe_hosts = {}
-        cmd = '%s/cli/atest host list -a acl_cros_test' % AUTOTEST_BIN
-        atest_out = Exec(cmd, output=True)
-        lines = atest_out.split('\n')
-        for line in lines:
-            fields = line.split()
-            if len(fields) > 4:
-                afe_hosts[fields[0]] = {}
-                afe_hosts[fields[0]]['status'] = fields[1]
-                afe_hosts[fields[0]]['locked'] = fields[2]
-                afe_hosts[fields[0]]['platform'] = fields[3]
-                afe_hosts[fields[0]]['labels'] = fields[4:]
-        # Remove atest's field labels.
-        if 'Host' in afe_hosts:
-            del afe_hosts['Host']
-        # Set up some dictionaries for each host.
-        for host in afe_hosts:
-            TB.hosts[host] = {}
-            TB.hosts[host]['data'] = {}  # Raw data from hosts.
-            TB.hosts[host]['rrddata'] = {}  # Formatted data.
-            TB.hosts[host]['status'] = None
-            TB.hosts[host]['time'] = None
-            for v in TB.version:
-                TB.hosts[host][v] = {}
-                TB.hosts[host][v]['PTR'] = None
-
-        return afe_hosts
-
-
-    def UpdateStatus(self):
-        """Update data from all monitored hosts."""
-
-        # Create new threads of class MonitorThread.
-        self.hostqty = len(self.afe_hosts)
-        for i in range(self.hostqty):
-            t = MonitorThread()
-            t.setDaemon(True)
-            self.threads.append(t)
-            t.start()
-
-        # Fill the requests queue with AutoTest host objects.
-        for host in self.afe_hosts:
-            TB.logger.debug('Placing %s in host queue.', host)
-            TB.q.put(host)
-
-
-        if TB.graph:
-            # Graphing takes much longer, so increase the max runtime.
-            maxtime = RUNTIME * 6
-        else:
-            maxtime = RUNTIME
-        # Queue.join() will wait for all jobs in the queue to finish, or
-        # until the timeout value is reached.
-        TB.logger.debug('Joining run queue.')
-        TB.q.join(timeout=maxtime)
-        TB.logger.info('%s hosts left in host queue', TB.q.qsize())
-        TB.logger.info('Runtime is %d seconds', (time() - TB.time))
-
-        loglevel = TB.logger.getEffectiveLevel()
-        if loglevel == 10:
-            for host in self.afe_hosts:
-                TB.logger.debug('%s status is %s', host,
-                                TB.hosts[host]['status'])
-
-        # If there are any running threads, give them time to finish.
-        # Since paramiko is multi threaded, this check is needed. A deadline
-        # will be set since we don't want the process to run indefinitely.
-        # A deadline needs to be set because one or more of the paramiko
-        # threads could hang.
-        deadline = time() + maxtime
-        running = True
-        while running:
-            for t in self.threads:
-                if t.isAlive():
-                    continue
-                else:
-                    self.threads.remove(t)
-            if len(self.threads) == 0:
-                TB.logger.info('All threads have completed their jobs.')
-
-                running = False
-            else:
-                TB.logger.debug('%d threads still running.', len(self.threads))
-                sleep(TIMEOUT)
-            waittime = deadline - time()
-            if waittime < 0:
-                TB.logger.info('Deadline reached. Aborting running threads.')
-                TB.logger.info('%d threads still running!', len(self.threads))
-                running = False
-
-
-    def CheckStatus(self, hostname):
-        """Check the status of one host.
-
-        Args:
-            hostname: hostname or ip address of host to check.
-        This method is primarily used for debugging purposes.
-        """
-        t = MonitorThread()
-        t.setDaemon(True)
-        t.start()
-
-        for host in self.afe_hosts:
-            if host == hostname:
-                TB.q.put(host)
-                break
-        TB.q.join(timeout=TIMEOUT)
-        TB.logger.info('%s status is %s', hostname,
-                       TB.hosts[hostname]['status'])
-
-
-    def ShowData(self):
-        """Show raw data collected from each host."""
-
-        for host in self.afe_hosts:
-            TB.logger.info('Hostname: %s', host)
-            for k in TB.hosts[host]['data']:
-                TB.logger.info('%s: %s' , k, TB.hosts[host]['data'][k])
-
-
-    def ValidIP(self, address):
-        """Verify address is a valid IP address.
-
-        Args:
-            address: string.
-        Returns:
-            boolean: True = valid IP address, False = not valid IP address.
-        """
-        octets = address.split('.')
-        if len(octets) != 4:
-            return False
-        for octet in octets:
-            if not 0 <= int(octet) <= 255:
-                return False
-        return True
-
-
-    def SortAFEHosts(self, afelist):
-        """Sort AFE host list by IP address.
-
-        Args:
-            afelist: list of AFE host objects.
-        Returns:
-            newlist: list of sorted AFE host objects.
-        """
-        iplist = []
-        hostlist = []
-
-        for h in afelist:
-            if self.ValidIP(h):
-                iplist.append(h)
-            else:
-                hostlist.append(h)
-
-        templist = [(IP(h).int(), h) for h in iplist]
-        templist.sort()
-        newlist = [h[1] for h in templist]
-        hostlist.sort()
-        newlist.extend(hostlist)
-
-        return newlist
-
-
-    def BuildLandingPage(self):
-        """Build the initial HTML landing page with links to all hosts."""
-        TB.logger.debug('Building Langing Page')
-        sorted_ip = []
-        sorted_hosts = []
-        downhosts = 0
-        readyhosts = 0
-        hostlist = self.afe_hosts.keys()
-        sorted_ip = self.SortAFEHosts(hostlist)
-        # Put host that are down first
-        for h in sorted_ip:
-            if not TB.hosts[h]['status']:
-                sorted_hosts.insert(downhosts, h)
-                downhosts = downhosts + 1
-            else:
-                sorted_hosts.append(h)
-                readyhosts = readyhosts + 1
-
-        # Create symlink to the log file if it does not exist.
-        if TB.graph:
-            log_filename = os.path.join(TB.home, 'monitor-graph.log')
-        else:
-            log_filename = os.path.join(TB.home, 'monitor.log')
-        if not os.path.isfile(log_filename):
-            try:
-                os.symlink(TB.logfile, log_filename)
-            except OSError, e:
-                TB.logger.error('Error linking to logfile\n%s', e)
-        LandPageFile = os.path.join(TB.home, 'index.html')
-        # The temp file is used so that there will always be viewable html page
-        # when the new page is being built.
-        LandPageTemp = os.path.join(TB.home, 'temp.html')
-        f = open(LandPageTemp, 'w')
-        f.write('<HTML><HEAD>')
-        f.write('<LINK REL="stylesheet" TYPE="text/css" HREF="table.css">')
-        f.write('<center><TITLE>AutoTest System Health Check</TITLE></HEAD>')
-        f.write('<BODY>')
-        f.write('<img src="chrome.png" style="float:left;"/>')
-        f.write('<table style="float: right">')
-        f.write('<TR><TD><em>Total Hosts</em><TD>%d' % (downhosts + readyhosts))
-        f.write('<TR><TD><em>Inaccessible Hosts</em><TD>%d' % downhosts)
-        f.write('<TR><TD><em>Accessible Hosts</em><TD>%d' % readyhosts)
-        f.write('<TR><TD><em>Update Log<em><TD><a href=%s>%s</a>' % (
-                'monitor.log', 'log'))
-        f.write('<TR><TD><em>Graphing Log<em><TD><a href=%s>%s</a>' % (
-                'monitor-graph.log', 'log'))
-        f.write('<TR><TD><em>Connection Log<em><TD><a href=%s>%s</a>' % (
-                'ssh.log', 'log'))
-        f.write('</table>')
-        f.write('<H1>CAUTOTEST Testbed</H1>')
-        f.write('<H2>System Health</H2>')
-        f.write('<BR><BR>')
-        f.write('<HR>')
-        f.write('<table>')
-        f.write('<CAPTION><EM>Graphs updated every hour</EM></CAPTION>')
-        f.write('<TR><TH>Hostname<TH>Status<TH>Labels<TH>Last Update')
-        f.write('<TH>Release<TH>Health</TR>')
-        for h in sorted_hosts:
-            link_dir = 'hosts/' + h + '/rrd'
-            rrd_dir = os.path.join(TB.home, 'hosts', h, 'rrd')
-            downfile = os.path.join(rrd_dir, 'downtime')
-            fqn = 'http://cautotest.corp.google.com/'
-            view_host = 'afe/#tab_id=view_host&object_id=%s' % h
-            hlink = fqn + view_host
-            if not os.path.isdir(rrd_dir):
-                os.makedirs(rrd_dir)
-                os.chmod(rrd_dir, 0755)
-            if TB.hosts[h]['status']:
-                if os.path.isfile(downfile):
-                    try:
-                        os.remove(downfile)
-                    except OSError, e:
-                        TB.logger.error('Error deleting %s\n%s', downfile, e)
-                if self.afe_hosts[h]['status'] == 'Running':
-                    status = 'Running'
-                    bgcolor = '#99CCFF'
-                else:
-                    status = 'Ready'
-                    bgcolor = '#FFFFFF'
-            else:
-                if os.path.isfile(downfile):
-                    status = 'Down'
-                    bgcolor = '#FF9999'
-                    df = open(downfile, 'r')
-                    TB.hosts[h]['time'] = df.read()
-                    df.close()
-                else:
-                    status = 'Unknown'
-                    bgcolor = '#E8E8E8'
-                    df = open(downfile, 'w')
-                    df.write(TB.hosts[h]['time'])
-                    df.close()
-
-            f.write('<tr bgcolor=%s><th>' % bgcolor)
-            f.write('<a href=%s>%s</a></th>' % (hlink, h))
-            f.write('<td><em>%s</em>' % status)
-            f.write('<td>')
-            f.write('<em><b>%s</b></em><br>' % self.afe_hosts[h]['platform'])
-            for label in self.afe_hosts[h]['labels']:
-                f.write('%s<br>' % label)
-            f.write('<td>%s' % TB.hosts[h]['time'])
-            if TB.hosts[h]['release']['PTR']:
-                f.write('<td>%s' % TB.hosts[h]['release']['PTR'])
-            else:
-                f.write('<td>Unknown')
-            index_file = os.path.join(rrd_dir, 'index.html')
-            if os.path.isfile(index_file):
-                f.write('<td><a href=%s' % TB.url)
-                f.write('%s/index.html target="_blank">' % link_dir)
-                f.write('health</a></td>')
-            else:
-                f.write('<td>None</td>')
-        f.write('</table><p>\n</center>\n</BODY></HTML>')
-        f.close()
-        shutil.copyfile(LandPageTemp, LandPageFile)
-        os.chmod(LandPageFile, 0644)
-
-
-class Resource(object):
-    """Contains structures and methods to collect health data on hosts.
-    For each resource in self.resources, there must also be a corresponding
-    method to format the data into what RRDTool expects.
-    """
-
-    def __init__(self):
-        self.files = {
-            'battery': '/proc/acpi/battery/BAT?/state',
-            'boot': '/tmp/firmware-boot-time /tmp/uptime-login-prompt-ready',
-            'cpu': '/proc/stat',
-            'load': '/proc/loadavg',
-            'memory': '/proc/meminfo',
-            'network': '/proc/net/dev',
-            'power': '/proc/acpi/processor/CPU0/throttling',
-            'temp': '/proc/acpi/thermal_zone/*/temperature',
-            'uptime': '/proc/uptime',
-            }
-        self.fs = {
-            'rootfsA_space': '/',
-            'rootfsA_inodes': '/',
-            'rootfsA_stats': 'sda2 ',
-            'rootfsB_space': '/',
-            'rootfsB_inodes': '/',
-            'rootfsB_stats': 'sda5 ',
-            'stateful_space': '/mnt/stateful_partition',
-            'stateful_inodes': '/mnt/stateful_partition',
-            'stateful_stats': 'sda1 ',
-            }
-        self.resources = []
-        for k in self.files:
-            self.resources.append(k)
-        for k in self.fs:
-            self.resources.append(k)
-
-
-    def FormatData(self, hostname):
-        """Convert collected data into the correct format for RRDTool.
-
-        Args:
-            hostname: string, hostname of AutoTest host.
-        """
-
-        ParseMethod = {
-                       'battery': self.ParseBattery,
-                       'boot': self.ParseBoot,
-                       'fs': self.ParseFS,
-                       'diskstats': self.ParseDiskStats,
-                       'cpu': self.ParseStat,
-                       'load': self.ParseLoadAvg,
-                       'memory': self.ParseMemInfo,
-                       'network': self.ParseNetDev,
-                       'power': self.ParsePower,
-                       'temp': self.ParseTemp,
-                       'uptime': self.ParseUpTime,
-                      }
-
-        # method_key is used here because multiple resource keys will use the
-        # same method to parse them.
-        for key in TB.hosts[hostname]['data']:
-            method_key = key
-            if key in self.fs:
-                if '_space' in key:
-                    method_key = 'fs'
-                elif '_inode' in key:
-                    method_key = 'fs'
-                elif '_stats' in key:
-                    method_key = 'diskstats'
-                else:
-                    TB.logger.error('Error in key name of %s', key)
-            if method_key in ParseMethod:
-                if len(TB.hosts[hostname]['data'][key]) > 0:
-                    ParseMethod[method_key](hostname, key)
-            else:
-                TB.logger.error('No method to parse resource %s', key)
-
-
-    def ProcessRRD(self, hostname):
-        """Process formatted data into RRD files.
-
-        Args:
-            hostname: string, hostname of AutoTest host.
-        """
-        hostdir = os.path.join(TB.home, 'hosts', hostname)
-        rrd_dir = os.path.join(hostdir, 'rrd')
-        if not os.path.exists(rrd_dir):
-            os.makedirs(rrd_dir)
-            os.chmod(rrd_dir, 0755)
-        os.chmod(hostdir, 0755)
-        for r in self.resources:
-            dk = None  # datakey only needs to be set if it's a file system.
-            if r in self.fs:
-                if '_space' in r:
-                    dk = 'fs_space'
-                elif '_inode' in r:
-                    dk = 'fs_inode'
-                elif '_stat' in r:
-                    dk = 'fs_stat'
-
-
-            rrd = RRD(r, hostname, rrd_dir, datakey=dk)
-            if not os.path.exists(rrd.rrdfile):
-                rrd.Create()
-            if TB.update == True:
-                TB.logger.debug('Updating %s for host %s', r, hostname)
-                rrd.Update()
-            if TB.graph:
-                TB.logger.debug('Building %s graphs for %s', r, hostname)
-                rrd.Graph()
-
-
-    def BuildHTML(self, hostname):
-        """Create HTML pages for to display the graphs.
-
-        Args:
-            hostname: string, host of AutoTest host.
-        """
-        mainindex = TB.url + 'index.html'
-        rrd_dir = os.path.join(TB.home, 'hosts', hostname, 'rrd')
-        resource_list = []
-        for r in self.resources:
-            resource_list.append(r)
-        resource_list.sort()
-        index_file = os.path.join(rrd_dir, 'index.html')
-        html_file = {}
-        for t in TB.rrdtimes:
-            html_file[t] = hostname + t + '.html'
-        pathname = {}
-        for name in html_file:
-            pathname[name] = os.path.join(rrd_dir, html_file[name])
-
-        # Create HTML files for each time period we are graphing.
-        for path in pathname:
-            f = open(pathname[path], 'w')
-            f.write('<HTML><HEAD>')
-            f.write('<center><TITLE>%s System Health</TITLE></HEAD>' %
-                    hostname)
-            f.write('<BODY><H1>%s System Health</H1>' % hostname)
-            for v in TB.version:
-                f.write('<H4>%s: %s</H4>' % (v, TB.hosts[hostname][v]['PTR']))
-            for t in TB.rrdtimes:
-                f.write('<a href="%s">%s</a>&nbsp;<b>|</b>' % (
-                        html_file[t], t))
-            f.write('<a href="%s">SystemHealth Home</a>' % mainindex)
-            f.write('<p><HR>')
-
-            f.write('<b>%s</b><table border=1 bgcolor=#EEEEEE>' % path)
-            newrow = True
-            for r in resource_list:
-                if newrow:
-                    f.write('<tr>')
-                f.write('<td>%s<br><a href=%s.html>' % (r, r))
-                f.write('<img src=%s%s.png width=475 height=250></a></td>' % (
-                    r, path))
-                if newrow:
-                    newrow = False
-                else:
-                    f.write('</tr>\n')
-                    newrow = True
-            f.write('</table><p>\n')
-            f.write('</center>\n')
-            f.write('<H5>Last Update: %s</H5>' % TB.hosts[hostname]['time'])
-            f.write('</BODY></HTML>')
-            f.close()
-            os.chmod(pathname[path], 0644)
-        if not os.path.isfile(index_file):
-            os.symlink(pathname[TB.rrdtimes[0]], index_file)
-
-        # Create HTML files for each resource for all time periods.
-        for r in resource_list:
-            rrdfile = os.path.join(rrd_dir, r + '.html')
-            f = open(rrdfile, 'w')
-            f.write('<HTML><HEAD>')
-            f.write('<center><TITLE>%s %s Resources</TITLE></HEAD>' % (
-                     hostname, r))
-            f.write('<BODY><H1>%s %s Resources</H1>' % (hostname, r))
-            for v in TB.version:
-                f.write('<H4>%s: %s</H4>' % (v, TB.hosts[hostname][v]['PTR']))
-            f.write('<table border=5 bgcolor=#B5B5B5>')
-            f.write('<tr>')
-            for t in TB.rrdtimes:
-                f.write('<td><a href="#%s"><b>%s</b></a>' % (t, t))
-            f.write('</table>')
-            f.write('<HR>')
-            f.write('<table border=1 bgcolor=#EEEEEE>')
-            for t in TB.rrdtimes:
-                f.write('<tr><td><a name="%s"><img src=%s%s.png>' % (t, r, t))
-                f.write('</a></td></tr>\n')
-            f.write('</table><p>\n')
-            f.write('</center>\n')
-            f.write('<H5>Last Update: %s</H5>' % TB.hosts[hostname]['time'])
-            f.write('</BODY></HTML>')
-            f.close()
-            os.chmod(rrdfile, 0644)
-
-
-    def ParseBattery(self, h, k):
-        """Convert /proc/acpi/battery/BAT0/state to a list of strings.
-
-        Args:
-            h: string, hostname of host in AutoTest.
-            k: string, resource key.
-        We only care about the values corresponding to the rrdkeys, so the other
-        values will be discarded.
-        """
-        rrdkeys = ['charging state', 'present rate', 'remaining capacity',]
-        TB.hosts[h]['rrddata'][k] = []
-        statlist = TB.hosts[h]['data'][k].split('\n')
-        for stat in statlist:
-            for key in rrdkeys:
-                if key in stat:
-                    stats = stat.split(':')
-                    temp = stats[1].split()
-                    if key == 'charging state':
-                        if temp[0] == 'discharging':
-                            TB.hosts[h]['rrddata'][k].append('0')
-                        else:
-                            TB.hosts[h]['rrddata'][k].append('1')
-                    else:
-                        TB.hosts[h]['rrddata'][k].append(temp[0])
-
-
-    def ParseBoot(self, h, k):
-        """Parse /tmp/uptime-login-prompt-ready for boot time.
-
-        Args:
-            h: string, hostname of host in AutoTest.
-            k: string, resource key.
-        We only want the first and 2nd values from the raw data.
-        """
-        fields = []
-        TB.hosts[h]['rrddata'][k] = []
-        lines = TB.hosts[h]['data'][k].split('\n')
-        for line in lines:
-            if not '==>' in line:
-                fields.extend(line.split())
-        TB.hosts[h]['rrddata'][k] = fields[0:2]
-
-
-    def ParseFS(self, h, k):
-        """Convert file system space and inode readings to a list of strings.
-
-        Args:
-            h: string, hostname of host in AutoTest.
-            k: string, resource key.
-        """
-        TB.hosts[h]['rrddata'][k] = []
-        lines = TB.hosts[h]['data'][k].split('\n')
-        for line in lines:
-            if not line.startswith('Filesystem'):
-                fields = line.split()
-                if len(fields) > 4:
-                    TB.hosts[h]['rrddata'][k].append(fields[2])
-                    TB.hosts[h]['rrddata'][k].append(fields[3])
-
-
-    def ParseDiskStats(self, h, k):
-        """Parse read and write sectors from /proc/diskstats to list of strings.
-
-        Args:
-            h: string, hostname of host in AutoTest.
-            k: string, resource key.
-        """
-        TB.hosts[h]['rrddata'][k] = []
-        fields = TB.hosts[h]['data'][k].split()
-        if len(fields) > 9:
-            TB.hosts[h]['rrddata'][k].append(fields[5])
-            TB.hosts[h]['rrddata'][k].append(fields[9])
-
-
-    def ParseStat(self, h, k):
-        """Convert /proc/stat to lists for CPU usage.
-
-        Args:
-            h: string, hostname of host in AutoTest.
-            k: string, resource key.
-        """
-        lines = TB.hosts[h]['data'][k].split('\n')
-        for line in lines:
-          if 'cpu ' in line:
-              vals = line.split()
-              TB.hosts[h]['rrddata'][k] = vals[1:5]
-
-
-    def ParseLoadAvg(self, h, k):
-        """Convert /proc/loadavg to a list of strings to monitor.
-
-        Args:
-            h: string, hostname of host in AutoTest.
-            k: string, resource key.
-        Process ID is discarded, as it's not needed.
-        """
-        statlist = TB.hosts[h]['data'][k].split()
-        TB.hosts[h]['rrddata'][k] = statlist[0:3]
-
-
-    def ParseMemInfo(self, h, k):
-        """Convert specified fields in /proc/meminfo to a list of strings.
-
-        Args:
-            h: string, hostname of host in AutoTest.
-            k: string, resoruce key.
-        """
-        TB.hosts[h]['rrddata'][k] = []
-        mem_keys = ['MemTotal', 'MemFree', 'Buffers', 'Cached', 'SwapTotal',
-                    'SwapFree']
-        lines = TB.hosts[h]['data'][k].split('\n')
-        for line in lines:
-            for key in mem_keys:
-                if key in line:
-                    if not 'SwapCached' in line:
-                        fields = line.split()
-                        TB.hosts[h]['rrddata'][k].append(fields[1])
-
-
-    def ParseNetDev(self, h, k):
-        """Convert /proc/net/dev to a list of strings of rec and xmit values.
-
-        Args:
-            h: string, hostname of host in AutoTest.
-            k: string, resource key.
-        """
-        net_keys = ['eth0', 'wlan0']
-        rrdlist = ['0', '0', '0', '0']
-        lines = TB.hosts[h]['data'][k].split('\n')
-        for key in net_keys:
-            for line in lines:
-                if key in line:
-                    # The following routine will ensure that the values are
-                    # placed in the correct order in case there is an expected
-                    # interface is not present.
-                    index = net_keys.index(key)
-                    if index:
-                      index = index*2
-                    (device, data) = line.split(':')
-                    fields = data.split()
-                    rrdlist[index] = fields[0]
-                    rrdlist[index+1] = fields[8]
-
-        TB.hosts[h]['rrddata'][k] = rrdlist
-
-
-    def ParsePower(self, h, k):
-        """Convert /proc/acpi/processor/CPU0/throttling to power percentage.
-
-        Args:
-            h: string, hostname of host in AutoTest.
-            k: string, resource key.
-        """
-        TB.hosts[h]['rrddata'][k] = []
-        lines = TB.hosts[h]['data'][k].split('\n')
-        for line in lines:
-            line = line.strip()
-            if line.startswith('*'):
-                fields = line.split(':')
-
-        if len(fields) > 1:
-            percent = fields[1].strip('%')
-            percent = percent.strip()
-            TB.hosts[h]['rrddata'][k].append(percent)
-
-
-    def ParseTemp(self, h, k):
-        """Convert temperature readings to a list of strings.
-
-        Args:
-            h: string, hostname of host in AutoTest.
-            k: string, resource key.
-        """
-        TB.hosts[h]['rrddata'][k] = []
-        statlist = TB.hosts[h]['data'][k].split()
-        if len(statlist) > 1:
-          TB.hosts[h]['rrddata'][k].append(statlist[1])
-
-
-    def ParseUpTime(self, h, k):
-        """Convert /proc/uptime to a list of strings.
-
-        Args:
-            h: string, hostname of host in AutoTest.
-            k: string, resource key.
-        Returns:
-            list of strings.
-        """
-
-        TB.hosts[h]['rrddata'][k] = TB.hosts[h]['data'][k].split()
-
-
-    def GetCommands(self):
-        """Routine for gathering data from files and file systems.
-        Returns:
-            dictionary of commands to run on hosts.
-        """
-
-        command = {}
-
-        for r in self.resources:
-            if r in self.files:
-                if r == 'boot':
-                    command[r] = 'head %s' % self.files[r]
-                else:
-                    command[r] = 'cat %s' % self.files[r]
-            elif r in self.fs:
-                if '_space' in r:
-                    command[r] = 'df -lP %s' % self.fs[r]
-                elif '_inode' in r:
-                    command[r] = 'df -iP %s' % self.fs[r]
-                elif '_stat' in r:
-                    command[r] = 'cat /proc/diskstats | grep %s' % self.fs[r]
-                else:
-                    TB.logger.error('Error in key name of %s', r)
-        return command
-
-
-class RRD(object):
-    """The class to create and update RRD data stores and graph them.
-
-    This class should be used to access all of the functions of RRDTool. It will
-    create the data files, update them, and create graphs/charts based on that
-    data. Datakey is needed when we are using the same data definitions for many
-    items of the same type, like file systems.
-    """
-    def __init__(self, rrdname, hostname, rrd_dir, datakey=None):
-        """
-        Args:
-            rrdname: string, item name(should match key from Resources)
-            hostname: string, hostname of the machine.
-            rrd_dir: string, directory for all rrd files and graphs.
-            datakey: string, overrides which data definition to use.
-        """
-        self.rrdtool = '/usr/bin/rrdtool'
-        self.rrd_dir = rrd_dir
-        if not os.path.exists(self.rrd_dir):
-            try:
-                os.makedirs(self.rrd_dir)
-                os.chmod(self.rrd_dir, 0755)
-            except OSError:
-                TB.logger.error('Error creating %s', self.rrd_dir)
-        self.rrdname = rrdname
-        self.hostname = hostname
-        rrd_filename = rrdname + '.rrd'
-        self.rrdfile = os.path.join(self.rrd_dir, rrd_filename)
-        file_system = 'Unknown'
-
-        if not datakey:
-            datakey = rrdname
-        else:
-            fields = rrdname.split('_')
-            if len(fields[0]) > 0:
-                file_system = fields[0]
-
-        data_def = {
-            'battery': {
-                'heartbeat': '600',
-                'min': '0',
-                'max': 'U',
-                'title': '"%s Battery Status' % self.hostname,
-                'type': 'GAUGE',
-                'units': '"Mili Amps"',
-                'items': [
-                    'State',
-                    'Rate',
-                    'Capacity',
-                    ],
-                'graph': [
-                    '-l 0 -r',
-                    'CDEF:bat=State,1,LT,50,UNKN,IF',
-                    'CDEF:ac=State,1,LT,UNKN,50,IF',
-                    'CDEF:RateD=State,1,LT,Rate,UNKN,IF',
-                    'CDEF:RateC=State,1,LT,UNKN,Rate,IF',
-                    'CDEF:bg=Capacity,UN,0,Capacity,IF,0,GT,INF,UNKN,IF',
-                    'AREA:bg#DDDDDD:',
-                    'AREA:Capacity#99CCFF:"Capacity      "',
-                    'LINE1:Capacity#3399FF:',
-                    'VDEF:max1=Capacity,MAXIMUM',
-                    'VDEF:min1=Capacity,MINIMUM',
-                    'VDEF:avg1=Capacity,AVERAGE',
-                    'GPRINT:max1:"Max %6.3lf%s"',
-                    'GPRINT:min1:"Min %6.3lf%s"',
-                    'GPRINT:avg1:" Avg %6.3lf%s"',
-                    'AREA:bat#CC0000:"Battery \\n"',
-                    'LINE2:RateD#990033:"Discharge Rate"',
-                    'VDEF:max2=RateD,MAXIMUM',
-                    'VDEF:min2=RateD,MINIMUM',
-                    'VDEF:avg2=RateD,AVERAGE',
-                    'GPRINT:max2:"Max %6.3lf%s"',
-                    'GPRINT:min2:"Min %6.3lf%s"',
-                    'GPRINT:avg2:"Avg %6.3lf%s"',
-                    'AREA:ac#33FF66:"AC Connected \\n"',
-                    'LINE2:RateC#009966:"Charge Rate   "',
-                    'VDEF:max3=RateC,MAXIMUM',
-                    'VDEF:min3=RateC,MINIMUM',
-                    'VDEF:avg3=RateC,AVERAGE',
-                    'GPRINT:max3:"Max %6.3lf%s"',
-                    'GPRINT:min3:"Min %6.3lf%s"',
-                    'GPRINT:avg3:" Avg %6.3lf%s\\n"',
-                    ],
-                },
-            'boot': {
-                'heartbeat': '600',
-                'min': '0',
-                'max': 'U',
-                'title': '"%s Boot time to Login Prompt' % self.hostname,
-                'type': 'GAUGE',
-                'units': '"Seconds"',
-                'items': [
-                    'firmware',
-                    'ready',
-                    ],
-                'graph': [
-                    '-l 0 -u 30 -r',
-                    'CDEF:total=firmware,ready,+',
-                    'CDEF:bg=total,UN,0,total,IF,0,GT,UNKN,INF,IF',
-                    'AREA:bg#DDDDDD:',
-                    'AREA:firmware#26466D:"Firmware    "',
-                    'LINE1:firmware#660000:',
-                    'VDEF:maxF=firmware,MAXIMUM',
-                    'VDEF:minF=firmware,MINIMUM',
-                    'VDEF:avgF=firmware,AVERAGE',
-                    'GPRINT:minF:"Min %2.1lf"',
-                    'GPRINT:maxF:"Max %2.1lf"',
-                    'GPRINT:avgF:"Avg %2.1lf Seconds \\n"',
-                    'AREA:ready#0BB5FF:"Login Prompt":STACK',
-                    'LINE1:firmware#660000:',
-                    'VDEF:maxR=ready,MAXIMUM',
-                    'VDEF:minR=ready,MINIMUM',
-                    'VDEF:avgR=ready,AVERAGE',
-                    'GPRINT:minR:"Min %2.1lf"',
-                    'GPRINT:maxR:"Max %2.1lf"',
-                    'GPRINT:avgR:"Avg %2.1lf Seconds \\n"',
-                    'VDEF:maxT=total,MAXIMUM',
-                    'VDEF:minT=total,MINIMUM',
-                    'VDEF:avgT=total,AVERAGE',
-                    'GPRINT:minT:"Total           Min %2.1lf"',
-                    'GPRINT:maxT:"Max %2.1lf"',
-                    'GPRINT:avgT:"Avg %2.1lf Seconds \\n"',
-                    'HRULE:15#FF0000',
-                    'HRULE:10#FFA500',
-                    ],
-                },
-            'cpu': {
-                'heartbeat': '600',
-                'min': '0',
-                'max': 'U',
-                'title': '"%s CPU Usage' % self.hostname,
-                'type': 'DERIVE',
-                'units': 'jiffies',
-                'items': [
-                    'user',
-                    'nice',
-                    'system',
-                    'idle',
-                    ],
-                'graph': [
-                    '-l 0 -r -u 99.99',
-                    'CDEF:l=user,0.1,0.1,IF',
-                    'CDEF:bg=user,UN,0,user,IF,0,GT,UNKN,INF,IF',
-                    'AREA:bg#DDDDDD:',
-                    'CDEF:tj=user,nice,+,system,+,idle,+',
-                    'CDEF:usr=100,user,*,tj,/',
-                    'CDEF:nic=100,nice,*,tj,/',
-                    'CDEF:sys=100,system,*,tj,/',
-                    'CDEF:idl=100,idle,*,tj,/',
-                    'CDEF:tot=100,tj,*,tj,/',
-                    'AREA:nic#0040A2:"Nice  "',
-                    'VDEF:maxN=nic,MAXIMUM',
-                    'VDEF:minN=nic,MINIMUM',
-                    'VDEF:avgN=nic,AVERAGE',
-                    'GPRINT:maxN:"Max %6.2lf%s"',
-                    'GPRINT:minN:"Min %6.2lf%s"',
-                    'GPRINT:avgN:"Avg %6.2lf%s \\n"',
-                    'AREA:sys#3399FF:System:STACK',
-                    'LINE2:l#70A5AC::STACK',
-                    'VDEF:maxS=sys,MAXIMUM',
-                    'VDEF:minS=sys,MINIMUM',
-                    'VDEF:avgS=sys,AVERAGE',
-                    'GPRINT:maxS:"Max %6.2lf%s"',
-                    'GPRINT:minS:"Min %6.2lf%s"',
-                    'GPRINT:avgS:"Avg %6.2lf%s \\n"',
-                    'AREA:usr#B0F5EC:"User  ":STACK',
-                    'LINE2:l#90C5CC::STACK',
-                    'VDEF:maxU=usr,MAXIMUM',
-                    'VDEF:minU=usr,MINIMUM',
-                    'VDEF:avgU=usr,AVERAGE',
-                    'GPRINT:maxU:"Max %6.2lf%s"',
-                    'GPRINT:minU:"Min %6.2lf%s"',
-                    'GPRINT:avgU:"Avg %6.2lf%s \\n"',
-                    'AREA:idl#EEFFFF:"Idle  ":STACK',
-                    'VDEF:maxI=idl,MAXIMUM',
-                    'VDEF:minI=idl,MINIMUM',
-                    'VDEF:avgI=idl,AVERAGE',
-                    'GPRINT:maxI:"Max %6.2lf%s"',
-                    'GPRINT:minI:"Min %6.2lf%s"',
-                    'GPRINT:avgI:"Avg %6.2lf%s \\n"',
-                    ],
-                },
-            'fs_inode': {
-                'heartbeat': '600',
-                'min': '0',
-                'max': 'U',
-                'title': '"%s %s File System Inodes' % (self.hostname,
-                file_system),
-                'type': 'GAUGE',
-                'units': 'Quantity',
-                'items': [
-                    'Used',
-                    'Free',
-                    ],
-                'graph': [
-                    '-l 0 -r',
-                    'CDEF:bg=Used,UN,0,Used,IF,0,GT,UNKN,INF,IF',
-                    'AREA:bg#DDDDDD',
-                    'CDEF:inodes=Used,Free,+',
-                    'VDEF:inodesTotal=inodes,LAST',
-                    'GPRINT:inodesTotal:"Total   %6.2lf %s\\n"',
-                    'AREA:Used#000066:"Used"',
-                    'VDEF:usedLast=Used,LAST',
-                    'GPRINT:usedLast:"%6.2lf %s"',
-                    'CDEF:usedPct=Used,100,*,inodes,/',
-                    'VDEF:pctUsed=usedPct,LAST',
-                    'GPRINT:pctUsed:"%6.2lf%%\\n"',
-                    'AREA:Free#3399FF:"Free":STACK',
-                    'VDEF:freeLast=Free,LAST',
-                    'GPRINT:freeLast:"%6.2lf %s"',
-                    'CDEF:freePct=100,usedPct,-',
-                    'VDEF:pctFree=freePct,LAST',
-                    'GPRINT:pctFree:"%6.2lf%%\\n"',
-                    ],
-                },
-            'fs_space': {
-                'heartbeat': '600',
-                'min': '0',
-                'max': 'U',
-                'title': '"%s %s File System Space' % (self.hostname,
-                file_system),
-                'type': 'GAUGE',
-                'units': 'Bytes',
-                'items': [
-                    'Used',
-                    'Free',
-                    ],
-                'graph': [
-                    '-l 0 -r',
-                    'CDEF:bg=Used,UN,0,Used,IF,0,GT,UNKN,INF,IF',
-                    'AREA:bg#DDDDDD',
-                    'CDEF:UsedB=Used,1024,*',
-                    'CDEF:FreeB=Free,1024,*',
-                    'CDEF:fs=UsedB,FreeB,+',
-                    'VDEF:fsTotal=fs,LAST',
-                    'GPRINT:fsTotal:"Total   %6.2lf %sB\\n"',
-                    'AREA:UsedB#003399:"Used"',
-                    'VDEF:usedLast=UsedB,LAST',
-                    'GPRINT:usedLast:"%6.2lf %sB"',
-                    'CDEF:usedPct=UsedB,100,*,fs,/',
-                    'VDEF:pctUsed=usedPct,LAST',
-                    'GPRINT:pctUsed:"%6.2lf%%\\n"',
-                    'AREA:FreeB#6699CC:"Free":STACK',
-                    'VDEF:freeLast=FreeB,LAST',
-                    'GPRINT:freeLast:"%6.2lf %sB"',
-                    'CDEF:freePct=100,usedPct,-',
-                    'VDEF:pctFree=freePct,LAST',
-                    'GPRINT:pctFree:"%6.2lf%%\\n"',
-                    ],
-                },
-            'fs_stat': {
-                'heartbeat': '600',
-                'min': 'U',
-                'max': 'U',
-                'title': '"%s %s File System Activity' % (self.hostname,
-                file_system),
-                'type': 'DERIVE',
-                'units': '"Bytes"',
-                'items': [
-                    'Reads',
-                    'Writes',
-                    ],
-                'graph': [
-                    '-r',
-                    'CDEF:bWrites=Writes,-512,*',
-                    'CDEF:bReads=Reads,512,*',
-                    'AREA:bWrites#990000:"Bytes Written\\n"',
-                    'AREA:bReads#0066CC:"Bytes Read"',
-                    'HRULE:0#000000',
-                    ],
-                },
-            'load': {
-                'heartbeat': '600',
-                'min': '0',
-                'max': '100',
-                'title': '"%s Load Levels' % self.hostname,
-                'type': 'GAUGE',
-                'units': 'proc/min',
-                'items': [
-                    'load_1',
-                    'load_5',
-                    'load_15',
-                    ],
-                'graph': [
-                    '-r',
-                    'CDEF:bg=load_1,UN,0,load_1,IF,0,GT,UNKN,INF,IF',
-                    'AREA:bg#DDDDDD:',
-                    'CDEF:bi=load_1,UN,0,load_1,IF,0,GT,INF,UNKN,IF',
-                    'AREA:bi#FEFEED:',
-                    'HRULE:1.0#44B5FF',
-                    'AREA:load_15#99FFCC:"Last 15 min"',
-                    'VDEF:max3=load_15,MAXIMUM',
-                    'VDEF:min3=load_15,MINIMUM',
-                    'VDEF:avg3=load_15,AVERAGE',
-                    'GPRINT:max3:"Max %6.2lf"',
-                    'GPRINT:min3:"Min %6.2lf"',
-                    'GPRINT:avg3:"Avg %6.2lf\\n"',
-                    'LINE2:load_5#3399FF:"Last 5 min "',
-                    'VDEF:max2=load_5,MAXIMUM',
-                    'VDEF:min2=load_5,MINIMUM',
-                    'VDEF:avg2=load_5,AVERAGE',
-                    'GPRINT:max2:"Max %6.2lf"',
-                    'GPRINT:min2:"Min %6.2lf"',
-                    'GPRINT:avg2:"Avg %6.2lf\\n"',
-                    'LINE2:load_1#993366:"Last 1 min "',
-                    'VDEF:max1=load_1,MAXIMUM',
-                    'VDEF:min1=load_1,MINIMUM',
-                    'VDEF:avg1=load_1,AVERAGE',
-                    'GPRINT:max1:"Max %6.2lf"',
-                    'GPRINT:min1:"Min %6.2lf"',
-                    'GPRINT:avg1:"Avg %6.2lf\\n"',
-                    ],
-                },
-            'memory': {
-                'heartbeat': '600',
-                'min': '0',
-                'max': '10000000',
-                'title': '"%s Memory Usage' % self.hostname,
-                'type': 'GAUGE',
-                'units': 'bytes',
-                'items': [
-                    'MemTotal',
-                    'MemFree',
-                    'Buffers',
-                    'Cached',
-                    'SwapTotal',
-                    'SwapFree',
-                    ],
-                'graph': [
-                    '-r',
-                    'CDEF:bg=MemTotal,UN,0,MemTotal,IF,0,GT,UNKN,INF,IF',
-                    'AREA:bg#DDDDDD:',
-                    'CDEF:sum=MemTotal,1024,*',
-                    'CDEF:free=MemFree,1024,*',
-                    'CDEF:buff=Buffers,1024,*',
-                    'CDEF:buffP=buff,100,*,sum,/',
-                    'CDEF:cache=Cached,1024,*',
-                    'CDEF:user=MemTotal,MemFree,Cached,+,Buffers,+,-,1024,*',
-                    'CDEF:l=user,1,1,IF',
-                    'AREA:user#003366:"User    "',
-                    'LINE2:l#AC1300::STACK',
-                    'VDEF:maxUser=user,MAXIMUM',
-                    'VDEF:minUser=user,MINIMUM',
-                    'VDEF:avgUser=user,AVERAGE',
-                    'VDEF:curUser=user,LAST',
-                    'GPRINT:curUser:"Last %6.2lf %s"',
-                    'GPRINT:avgUser:"Avg %6.2lf %s"',
-                    'GPRINT:maxUser:"Max %6.2lf %s"',
-                    'GPRINT:minUser:"Min %6.2lf %s\\n"',
-                    'AREA:cache#336699:"Cached  ":STACK',
-                    'LINE2:l#DF7900::STACK',
-                    'VDEF:maxCache=cache,MAXIMUM',
-                    'VDEF:minCache=cache,MINIMUM',
-                    'VDEF:avgCache=cache,AVERAGE',
-                    'VDEF:curCache=cache,LAST',
-                    'GPRINT:curCache:"Last %6.2lf %s"',
-                    'GPRINT:avgCache:"Avg %6.2lf %s"',
-                    'GPRINT:maxCache:"Max %6.2lf %s"',
-                    'GPRINT:minCache:"Min %6.2lf %s\\n"',
-                    'AREA:buff#99CCFF:"Buffers":STACK',
-                    'LINE2:l#DFAC00::STACK',
-                    'VDEF:maxBuff=buff,MAXIMUM',
-                    'VDEF:minBuff=buff,MINIMUM',
-                    'VDEF:avgBuff=buff,AVERAGE',
-                    'VDEF:curBuff=buff,LAST',
-                    'GPRINT:curBuff:"Last %6.2lf %s"',
-                    'GPRINT:avgBuff:"Avg %6.2lf %s"',
-                    'GPRINT:maxBuff:"Max %6.2lf %s"',
-                    'GPRINT:minBuff:"Min %6.2lf %s\\n"',
-                    'AREA:free#CCFFCC:"Unused ":STACK',
-                    'VDEF:maxFree=free,MAXIMUM',
-                    'VDEF:minFree=free,MINIMUM',
-                    'VDEF:avgFree=free,AVERAGE',
-                    'VDEF:curFree=free,LAST',
-                    'GPRINT:curFree:"Last %6.2lf %s"',
-                    'GPRINT:avgFree:"Avg %6.2lf %s"',
-                    'GPRINT:maxFree:"Max %6.2lf %s"',
-                    'GPRINT:minFree:"Min %6.2lf %s\\n"',
-                    ],
-                },
-            'network': {
-                'heartbeat': '600',
-                'min': '0',
-                'max': '12500000',
-                'title': '"%s Network Traffic' % self.hostname,
-                'type': 'DERIVE',
-                'units': 'bytes/s',
-                'items': [
-                    'r_eth0',
-                    'x_eth0',
-                    'r_wlan0',
-                    'x_wlan0',
-                    ],
-                'graph': [
-                    '-r',
-                    'VDEF:max1=r_eth0,MAXIMUM',
-                    'CDEF:eoff=r_eth0,UN,0,r_eth0,IF,0,GT,UNKN,0,IF',
-                    'CDEF:eon=0,r_eth0,UN,0,r_eth0,IF,0,GT,max1,50,/,UNKN,IF,-',
-                    'CDEF:bi=r_eth0,UN,0,r_eth0,IF,0,GT,INF,UNKN,IF',
-                    'CDEF:bg=r_eth0,UN,0,r_eth0,IF,0,GT,UNKN,INF,IF',
-                    'AREA:bi#DDDDDD:',
-                    'AREA:r_eth0#000066:"Eth0 In "',
-                    'LINE1:r_eth0#0000CC:',
-                    'VDEF:min1=r_eth0,MINIMUM',
-                    'VDEF:avg1=r_eth0,AVERAGE',
-                    'VDEF:tot1=r_eth0,TOTAL',
-                    'GPRINT:max1:"Max %6.2lf%s"',
-                    'GPRINT:min1:"Min %6.2lf%s"',
-                    'GPRINT:avg1:"Avg %6.2lf%s"',
-                    'GPRINT:tot1:"Sum %6.2lf%s\\n"',
-                    'CDEF:xmit0=x_eth0,-1,*',
-                    'AREA:xmit0#990033:"Eth0 Out"',
-                    'VDEF:max2=x_eth0,MAXIMUM',
-                    'VDEF:min2=x_eth0,MINIMUM',
-                    'VDEF:avg2=x_eth0,AVERAGE',
-                    'VDEF:tot2=x_eth0,TOTAL',
-                    'GPRINT:max2:"Max %6.2lf%s"',
-                    'GPRINT:min2:"Min %6.2lf%s"',
-                    'GPRINT:avg2:"Avg %6.2lf%s"',
-                    'GPRINT:tot2:"Sum %6.2lf%s\\n"',
-                    'AREA:bg#DDDDDD:',
-                    'LINE3:eoff#000000:"Eth0 Offline \\n"',
-                    'LINE3:eon#00CC66:"Eth0 Online \\n"',
-                    'AREA:r_wlan0#6699CC:"Wlan0 In "',
-                    'VDEF:min3=r_wlan0,MINIMUM',
-                    'VDEF:max3=r_wlan0,MAXIMUM',
-                    'VDEF:avg3=r_wlan0,AVERAGE',
-                    'VDEF:tot3=r_wlan0,TOTAL',
-                    'GPRINT:max3:"Max %6.2lf%s"',
-                    'GPRINT:min3:"Min %6.2lf%s"',
-                    'GPRINT:avg3:"Avg %6.2lf%s"',
-                    'GPRINT:tot3:"Sum %6.2lf%s\\n"',
-                    'CDEF:xmit1=x_wlan0,-1,*',
-                    'AREA:xmit1#FF6666:"Wlan0 Out"',
-                    'VDEF:max4=x_wlan0,MAXIMUM',
-                    'VDEF:min4=x_wlan0,MINIMUM',
-                    'VDEF:avg4=x_wlan0,AVERAGE',
-                    'VDEF:tot4=x_wlan0,TOTAL',
-                    'GPRINT:max4:"Max %6.2lf%s"',
-                    'GPRINT:min4:"Min %6.2lf%s"',
-                    'GPRINT:avg4:"Avg %6.2lf%s"',
-                    'GPRINT:tot4:"Sum %6.2lf%s\\n"',
-                    ],
-               },
-            'power': {
-                'heartbeat': '600',
-                'min': '0',
-                'max': '100',
-                'title': '"%s Power State' % self.hostname,
-                'type': 'GAUGE',
-                'units': 'Percentage',
-                'items': ['state',],
-                'graph': [
-                    '-l 0 -r',
-                    'CDEF:bg=state,UN,0,state,IF,0,GT,UNKN,INF,IF',
-                    'AREA:bg#DDDDDD:',
-                    'VDEF:pstate=state,LAST',
-                    'AREA:pstate#CC3333:"Power Setting "',
-                    'VDEF:pstateMax=state,MAXIMUM',
-                    'VDEF:pstateMin=state,MINIMUM',
-                    'VDEF:pstateAvg=state,AVERAGE',
-                    'GPRINT:pstateMax:"Max %6.2lf%s%%"',
-                    'GPRINT:pstateMin:"Min %6.2lf%s%%"',
-                    'GPRINT:pstateAvg:"Avg %6.2lf%s%%\\n"',
-                    ],
-                },
-            'temp': {
-                'heartbeat': '600',
-                'min': '0',
-                'max': '100',
-                'title': '"%s Temperature Readings' % self.hostname,
-                'type': 'GAUGE',
-                'units': 'Celsius',
-                'items': [
-                    'cpu',
-                    ],
-                'graph': [
-                    '-l 20 -r',
-                    'CDEF:bg=cpu,UN,0,cpu,IF,0,GT,UNKN,INF,IF',
-                    'AREA:bg#DDDDDD:',
-                    'CDEF:cool=cpu,40,LE,cpu,UNKN,IF',
-                    'CDEF:warm=cpu,40,60,LIMIT',
-                    'CDEF:hot=cpu,60,GE,cpu,UNKN,IF',
-                    'AREA:cool#B0F5EC:"Cool "',
-                    'AREA:warm#FFCC00:"Warm "',
-                    'AREA:hot#CC3300:"Hot  \\n"',
-                    'VDEF:maxC=cpu,MAXIMUM',
-                    'VDEF:minC=cpu,MINIMUM',
-                    'VDEF:avgC=cpu,AVERAGE',
-                    'GPRINT:minC:"Min %2.1lf"',
-                    'GPRINT:maxC:"Max %2.1lf"',
-                    'GPRINT:avgC:"Avg %2.1lf Celsius \\n"',
-                    'LINE1:cpu#660000:',
-                    'HRULE:60#FF0000',
-                    'HRULE:20#FFA500',
-                    ],
-                },
-            'uptime': {
-                'heartbeat': '600',
-                'min': '0',
-                'max': 'U',
-                'title': '"%s Uptime Readings' % self.hostname,
-                'type': 'GAUGE',
-                'units': 'hours',
-                'items': [
-                    'uptime',
-                    'idletime',
-                    ],
-                'graph': [
-                    '-r',
-                    'CDEF:bg=uptime,UN,0,uptime,IF,0,GT,UNKN,INF,IF',
-                    'AREA:bg#DDDDDD:',
-                    'CDEF:upHours=uptime,3600,/',
-                    'CDEF:idleHours=idletime,3600,/',
-                    'AREA:upHours#99CC99:"Uptime  "',
-                    'GPRINT:upHours:MIN:"Min %8.2lf"',
-                    'GPRINT:upHours:MAX:"Max %8.2lf"',
-                    'GPRINT:upHours:AVERAGE:"Avg %8.2lf"',
-                    'GPRINT:upHours:LAST:"Last %8.2lf\\n"',
-                    'LINE2:idleHours#333333:"Idletime"',
-                    'GPRINT:idleHours:MIN:"Min %8.2lf"',
-                    'GPRINT:idleHours:MAX:"Max %8.2lf"',
-                    'GPRINT:idleHours:AVERAGE:"Avg %8.2lf"',
-                    'GPRINT:idleHours:LAST:"Last %8.2lf\\n"',
-                    ],
-                },
-            }
-
-        self.dd = data_def[datakey]
-
-    def Create(self):
-        """Create an empty RRD file.
-
-        Returns:
-            boolean: True = Success, False = failure.
-        """
-
-        stime = int(time()) -5 * 86400
-        rrd_suffix = ['RRA:AVERAGE:0.5:1:576',
-                      'RRA:AVERAGE:0.5:6:672',
-                      'RRA:AVERAGE:0.5:24:732',
-                      'RRA:AVERAGE:0.5:144:1460',
-                     ]
-
-        rrd_cmd = [self.rrdtool, 'create', self.rrdfile, '--start', str(stime),
-                   '--step', '300']
-        for ds in self.dd['items']:
-            ds_str = 'DS:%s:%s:%s:%s:%s' % (ds, self.dd['type'],
-                                            self.dd['heartbeat'],
-                                            self.dd['min'],
-                                            self.dd['max'])
-            rrd_cmd.append(ds_str)
-        rrd_cmd = rrd_cmd + rrd_suffix
-        # Convert the rrd_cmd to a string with space separated commands.
-        exec_str = ' '.join(rrd_cmd)
-        result = Exec(exec_str)
-        if result:
-            TB.logger.error('Error executing:')
-            TB.logger.error('%s\n', exec_str)
-
-        return result
-
-
-    def Update(self):
-        """Update an existing RRD file.
-
-        Returns:
-            boolean: True = Success, False = errors.
-        """
-        if len(TB.hosts[self.hostname]['rrddata'][self.rrdname]) < 2:
-            data = 'N:' + TB.hosts[self.hostname]['rrddata'][self.rrdname][0]
-        else:
-            data = 'N:' + ':'.join(
-                TB.hosts[self.hostname]['rrddata'][self.rrdname])
-        rrd_cmd = [self.rrdtool, 'update', self.rrdfile, data]
-        exec_str = ' '.join(rrd_cmd)
-        result = Exec(exec_str)
-        if result:
-            TB.logger.error('Error executing:')
-            TB.logger.error('%s\n', exec_str)
-
-        return result
-
-
-    def Graph(self):
-        """Create a graph of a tracked resource."""
-        width = '850'
-        height = '300'
-        end = 'now'
-        rcolor = {'release': '#9966FF',
-                  'firmware': '#990033',
-                  'ec_firmware': '#009933',
-                 }
-
-        for time in TB.rrdtimes:
-            png_filename = self.rrdname + time + '.png'
-            png_file = os.path.join(self.rrd_dir, png_filename)
-
-            title = self.dd['title'] + ' ' + time + '"'
-
-            rrd_cmd = [self.rrdtool, 'graph', png_file, '--imgformat PNG',
-                       '-s', time, '--end', end,
-                       '--width', width, '--height', height,
-                       '--vertical-label', self.dd['units'], '--title', title]
-
-            for ds in self.dd['items']:
-                rrd_cmd.append('DEF:%s=%s:%s:AVERAGE' % (ds, self.rrdfile, ds))
-            rrd_cmd = rrd_cmd + self.dd['graph']
-            rrd_cmd.append('COMMENT:"Release History \\s"')
-            rrd_cmd.append('COMMENT:"=============== \\n"')
-            for v in TB.version:
-                sorted_items = []
-                for k in TB.hosts[self.hostname][v]:
-                    if k != 'PTR':
-                        sorted_items.append(k)
-                    sorted_items.sort()
-                for i in sorted_items:
-                    # Get a date/time string to display, localtime requires
-                    # a float, so convert i to float.
-                    datetime = strftime('%D %H\\:%M', localtime(float(i)))
-                    # Need to escape any ':' for RRDTool.
-                    filter_val = (
-                        TB.hosts[self.hostname][v][i].replace(':', '\\:'))
-                    # Insert Veritical Lines for release and firmware updates.
-                    vrule = 'VRULE:%s%s:"%s %s=%s \\n"' % (i, rcolor[v],
-                            datetime, v, filter_val)
-                    rrd_cmd.append(vrule)
-
-            exec_str = ' '.join(rrd_cmd)
-            result = Exec(exec_str)
-            if result:
-                TB.logger.error('Error while running %s', exec_str)
-            if os.path.isfile(png_file):
-                os.chmod(png_file, 0644)
-
-
-class TBQueue(Queue.Queue):
-    """A subclass of class Queue to override join method with timeout."""
-
-    def __init__(self):
-        Queue.Queue.__init__(self)
-
-
-    def join(self, timeout=None):
-        deadline = None
-        waittime = None
-        if timeout:
-            deadline = time() + timeout
-        self.all_tasks_done.acquire()
-        try:
-            while self.unfinished_tasks:
-                if deadline:
-                    waittime = deadline - time()
-                    if waittime < 0:
-                        break
-                self.all_tasks_done.wait(waittime)
-        finally:
-            self.all_tasks_done.release()
-
-
-def Exec(cmd, output=False):
-    """Run subprocess.Popen() and return output if output=True.
-
-    Args:
-        cmd: string, represents command with arguments.
-        output: boolean, True=capture and return output.
-    Returns:
-        string if output = True
-        return code of command if output = False
-    """
-
-    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
-                         stderr=subprocess.PIPE)
-    p.wait()
-    out = p.stdout.read()
-    errors = p.stderr.read()
-    if p.returncode:
-        TB.logger.error(out)
-        TB.logger.error(errors)
-
-    if output:
-        return out
-    else:
-        return p.returncode
-
-
-def ParseArgs():
-    """Parse all command line options."""
-    # Assume Chrome OS source is located on /usr/local/google.
-    homedir = os.environ['HOME']
-    logfile = os.path.join(homedir, 'monitor.log')
-    cros_src = '/usr/local/google' + homedir + '/chromeos/src'
-    systemhealth_home = os.path.join(homedir, 'www', 'systemhealth')
-
-    parser = optparse.OptionParser(version= __version__)
-    parser.add_option('--debug',
-                      help='Set the debug level [default: %default]',
-                      type='choice',
-                      choices=['debug', 'info', 'warning', 'error',
-                               'critical',],
-                      default='info',
-                      dest='debug')
-    parser.add_option('--gclient',
-                      help='pathname of Chrome OS source [default: %default]',
-                      default=cros_src,
-                      dest='gclient')
-    parser.add_option('--graph',
-                      help='Create graphs for each host [default: %default]',
-                      default=False,
-                      dest='graph')
-    parser.add_option('--home',
-                      help='Systemhealth home directory [default: %default]',
-                      default=systemhealth_home,
-                      dest='home')
-    parser.add_option('--html',
-                      help='Build HTML pages for hosts [default: %default]',
-                      default=False,
-                      dest='html')
-    parser.add_option('--logfile',
-                      help='name of logfile [default: %default]',
-                      default=logfile,
-                      dest='logfile')
-    parser.add_option('--log_to_stdout',
-                      help='Send output to StdOut [default: %default]',
-                      default=False,
-                      dest='log_to_stdout')
-    parser.add_option('--update',
-                      help='Collect data from hosts [default: %default]',
-                      default=True,
-                      dest='update')
-    parser.add_option('--url',
-                      help='URL for landing page [default: %default]',
-                      default='http://www/~chromeos-test/systemhealth/',
-                      dest='url')
-
-    return parser.parse_args()
-
-
-def CheckRun(action):
-    """Check the run status of monitor.py, and add/remove run files.
-
-    This function will ensure we only running one program with either the graph
-    or update option.
-    Args:
-        action: string, indicates if monitor.py is starting or stopping.
-    """
-    if action == 'start':
-        if TB.update == True:
-            if os.path.isfile(TB.update_runfile):
-                TB.logger.info('Exiting, already running with update option')
-                sys.exit(1)
-            else:
-                try:
-                    open(TB.update_runfile, 'w').close()
-                except IOError, e:
-                    TB.logger.error('Error with %s\n%s', TB.update_runfile, e)
-        if TB.graph:
-            if os.path.isfile(TB.graph_runfile):
-                TB.logger.info('Exiting, already running with graph option')
-                sys.exit(1)
-            else:
-                try:
-                    open(TB.graph_runfile, 'w').close()
-                except IOError, e:
-                    TB.logger.error('Error with %s\n%s', TB.graph_runfile, e)
-    elif action == 'stop':
-        if TB.update == True:
-            if os.path.isfile(TB.update_runfile):
-                try:
-                    os.remove(TB.update_runfile)
-                except IOError, e:
-                    TB.logger.error('Error with %s\n%s', TB.update_runfile, e)
-        if TB.graph:
-            if os.path.isfile(TB.graph_runfile):
-                try:
-                    os.remove(TB.graph_runfile)
-                except IOError, e:
-                    TB.logger.error('Error with %s\n%s', TB.graph_runfile, e)
-    else:
-        TB.logger.error('Unknown option passed to CheckRun(): %s', action)
-        sys.exit(1)
-
-
-def main(argv):
-    options, args = ParseArgs()
-
-    global TB
-    TB = TestBed(options.logfile, options.log_to_stdout, options.debug,
-                 options.graph, options.home, options.html, options.gclient,
-                 options.update, options.url)
-    CheckRun('start')
-    sysmon = Monitor()
-    sysmon.UpdateStatus()
-    sysmon.BuildLandingPage()
-    runtime = time() - TB.time
-    endtime = strftime('%H:%M:%S', localtime())
-    TB.logger.info('End Time: %s', endtime)
-    TB.logger.info('Time of run: %s seconds', runtime)
-    TB.logger.info('Ran with %d threads', sysmon.hostqty)
-    CheckRun('stop')
-
-if __name__ == '__main__':
-    main(sys.argv)
diff --git a/utils/set_tree_status.py b/utils/set_tree_status.py
deleted file mode 100755
index d140eb7..0000000
--- a/utils/set_tree_status.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-#
-# This utility allows for easy update to chromium os tree status, with proper
-# password protected authorization.
-#
-# Example usage:
-# ./set_tree_status.py [options] "a quoted space separated message."
-
-import getpass
-import optparse
-import os
-import sys
-import urllib
-
-CHROMEOS_STATUS_SERVER = 'https://chromiumos-status.appspot.com'
-
-
-def get_status():
-    response = urllib.urlopen(CHROMEOS_STATUS_SERVER + '/current?format=raw')
-    return response.read()
-
-
-def get_pwd():
-    password_file = os.path.join('/home', getpass.getuser(),
-                                 '.status_password.txt')
-    if os.path.isfile(password_file):
-        return open(password_file, 'r').read().strip()
-    return getpass.getpass()
-
-
-def post_status(force, message):
-    if not force:
-        status = get_status()
-        if 'tree is closed' in status.lower():
-            print >> sys.stderr, 'Tree is already closed for some other reason.'
-            print >> sys.stderr, status
-            return -1
-    data = {
-        'message': message,
-        'username': getpass.getuser(),
-        'password': get_pwd(),
-    }
-    urllib.urlopen(CHROMEOS_STATUS_SERVER + '/status', urllib.urlencode(data))
-    return 0
-
-
-if __name__ == '__main__':
-    parser = optparse.OptionParser("%prog [options] quoted_message")
-    parser.add_option('--noforce',
-                      dest='force', action='store_false',
-                      default=True,
-                      help='Dont force to close tree if it is already closed.')
-    options, args = parser.parse_args()
-    if not args:
-        print >> sys.stderr, 'missing tree close message.'
-    sys.exit(post_status(options.force, args[0]))