in osbenchmark/workload/loader.py [0:0]
def read(self, workload_name, workload_spec_file, mapping_dir):
"""
Reads a workload file, verifies it against the JSON schema and if valid, creates a workload.
:param workload_name: The name of the workload.
:param workload_spec_file: The complete path to the workload specification file.
:param mapping_dir: The directory where the mapping files for this workload are stored locally.
:return: A corresponding workload instance if the workload file is valid.
"""
self.logger.info("Reading workload specification file [%s].", workload_spec_file)
# render the workload to a temporary file instead of dumping it into the logs. It is easier to check for error messages
# involving lines numbers and it also does not bloat Benchmark's log file so much.
tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".json")
try:
rendered = render_template_from_file(
workload_spec_file, self.workload_params,
complete_workload_params=self.complete_workload_params)
with open(tmp.name, "wt", encoding="utf-8") as f:
f.write(rendered)
self.logger.info("Final rendered workload for '%s' has been written to '%s'.", workload_spec_file, tmp.name)
workload_spec = json.loads(rendered)
except jinja2.exceptions.TemplateNotFound:
self.logger.exception("Could not load [%s]", workload_spec_file)
raise exceptions.SystemSetupError("Workload {} does not exist".format(workload_name))
except json.JSONDecodeError as e:
self.logger.exception("Could not load [%s].", workload_spec_file)
msg = "Could not load '{}': {}.".format(workload_spec_file, str(e))
if e.doc and e.lineno > 0 and e.colno > 0:
line_idx = e.lineno - 1
lines = e.doc.split("\n")
ctx_line_count = 3
ctx_start = max(0, line_idx - ctx_line_count)
ctx_end = min(line_idx + ctx_line_count, len(lines))
erroneous_lines = lines[ctx_start:ctx_end]
erroneous_lines.insert(line_idx - ctx_start + 1, "-" * (e.colno - 1) + "^ Error is here")
msg += " Lines containing the error:\n\n{}\n\n".format("\n".join(erroneous_lines))
msg += "The complete workload has been written to '{}' for diagnosis.".format(tmp.name)
raise WorkloadSyntaxError(msg)
except Exception as e:
self.logger.exception("Could not load [%s].", workload_spec_file)
msg = "Could not load '{}'. The complete workload has been written to '{}' for diagnosis.".format(workload_spec_file, tmp.name)
# Convert to string early on to avoid serialization errors with Jinja exceptions.
raise WorkloadSyntaxError(msg, str(e))
# check the workload version before even attempting to validate the JSON format to avoid bogus errors.
raw_version = workload_spec.get("version", WorkloadFileReader.MAXIMUM_SUPPORTED_TRACK_VERSION)
try:
workload_version = int(raw_version)
except ValueError:
raise exceptions.InvalidSyntax("version identifier for workload %s must be numeric but was [%s]" % (
workload_name, str(raw_version)))
if WorkloadFileReader.MINIMUM_SUPPORTED_TRACK_VERSION > workload_version:
raise exceptions.BenchmarkError("Workload {} is on version {} but needs to be updated at least to version {} to work with the "
"current version of Benchmark.".format(workload_name, workload_version,
WorkloadFileReader.MINIMUM_SUPPORTED_TRACK_VERSION))
if WorkloadFileReader.MAXIMUM_SUPPORTED_TRACK_VERSION < workload_version:
raise exceptions.BenchmarkError("Workload {} requires a newer version of Benchmark. "
"Please upgrade Benchmark (supported workload version: {}, "
"required workload version: {}).".format(
workload_name,
WorkloadFileReader.MAXIMUM_SUPPORTED_TRACK_VERSION,
workload_version))
try:
jsonschema.validate(workload_spec, self.workload_schema)
except jsonschema.exceptions.ValidationError as ve:
raise WorkloadSyntaxError(
"Workload '{}' is invalid.\n\nError details: {}\nInstance: {}\nPath: {}\nSchema path: {}".format(
workload_name, ve.message, json.dumps(
ve.instance, indent=4, sort_keys=True),
ve.absolute_path, ve.absolute_schema_path))
current_workload = self.read_workload(workload_name, workload_spec, mapping_dir)
unused_user_defined_workload_params = self.complete_workload_params.unused_user_defined_workload_params()
if len(unused_user_defined_workload_params) > 0:
err_msg = (
"Some of your workload parameter(s) {} are not used by this workload; perhaps you intend to use {} instead.\n\n"
"All workload parameters you provided are:\n"
"{}\n\n"
"All parameters exposed by this workload:\n"
"{}".format(
",".join(opts.double_quoted_list_of(sorted(unused_user_defined_workload_params))),
",".join(opts.double_quoted_list_of(sorted(opts.make_list_of_close_matches(
unused_user_defined_workload_params,
self.complete_workload_params.workload_defined_params
)))),
"\n".join(opts.bulleted_list_of(sorted(list(self.workload_params.keys())))),
"\n".join(opts.bulleted_list_of(self.complete_workload_params.sorted_workload_defined_params))))
self.logger.critical(err_msg)
# also dump the message on the console
console.println(err_msg)
raise exceptions.WorkloadConfigError(
"Unused workload parameters {}.".format(sorted(unused_user_defined_workload_params))
)
return current_workload