diff options
author | Stevan Radakovic <stevan.radakovic@linaro.org> | 2018-02-19 12:28:32 +0100 |
---|---|---|
committer | Stevan Radakovic <stevan.radakovic@linaro.org> | 2018-02-19 15:53:07 +0100 |
commit | 04f269f006a91ad48dce615972316f728344116a (patch) | |
tree | f44737dce1ce54b9a29c060e8470a8983ebfbdc0 | |
parent | e4de3220859df10124d0c0a89a3db99ce98fc614 (diff) |
LAVA-107 - Drop lava-dashboard-tool
Drop lava_dashboard_tool module and update the documentation.
Drop v1 device configuration.
Change-Id: I0d1f9bd0bf8c492b45ca8a784b057f249f1814f0
-rw-r--r-- | MANIFEST.in | 1 | ||||
-rwxr-xr-x | ci-run | 2 | ||||
-rw-r--r-- | entry_points.ini | 43 | ||||
-rw-r--r-- | lava/device/__init__.py | 97 | ||||
-rw-r--r-- | lava/device/commands.py | 132 | ||||
-rw-r--r-- | lava/device/templates.py | 82 | ||||
-rw-r--r-- | lava/device/tests/__init__.py | 0 | ||||
-rw-r--r-- | lava/device/tests/test_commands.py | 198 | ||||
-rw-r--r-- | lava/device/tests/test_device.py | 119 | ||||
-rw-r--r-- | lava/helper/dispatcher.py | 70 | ||||
-rw-r--r-- | lava/helper/tests/test_dispatcher.py | 77 | ||||
-rw-r--r-- | lava_dashboard_tool/__init__.py | 23 | ||||
-rw-r--r-- | lava_dashboard_tool/commands.py | 786 | ||||
-rw-r--r-- | lava_dashboard_tool/main.py | 38 | ||||
-rw-r--r-- | lava_dashboard_tool/tests/__init__.py | 0 | ||||
-rw-r--r-- | lava_dashboard_tool/tests/test_commands.py | 44 | ||||
-rw-r--r-- | lava_scheduler_tool/commands.py | 59 | ||||
-rw-r--r-- | lava_tool/tests/__init__.py | 4 | ||||
-rw-r--r-- | man/lava-tool.rst | 209 | ||||
-rw-r--r-- | man/lava.rst | 133 |
20 files changed, 2 insertions, 2115 deletions
diff --git a/MANIFEST.in b/MANIFEST.in index 7cb6e6d..38af42a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -14,6 +14,5 @@ include integration-tests include man/* recursive-include integration-tests.d/ * recursive-include lava *.py *.yaml -recursive-include lava_dashboard_tool/ *.py recursive-include lava_scheduler_tool/ *.py recursive-include lava_tool/ *.py @@ -4,10 +4,8 @@ set -e pep8 --ignore E501,E722 lava pep8 --ignore E501,E722 lava_scheduler_tool -pep8 --ignore E501,E722,W291 lava_dashboard_tool pep8 --ignore E501,E722 lava_tool python -m unittest discover lava -v python -m unittest discover lava_tool -v -python -m unittest discover lava_dashboard_tool -v python -m unittest discover lava_scheduler_tool -v diff --git a/entry_points.ini b/entry_points.ini index 0c3feb9..9055575 100644 --- a/entry_points.ini +++ b/entry_points.ini @@ -1,14 +1,11 @@ [console_scripts] lava-tool = lava_tool.dispatcher:main lava = lava.tool.main:LavaDispatcher.run -lava-dashboard-tool=lava_dashboard_tool.main:main [lava.commands] help = lava.tool.commands.help:help scheduler = lava_scheduler_tool.commands:scheduler -dashboard = lava_dashboard_tool.commands:dashboard job = lava.job.commands:job -device = lava.device.commands:device testdef = lava.testdef.commands:testdef init = lava.commands:init submit = lava.commands:submit @@ -34,16 +31,6 @@ wait-job-events = lava_scheduler_tool.commands:wait_job_events jobs-list=lava_scheduler_tool.commands:jobs_list devices-list=lava_scheduler_tool.commands:devices_list get-pipeline-device-config = lava_scheduler_tool.commands:get_pipeline_device_config -bundles=lava_dashboard_tool.commands:bundles -data_views=lava_dashboard_tool.commands:data_views -deserialize=lava_dashboard_tool.commands:deserialize -get=lava_dashboard_tool.commands:get -make_stream=lava_dashboard_tool.commands:make_stream -pull=lava_dashboard_tool.commands:pull -put=lava_dashboard_tool.commands:put -query_data_view=lava_dashboard_tool.commands:query_data_view -server_version=lava_dashboard_tool.commands:server_version -streams=lava_dashboard_tool.commands:streams compare-device-conf=lava_scheduler_tool.commands:compare_device_conf device-dictionary = lava_scheduler_tool.commands:device_dictionary validate-pipeline-devices = lava_scheduler_tool.commands:validate_pipeline_devices @@ -63,30 +50,6 @@ jobs-list=lava_scheduler_tool.commands:jobs_list devices-list=lava_scheduler_tool.commands:devices_list get-pipeline-device-config = lava_scheduler_tool.commands:get_pipeline_device_config -[lava.dashboard.commands] -bundles=lava_dashboard_tool.commands:bundles -data_views=lava_dashboard_tool.commands:data_views -deserialize=lava_dashboard_tool.commands:deserialize -get=lava_dashboard_tool.commands:get -make_stream=lava_dashboard_tool.commands:make_stream -pull=lava_dashboard_tool.commands:pull -put=lava_dashboard_tool.commands:put -query_data_view=lava_dashboard_tool.commands:query_data_view -server_version=lava_dashboard_tool.commands:server_version -streams=lava_dashboard_tool.commands:streams - -[lava_dashboard_tool.commands] -bundles=lava_dashboard_tool.commands:bundles -data_views=lava_dashboard_tool.commands:data_views -deserialize=lava_dashboard_tool.commands:deserialize -get=lava_dashboard_tool.commands:get -make_stream=lava_dashboard_tool.commands:make_stream -pull=lava_dashboard_tool.commands:pull -put=lava_dashboard_tool.commands:put -query_data_view=lava_dashboard_tool.commands:query_data_view -server_version=lava_dashboard_tool.commands:server_version -streams=lava_dashboard_tool.commands:streams - [lava.job.commands] new = lava.job.commands:new submit = lava.job.commands:submit @@ -94,12 +57,6 @@ status = lava.job.commands:status details = lava.job.commands:details run = lava.job.commands:run -[lava.device.commands] -add = lava.device.commands:add -remove = lava.device.commands:remove -config = lava.device.commands:config -list = lava.device.commands:list - [lava.testdef.commands] new = lava.testdef.commands:new run = lava.testdef.commands:run diff --git a/lava/device/__init__.py b/lava/device/__init__.py deleted file mode 100644 index 35fe181..0000000 --- a/lava/device/__init__.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (C) 2013 Linaro Limited -# -# Author: Milo Casagrande <milo.casagrande@linaro.org> -# -# This file is part of lava-tool. -# -# lava-tool is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# as published by the Free Software Foundation -# -# lava-tool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with lava-tool. If not, see <http://www.gnu.org/licenses/>. - -"""Device class.""" - -import re - -from copy import deepcopy - -from lava.device.templates import ( - DEFAULT_TEMPLATE, - HOSTNAME_PARAMETER, - KNOWN_TEMPLATES, -) -from lava.helper.template import expand_template - - -def __re_compile(name): - """Creates a generic regex for the specified device name. - - :param name: The name of the device. - :return A Pattern object. - """ - return re.compile('^.*{0}.*'.format(name), re.I) - - -# Dictionary of know devices. -# Keys are the general device name taken from lava.device.templates, values -# are tuples of: a regex matcher to match the device, and the device associated -# template. -KNOWN_DEVICES = dict([(device, (__re_compile(device), template)) - for device, template in KNOWN_TEMPLATES.iteritems()]) - - -class Device(object): - - """A generic device.""" - - def __init__(self, data, hostname=None): - self.data = deepcopy(data) - self.hostname = hostname - - def write(self, conf_file): - """Writes the object to file. - - :param conf_file: The full path of the file where to write.""" - with open(conf_file, 'w') as write_file: - write_file.write(str(self)) - - def update(self, config): - """Updates the Device object values based on the provided config. - - :param config: A Config instance. - """ - # We should always have a hostname, since it defaults to the name - # given on the command line for the config file. - if self.hostname is not None: - # We do not ask the user again this parameter. - self.data[HOSTNAME_PARAMETER.id].value = self.hostname - self.data[HOSTNAME_PARAMETER.id].asked = True - - expand_template(self.data, config) - - def __str__(self): - string_list = [] - for key, value in self.data.iteritems(): - string_list.append("{0} = {1}\n".format(str(key), str(value))) - return "".join(string_list) - - -def get_known_device(name): - """Tries to match a device name with a known device type. - - :param name: The name of the device we want matched to a real device. - :return A Device instance. - """ - instance = Device(DEFAULT_TEMPLATE, hostname=name) - for _, (matcher, dev_template) in KNOWN_DEVICES.iteritems(): - if matcher.match(name): - instance = Device(dev_template, hostname=name) - break - return instance diff --git a/lava/device/commands.py b/lava/device/commands.py deleted file mode 100644 index a3a790a..0000000 --- a/lava/device/commands.py +++ /dev/null @@ -1,132 +0,0 @@ -# Copyright (C) 2013 Linaro Limited -# -# Author: Milo Casagrande <milo.casagrande@linaro.org> -# -# This file is part of lava-tool. -# -# lava-tool is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# as published by the Free Software Foundation -# -# lava-tool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with lava-tool. If not, see <http://www.gnu.org/licenses/>. - -""" -Device specific commands class. -""" - -import os -import sys - -from lava.device import get_known_device -from lava.helper.command import ( - BaseCommand, -) -from lava.helper.dispatcher import ( - get_device_file, - get_devices_path, - get_devices, -) -from lava.tool.command import CommandGroup -from lava.tool.errors import CommandError -from lava_tool.utils import ( - can_edit_file, - edit_file, -) - -DEVICE_FILE_SUFFIX = "conf" - - -class device(CommandGroup): - """LAVA devices handling.""" - - namespace = "lava.device.commands" - - -class add(BaseCommand): - """Adds a new device.""" - - @classmethod - def register_arguments(cls, parser): - super(add, cls).register_arguments(parser) - parser.add_argument("DEVICE", help="The name of the device to add.") - - def invoke(self): - real_file_name = ".".join([self.args.DEVICE, DEVICE_FILE_SUFFIX]) - - if get_device_file(real_file_name) is not None: - print >> sys.stdout, ("A device configuration file named '{0}' " - "already exists.".format(real_file_name)) - print >> sys.stdout, ("Use 'lava device config {0}' to edit " - "it.".format(self.args.DEVICE)) - sys.exit(-1) - - devices_path = get_devices_path() - device_conf_file = os.path.abspath(os.path.join(devices_path, - real_file_name)) - - device = get_known_device(self.args.DEVICE) - device.update(self.config) - device.write(device_conf_file) - - print >> sys.stdout, ("Created device file '{0}' in: {1}".format( - real_file_name, devices_path)) - edit_file(device_conf_file) - - -class remove(BaseCommand): - """Removes the specified device.""" - - @classmethod - def register_arguments(cls, parser): - super(remove, cls).register_arguments(parser) - parser.add_argument("DEVICE", - help="The name of the device to remove.") - - def invoke(self): - real_file_name = ".".join([self.args.DEVICE, DEVICE_FILE_SUFFIX]) - device_conf = get_device_file(real_file_name) - - if device_conf: - try: - os.remove(device_conf) - print >> sys.stdout, ("Device configuration file '{0}' " - "removed.".format(real_file_name)) - except OSError: - raise CommandError("Cannot remove file '{0}' at: {1}.".format( - real_file_name, os.path.dirname(device_conf))) - else: - print >> sys.stdout, ("No device configuration file '{0}' " - "found.".format(real_file_name)) - - -class config(BaseCommand): - """Opens the specified device config file.""" - @classmethod - def register_arguments(cls, parser): - super(config, cls).register_arguments(parser) - parser.add_argument("DEVICE", - help="The name of the device to edit.") - - def invoke(self): - real_file_name = ".".join([self.args.DEVICE, DEVICE_FILE_SUFFIX]) - device_conf = get_device_file(real_file_name) - - if device_conf and can_edit_file(device_conf): - edit_file(device_conf) - else: - raise CommandError("Cannot edit file '{0}'".format(real_file_name)) - - -class list(BaseCommand): - """Lists configured devices.""" - - def invoke(self): - device_list = map(lambda d: d.hostname, get_devices()) - for device in sorted(device_list): - print device diff --git a/lava/device/templates.py b/lava/device/templates.py deleted file mode 100644 index e260117..0000000 --- a/lava/device/templates.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright (C) 2013 Linaro Limited -# -# Author: Milo Casagrande <milo.casagrande@linaro.org> -# -# This file is part of lava-tool. -# -# lava-tool is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# as published by the Free Software Foundation -# -# lava-tool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with lava-tool. If not, see <http://www.gnu.org/licenses/>. - -""" -This is just a place where to store a template like dictionary that -will be used to serialize a Device object. -""" - -from copy import copy - -from lava.parameter import Parameter - -# The hostname parameter is always in the DEFAULT config section. -HOSTNAME_PARAMETER = Parameter("hostname") -DEVICE_TYPE_PARAMETER = Parameter("device_type", depends=HOSTNAME_PARAMETER) -CONNECTION_COMMAND_PARMAETER = Parameter("connection_command", - depends=DEVICE_TYPE_PARAMETER) - -DEFAULT_TEMPLATE = { - 'hostname': HOSTNAME_PARAMETER, - 'device_type': DEVICE_TYPE_PARAMETER, - 'connection_command': CONNECTION_COMMAND_PARMAETER, -} - -# Specialized copies of the parameters. -# We need this or we might end up asking the user twice the same parameter due -# to different object references when one Parameter depends on a "specialized" -# one, different from the defaults. -PANDA_DEVICE_TYPE = copy(DEVICE_TYPE_PARAMETER) -PANDA_DEVICE_TYPE.value = "panda" -PANDA_DEVICE_TYPE.asked = True - -PANDA_CONNECTION_COMMAND = copy(CONNECTION_COMMAND_PARMAETER) -PANDA_CONNECTION_COMMAND.depends = PANDA_DEVICE_TYPE - -VEXPRESS_DEVICE_TYPE = copy(DEVICE_TYPE_PARAMETER) -VEXPRESS_DEVICE_TYPE.value = "vexpress" -VEXPRESS_DEVICE_TYPE.asked = True - -VEXPRESS_CONNECTION_COMMAND = copy(CONNECTION_COMMAND_PARMAETER) -VEXPRESS_CONNECTION_COMMAND.depends = VEXPRESS_DEVICE_TYPE - -QEMU_DEVICE_TYPE = copy(DEVICE_TYPE_PARAMETER) -QEMU_DEVICE_TYPE.value = "qemu" -QEMU_DEVICE_TYPE.asked = True - -QEMU_CONNECTION_COMMAND = copy(CONNECTION_COMMAND_PARMAETER) -QEMU_CONNECTION_COMMAND.depends = QEMU_DEVICE_TYPE - -# Dictionary with templates of known devices. -KNOWN_TEMPLATES = { - 'panda': { - 'hostname': HOSTNAME_PARAMETER, - 'device_type': PANDA_DEVICE_TYPE, - 'connection_command': PANDA_CONNECTION_COMMAND, - }, - 'vexpress': { - 'hostname': HOSTNAME_PARAMETER, - 'device_type': VEXPRESS_DEVICE_TYPE, - 'connection_command': VEXPRESS_CONNECTION_COMMAND, - }, - 'qemu': { - 'hostname': HOSTNAME_PARAMETER, - 'device_type': QEMU_DEVICE_TYPE, - 'connection_command': QEMU_CONNECTION_COMMAND, - } -} diff --git a/lava/device/tests/__init__.py b/lava/device/tests/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lava/device/tests/__init__.py +++ /dev/null diff --git a/lava/device/tests/test_commands.py b/lava/device/tests/test_commands.py deleted file mode 100644 index 22a652a..0000000 --- a/lava/device/tests/test_commands.py +++ /dev/null @@ -1,198 +0,0 @@ -# Copyright (C) 2013 Linaro Limited -# -# Author: Milo Casagrande <milo.casagrande@linaro.org> -# -# This file is part of lava-tool. -# -# lava-tool is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# as published by the Free Software Foundation -# -# lava-tool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with lava-tool. If not, see <http://www.gnu.org/licenses/>. - -""" -lava.device.commands unit tests. -""" - -import os - -from mock import ( - MagicMock, - call, - patch, -) - -from lava.device.commands import ( - add, - config, - remove, - list, -) -from lava.helper.tests.helper_test import HelperTest -from lava.tool.errors import CommandError - - -class AddCommandTest(HelperTest): - - def test_register_argument(self): - # Make sure that the parser add_argument is called and we have the - # correct argument. - add_command = add(self.parser, self.args) - add_command.register_arguments(self.parser) - name, args, kwargs = self.parser.method_calls[0] - self.assertIn("--non-interactive", args) - - name, args, kwargs = self.parser.method_calls[1] - self.assertIn("DEVICE", args) - - @patch("lava.device.commands.edit_file", create=True) - @patch("lava.device.Device.__str__") - @patch("lava.device.Device.update") - @patch("lava.device.commands.get_device_file") - @patch("lava.device.commands.get_devices_path") - def test_add_invoke_0(self, mocked_get_devices_path, - mocked_get_device_file, mocked_update, mocked_str, - mocked_edit_file): - # Tests invocation of the add command. Verifies that the conf file is - # written to disk. - mocked_get_devices_path.return_value = self.temp_dir - mocked_get_device_file.return_value = None - mocked_str.return_value = "" - - add_command = add(self.parser, self.args) - add_command.invoke() - - expected_path = os.path.join(self.temp_dir, - ".".join([self.device, "conf"])) - self.assertTrue(os.path.isfile(expected_path)) - - @patch("lava.device.commands.edit_file", create=True) - @patch("lava.device.commands.get_known_device") - @patch("lava.device.commands.get_devices_path") - @patch("lava.device.commands.sys.exit") - @patch("lava.device.commands.get_device_file") - def test_add_invoke_1(self, mocked_get_device_file, mocked_sys_exit, - mocked_get_devices_path, mocked_get_known_device, - mocked_edit_file): - mocked_get_devices_path.return_value = self.temp_dir - mocked_get_device_file.return_value = self.temp_file.name - - add_command = add(self.parser, self.args) - add_command.invoke() - - self.assertTrue(mocked_sys_exit.called) - - -class RemoveCommandTests(HelperTest): - - def test_register_argument(self): - # Make sure that the parser add_argument is called and we have the - # correct argument. - command = remove(self.parser, self.args) - command.register_arguments(self.parser) - name, args, kwargs = self.parser.method_calls[0] - self.assertIn("--non-interactive", args) - - name, args, kwargs = self.parser.method_calls[1] - self.assertIn("DEVICE", args) - - @patch("lava.device.commands.edit_file", create=True) - @patch("lava.device.Device.__str__", return_value="") - @patch("lava.device.Device.update") - @patch("lava.device.commands.get_device_file") - @patch("lava.device.commands.get_devices_path") - def test_remove_invoke(self, get_devices_path_mock, get_device_file_mock, - mocked_update, mocked_str, mocked_edit_file): - # Tests invocation of the remove command. Verifies that the conf file - # has been correctly removed. - # First we add a new conf file, then we remove it. - get_device_file_mock.return_value = None - get_devices_path_mock.return_value = self.temp_dir - - add_command = add(self.parser, self.args) - add_command.invoke() - - expected_path = os.path.join(self.temp_dir, - ".".join([self.device, "conf"])) - - # Set new values for the mocked function. - get_device_file_mock.return_value = expected_path - - remove_command = remove(self.parser, self.args) - remove_command.invoke() - - self.assertFalse(os.path.isfile(expected_path)) - - @patch("lava.device.commands.get_device_file", - new=MagicMock(return_value="/root")) - def test_remove_invoke_raises(self): - # Tests invocation of the remove command, with a non existent device - # configuration file. - remove_command = remove(self.parser, self.args) - self.assertRaises(CommandError, remove_command.invoke) - - -class ConfigCommanTests(HelperTest): - - def test_register_argument(self): - # Make sure that the parser add_argument is called and we have the - # correct argument. - command = config(self.parser, self.args) - command.register_arguments(self.parser) - name, args, kwargs = self.parser.method_calls[0] - self.assertIn("--non-interactive", args) - - name, args, kwargs = self.parser.method_calls[1] - self.assertIn("DEVICE", args) - - @patch("lava.device.commands.can_edit_file", create=True) - @patch("lava.device.commands.edit_file", create=True) - @patch("lava.device.commands.get_device_file") - def test_config_invoke_0(self, mocked_get_device_file, mocked_edit_file, - mocked_can_edit_file): - command = config(self.parser, self.args) - - mocked_can_edit_file.return_value = True - mocked_get_device_file.return_value = self.temp_file.name - command.invoke() - - self.assertTrue(mocked_edit_file.called) - self.assertEqual([call(self.temp_file.name)], - mocked_edit_file.call_args_list) - - @patch("lava.device.commands.get_device_file", - new=MagicMock(return_value=None)) - def test_config_invoke_raises_0(self): - # Tests invocation of the config command, with a non existent device - # configuration file. - config_command = config(self.parser, self.args) - self.assertRaises(CommandError, config_command.invoke) - - @patch("lava.device.commands.get_device_file", - new=MagicMock(return_value="/etc/password")) - def test_config_invoke_raises_1(self): - # Tests invocation of the config command, with a non writable file. - # Hopefully tests are not run as root. - config_command = config(self.parser, self.args) - self.assertRaises(CommandError, config_command.invoke) - - -class ListCommandTests(HelperTest): - - class FakeDevice(object): - def __init__(self, hostname): - self.hostname = hostname - - @patch('lava.device.commands.get_devices', create=True) - def test_list_devices(self, get_devices): - get_devices.return_value = [ListCommandTests.FakeDevice('foo'), ListCommandTests.FakeDevice('bar')] - command = list(self.parser, self.args) - command.invoke() - - get_devices.assert_any_call() diff --git a/lava/device/tests/test_device.py b/lava/device/tests/test_device.py deleted file mode 100644 index c8185f4..0000000 --- a/lava/device/tests/test_device.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright (C) 2013 Linaro Limited -# -# Author: Milo Casagrande <milo.casagrande@linaro.org> -# -# This file is part of lava-tool. -# -# lava-tool is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# as published by the Free Software Foundation -# -# lava-tool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with lava-tool. If not, see <http://www.gnu.org/licenses/>. - -""" -Device class unit tests. -""" - -from mock import patch - -from lava.config import Config -from lava.device import ( - Device, - get_known_device, -) -from lava.device.templates import ( - HOSTNAME_PARAMETER, - PANDA_DEVICE_TYPE, - PANDA_CONNECTION_COMMAND, -) -from lava.helper.tests.helper_test import HelperTest -from lava.parameter import Parameter - - -class DeviceTest(HelperTest): - - def test_get_known_device_panda_0(self): - # User creates a new device with a guessable name for a device. - instance = get_known_device('panda_new_01') - self.assertIsInstance(instance, Device) - self.assertEqual(instance.data['device_type'].value, 'panda') - - def test_get_known_device_panda_1(self): - # User creates a new device with a guessable name for a device. - # Name passed has capital letters. - instance = get_known_device('new_PanDa_02') - self.assertIsInstance(instance, Device) - self.assertEqual(instance.data['device_type'].value, 'panda') - - def test_get_known_device_vexpress_0(self): - # User creates a new device with a guessable name for a device. - # Name passed has capital letters. - instance = get_known_device('a_VexPress_Device') - self.assertIsInstance(instance, Device) - self.assertEqual(instance.data['device_type'].value, 'vexpress') - - def test_get_known_device_vexpress_1(self): - # User creates a new device with a guessable name for a device. - instance = get_known_device('another-vexpress') - self.assertIsInstance(instance, Device) - self.assertIsInstance(instance.data['device_type'], Parameter) - self.assertEqual(instance.data['device_type'].value, 'vexpress') - - @patch("lava.config.Config.save") - def test_device_update_1(self, patched_save): - # Tests that when calling update() on a Device, the template gets - # updated with the correct values from a Config instance. - hostname = "panda_device" - - config = Config() - config._config_file = self.temp_file.name - config.put_parameter(HOSTNAME_PARAMETER, hostname) - config.put_parameter(PANDA_DEVICE_TYPE, "panda") - config.put_parameter(PANDA_CONNECTION_COMMAND, "test") - - expected = { - "hostname": hostname, - "device_type": "panda", - "connection_command": "test" - } - - instance = get_known_device(hostname) - instance.update(config) - - self.assertEqual(expected, instance.data) - - @patch("lava.config.Config.save") - def test_device_write(self, mocked_save): - # User tries to create a new panda device. The conf file is written - # and contains the expected results. - hostname = "panda_device" - - config = Config() - config._config_file = self.temp_file.name - config.put_parameter(HOSTNAME_PARAMETER, hostname) - config.put_parameter(PANDA_DEVICE_TYPE, "panda") - config.put_parameter(PANDA_CONNECTION_COMMAND, "test") - - expected = { - "hostname": hostname, - "device_type": "panda", - "connection_command": "test" - } - - instance = get_known_device(hostname) - instance.update(config) - instance.write(self.temp_file.name) - - expected = ("hostname = panda_device\nconnection_command = test\n" - "device_type = panda\n") - - obtained = "" - with open(self.temp_file.name) as f: - obtained = f.read() - self.assertEqual(expected, obtained) diff --git a/lava/helper/dispatcher.py b/lava/helper/dispatcher.py index 5da01a9..4789e15 100644 --- a/lava/helper/dispatcher.py +++ b/lava/helper/dispatcher.py @@ -28,18 +28,6 @@ from lava.tool.errors import CommandError DEFAULT_DEVICES_PATH = "devices" -def get_dispatcher_paths(): - """Tries to get the dispatcher paths from lava-dispatcher. - - :return A list of paths. - """ - try: - from lava_dispatcher.config import write_path - return write_path() - except ImportError: - raise CommandError("Cannot find lava-dispatcher installation.") - - def get_devices(): """Gets the devices list from the dispatcher. @@ -50,61 +38,3 @@ def get_devices(): return get_devices() except ImportError: raise CommandError("Cannot find lava-dispatcher installation.") - - -def get_device_file(file_name): - """Retrieves the config file name specified, if it exists. - - :param file_name: The config file name to search. - :return The path to the file, or None if it does not exist. - """ - try: - from lava_dispatcher.config import get_config_file - return get_config_file(os.path.join(DEFAULT_DEVICES_PATH, - file_name)) - except ImportError: - raise CommandError("Cannot find lava-dispatcher installation.") - - -def choose_devices_path(paths): - """Picks the first path that is writable by the user. - - :param paths: A list of paths. - :return The first path where it is possible to write. - """ - valid_path = None - for path in paths: - path = os.path.join(path, DEFAULT_DEVICES_PATH) - if os.path.exists(path): - name = "".join(random.choice(string.ascii_letters) - for x in range(6)) - test_file = os.path.join(path, name) - try: - fp = open(test_file, 'a') - fp.close() - except IOError: - # Cannot write here. - continue - else: - valid_path = path - if os.path.isfile(test_file): - os.unlink(test_file) - break - else: - try: - os.makedirs(path) - except OSError: - # Cannot write here either. - continue - else: - valid_path = path - break - else: - raise CommandError("Insufficient permissions to create new " - "devices.") - return valid_path - - -def get_devices_path(): - """Gets the path to the devices in the LAVA dispatcher.""" - return choose_devices_path(get_dispatcher_paths()) diff --git a/lava/helper/tests/test_dispatcher.py b/lava/helper/tests/test_dispatcher.py deleted file mode 100644 index 1eb1b3a..0000000 --- a/lava/helper/tests/test_dispatcher.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (C) 2013 Linaro Limited -# -# Author: Milo Casagrande <milo.casagrande@linaro.org> -# -# This file is part of lava-tool. -# -# lava-tool is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# as published by the Free Software Foundation -# -# lava-tool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with lava-tool. If not, see <http://www.gnu.org/licenses/>. - -"""lava.helper.dispatcher tests.""" - -import os -import tempfile - -from mock import patch - -from lava.tool.errors import CommandError -from lava.helper.tests.helper_test import HelperTest -from lava.helper.dispatcher import ( - choose_devices_path, -) - - -class DispatcherTests(HelperTest): - - def setUp(self): - super(DispatcherTests, self).setUp() - self.devices_dir = os.path.join(tempfile.gettempdir(), "devices") - os.makedirs(self.devices_dir) - - def tearDown(self): - super(DispatcherTests, self).tearDown() - os.removedirs(self.devices_dir) - - def test_choose_devices_path_0(self): - # Tests that when passing more than one path, the first writable one - # is returned. - obtained = choose_devices_path( - ["/", "/root", self.temp_dir, os.path.expanduser("~")]) - expected = os.path.join(self.temp_dir, "devices") - self.assertEqual(expected, obtained) - - def test_choose_devices_path_1(self): - # Tests that when passing a path that is not writable, CommandError - # is raised. - self.assertRaises(CommandError, choose_devices_path, - ["/", "/root", "/root/tmpdir"]) - - def test_choose_devices_path_2(self): - # Tests that the correct path for devices is created on the filesystem. - expected_path = os.path.join(self.temp_dir, "devices") - obtained = choose_devices_path([self.temp_dir]) - self.assertEqual(expected_path, obtained) - self.assertTrue(os.path.isdir(expected_path)) - - def test_choose_devices_path_3(self): - # Tests that returns the already existing devices path. - obtained = choose_devices_path([tempfile.gettempdir()]) - self.assertEqual(self.devices_dir, obtained) - - @patch("__builtin__.open") - def test_choose_devices_path_4(self, mocked_open): - # Tests that when IOError is raised and we pass only one dir - # CommandError is raised. - mocked_open.side_effect = IOError() - self.assertRaises(CommandError, choose_devices_path, - [tempfile.gettempdir()]) - self.assertTrue(mocked_open.called) diff --git a/lava_dashboard_tool/__init__.py b/lava_dashboard_tool/__init__.py deleted file mode 100644 index fc9437f..0000000 --- a/lava_dashboard_tool/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2010,2011 Linaro Limited -# -# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org> -# -# This file is part of lava-dashboard-tool. -# -# lava-dashboard-tool is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# as published by the Free Software Foundation -# -# lava-dashboard-tool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with lava-dashboard-tool. If not, see <http://www.gnu.org/licenses/>. - -""" -Lava Tool package -""" -from lava_tool import version -__version__ = version() diff --git a/lava_dashboard_tool/commands.py b/lava_dashboard_tool/commands.py deleted file mode 100644 index c27ad28..0000000 --- a/lava_dashboard_tool/commands.py +++ /dev/null @@ -1,786 +0,0 @@ -# Copyright (C) 2010,2011 Linaro Limited -# -# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org> -# -# This file is part of lava-dashboard-tool. -# -# lava-dashboard-tool is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# as published by the Free Software Foundation -# -# lava-dashboard-tool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with lava-dashboard-tool. If not, see <http://www.gnu.org/licenses/>. - -""" -Module with command-line tool commands that interact with the dashboard -server. All commands listed here should have counterparts in the -launch_control.dashboard_app.xml_rpc package. -""" - -import argparse -import contextlib -import errno -import os -import socket -import sys -import urlparse -import xmlrpclib - - -from lava_tool.authtoken import AuthenticatingServerProxy, KeyringAuthBackend -from lava.tool.command import Command, CommandGroup - - -class dashboard(CommandGroup): - - """ - Commands for interacting with LAVA Dashboard - """ - - namespace = "lava.dashboard.commands" - - -class InsufficientServerVersion(Exception): - - """ - Exception raised when server version that a command interacts with is too - old to support required features. - """ - - def __init__(self, server_version, required_version): - self.server_version = server_version - self.required_version = required_version - - -class DataSetRenderer(object): - - """ - ** DEPRECATED ** - Support class for rendering a table out of list of dictionaries. - - It supports several features that make printing tabular data easier. - * Automatic layout - * Custom column headers - * Custom cell formatting - * Custom table captions - * Custom column ordering - * Custom Column separators - * Custom dataset notification - - The primary method is render() which does all of the above. You - need to pass a dataset argument which is a list of dictionaries. - Each dictionary must have the same keys. In particular the first row - is used to determine columns. - """ - - def __init__(self, column_map=None, row_formatter=None, empty=None, - order=None, caption=None, separator=" ", - header_separator=None): - if column_map is None: - column_map = {} - if row_formatter is None: - row_formatter = {} - if empty is None: - empty = "There is no data to display" - self.column_map = column_map - self.row_formatter = row_formatter - self.empty = empty - self.order = order - self.separator = separator - self.caption = caption - self.header_separator = header_separator - - def _analyze_dataset(self, dataset): - """ - ** DEPRECATED ** - - Determine the columns that will be displayed and the maximum - length of each of those columns. - - Returns a tuple (dataset, columms, maxlen) where columns is a - list of column names and maxlen is a dictionary mapping from - column name to maximum length of any value in the row or the - column header and the dataset is a copy of the dataset altered - as necessary. - """ - if self.order: - columns = self.order - else: - columns = sorted(dataset[0].keys()) - if self.row_formatter: - dataset_out = [dict(row) for row in dataset] - else: - dataset_out = dataset - for row in dataset_out: - for column in row: - if column in self.row_formatter: - row[column] = self.row_formatter[column](row[column]) - maxlen = dict( - [(column, max( - len(self.column_map.get(column, column)), - max([ - len(str(row[column])) for row in dataset_out]))) - for column in columns]) - return dataset_out, columns, maxlen - - def _render_header(self, dataset, columns, maxlen): - """ - Render a header, possibly with a caption string - - ** DEPRECATED ** - """ - total_len = sum(maxlen.itervalues()) - if len(columns): - total_len += len(self.separator) * (len(columns) - 1) - # Print the caption - if self.caption: - print "{0:^{1}}".format(self.caption, total_len) - print "=" * total_len - # Now print the coulum names - print self.separator.join([ - "{0:^{1}}".format(self.column_map.get(column, column), - maxlen[column]) for column in columns]) - # Finally print the header separator - if self.header_separator: - print "-" * total_len - - def _render_rows(self, dataset, columns, maxlen): - """ - ** DEPRECATED ** - - Render rows of the dataset. - - Each row is printed on one line using the maxlen argument to - determine correct column size. Text is aligned left. - """ - for row in dataset: - print self.separator.join([ - "{0!s:{1}}".format(row[column], maxlen[column]) - for column in columns]) - - def _render_dataset(self, dataset): - """ - ** DEPRECATED ** - - Render the header followed by the rows of data. - """ - dataset, columns, maxlen = self._analyze_dataset(dataset) - self._render_header(dataset, columns, maxlen) - self._render_rows(dataset, columns, maxlen) - - def _render_empty_dataset(self): - """ - ** DEPRECATED ** - - Render empty dataset. - """ - print self.empty - - def render(self, dataset): - if len(dataset) > 0: - self._render_dataset(dataset) - else: - self._render_empty_dataset() - - -class XMLRPCCommand(Command): - - """ - ** DEPRECATED ** - - Abstract base class for commands that interact with dashboard server - over XML-RPC. - - The only difference is that you should implement invoke_remote() - instead of invoke(). The provided implementation catches several - socket and XML-RPC errors and prints a pretty error message. - """ - - @staticmethod - def _construct_xml_rpc_url(url): - """ - Construct URL to the XML-RPC service out of the given URL - """ - parts = urlparse.urlsplit(url) - if not parts.path.endswith("/RPC2/"): - path = parts.path.rstrip("/") + "/xml-rpc/" - else: - path = parts.path - return urlparse.urlunsplit( - (parts.scheme, parts.netloc, path, "", "")) - - @staticmethod - def _strict_server_version(version): - """ - ** DEPRECATED ** - - Calculate strict server version (as defined by - distutils.version.StrictVersion). This works by discarding .candidate - and .dev release-levels. - """ - try: - major, minor, micro, releaselevel, serial = version.split(".") - except ValueError: - raise ValueError( - ("version %r does not follow pattern " - "'major.minor.micro.releaselevel.serial'") % version) - if releaselevel in ["dev", "candidate", "final"]: - return "%s.%s.%s" % (major, minor, micro) - elif releaselevel == "alpha": - return "%s.%s.%sa%s" % (major, minor, micro, serial) - elif releaselevel == "beta": - return "%s.%s.%sb%s" % (major, minor, micro, serial) - else: - raise ValueError( - ("releaselevel %r is not one of 'final', 'alpha', 'beta', " - "'candidate' or 'final'") % releaselevel) - - def _check_server_version(self, server_obj, required_version): - """ - ** DEPRECATED ** - - Obsolete function dating from pre-packaging requirements - """ - return True - - def __init__(self, parser, args): - super(XMLRPCCommand, self).__init__(parser, args) - xml_rpc_url = self._construct_xml_rpc_url(self.args.dashboard_url) - self.server = AuthenticatingServerProxy( - xml_rpc_url, - verbose=args.verbose_xml_rpc, - allow_none=True, - use_datetime=True, - auth_backend=KeyringAuthBackend()) - - def use_non_legacy_api_if_possible(self, name='server'): - # Legacy APIs are registered in top-level object, non-legacy APIs are - # prefixed with extension name. - if "dashboard.version" in getattr(self, name).system.listMethods(): - setattr(self, name, getattr(self, name).dashboard) - - @classmethod - def register_arguments(cls, parser): - dashboard_group = parser.add_argument_group( - "dashboard specific arguments") - default_dashboard_url = os.getenv("DASHBOARD_URL") - if default_dashboard_url: - dashboard_group.add_argument("--dashboard-url", - metavar="URL", help="URL of your validation dashboard (currently %(default)s)", - default=default_dashboard_url) - else: - dashboard_group.add_argument("--dashboard-url", required=True, - metavar="URL", help="URL of your validation dashboard") - debug_group = parser.add_argument_group("debugging arguments") - debug_group.add_argument("--verbose-xml-rpc", - action="store_true", default=False, - help="Show XML-RPC data") - return dashboard_group - - @contextlib.contextmanager - def safety_net(self): - try: - yield - except socket.error as ex: - print >> sys.stderr, "Unable to connect to server at %s" % ( - self.args.dashboard_url,) - # It seems that some errors are reported as -errno - # while others as +errno. - ex.errno = abs(ex.errno) - if ex.errno == errno.ECONNREFUSED: - print >> sys.stderr, "Connection was refused." - parts = urlparse.urlsplit(self.args.dashboard_url) - if parts.netloc == "localhost:8000": - print >> sys.stderr, "Perhaps the server is not running?" - elif ex.errno == errno.ENOENT: - print >> sys.stderr, "Unable to resolve address" - else: - print >> sys.stderr, "Socket %d: %s" % (ex.errno, ex.strerror) - except xmlrpclib.ProtocolError as ex: - print >> sys.stderr, "Unable to exchange XML-RPC message with dashboard server" - print >> sys.stderr, "HTTP error code: %d/%s" % ( - ex.errcode, ex.errmsg) - except xmlrpclib.Fault as ex: - self.handle_xmlrpc_fault(ex.faultCode, ex.faultString) - except InsufficientServerVersion as ex: - print >> sys.stderr, ("This command requires at least server version " - "%s, actual server version is %s" % - (ex.required_version, ex.server_version)) - - def invoke(self): - with self.safety_net(): - self.use_non_legacy_api_if_possible() - return self.invoke_remote() - - def handle_xmlrpc_fault(self, faultCode, faultString): - if faultCode == 500: - print >> sys.stderr, "Dashboard server has experienced internal error" - print >> sys.stderr, faultString - else: - print >> sys.stderr, "XML-RPC error %d: %s" % ( - faultCode, faultString) - - def invoke_remote(self): - raise NotImplementedError() - - -class server_version(XMLRPCCommand): - - """ - Display LAVA server version - """ - - def invoke_remote(self): - print "LAVA server version: %s" % (self.server.version(),) - - -class put(XMLRPCCommand): - - """ - Upload a bundle on the server - """ - - @classmethod - def register_arguments(cls, parser): - super(put, cls).register_arguments(parser) - parser.add_argument("LOCAL", - type=argparse.FileType("rb"), - help="pathname on the local file system") - parser.add_argument("REMOTE", - default="/anonymous/", nargs='?', - help="pathname on the server") - - def invoke_remote(self): - content = self.args.LOCAL.read() - filename = self.args.LOCAL.name - pathname = self.args.REMOTE - content_sha1 = self.server.put(content, filename, pathname) - print "Stored as bundle {0}".format(content_sha1) - - def handle_xmlrpc_fault(self, faultCode, faultString): - if faultCode == 404: - print >> sys.stderr, "Bundle stream %s does not exist" % ( - self.args.REMOTE) - elif faultCode == 409: - print >> sys.stderr, "You have already uploaded this bundle to the dashboard" - else: - super(put, self).handle_xmlrpc_fault(faultCode, faultString) - - -class get(XMLRPCCommand): - - """ - Download a bundle from the server - """ - - @classmethod - def register_arguments(cls, parser): - super(get, cls).register_arguments(parser) - parser.add_argument("SHA1", - type=str, - help="SHA1 of the bundle to download") - parser.add_argument("--overwrite", - action="store_true", - help="Overwrite files on the local disk") - parser.add_argument("--output", "-o", - type=argparse.FileType("wb"), - default=None, - help="Alternate name of the output file") - - def invoke_remote(self): - response = self.server.get(self.args.SHA1) - if self.args.output is None: - filename = self.args.SHA1 - if os.path.exists(filename) and not self.args.overwrite: - print >> sys.stderr, "File {filename!r} already exists".format( - filename=filename) - print >> sys.stderr, "You may pass --overwrite to write over it" - return -1 - stream = open(filename, "wb") - else: - stream = self.args.output - filename = self.args.output.name - stream.write(response['content']) - print "Downloaded bundle {0} to file {1!r}".format( - self.args.SHA1, filename) - - def handle_xmlrpc_fault(self, faultCode, faultString): - if faultCode == 404: - print >> sys.stderr, "Bundle {sha1} does not exist".format( - sha1=self.args.SHA1) - else: - super(get, self).handle_xmlrpc_fault(faultCode, faultString) - - -class deserialize(XMLRPCCommand): - - """ - Deserialize a bundle on the server - """ - - @classmethod - def register_arguments(cls, parser): - super(deserialize, cls).register_arguments(parser) - parser.add_argument("SHA1", - type=str, - help="SHA1 of the bundle to deserialize") - - def invoke_remote(self): - self.server.deserialize(self.args.SHA1) - print "Bundle {sha1} deserialized".format( - sha1=self.args.SHA1) - - def handle_xmlrpc_fault(self, faultCode, faultString): - if faultCode == 404: - print >> sys.stderr, "Bundle {sha1} does not exist".format( - sha1=self.args.SHA1) - elif faultCode == 409: - print >> sys.stderr, "Unable to deserialize bundle {sha1}".format( - sha1=self.args.SHA1) - print >> sys.stderr, faultString - else: - super( - deserialize, - self).handle_xmlrpc_fault( - faultCode, - faultString) - - -def _get_pretty_renderer(**kwargs): - if "separator" not in kwargs: - kwargs["separator"] = " | " - if "header_separator" not in kwargs: - kwargs["header_separator"] = True - return DataSetRenderer(**kwargs) - - -class streams(XMLRPCCommand): - - """ - Show streams you have access to - """ - - renderer = _get_pretty_renderer( - order=('pathname', 'bundle_count', 'name'), - column_map={ - 'pathname': 'Pathname', - 'bundle_count': 'Number of bundles', - 'name': 'Name'}, - row_formatter={ - 'name': lambda name: name or "(not set)"}, - empty="There are no streams you can access on the server", - caption="Bundle streams") - - def invoke_remote(self): - self.renderer.render(self.server.streams()) - - -class bundles(XMLRPCCommand): - - """ - Show bundles in the specified stream - """ - - renderer = _get_pretty_renderer( - column_map={ - 'uploaded_by': 'Uploader', - 'uploaded_on': 'Upload date', - 'content_filename': 'File name', - 'content_sha1': 'SHA1', - 'is_deserialized': "Deserialized?"}, - row_formatter={ - 'is_deserialized': lambda x: "yes" if x else "no", - 'uploaded_by': lambda x: x or "(anonymous)", - 'uploaded_on': lambda x: x}, - order=('content_sha1', 'content_filename', 'uploaded_by', - 'uploaded_on', 'is_deserialized'), - empty="There are no bundles in this stream", - caption="Bundles", - separator=" | ") - - @classmethod - def register_arguments(cls, parser): - super(bundles, cls).register_arguments(parser) - parser.add_argument("PATHNAME", - default="/anonymous/", nargs='?', - help="pathname on the server (defaults to %(default)s)") - - def invoke_remote(self): - self.renderer.render(self.server.bundles(self.args.PATHNAME)) - - def handle_xmlrpc_fault(self, faultCode, faultString): - if faultCode == 404: - print >> sys.stderr, "Bundle stream %s does not exist" % ( - self.args.PATHNAME) - else: - super(bundles, self).handle_xmlrpc_fault(faultCode, faultString) - - -class make_stream(XMLRPCCommand): - - """ - Create a bundle stream on the server - """ - - @classmethod - def register_arguments(cls, parser): - super(make_stream, cls).register_arguments(parser) - parser.add_argument( - "pathname", - type=str, - help="Pathname of the bundle stream to create") - parser.add_argument( - "--name", - type=str, - default="", - help="Name of the bundle stream (description)") - - def invoke_remote(self): - self._check_server_version(self.server, "0.3") - pathname = self.server.make_stream(self.args.pathname, self.args.name) - print "Bundle stream {pathname} created".format(pathname=pathname) - - -def _round_float_value_2_decimals(value): - return "%0.2f" % (round(value, 1),) - - -class pull(XMLRPCCommand): - """ - Copy bundles and bundle streams from one dashboard to another. - This command checks for two environment varialbes: - The value of DASHBOARD_URL is used as a replacement for --dashbard-url. - The value of REMOTE_DASHBOARD_URL as a replacement for FROM. - Their presence automatically makes the corresponding argument optional. - """ - - def __init__(self, parser, args): - super(pull, self).__init__(parser, args) - remote_xml_rpc_url = self._construct_xml_rpc_url(self.args.FROM) - self.remote_server = AuthenticatingServerProxy( - remote_xml_rpc_url, - verbose=args.verbose_xml_rpc, - use_datetime=True, - allow_none=True, - auth_backend=KeyringAuthBackend()) - self.use_non_legacy_api_if_possible('remote_server') - - @classmethod - def register_arguments(cls, parser): - group = super(pull, cls).register_arguments(parser) - default_remote_dashboard_url = os.getenv("REMOTE_DASHBOARD_URL") - if default_remote_dashboard_url: - group.add_argument( - "FROM", nargs="?", - help="URL of the remote validation dashboard (currently %(default)s)", - default=default_remote_dashboard_url) - else: - group.add_argument( - "FROM", - help="URL of the remote validation dashboard)") - group.add_argument( - "STREAM", - nargs="*", - help="Streams to pull from (all by default)") - - @staticmethod - def _filesizeformat(num_bytes): - """ - Formats the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, - 102 num_bytes, etc). - """ - try: - num_bytes = float(num_bytes) - except (TypeError, ValueError, UnicodeDecodeError): - return "%(size)d byte", "%(size)d num_bytes" % {'size': 0} - - if num_bytes < 1024: - return "%(size)d bytes" % {'size': num_bytes} - if num_bytes < 1024 * 1024: - return "%s KB" % _round_float_value_2_decimals(num_bytes / 1024) - if num_bytes < 1024 * 1024 * 1024: - return "%s MB" % _round_float_value_2_decimals(num_bytes / (1024 * 1024)) - return "%s GB" % _round_float_value_2_decimals(num_bytes / (1024 * 1024 * 1024)) - - def invoke_remote(self): - self._check_server_version(self.server, "0.3") - - print "Checking local and remote streams" - remote = self.remote_server.streams() - if self.args.STREAM: - # Check that all requested streams are available remotely - requested_set = frozenset(self.args.STREAM) - remote_set = frozenset((stream["pathname"] for stream in remote)) - unavailable_set = requested_set - remote_set - if unavailable_set: - print >> sys.stderr, "Remote stream not found: %s" % ", ".join( - unavailable_set) - return -1 - # Limit to requested streams if necessary - remote = [ - stream for stream in remote if stream[ - "pathname"] in requested_set] - local = self.server.streams() - missing_pathnames = set([stream["pathname"] - for stream in remote]) - set([stream["pathname"] for stream in local]) - for stream in remote: - if stream["pathname"] in missing_pathnames: - self.server.make_stream(stream["pathname"], stream["name"]) - local_bundles = [] - else: - local_bundles = [ - bundle for bundle in self.server.bundles(stream["pathname"])] - remote_bundles = [ - bundle for bundle in self.remote_server.bundles(stream["pathname"])] - missing_bundles = set( - (bundle["content_sha1"] for bundle in remote_bundles)) - missing_bundles -= set( - (bundle["content_sha1"] for bundle in local_bundles)) - try: - missing_bytes = sum( - (bundle["content_size"] - for bundle in remote_bundles - if bundle["content_sha1"] in missing_bundles)) - except KeyError as ex: - # Older servers did not return content_size so this part is - # optional - missing_bytes = None - if missing_bytes: - print "Stream %s needs update (%s)" % (stream["pathname"], self._filesizeformat(missing_bytes)) - elif missing_bundles: - print "Stream %s needs update (no estimate available)" % (stream["pathname"],) - else: - print "Stream %s is up to date" % (stream["pathname"],) - for content_sha1 in missing_bundles: - print "Getting %s" % (content_sha1,), - sys.stdout.flush() - data = self.remote_server.get(content_sha1) - print "got %s, storing" % (self._filesizeformat(len(data["content"]))), - sys.stdout.flush() - try: - self.server.put( - data["content"], - data["content_filename"], - stream["pathname"]) - except xmlrpclib.Fault as ex: - if ex.faultCode == 409: # duplicate - print "already present (in another stream)" - else: - raise - else: - print "done" - - -class data_views(XMLRPCCommand): - """ - Show data views defined on the server - """ - renderer = _get_pretty_renderer( - column_map={ - 'name': 'Name', - 'summary': 'Summary', - }, - order=('name', 'summary'), - empty="There are no data views defined yet", - caption="Data Views") - - def invoke_remote(self): - self._check_server_version(self.server, "0.4") - self.renderer.render(self.server.data_views()) - print - print "Tip: to invoke a data view try `lc-tool query-data-view`" - - -class query_data_view(XMLRPCCommand): - """ - Invoke a specified data view - """ - @classmethod - def register_arguments(cls, parser): - super(query_data_view, cls).register_arguments(parser) - parser.add_argument("QUERY", metavar="QUERY", nargs="...", - help="Data view name and any optional \ - and required arguments") - - def _probe_data_views(self): - """ - Probe the server for information about data views - """ - with self.safety_net(): - self.use_non_legacy_api_if_possible() - self._check_server_version(self.server, "0.4") - return self.server.data_views() - - def reparse_arguments(self, parser, raw_args): - self.data_views = self._probe_data_views() - if self.data_views is None: - return - # Here we hack a little, the last actuin is the QUERY action added - # in register_arguments above. By removing it we make the output - # of lc-tool query-data-view NAME --help more consistent. - del parser._actions[-1] - subparsers = parser.add_subparsers( - title="Data views available on the server") - for data_view in self.data_views: - data_view_parser = subparsers.add_parser( - data_view["name"], - help=data_view["summary"], - epilog=data_view["documentation"]) - data_view_parser.set_defaults(data_view=data_view) - group = data_view_parser.add_argument_group("Data view parameters") - for argument in data_view["arguments"]: - if argument["default"] is None: - group.add_argument( - "--{name}".format( - name=argument["name"].replace("_", "-")), - dest=argument["name"], - help=argument["help"], - type=str, - required=True) - else: - group.add_argument( - "--{name}".format( - name=argument["name"].replace("_", "-")), - dest=argument["name"], - help=argument["help"], - type=str, - default=argument["default"]) - self.args = self.parser.parse_args(raw_args) - - def invoke(self): - # Override and _not_ call 'use_non_legacy_api_if_possible' as we - # already did this reparse_arguments - with self.safety_net(): - return self.invoke_remote() - - def invoke_remote(self): - if self.data_views is None: - return -1 - self._check_server_version(self.server, "0.4") - # Build a collection of arguments for data view - data_view_args = {} - for argument in self.args.data_view["arguments"]: - arg_name = argument["name"] - if arg_name in self.args: - data_view_args[arg_name] = getattr(self.args, arg_name) - # Invoke the data view - response = self.server.query_data_view( - self.args.data_view["name"], - data_view_args) - # Create a pretty-printer - renderer = _get_pretty_renderer( - caption=self.args.data_view["summary"], - order=[item["name"] for item in response["columns"]]) - # Post-process the data so that it fits the printer - data_for_renderer = [ - dict(zip( - [column["name"] for column in response["columns"]], - row)) - for row in response["rows"]] - # Print the data - renderer.render(data_for_renderer) diff --git a/lava_dashboard_tool/main.py b/lava_dashboard_tool/main.py deleted file mode 100644 index 9339036..0000000 --- a/lava_dashboard_tool/main.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (C) 2011 Linaro Limited -# -# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org> -# Author: Michael Hudson-Doyle <michael.hudson@linaro.org> -# -# This file is part of lava-dashboard-tool. -# -# lava-dashboard-tool is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# as published by the Free Software Foundation -# -# lava-dashboard-tool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with lava-dashboard-tool. If not, see <http://www.gnu.org/licenses/>. - - -from lava_tool.dispatcher import LavaDispatcher, run_with_dispatcher_class - - -class LaunchControlDispatcher(LavaDispatcher): - - toolname = 'lava_dashboard_tool' - description = """ - Command line tool for interacting with Lava Dashboard - ** DEPRECATED ** - """ - epilog = """ - All bugs should be reported to Linaro at - - https://bugs.linaro.org/enter_bug.cgi?product=LAVA%20Framework - """ - - -def main(): - run_with_dispatcher_class(LaunchControlDispatcher) diff --git a/lava_dashboard_tool/tests/__init__.py b/lava_dashboard_tool/tests/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/lava_dashboard_tool/tests/__init__.py +++ /dev/null diff --git a/lava_dashboard_tool/tests/test_commands.py b/lava_dashboard_tool/tests/test_commands.py deleted file mode 100644 index 07cff45..0000000 --- a/lava_dashboard_tool/tests/test_commands.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (C) 2010,2011 Linaro Limited -# -# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org> -# -# This file is part of lava-dashboard-tool. -# -# lava-dashboard-tool is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# as published by the Free Software Foundation -# -# lava-dashboard-tool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with lava-dashboard-tool. If not, see <http://www.gnu.org/licenses/>. - -""" -Unit tests for the launch_control.commands package -""" - -from unittest import TestCase - -from lava_dashboard_tool.commands import XMLRPCCommand - - -class XMLRPCCommandTestCase(TestCase): - - def test_construct_xml_rpc_url_preserves_path(self): - self.assertEqual( - XMLRPCCommand._construct_xml_rpc_url("http://domain/path"), - "http://domain/path/xml-rpc/") - self.assertEqual( - XMLRPCCommand._construct_xml_rpc_url("http://domain/path/"), - "http://domain/path/xml-rpc/") - - def test_construct_xml_rpc_url_adds_proper_suffix(self): - self.assertEqual( - XMLRPCCommand._construct_xml_rpc_url("http://domain/"), - "http://domain/xml-rpc/") - self.assertEqual( - XMLRPCCommand._construct_xml_rpc_url("http://domain"), - "http://domain/xml-rpc/") diff --git a/lava_scheduler_tool/commands.py b/lava_scheduler_tool/commands.py index 1a927cb..99e598f 100644 --- a/lava_scheduler_tool/commands.py +++ b/lava_scheduler_tool/commands.py @@ -50,7 +50,6 @@ from lava_scheduler_tool.scheduler import ( if sys.version_info < (3, 0): import urlparse import xmlrpclib - from lava_dashboard_tool.commands import _get_pretty_renderer # Enable only once python3 support is ready, then switch over. # else: # import urllib.parse # pylint: disable=import-error,unused-import,no-name-in-module @@ -329,19 +328,6 @@ class jobs_list(Command): # pylint: disable=invalid-name """ Get list of running and submitted jobs from the scheduler. """ - renderer = _get_pretty_renderer( - order=('id', 'description', 'status', 'actual_device', 'requested_device'), - column_map={ - 'id': 'Job ID', - 'description': 'Job description', - 'status': 'Job status', - 'actual_device': 'Device', - 'requested_device': 'Requested device or device type'}, - row_formatter={ - 'actual_device': lambda x: x or "", - 'requested_device': lambda x: x or ""}, - empty="There are no running or submitted jobs", - caption="Jobs list") def reparse_arguments(self, parser, raw_args): pass @@ -359,26 +345,7 @@ class jobs_list(Command): # pylint: disable=invalid-name except xmlrpclib.Fault as exc: raise CommandError(str(exc)) - data_for_renderer = [] - for row in ret_list: - if row[6]: - job_id = row[6] - else: - job_id = row[0] - if row[4]: - req_d = row[4]["hostname"] - else: - req_d = row[5]["name"] - if row[3]: - req_d = "" - act_d = row[3]["hostname"] - else: - act_d = "" - data_for_renderer.append( - dict(zip(['id', 'description', 'status', 'actual_device', 'requested_device'], - [job_id, row[1], row[2], act_d, req_d]))) - - self.renderer.render(data_for_renderer) + print(ret_list) class devices_list(Command): # pylint: disable=invalid-name @@ -386,18 +353,6 @@ class devices_list(Command): # pylint: disable=invalid-name Get list of devices from the scheduler. """ - renderer = _get_pretty_renderer( - order=('hostname', 'device_type_name', 'status', 'job'), - column_map={ - 'hostname': 'Hostname', - 'device_type_name': 'Device type', - 'status': 'Status', - 'job': 'Job ID'}, - row_formatter={ - 'job': lambda x: x or ""}, - empty="There are no devices", - caption="Devices list") - def reparse_arguments(self, parser, raw_args): pass @@ -411,17 +366,7 @@ class devices_list(Command): # pylint: disable=invalid-name self.args.SERVER, auth_backend=KeyringAuthBackend()) all_devices = server.scheduler.all_devices() - data_for_renderer = [] - for row in all_devices: - if row[3]: - job_id = row[3] - else: - job_id = "" - data_for_renderer.append( - dict(zip(['hostname', 'device_type_name', 'status', 'job'], - [row[0], row[1], row[2], job_id]))) - - self.renderer.render(data_for_renderer) + print(all_devices) class get_pipeline_device_config(Command): # pylint: disable=invalid-name diff --git a/lava_tool/tests/__init__.py b/lava_tool/tests/__init__.py index 92e6531..41e3e02 100644 --- a/lava_tool/tests/__init__.py +++ b/lava_tool/tests/__init__.py @@ -29,14 +29,11 @@ def app_modules(): 'lava_tool.commands', 'lava_tool.dispatcher', 'lava_tool.interface', - 'lava_dashboard_tool.commands', ] def test_modules(): return [ - 'lava.device.tests.test_commands', - 'lava.device.tests.test_device', 'lava.helper.tests.test_command', 'lava.helper.tests.test_dispatcher', 'lava.helper.tests.test_template', @@ -48,7 +45,6 @@ def test_modules(): 'lava.tests.test_commands', 'lava.tests.test_config', 'lava.tests.test_parameter', - 'lava_dashboard_tool.tests.test_commands', 'lava_tool.tests.test_auth_commands', 'lava_tool.tests.test_authtoken', 'lava_tool.tests.test_commands', diff --git a/man/lava-tool.rst b/man/lava-tool.rst index 1c1fc57..2daa355 100644 --- a/man/lava-tool.rst +++ b/man/lava-tool.rst @@ -35,26 +35,6 @@ streams, make-stream, pull. Available subcommands ##################### -data-views - Show data views defined on the server **DEPRECATED** - - Usage: - lava-tool data-views [-h] --dashboard-url URL [--verbose-xml-rpc] - [--experimental-notice] - - Optional arguments: - -h, --help show this help message and exit - - Dashboard specific arguments: - --dashboard-url URL URL of your validation dashboard - - Debugging arguments: - --verbose-xml-rpc Show XML-RPC data - - Experimental commands: - --experimental-notice - Explain the nature of experimental commands - job-output Get job output from the scheduler @@ -87,47 +67,6 @@ devices-list help Show a summary of all available commands -deserialize - Deserialize a bundle on the server **DEPRECATED** - - Usage: - lava-tool deserialize [-h] --dashboard-url URL [--verbose-xml-rpc] SHA1 - - Positional arguments: - SHA1 - SHA1 of the bundle to deserialize - - Optional arguments: - -h, --help show this help message and exit - - Dashboard specific arguments: - --dashboard-url URL URL of your validation dashboard - - Debugging arguments: - --verbose-xml-rpc Show XML-RPC data - -get - Download a bundle from the server **DEPRECATED** - - Usage: - lava-tool get [-h] --dashboard-url URL [--verbose-xml-rpc] - [--overwrite] [--output OUTPUT] SHA1 - - Positional arguments: - SHA1 - SHA1 of the bundle to download - - Optional arguments: - -h, --help show this help message and exit - --overwrite Overwrite files on the local disk - --output OUTPUT, -o OUTPUT Alternate name of the output file - - Dashboard specific arguments: - --dashboard-url URL URL of your validation dashboard - - Debugging arguments: - --verbose-xml-rpc Show XML-RPC data - auth-add Add an authentication token @@ -185,63 +124,6 @@ auth-list Optional arguments: -h, --help show this help message and exit -put - Upload a bundle on the server **DEPRECATED** - - Usage: - lava-tool put [-h] --dashboard-url URL [--verbose-xml-rpc] LOCAL - [REMOTE] - - Positional arguments: - LOCAL - pathname on the local file system - REMOTE - pathname on the server - - Optional arguments: - -h, --help show this help message and exit - - Dashboard specific arguments: - --dashboard-url URL URL of your validation dashboard - - Debugging arguments: - --verbose-xml-rpc Show XML-RPC data - -bundles - Show bundles in the specified stream **DEPRECATED** - - Usage: - lava-tool bundles [-h] --dashboard-url URL [--verbose-xml-rpc] - [PATHNAME] - - Positional arguments: - PATHNAME - pathname on the server (defaults to /anonymous/) - - Optional arguments: - -h, --help show this help message and exit - - Dashboard specific arguments: - --dashboard-url URL URL of your validation dashboard - - Debugging arguments: - --verbose-xml-rpc Show XML-RPC data - -server-version - Display dashboard server version **DEPRECATED** - - Usage: - lava-tool server-version [-h] --dashboard-url URL [--verbose-xml-rpc] - - Optional arguments: - -h, --help show this help message and exit - - Dashboard specific arguments: - --dashboard-url URL URL of your validation dashboard - - Debugging arguments: - --verbose-xml-rpc Show XML-RPC data - cancel-job Cancel job @@ -281,29 +163,6 @@ version Optional arguments: -h, --help show this help message and exit -query-data-view - Invoke a specified data view **DEPRECATED** - - Usage: - lava-tool restore [-h] --dashboard-url URL [--verbose-xml-rpc] - [--experimental-notice] QUERY - - Positional arguments: - QUERY - Data view name and any optional and required arguments - - Optional arguments: - -h, --help show this help message and exit - - Dashboard specific arguments: - --dashboard-url URL URL of your validation dashboard - - Debugging arguments: - --verbose-xml-rpc Show XML-RPC data - - Experimental commands: - --experimental-notice Explain the nature of experimental commands - submit-job Submit a job to lava-scheduler @@ -398,42 +257,6 @@ validate-pipeline-devices -h, --help show this help message and exit --name NAME Hostname of the device or device_type name. -streams - Show streams you have access to **DEPRECATED** - - Usage: - lava-tool streams [-h] --dashboard-url URL [--verbose-xml-rpc] - - Optional arguments: - -h, --help show this help message and exit - - Dashboard specific arguments: - --dashboard-url URL URL of your validation dashboard - - Debugging arguments: - --verbose-xml-rpc Show XML-RPC data - -make-stream - Create a bundle stream on the server **DEPRECATED** - - Usage: - lava-tool make-stream [-h] --dashboard-url URL [--verbose-xml-rpc] - [--name NAME] pathname - - Positional arguments: - pathname - Pathname of the bundle stream to create - - Optional arguments: - -h, --help show this help message and exit - --name NAME Name of the bundle stream (description) - - Dashboard specific arguments: - --dashboard-url URL URL of your validation dashboard - - Debugging arguments: - --verbose-xml-rpc Show XML-RPC data - compare-device-conf Compare device configurations and output a diff. @@ -453,38 +276,6 @@ compare-device-conf --dispatcher-config-dir DISPATCHER_CONFIG_DIR Where to find the device_type templates. -pull - Copy bundles and bundle streams from one dashboard to another **DEPRECATED** - - Usage: - lava-tool pull [-h] --dashboard-url URL [--verbose-xml-rpc] - [--experimental-notice] FROM [STREAM [STREAM ...]] - - Positional arguments: - FROM - URL of the remote validation dashboard - - Optional arguments: - -h, --help show this help message and exit - - Dashboard specific arguments: - --dashboard-url URL URL of your validation dashboard - - STREAM - Streams to pull from (all by default) - - Debugging arguments: - --verbose-xml-rpc Show XML-RPC data - - Experimental commands: - --experimental-notice Explain the nature of experimental commands - - This command checks for two environment variables: The value of - DASHBOARD_URL is used as a replacement for --dashboard-url. The value of - REMOTE_DASHBOARD_URL as a replacement for FROM. Their presence - automatically makes the corresponding argument optional. - - get-pipeline-device-config Get pipeline device configuration to a local file or stdout. diff --git a/man/lava.rst b/man/lava.rst index 4ab40eb..0b8f705 100644 --- a/man/lava.rst +++ b/man/lava.rst @@ -133,44 +133,6 @@ job submit Submits the specified job file. -dashboard - Commands for interacting with LAVA Dashboard - - Usage: lava dashboard [-h] {pull, deserialize, data-views, get, bundles, - query-data-view, version, streams, server-version, put, make-stream} - - - Optional arguments: - -h, --help show this help message and exit - - Sub-command to invoke: {pull, deserialize, data-views, get, bundles, query-data-view, version, streams, server-version, put, make-stream} - pull - Copy bundles and bundle streams from one dashboard to - another. This command checks for two environment varialbes: The - value of DASHBOARD_URL is used as a replacement for --dashbard-url. - The value of REMOTE_DASHBOARD_URL as a replacement for FROM. Their - presence automatically makes the corresponding argument optional. - deserialize - Deserialize a bundle on the server - data-views - Show data views defined on the server - get - Download a bundle from the server - bundles - Show bundles in the specified stream - query-data-view - Invoke a specified data view - version - Show dashboard client version - streams - Show streams you have access to - server-version - Display LAVA server version - put - Upload a bundle on the server - make-stream - Create a bundle stream on the server - scheduler Interact with LAVA Scheduler @@ -204,24 +166,6 @@ scheduler Get list of running and submitted jobs from the scheduler. -device - LAVA devices handling. - - Usage: lava device [-h] {list, add, config, remove} ... - - Optional arguments: - -h, --help show this help message and exit - - Sub-command to invoke: {list,add,config,remove} - list - Lists configured devices. - add - Adds a new device. - config - Opens the specified device config file. - remove - Removes the specified device. - testdef LAVA test definitions handling. @@ -252,80 +196,3 @@ details -h, --help Show this help message and exit --non-interactive, -n Do not ask for input parameters. - -devices - Lists all the configured devices in this LAVA instance. - - Usage: lava devices [-h] [--config-dir CONFIG_DIR] [--config CONFIG] - - Optional arguments: - -h, --help Show this help message and exit - --config-dir CONFIG_DIR - Configuration directory override (currently None) - --config CONFIG Custom config file - -connect - Connects to the device is connection command is specified in device conf. - - Uage: lava connect [-h] [--config-dir CONFIG_DIR] [--config CONFIG] device - - Positional arguments: - device - - Optional arguments: - -h, --help show this help message and exit - --config-dir CONFIG_DIR - Configuration directory override (currently None) - --config CONFIG Custom config file - -dispatch - Run test scenarios on virtual and physical hardware - - Usage: lava dispatch [-h] [--config-dir CONFIG_DIR] [--config CONFIG] - [--oob-fd OOB_FD] [--output-dir OUTPUT_DIR] [--validate] - [--job-id JOB_ID] [--socket-addr SOCKET_ADDR] - [--master-cert MASTER_CERT] [--slave-cert SLAVE_CERT] - [--target TARGET] [--env-dut-path ENV_DUT_PATH] - JOB - - Positional arguments: - JOB Test scenario file - - Optional arguments: - -h, --help show this help message and exit - --config-dir CONFIG_DIR - Configuration directory override (currently None) - --config CONFIG Custom config file - --oob-fd OOB_FD Used internally by LAVA scheduler. - --output-dir OUTPUT_DIR - Directory to put structured output in. - --validate Just validate the job file, do not execute any - steps. - --job-id JOB_ID Set the scheduler job identifier. - This alters process name for easier debugging. - --socket-addr SOCKET_ADDR - Address of the ZMQ socket used to send the logs - to the master. - --master-cert MASTER_CERT - Master certificate file - --slave-cert SLAVE_CERT - Slave certificate file - --target TARGET Run the job on a specific target device - --env-dut-path ENV_DUT_PATH - File with environment variables to be exported to - the device - -power-cycle - Runs the hard_reset_command if specified in device configuration. - - Usage: lava power-cycle [-h] [--config-dir CONFIG_DIR] [--config CONFIG] - device - - Positional arguments: - device - - Optional arguments: - -h, --help show this help message and exit - --config-dir CONFIG_DIR - Configuration directory override (currently None) - --config CONFIG Custom config file |