"""Common utility functions."""
import json
import os
import signal
import stat
import subprocess
import time
from functools import wraps
FAIL = 1
TIME_OUT = 5
cur_abs_path, _ = os.path.split(os.path.abspath(__file__))
def close_child_process(proc):
try:
os.killpg(proc.pid, signal.SIGKILL)
except ProcessLookupError as err:
_ = err
return 'success'
except Exception as err:
return str(err)
return 'success'
def retry(retry_times, log, task, wait_times):
def decorate(func):
@wraps(func)
def wrapper(*args, **kwargs):
err = ""
for i in range(retry_times):
try:
return func(*args, **kwargs)
except Exception as _err:
log.info("Execute task[%s] %s/%s times", task, i + 1, retry_times)
err = _err
time.sleep(wait_times)
continue
else:
raise err
return wrapper
return decorate
def exec_popen(cmd, timeout=TIME_OUT):
"""Execute command via subprocess; on timeout, kill process group to avoid zombies."""
bash_cmd = ["bash"]
pobj = subprocess.Popen(bash_cmd, shell=False, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid)
pobj.stdin.write(cmd.encode())
pobj.stdin.write(os.linesep.encode())
try:
stdout, stderr = pobj.communicate(timeout=timeout)
except subprocess.TimeoutExpired:
close_child_process(pobj)
try:
pobj.communicate(timeout=5)
except Exception:
pass
return -1, "", f"Command timed out after {timeout}s"
except Exception as err:
close_child_process(pobj)
try:
pobj.communicate(timeout=5)
except Exception:
pass
return pobj.returncode, "", str(err)
return_code = pobj.returncode
stdout, stderr = stdout.decode(), stderr.decode()
if stdout[-1:] == os.linesep:
stdout = stdout[:-1]
if stderr[-1:] == os.linesep:
stderr = stderr[:-1]
return return_code, stdout, stderr
def read_json_config(file_path):
with open(file_path, "r") as f:
return json.loads(f.read())
def write_json_config(file_path, data):
flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
modes = stat.S_IWUSR | stat.S_IRUSR
with os.fdopen(os.open(file_path, flags, modes), 'w') as fp:
json.dump(data, fp, indent=4)
def file_reader(file_path):
with open(file_path, 'r') as file:
return file.read()
def get_status(status: str, status_class: object) -> str:
for key, value in status_class.__dict__.items():
if value == status:
return key
return status