2023-11-30 22:32:06 +00:00
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
import signal
|
|
|
|
import subprocess
|
|
|
|
import time
|
|
|
|
import typing
|
|
|
|
|
|
|
|
import allure
|
|
|
|
import psutil
|
|
|
|
|
|
|
|
import configs
|
|
|
|
from configs.system import IS_WIN
|
|
|
|
|
2023-11-30 10:51:00 +00:00
|
|
|
LOG = logging.getLogger(__name__)
|
2023-11-30 22:32:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
def find_process_by_port(port: int) -> typing.List[int]:
|
|
|
|
pid_list = []
|
|
|
|
for proc in psutil.process_iter():
|
|
|
|
try:
|
|
|
|
for conns in proc.connections(kind='inet'):
|
|
|
|
if conns.laddr.port == port:
|
|
|
|
pid_list.append(proc.pid)
|
|
|
|
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
|
|
|
pass
|
|
|
|
return pid_list
|
|
|
|
|
|
|
|
|
|
|
|
def find_free_port(start: int, step: int):
|
|
|
|
while find_process_by_port(start):
|
|
|
|
start+=step
|
|
|
|
return start
|
|
|
|
|
|
|
|
@allure.step('Kill process')
|
2023-11-30 10:51:00 +00:00
|
|
|
def kill_process(pid, sig: signal.Signals = signal.SIGKILL):
|
|
|
|
LOG.debug('Sending %s to %d process', sig.name, pid)
|
2023-11-30 22:32:06 +00:00
|
|
|
try:
|
2023-11-30 10:51:00 +00:00
|
|
|
os.kill(pid, sig)
|
2023-11-30 22:32:06 +00:00
|
|
|
except ProcessLookupError as err:
|
2023-11-30 10:51:00 +00:00
|
|
|
LOG.error('Failed to find process %d: %s', pid, err)
|
|
|
|
raise err
|
|
|
|
|
|
|
|
@allure.step('Kill process with retries')
|
|
|
|
def kill_process_with_retries(pid, sig: signal.Signals = signal.SIGTERM, attempts: int = 3):
|
|
|
|
LOG.debug('Killing process: %d', pid)
|
|
|
|
try:
|
|
|
|
p = psutil.Process(pid)
|
|
|
|
except psutil.NoSuchProcess:
|
|
|
|
LOG.warning('Process %d already gone.', pid)
|
|
|
|
return
|
|
|
|
|
|
|
|
p.terminate()
|
|
|
|
|
|
|
|
while attempts > 0:
|
|
|
|
attempts -= 1
|
2023-11-30 22:32:06 +00:00
|
|
|
try:
|
2023-11-30 10:51:00 +00:00
|
|
|
LOG.warning('Waiting for process to exit: %d', pid)
|
|
|
|
p.wait()
|
|
|
|
except TimeoutError as err:
|
|
|
|
p.kill()
|
|
|
|
else:
|
|
|
|
return
|
2023-11-30 22:32:06 +00:00
|
|
|
|
2023-11-30 10:51:00 +00:00
|
|
|
raise RuntimeError('Failed to kill proicess: %d' % pid)
|
2023-11-30 22:32:06 +00:00
|
|
|
|
|
|
|
@allure.step('System execute command')
|
|
|
|
def execute(
|
|
|
|
command: list,
|
2023-11-30 10:51:00 +00:00
|
|
|
stderr=subprocess.STDOUT,
|
|
|
|
stdout=subprocess.STDOUT,
|
|
|
|
shell=False,
|
2023-11-30 22:32:06 +00:00
|
|
|
):
|
2023-11-30 10:51:00 +00:00
|
|
|
LOG.info('Executing: %s', command)
|
2023-11-30 22:32:06 +00:00
|
|
|
process = subprocess.Popen(command, shell=shell, stderr=stderr, stdout=stdout)
|
|
|
|
return process.pid
|
|
|
|
|
|
|
|
@allure.step('System run command')
|
|
|
|
def run(
|
|
|
|
command: list,
|
2023-11-30 10:51:00 +00:00
|
|
|
stderr=subprocess.STDOUT,
|
|
|
|
stdout=subprocess.STDOUT,
|
|
|
|
shell=False,
|
|
|
|
timeout_sec=configs.timeouts.PROCESS_TIMEOUT_SEC
|
2023-11-30 22:32:06 +00:00
|
|
|
):
|
2023-11-30 10:51:00 +00:00
|
|
|
LOG.info('Running: %s', command)
|
|
|
|
process = subprocess.run(
|
|
|
|
command,
|
|
|
|
shell=shell,
|
|
|
|
stderr=stderr,
|
|
|
|
stdout=stdout,
|
|
|
|
timeout=timeout_sec,
|
|
|
|
check=True
|
|
|
|
)
|