blob: 5e935f9a534b7073c12518f24c5ae9e13f4e7d96 [file] [log] [blame]
# Copyright 2015 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.
"""cros devices: List and configure Brillo devices connected over USB."""
from __future__ import print_function
from chromite.cli import command
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging
from chromite.lib import remote_access
@command.CommandDecorator('devices')
class DevicesCommand(command.CliCommand):
"""List and configure Brillo devices connected over USB.
This command takes an optional subcommand: "alias" or "full-reset". If no
subcommand is given, this command will print out information of USB-connected
Brillo devices. No other subcommand is supported.
When multiple Brillo devices are connected over USB, "--device" flag can be
used to specify which device is targeted.
"""
EPILOG = """
To list information of USB-connected devices:
cros devices
To set the device's alias to "toaster1":
cros devices alias toaster1
To reset the device to a fresh image for the current SDK version:
cros devices full-reset
"""
# Override base class property to enable stats upload.
upload_stats = True
ALIAS_CMD = 'alias'
FULL_RESET_CMD = 'full-reset'
def __init__(self, options):
"""Initialize DevicesCommand."""
super(DevicesCommand, self).__init__(options)
self.cmd = None
self.alias_name = None
self.device = None
# SSH connection settings.
self.ssh_hostname = None
self.ssh_port = None
self.ssh_username = None
self.ssh_private_key = None
@classmethod
def AddParser(cls, parser):
"""Add parser arguments."""
super(cls, DevicesCommand).AddParser(parser)
# Device argument is always optional for the `devices` tool.
cls.AddDeviceArgument(parser, optional=True)
parser.add_argument(
'--private-key', type='path', default=None,
help='SSH identify file (private key).')
parser.add_argument(
'subcommand', nargs='?',
help='Optional subcommand ("alias" or "full-reset").')
parser.add_argument(
'alias_name', nargs='?',
help='The user-friendly alias name for the device. This is needed only '
'when "alias" subcommand is used.')
def _ReadOptions(self):
"""Process options and set variables."""
self.cmd = self.options.subcommand
if self.cmd and self.cmd not in (self.ALIAS_CMD, self.FULL_RESET_CMD):
cros_build_lib.Die('Invalid subcommand: %s', self.cmd)
self.alias_name = self.options.alias_name
if self.cmd == self.FULL_RESET_CMD and self.alias_name:
cros_build_lib.Die('Extra argument: %s', self.alias_name)
if self.cmd == self.ALIAS_CMD and not self.alias_name:
cros_build_lib.Die('Missing alias argument')
if self.options.device:
self.ssh_hostname = self.options.device.hostname
self.ssh_username = self.options.device.username
self.ssh_port = self.options.device.port
self.ssh_private_key = self.options.private_key
def _PrintDeviceInfo(self, devices):
"""Print out information about devices."""
rows = [('Alias Name', 'IP Address')]
rows.extend((device.alias, device.hostname) for device in devices)
# Number of offset spaces for the second column. Get the max length of items
# in the first column, and add 4 extra spaces to make a clear table view.
offset = max(len(row[0]) for row in rows) + 4
for row in rows:
print('%-*s%s' % (offset, row[0], row[1]))
def _ListDevices(self):
"""List all USB-connected Brillo devices."""
devices = remote_access.GetUSBConnectedDevices()
if devices:
print('Info of all USB-connected Brillo devices:')
self._PrintDeviceInfo(devices)
else:
print('No USB-connected Brillo devices are found.')
def _FullReset(self):
"""Perform a full reset for the device."""
logging.info('Ready to full reset the device.')
# TODO(yimingc): Implement the full reset functionality.
def Run(self):
"""Run cros devices."""
self.options.Freeze()
self._ReadOptions()
try:
if self.cmd == self.ALIAS_CMD:
try:
with remote_access.ChromiumOSDeviceHandler(
self.ssh_hostname, port=self.ssh_port, username=self.ssh_username,
private_key=self.ssh_private_key) as device:
device.SetAlias(self.alias_name)
except remote_access.InvalidDevicePropertyError as e:
cros_build_lib.Die('The alias provided is invalid: %s', e)
elif self.cmd == self.FULL_RESET_CMD:
self._FullReset()
else:
if self.options.device:
with remote_access.ChromiumOSDeviceHandler(
self.ssh_hostname, port=self.ssh_port, username=self.ssh_username,
private_key=self.ssh_private_key) as device:
self._PrintDeviceInfo([device])
else:
self._ListDevices()
except (Exception, KeyboardInterrupt) as e:
cros_build_lib.Die('Command failed: %s', e)