avocado/plugins/jobscripts.py
import os
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import Init, JobPost, JobPre
from avocado.core.settings import settings
from avocado.core.utils.path import prepend_base_path
from avocado.utils import process
class JobScriptsInit(Init):
name = "jobscripts-init"
description = "Jobscripts plugin initialization"
def initialize(self):
help_msg = "Warn if configured (or default) directory does not exist"
settings.register_option(
section="plugins.jobscripts",
key="warn_non_existing_dir",
key_type=bool,
default=False,
help_msg=help_msg,
)
help_msg = "Warn if any script run return non-zero status"
settings.register_option(
section="plugins.jobscripts",
key="warn_non_zero_status",
key_type=bool,
default=True,
help_msg=help_msg,
)
help_msg = "Directory with scripts to be executed before a job is run"
default = "/etc/avocado/scripts/job/pre.d/"
settings.register_option(
section="plugins.jobscripts",
key="pre",
key_type=prepend_base_path,
help_msg=help_msg,
default=default,
)
help_msg = "Directory with scripts to be executed after a job is run"
default = "/etc/avocado/scripts/job/post.d/"
settings.register_option(
section="plugins.jobscripts",
key="post",
key_type=prepend_base_path,
help_msg=help_msg,
default=default,
)
class JobScripts(JobPre, JobPost):
name = "jobscripts"
description = "Runs scripts before/after the job is run"
def _run_scripts(self, kind, scripts_dir, job):
config = job.config
if not os.path.isdir(scripts_dir):
if config.get("plugins.jobscripts.warn_non_existing_dir"):
LOG_UI.error(
"Directory configured to hold %s-job scripts "
"has not been found: %s",
kind,
scripts_dir,
)
return
dir_list = os.listdir(scripts_dir)
scripts = [os.path.join(scripts_dir, f) for f in dir_list]
scripts = [f for f in scripts if os.access(f, os.R_OK | os.X_OK)]
scripts.sort()
if not scripts:
return
env = self._job_to_environment_variables(job)
non_zero_namespace = "plugins.jobscripts.warn_non_zero_status"
warn_non_zero_status = config.get(non_zero_namespace)
for script in scripts:
result = process.run(script, ignore_status=True, env=env)
if (result.exit_status != 0) and warn_non_zero_status:
LOG_UI.error(
'%s job script "%s" exited with status "%i"',
kind.capitalize(),
script,
result.exit_status,
)
@staticmethod
def _job_to_environment_variables(job):
env = {}
env["AVOCADO_JOB_UNIQUE_ID"] = job.unique_id
env["AVOCADO_JOB_STATUS"] = job.status
if job.logdir is not None:
env["AVOCADO_JOB_LOGDIR"] = job.logdir
return env
def pre(self, job):
path = job.config.get("plugins.jobscripts.pre")
self._run_scripts("pre", path, job)
def post(self, job):
path = job.config.get("plugins.jobscripts.post")
self._run_scripts("post", path, job)