Exemplo n.º 1
0
 def initialize(self, context):
     # pylint: disable=access-member-before-definition
     self.in_chroot = False if which('dut-control') is None else True
     self.poller = None
     domains_string = '_mw '.join(self.power_domains + [''])
     password = ''
     if not self.in_chroot:
         self.logger.info('Instrument {} requires sudo acces on this machine'.format(self.name))
         self.logger.info('You need to be sudoer to use it.')
         password = getpass.getpass()
         check = subprocess.call('echo {} | sudo -S ls > /dev/null'.format(password), shell=True)
         if check:
             raise InstrumentError('Given password was either wrong or you are not a sudoer')
     self.server_session = CrosSdkSession(self.chroot_path, password=password)
     self.cros_session = CrosSdkSession(self.chroot_path, password=password)
     password = ''
     self.server_session.send_command('sudo servod -b {b} -c {b}.xml&'.format(b=self.board_name))
     checks = 0
     while True:
         if checks >= self.servod_max_tries:
             raise InstrumentError('Failed to start servod in cros_sdk environment')
         server_lines = self.server_session.get_lines(timeout=1, from_stderr=True,
                                                      timeout_only_for_first_line=False)
         if server_lines and 'Listening on' in server_lines[-1]:
             break
         time.sleep(self.servod_delay_between_tries)
         checks += 1
     self.port = int(server_lines[-1].split()[-1])
     self.command = 'dut-control {} -p {}'.format(domains_string, self.port)
     if not self.labels:
         self.labels = ["PORT_{}".format(channel) for channel, _ in enumerate(self.power_domains)]
     self.power_data = None
     self.stopped = True
Exemplo n.º 2
0
    def _start_servod(self):
        in_chroot = False if which('dut-control') is None else True
        password = ''
        if not in_chroot:
            msg = 'Instrument %s requires sudo access on this machine to start `servod`'
            self.logger.info(msg, self.name)
            self.logger.info('You need to be sudoer to use it.')
            password = getpass.getpass()
            check = subprocess.call('echo {} | sudo -S ls > /dev/null'.format(password), shell=True)
            if check:
                raise InstrumentError('Given password was either wrong or you are not a sudoer')
        self.server_session = CrosSdkSession(self.chroot_path, password=password)
        password = ''

        command = 'sudo servod -b {b} -c {b}.xml'
        if self.vid and self.pid:
            command += " -v " + self.vid
            command += " -p " + self.pid
        command += '&'
        self.server_session.send_command(command.format(b=self.board_name))
        for _ in xrange(self.servod_max_tries):
            server_lines = self.server_session.get_lines(timeout=1, from_stderr=True,
                                                         timeout_only_for_first_line=False)
            if server_lines:
                if 'Listening on' in server_lines[-1]:
                    self.port = int(server_lines[-1].split()[-1])
                    break
            time.sleep(self.servod_delay_between_tries)
        else:
            raise InstrumentError('Failed to start servod in cros_sdk environment')
Exemplo n.º 3
0
class ServoPowerMonitor(Instrument):

    name = 'servo_power_monitor'
    description = """Collects power traces using the Chromium OS Servo Board.

                     Servo is a debug board used for Chromium OS test and development. Among other uses, it allows
                     access to the built in power monitors (if present) of a Chrome OS device. More information on
                     Servo board can be found in the link bellow:

                     https://www.chromium.org/chromium-os/servo

                     In order to use this instrument you need to be a sudoer and you need a chroot environment. More
                     information on the chroot environment can be found on the link bellow:

                     https://www.chromium.org/chromium-os/developer-guide

                    """

    parameters = [
        Parameter('power_domains', kind=list_of_strings, default=[],
                  description="""The names of power domains to be monitored by the instrument using servod."""),
        Parameter('labels', kind=list_of_strings, default=[],
                  description="""Meaningful labels for each of the monitored domains."""),
        Parameter('chroot_path', kind=str, default='',
                  description="""Path to chroot direcory on the host."""),
        Parameter('sampling_rate', kind=int, default=10,
                  description="""Samples per second."""),
        Parameter('board_name', kind=str, mandatory=True,
                  description="""The name of the board under test."""),
    ]

    # When trying to initialize servod, it may take some time until the server is up
    # Therefore we need to poll to identify when the sever has successfully started
    # servod_max_tries specifies the maximum number of times we will check to see if the server has started
    # while servod_delay_between_tries is the sleep time between checks.
    servod_max_tries = 100
    servod_delay_between_tries = 0.1

    def initialize(self, context):
        # pylint: disable=access-member-before-definition
        self.in_chroot = False if which('dut-control') is None else True
        self.poller = None
        domains_string = '_mw '.join(self.power_domains + [''])
        password = ''
        if not self.in_chroot:
            self.logger.info('Instrument {} requires sudo acces on this machine'.format(self.name))
            self.logger.info('You need to be sudoer to use it.')
            password = getpass.getpass()
            check = subprocess.call('echo {} | sudo -S ls > /dev/null'.format(password), shell=True)
            if check:
                raise InstrumentError('Given password was either wrong or you are not a sudoer')
        self.server_session = CrosSdkSession(self.chroot_path, password=password)
        self.cros_session = CrosSdkSession(self.chroot_path, password=password)
        password = ''
        self.server_session.send_command('sudo servod -b {b} -c {b}.xml&'.format(b=self.board_name))
        checks = 0
        while True:
            if checks >= self.servod_max_tries:
                raise InstrumentError('Failed to start servod in cros_sdk environment')
            server_lines = self.server_session.get_lines(timeout=1, from_stderr=True,
                                                         timeout_only_for_first_line=False)
            if server_lines and 'Listening on' in server_lines[-1]:
                break
            time.sleep(self.servod_delay_between_tries)
            checks += 1
        self.port = int(server_lines[-1].split()[-1])
        self.command = 'dut-control {} -p {}'.format(domains_string, self.port)
        if not self.labels:
            self.labels = ["PORT_{}".format(channel) for channel, _ in enumerate(self.power_domains)]
        self.power_data = None
        self.stopped = True

    def validate(self):
        if self.labels and not len(self.power_domains) == len(self.labels):
            raise ConfigError('There should be exactly one label per power domain')

    def setup(self, context):
        # pylint: disable=access-member-before-definition
        self.output_directory = os.path.join(context.output_directory, 'servo_power_monitor')
        self.outfiles = [os.path.join(self.output_directory, '{}.csv'.format(label)) for label in self.labels]
        self.poller = PowerPoller(self.cros_session, self.command, self.outfiles, self.sampling_rate)

    def start(self, context):
        self.poller.start()
        self.stopped = False

    def stop(self, context):
        self.power_data = self.poller.stop()
        self.poller.join()
        self.stopped = True

    def update_result(self, context):
        os.mkdir(os.path.dirname(self.outfiles[0]))
        for i, outfile in enumerate(self.outfiles):
            self.power_data[i] = [float(v) / 1000.0 for v in self.power_data[i]]
            metric_name = '{}_power'.format(self.labels[i])
            sample_sum = sum(self.power_data[i])
            power = sample_sum / len(self.power_data[i])
            context.result.add_metric(metric_name, round(power, 3), 'Watts')
            metric_name = '{}_energy'.format(self.labels[i])
            energy = sample_sum * (1.0 / self.sampling_rate)
            context.result.add_metric(metric_name, round(energy, 3), 'Joules')
            with open(outfile, 'wb') as f:
                c = csv.writer(f)
                c.writerow(['{}_power'.format(self.labels[i])])
                for val in self.power_data[i]:
                    c.writerow([val])

    def teardown(self, context):
        if not self.stopped:
            self.stop(context)
        self.server_session.kill_session()
        self.cros_session.kill_session()
Exemplo n.º 4
0
class ServoPowerMonitor(Instrument):

    name = 'servo_power'
    description = """
    Collects power traces using the Chromium OS Servo Board.

    Servo is a debug board used for Chromium OS test and development. Among other uses, it allows
    access to the built in power monitors (if present) of a Chrome OS device. More information on
    Servo board can be found in the link bellow:

    https://www.chromium.org/chromium-os/servo

    In order to use this instrument you need to be a sudoer and you need a chroot environment. More
    information on the chroot environment can be found on the link bellow:

    https://www.chromium.org/chromium-os/developer-guide

    If you wish to run servod on a remote machine you will need to allow it to accept external connections
    using the `--host` command line option, like so:
    `sudo servod -b some_board -c some_board.xml --host=''`

    """

    parameters = [
        Parameter('power_domains', kind=list_of_strings, default=[],
                  description="""The names of power domains to be monitored by the
                                 instrument using servod."""),
        Parameter('labels', kind=list_of_strings, default=[],
                  description="""Meaningful labels for each of the monitored domains."""),
        Parameter('chroot_path', kind=str,
                  description="""Path to chroot direcory on the host."""),
        Parameter('sampling_rate', kind=int, default=10,
                  description="""Samples per second."""),
        Parameter('board_name', kind=str, mandatory=True,
                  description="""The name of the board under test."""),
        Parameter('autostart', kind=bool, default=True,
                  description="""Automatically start `servod`. Set to `False` if you want to
                                 use an already running `servod` instance or a remote servo"""),
        Parameter('host', kind=str, default="localhost",
                  description="""When `autostart` is set to `False` you can specify the host
                                 on which `servod` is running allowing you to remotelly access
                                 as servo board.

                                 if `autostart` is `True` this parameter is ignored and `localhost`
                                 is used instead"""),
        Parameter('port', kind=int, default=9999,
                  description="""When `autostart` is set to false you must provide the port
                                 that `servod` is running on

                                 If `autostart` is `True` this parameter is ignored and the port
                                 output during the startup of `servod` will be used."""),
        Parameter('vid', kind=str,
                  description="""When more than one servo is plugged in, you must provide
                                 a vid/pid pair to identify the servio you wish to use."""),
        Parameter('pid', kind=str,
                  description="""When more than one servo is plugged in, you must provide
                                 a vid/pid pair to identify the servio you wish to use."""),
    ]

    # When trying to initialize servod, it may take some time until the server is up
    # Therefore we need to poll to identify when the sever has successfully started
    # servod_max_tries specifies the maximum number of times we will check to see if the server has started
    # while servod_delay_between_tries is the sleep time between checks.
    servod_max_tries = 100
    servod_delay_between_tries = 0.1

    def validate(self):
        # pylint: disable=access-member-before-definition
        if self.labels and len(self.power_domains) != len(self.labels):
            raise ConfigError('There should be exactly one label per power domain')
        if self.autostart:
            if self.host != 'localhost':  # pylint: disable=access-member-before-definition
                self.logger.warning('Ignoring host "%s" since autostart is set to "True"', self.host)
                self.host = "localhost"
        if (self.vid is None) != (self.pid is None):
            raise ConfigError('`vid` and `pid` must both be specified')

    def initialize(self, context):
        # pylint: disable=access-member-before-definition
        self.poller = None
        self.data = None
        self.stopped = True

        if self.device.platform != "chromeos":
            raise InstrumentError("servo_power instrument only supports Chrome OS devices.")

        if not self.labels:
            self.labels = ["PORT_{}".format(channel) for channel, _ in enumerate(self.power_domains)]

        self.power_domains = [channel if channel.endswith("_mw") else
                              "{}_mw".format(channel) for channel in self.power_domains]
        self.label_map = {pd: l for pd, l in zip(self.power_domains, self.labels)}

        if self.autostart:
            self._start_servod()

    def setup(self, context):
        # pylint: disable=access-member-before-definition
        self.outfile = os.path.join(context.output_directory, 'servo.csv')
        self.poller = PowerPoller(self.host, self.port, self.power_domains, self.sampling_rate)

    def start(self, context):
        self.poller.start()
        self.stopped = False

    def stop(self, context):
        self.data = self.poller.stop()
        self.poller.join()
        self.stopped = True

        timestamps = self.data.pop("timestamp")
        for channel, data in self.data.iteritems():
            label = self.label_map[channel]
            data = [float(v) / 1000.0 for v in data]
            sample_sum = sum(data)

            metric_name = '{}_power'.format(label)
            power = sample_sum / len(data)
            context.result.add_metric(metric_name, round(power, 3), 'Watts')

            metric_name = '{}_energy'.format(label)
            energy = sample_sum * (1.0 / self.sampling_rate)
            context.result.add_metric(metric_name, round(energy, 3), 'Joules')

        with open(self.outfile, 'wb') as f:
            c = csv.writer(f)
            headings = ['timestamp'] + ['{}_power'.format(label) for label in self.labels]
            c.writerow(headings)
            for row in zip(timestamps, *self.data.itervalues()):
                c.writerow(row)

    def teardown(self, context):
        if not self.stopped:
            self.stop(context)
        if self.autostart:
            self.server_session.kill_session()

    def _start_servod(self):
        in_chroot = False if which('dut-control') is None else True
        password = ''
        if not in_chroot:
            msg = 'Instrument %s requires sudo access on this machine to start `servod`'
            self.logger.info(msg, self.name)
            self.logger.info('You need to be sudoer to use it.')
            password = getpass.getpass()
            check = subprocess.call('echo {} | sudo -S ls > /dev/null'.format(password), shell=True)
            if check:
                raise InstrumentError('Given password was either wrong or you are not a sudoer')
        self.server_session = CrosSdkSession(self.chroot_path, password=password)
        password = ''

        command = 'sudo servod -b {b} -c {b}.xml'
        if self.vid and self.pid:
            command += " -v " + self.vid
            command += " -p " + self.pid
        command += '&'
        self.server_session.send_command(command.format(b=self.board_name))
        for _ in xrange(self.servod_max_tries):
            server_lines = self.server_session.get_lines(timeout=1, from_stderr=True,
                                                         timeout_only_for_first_line=False)
            if server_lines:
                if 'Listening on' in server_lines[-1]:
                    self.port = int(server_lines[-1].split()[-1])
                    break
            time.sleep(self.servod_delay_between_tries)
        else:
            raise InstrumentError('Failed to start servod in cros_sdk environment')