103 lines
3.2 KiB
Plaintext
Executable File
103 lines
3.2 KiB
Plaintext
Executable File
#!/usr/local/sbin/charm-env python3
|
|
|
|
import os
|
|
import subprocess
|
|
import tarfile
|
|
import tempfile
|
|
import traceback
|
|
from contextlib import contextmanager
|
|
from datetime import datetime
|
|
from charmhelpers.core.hookenv import action_set, local_unit
|
|
|
|
archive_dir = None
|
|
log_file = None
|
|
|
|
|
|
@contextmanager
|
|
def archive_context():
|
|
""" Open a context with a new temporary directory.
|
|
|
|
When the context closes, the directory is archived, and the archive
|
|
location is added to Juju action output. """
|
|
global archive_dir
|
|
global log_file
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
name = "debug-" + datetime.now().strftime("%Y%m%d%H%M%S")
|
|
archive_dir = os.path.join(temp_dir, name)
|
|
os.makedirs(archive_dir)
|
|
with open("%s/debug.log" % archive_dir, "w") as log_file:
|
|
yield
|
|
os.chdir(temp_dir)
|
|
tar_path = "/home/ubuntu/%s.tar.gz" % name
|
|
with tarfile.open(tar_path, "w:gz") as f:
|
|
f.add(name)
|
|
action_set({
|
|
"path": tar_path,
|
|
"command": "juju scp %s:%s ." % (local_unit(), tar_path),
|
|
"message": " ".join([
|
|
"Archive has been created on unit %s." % local_unit(),
|
|
"Use the juju scp command to copy it to your local machine."
|
|
])
|
|
})
|
|
|
|
|
|
def log(msg):
|
|
""" Log a message that will be included in the debug archive.
|
|
|
|
Must be run within archive_context """
|
|
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
for line in str(msg).splitlines():
|
|
log_file.write(timestamp + " | " + line.rstrip() + "\n")
|
|
|
|
|
|
def run_script(script):
|
|
""" Run a single script. Must be run within archive_context """
|
|
log("Running script: " + script)
|
|
script_dir = os.path.join(archive_dir, script)
|
|
os.makedirs(script_dir)
|
|
env = os.environ.copy()
|
|
env["PYTHONPATH"] = "lib" # allow same imports as reactive code
|
|
env["DEBUG_SCRIPT_DIR"] = script_dir
|
|
with open(script_dir + "/stdout", "w") as stdout:
|
|
with open(script_dir + "/stderr", "w") as stderr:
|
|
process = subprocess.Popen(
|
|
"debug-scripts/" + script,
|
|
stdout=stdout, stderr=stderr, env=env
|
|
)
|
|
try:
|
|
exit_code = process.wait(timeout=300)
|
|
except subprocess.TimeoutExpired:
|
|
log("ERROR: still running, terminating")
|
|
process.terminate()
|
|
try:
|
|
exit_code = process.wait(timeout=10)
|
|
except subprocess.TimeoutExpired:
|
|
log("ERROR: still running, killing")
|
|
process.kill()
|
|
exit_code = process.wait(timeout=10)
|
|
if exit_code != 0:
|
|
log("ERROR: %s failed with exit code %d" % (script, exit_code))
|
|
|
|
|
|
def run_all_scripts():
|
|
""" Run all scripts. For the sake of robustness, log and ignore any
|
|
exceptions that occur.
|
|
|
|
Must be run within archive_context """
|
|
scripts = os.listdir("debug-scripts")
|
|
for script in scripts:
|
|
try:
|
|
run_script(script)
|
|
except:
|
|
log(traceback.format_exc())
|
|
|
|
|
|
def main():
|
|
""" Open an archive context and run all scripts. """
|
|
with archive_context():
|
|
run_all_scripts()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|