mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-09-02 03:12:34 +01:00
New target description + moving target stuff under "framework"
Changing the way target descriptions work from a static mapping to something that is dynamically generated and is extensible via plugins. Also moving core target implementation stuff under "framework".
This commit is contained in:
106
wa/commands/list.py
Normal file
106
wa/commands/list.py
Normal file
@@ -0,0 +1,106 @@
|
||||
# Copyright 2014-2015 ARM Limited
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
from wa import Command, settings
|
||||
from wa.framework import pluginloader
|
||||
from wa.framework.plugin import PluginLoader
|
||||
from wa.framework.target.descriptor import get_target_descriptions
|
||||
from wa.utils.doc import get_summary
|
||||
from wa.utils.formatter import DescriptionListFormatter
|
||||
|
||||
|
||||
class ListCommand(Command):
|
||||
|
||||
name = 'list'
|
||||
description = 'List available WA plugins with a short description of each.'
|
||||
|
||||
def initialize(self, context):
|
||||
kinds = get_kinds()
|
||||
self.parser.add_argument('kind', metavar='KIND',
|
||||
help=('Specify the kind of plugin to list. Must be '
|
||||
'one of: {}'.format(', '.join(kinds))),
|
||||
choices=kinds)
|
||||
self.parser.add_argument('-n', '--name',
|
||||
help='Filter results by the name specified')
|
||||
self.parser.add_argument('-o', '--packaged-only', action='store_true',
|
||||
help='''
|
||||
Only list plugins packaged with WA itself. Do
|
||||
not list plugins installed locally or from
|
||||
other packages.
|
||||
''')
|
||||
self.parser.add_argument('-p', '--platform',
|
||||
help='''
|
||||
Only list results that are supported by the
|
||||
specified platform.
|
||||
''')
|
||||
|
||||
def execute(self, state, args):
|
||||
filters = {}
|
||||
if args.name:
|
||||
filters['name'] = args.name
|
||||
|
||||
if args.kind == 'targets':
|
||||
list_targets()
|
||||
else:
|
||||
list_plugins(args, filters)
|
||||
|
||||
|
||||
def get_kinds():
|
||||
kinds = pluginloader.kinds
|
||||
if 'target_descriptor' in kinds:
|
||||
kinds.remove('target_descriptor')
|
||||
kinds.append('target')
|
||||
return ['{}s'.format(name) for name in kinds]
|
||||
|
||||
|
||||
def list_targets():
|
||||
targets = get_target_descriptions()
|
||||
targets = sorted(targets, key=lambda x: x.name)
|
||||
|
||||
output = DescriptionListFormatter()
|
||||
for target in targets:
|
||||
output.add_item(target.description or '', target.name)
|
||||
print output.format_data()
|
||||
|
||||
|
||||
def list_plugins(args, filters):
|
||||
results = pluginloader.list_plugins(args.kind[:-1])
|
||||
if filters or args.platform:
|
||||
filtered_results = []
|
||||
for result in results:
|
||||
passed = True
|
||||
for k, v in filters.iteritems():
|
||||
if getattr(result, k) != v:
|
||||
passed = False
|
||||
break
|
||||
if passed and args.platform:
|
||||
passed = check_platform(result, args.platform)
|
||||
if passed:
|
||||
filtered_results.append(result)
|
||||
else: # no filters specified
|
||||
filtered_results = results
|
||||
|
||||
if filtered_results:
|
||||
output = DescriptionListFormatter()
|
||||
for result in sorted(filtered_results, key=lambda x: x.name):
|
||||
output.add_item(get_summary(result), result.name)
|
||||
print output.format_data()
|
||||
|
||||
|
||||
def check_platform(plugin, platform):
|
||||
supported_platforms = getattr(plugin, 'supported_platforms', [])
|
||||
if supported_platforms:
|
||||
return platform in supported_platforms
|
||||
return True
|
@@ -18,70 +18,117 @@ import os
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
import wa
|
||||
from wa import Command, settings
|
||||
from wa.framework import log
|
||||
from wa.framework.agenda import Agenda
|
||||
from wa.framework.output import RunOutput
|
||||
from wa.framework import pluginloader
|
||||
from wa.framework.configuration import RunConfiguration
|
||||
from wa.framework.configuration.parsers import AgendaParser, ConfigParser
|
||||
from wa.framework.execution import Executor
|
||||
from wa.framework.output import init_wa_output
|
||||
from wa.framework.version import get_wa_version
|
||||
from wa.framework.exception import NotFoundError, ConfigError
|
||||
from wa.utils import log
|
||||
from wa.utils.types import toggle_set
|
||||
|
||||
|
||||
class RunCommand(Command):
|
||||
|
||||
name = 'run'
|
||||
description = """
|
||||
description = '''
|
||||
Execute automated workloads on a remote device and process the resulting output.
|
||||
"""
|
||||
|
||||
'''
|
||||
|
||||
def initialize(self, context):
|
||||
self.parser.add_argument('agenda', metavar='AGENDA',
|
||||
help="""
|
||||
Agenda for this workload automation run. This defines which
|
||||
workloads will be executed, how many times, with which
|
||||
tunables, etc. See example agendas in {} for an example of
|
||||
how this file should be structured.
|
||||
""".format(os.path.dirname(wlauto.__file__)))
|
||||
Agenda for this workload automation run. This
|
||||
defines which workloads will be executed, how
|
||||
many times, with which tunables, etc. See
|
||||
example agendas in {} for an example of how
|
||||
this file should be structured.
|
||||
""".format(os.path.dirname(wa.__file__)))
|
||||
self.parser.add_argument('-d', '--output-directory', metavar='DIR', default=None,
|
||||
help="""
|
||||
Specify a directory where the output will be generated. If
|
||||
the directory already exists, the script will abort unless -f
|
||||
option (see below) is used, in which case the contents of the
|
||||
directory will be overwritten. If this option is not specified,
|
||||
then {} will be used instead.
|
||||
""".format(settings.output_directory))
|
||||
Specify a directory where the output will be
|
||||
generated. If the directory already exists,
|
||||
the script will abort unless -f option (see
|
||||
below) is used, in which case the contents of
|
||||
the directory will be overwritten. If this
|
||||
option is not specified, then {} will be used
|
||||
instead.
|
||||
""".format(settings.default_output_directory))
|
||||
self.parser.add_argument('-f', '--force', action='store_true',
|
||||
help="""
|
||||
Overwrite output directory if it exists. By default, the script
|
||||
will abort in this situation to prevent accidental data loss.
|
||||
Overwrite output directory if it exists. By
|
||||
default, the script will abort in this
|
||||
situation to prevent accidental data loss.
|
||||
""")
|
||||
self.parser.add_argument('-i', '--id', action='append', dest='only_run_ids', metavar='ID',
|
||||
help="""
|
||||
Specify a workload spec ID from an agenda to run. If this is
|
||||
specified, only that particular spec will be run, and other
|
||||
workloads in the agenda will be ignored. This option may be
|
||||
used to specify multiple IDs.
|
||||
Specify a workload spec ID from an agenda to
|
||||
run. If this is specified, only that
|
||||
particular spec will be run, and other
|
||||
workloads in the agenda will be ignored. This
|
||||
option may be used to specify multiple IDs.
|
||||
""")
|
||||
self.parser.add_argument('--disable', action='append', dest='instruments_to_disable',
|
||||
default=[],
|
||||
metavar='INSTRUMENT', help="""
|
||||
Specify an instrument to disable from the command line. This
|
||||
equivalent to adding "~{metavar}" to the instrumentation list in
|
||||
the agenda. This can be used to temporarily disable a troublesome
|
||||
instrument for a particular run without introducing permanent
|
||||
change to the config (which one might then forget to revert).
|
||||
This option may be specified multiple times.
|
||||
Specify an instrument to disable from the
|
||||
command line. This equivalent to adding
|
||||
"~{metavar}" to the instrumentation list in
|
||||
the agenda. This can be used to temporarily
|
||||
disable a troublesome instrument for a
|
||||
particular run without introducing permanent
|
||||
change to the config (which one might then
|
||||
forget to revert). This option may be
|
||||
specified multiple times.
|
||||
""")
|
||||
|
||||
def execute(self, args): # NOQA
|
||||
def execute(self, config, args):
|
||||
output = self.set_up_output_directory(config, args)
|
||||
log.add_file(output.logfile)
|
||||
|
||||
self.logger.debug('Version: {}'.format(get_wa_version()))
|
||||
self.logger.debug('Command Line: {}'.format(' '.join(sys.argv)))
|
||||
|
||||
disabled_instruments = toggle_set(["~{}".format(i)
|
||||
for i in args.instruments_to_disable])
|
||||
config.jobs_config.disable_instruments(disabled_instruments)
|
||||
config.jobs_config.only_run_ids(args.only_run_ids)
|
||||
|
||||
parser = AgendaParser()
|
||||
if os.path.isfile(args.agenda):
|
||||
parser.load_from_path(config, args.agenda)
|
||||
shutil.copy(args.agenda, output.raw_config_dir)
|
||||
else:
|
||||
try:
|
||||
pluginloader.get_plugin_class(args.agenda, kind='workload')
|
||||
agenda = {'workloads': [{'name': args.agenda}]}
|
||||
parser.load(config, agenda, 'CMDLINE_ARGS')
|
||||
except NotFoundError:
|
||||
msg = 'Agenda file "{}" does not exist, and there no workload '\
|
||||
'with that name.\nYou can get a list of available '\
|
||||
'by running "wa list workloads".'
|
||||
raise ConfigError(msg.format(args.agenda))
|
||||
|
||||
executor = Executor()
|
||||
executor.execute(config, output)
|
||||
|
||||
def set_up_output_directory(self, config, args):
|
||||
if args.output_directory:
|
||||
output_directory = args.output_directory
|
||||
else:
|
||||
output_directory = settings.default_output_directory
|
||||
self.logger.debug('Using output directory: {}'.format(output_directory))
|
||||
try:
|
||||
executor = Executor(args.output_directory, args.force)
|
||||
except RuntimeError:
|
||||
self.logger.error('Output directory {} exists.'.format(args.output_directory))
|
||||
self.logger.error('Please specify another location, or use -f option to overwrite.\n')
|
||||
return 2
|
||||
for path in settings.get_config_paths():
|
||||
executor.load_config(path)
|
||||
executor.load_agenda(args.agenda)
|
||||
for itd in args.instruments_to_disable:
|
||||
self.logger.debug('Globally disabling instrument "{}" (from command line option)'.format(itd))
|
||||
executor.disable_instrument(itd)
|
||||
executor.initialize()
|
||||
executor.execute(selectors={'ids': args.only_run_ids})
|
||||
executor.finalize()
|
||||
return init_wa_output(output_directory, config, args.force)
|
||||
except RuntimeError as e:
|
||||
if 'path exists' in str(e):
|
||||
msg = 'Output directory "{}" exists.\nPlease specify another '\
|
||||
'location, or use -f option to overwrite.'
|
||||
self.logger.critical(msg.format(output_directory))
|
||||
sys.exit(1)
|
||||
else:
|
||||
raise e
|
||||
|
Reference in New Issue
Block a user