1
0
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:
Sergei Trofimov
2017-03-06 11:10:25 +00:00
parent 18d001fd76
commit 42539bbe0d
43 changed files with 6229 additions and 2586 deletions

106
wa/commands/list.py Normal file
View 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

View File

@@ -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