Home | History | Annotate | Download | only in platform_BootPerfServer
      1 # Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import logging
      6 import os
      7 import re
      8 import shutil
      9 import traceback
     10 from autotest_lib.client.common_lib import error
     11 from autotest_lib.client.bin import utils
     12 from autotest_lib.server import test, autotest
     13 
     14 
     15 LOWER_IS_BETTER_METRICS = set(['rdbytes', 'seconds'])
     16 
     17 
     18 class platform_BootPerfServer(test.test):
     19     """A test that reboots the client and collect boot perf data."""
     20     version = 1
     21 
     22 
     23     def upload_perf_keyvals(self, keyvals):
     24         """Upload perf keyvals in dictionary |keyvals| to Chrome perf dashboard.
     25 
     26         This method assumes that the key of a perf keyval is in the format
     27         of "units_description". The text before the first underscore represents
     28         the units and the rest of the text represents
     29         a description of the measured perf value. For instance,
     30         'seconds_kernel_to_login', 'rdbytes_kernel_to_startup'.
     31 
     32         @param keyvals: A dictionary that maps a perf metric to its value.
     33 
     34         """
     35         for key, val in keyvals.items():
     36             match = re.match(r'^(.+?)_.+$', key)
     37             if match:
     38                 units = match.group(1)
     39                 higher_is_better = units not in LOWER_IS_BETTER_METRICS
     40                 self.output_perf_value(
     41                         description=key, value=val,
     42                         units=units, higher_is_better=higher_is_better)
     43 
     44 
     45     def run_once(self, host=None, upload_perf=False):
     46         self.client = host
     47         self.client_test = 'platform_BootPerf'
     48 
     49         # Run a login test to complete the OOBE flow, if we haven't already.
     50         # This is so that we measure boot times for the stable state.
     51         try:
     52             self.client.run('ls /home/chronos/.oobe_completed')
     53         except error.AutoservRunError:
     54             logging.info('Taking client through OOBE.')
     55             client_at = autotest.Autotest(self.client)
     56             client_at.run_test('login_LoginSuccess', disable_sysinfo=True)
     57 
     58         # Reboot the client
     59         logging.info('BootPerfServer: reboot %s', self.client.hostname)
     60         try:
     61             self.client.reboot(reboot_timeout=90)
     62         except error.AutoservRebootError as e:
     63             raise error.TestFail('%s.\nTest failed with error %s' % (
     64                     traceback.format_exc(), str(e)))
     65 
     66         # Collect the performance metrics by running a client side test
     67         logging.info('BootPerfServer: start client test')
     68         client_at = autotest.Autotest(self.client)
     69         client_at.run_test(
     70             self.client_test, last_boot_was_reboot=True, disable_sysinfo=True)
     71 
     72         # In the client results directory are a 'keyval' file, and
     73         # various raw bootstat data files.  First promote the client
     74         # test 'keyval' as our own.
     75         logging.info('BootPerfServer: gather client results')
     76         client_results_dir = os.path.join(
     77             self.outputdir, self.client_test, "results")
     78         src = os.path.join(client_results_dir, "keyval")
     79         dst = os.path.join(self.resultsdir, "keyval")
     80         if os.path.exists(src):
     81             client_results = open(src, "r")
     82             server_results = open(dst, "a")
     83             shutil.copyfileobj(client_results, server_results)
     84             server_results.close()
     85             client_results.close()
     86         else:
     87             logging.warning('Unable to locate %s', src)
     88 
     89         # Upload perf keyvals in the client keyval file to perf dashboard.
     90         if upload_perf:
     91             logging.info('Output perf data for iteration %03d', self.iteration)
     92             perf_keyvals = utils.read_keyval(src, type_tag='perf')
     93             self.upload_perf_keyvals(perf_keyvals)
     94 
     95         # Everything that isn't the client 'keyval' file is raw data
     96         # from the client test:  move it to a per-iteration
     97         # subdirectory.  We move instead of copying so we can be sure
     98         # we don't have any stale results in the next iteration
     99         if self.iteration is not None:
    100             rawdata_dir = "rawdata.%03d" % self.iteration
    101         else:
    102             rawdata_dir = "rawdata"
    103         rawdata_dir = os.path.join(self.resultsdir, rawdata_dir)
    104         shutil.move(client_results_dir, rawdata_dir)
    105         try:
    106             os.remove(os.path.join(rawdata_dir, "keyval"))
    107         except Exception:
    108             pass
    109