update
This commit is contained in:
parent
533f7982c8
commit
97bd3a1c88
155
services/cmd/handler.py
Normal file
155
services/cmd/handler.py
Normal file
@ -0,0 +1,155 @@
|
||||
import subprocess
|
||||
import lib.color_log as color_log
|
||||
import shutil
|
||||
import os
|
||||
import shlex
|
||||
from services.odoo.connection import OdooConnection
|
||||
|
||||
|
||||
class SSHHandler:
|
||||
def __init__(self, config_path="config/settings.yaml"):
|
||||
self.config = OdooConnection(config_path)
|
||||
|
||||
def _check_sshpass():
|
||||
"""Check if sshpass is installed in the system."""
|
||||
return shutil.which("sshpass") is not None
|
||||
|
||||
def _build_command(host, cmd, ssh_user="root", ssh_key_path=None, passphrase=None):
|
||||
"""
|
||||
Build an SSH command with the given parameters.
|
||||
|
||||
Args:
|
||||
host (str): The target host
|
||||
cmd (str): The command to execute
|
||||
ssh_user (str): SSH user (default: root)
|
||||
ssh_key_path (str, optional): Path to SSH key file
|
||||
passphrase (str, optional): Passphrase for SSH key
|
||||
|
||||
Returns:
|
||||
tuple: (args, env) where args is a list of command arguments, and env is a dictionary of environment variables
|
||||
"""
|
||||
# For local execution
|
||||
if host in ["localhost", "127.0.0.1"]:
|
||||
return ["bash", "-c", cmd], None
|
||||
|
||||
# Build SSH command as a list of arguments
|
||||
args = [
|
||||
"ssh",
|
||||
"-o",
|
||||
"StrictHostKeyChecking=no",
|
||||
"-o",
|
||||
"UserKnownHostsFile=/dev/null",
|
||||
"-t",
|
||||
]
|
||||
if ssh_key_path:
|
||||
args.extend(["-i", ssh_key_path])
|
||||
args.append(f"{ssh_user}@{host}")
|
||||
# Quote the command safely for remote execution
|
||||
remote_cmd = f"sudo -s bash -c {shlex.quote(cmd)}"
|
||||
args.append(remote_cmd)
|
||||
|
||||
env = None
|
||||
# Handle passphrase securely with sshpass
|
||||
if passphrase:
|
||||
if not SSHHandler._check_sshpass():
|
||||
raise RuntimeError(
|
||||
"sshpass is required for passphrase authentication but not installed"
|
||||
)
|
||||
args = ["sshpass", "-e"] + args
|
||||
env = {"SSHPASS": passphrase}
|
||||
|
||||
return args, env
|
||||
|
||||
def execute_command(args, instance_name, capture_output=True, env=None):
|
||||
"""
|
||||
Execute a command and handle errors.
|
||||
|
||||
Args:
|
||||
args (list): List of command arguments
|
||||
instance_name (str): Name of the instance (for logging)
|
||||
capture_output (bool): Whether to capture command output
|
||||
env (dict, optional): Environment variables to set for the command
|
||||
|
||||
Returns:
|
||||
str: Command output if capture_output is True
|
||||
|
||||
Raises:
|
||||
subprocess.CalledProcessError: If command execution fails
|
||||
"""
|
||||
try:
|
||||
# Log the command being executed
|
||||
color_log.Show("INFO", f"Executing command: {' '.join(args)}")
|
||||
|
||||
# Create a copy of the current environment
|
||||
cmd_env = os.environ.copy()
|
||||
# Update with any additional environment variables
|
||||
if env:
|
||||
cmd_env.update(env)
|
||||
|
||||
# Execute the command with subprocess
|
||||
result = subprocess.run(
|
||||
args, check=True, capture_output=capture_output, text=True, env=cmd_env
|
||||
)
|
||||
|
||||
# Handle output if captured
|
||||
if capture_output:
|
||||
if result.stdout:
|
||||
print(result.stdout.strip())
|
||||
if result.stderr:
|
||||
print(result.stderr.strip())
|
||||
|
||||
color_log.Show("OK", f"Command executed successfully for {instance_name}")
|
||||
return result.stdout if capture_output else None
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
# Handle errors and log output
|
||||
if capture_output:
|
||||
if e.stdout:
|
||||
print(e.stdout.strip())
|
||||
if e.stderr:
|
||||
print(e.stderr.strip())
|
||||
|
||||
color_log.Show(
|
||||
"FAILED",
|
||||
f"Error executing command for {instance_name}: {e}",
|
||||
)
|
||||
raise
|
||||
|
||||
def run_ssh_command(
|
||||
host,
|
||||
cmd,
|
||||
instance_name,
|
||||
ssh_user="root",
|
||||
ssh_key_path=None,
|
||||
passphrase=None,
|
||||
capture_output=True,
|
||||
env=None,
|
||||
):
|
||||
"""
|
||||
Execute a command on a remote host via SSH or locally if host is localhost.
|
||||
|
||||
Args:
|
||||
host (str): The target host
|
||||
cmd (str): The command to execute
|
||||
instance_name (str): Name of the instance (for logging)
|
||||
ssh_user (str): SSH user (default: root)
|
||||
ssh_key_path (str, optional): Path to SSH key file
|
||||
passphrase (str, optional): Passphrase for SSH key
|
||||
capture_output (bool): Whether to capture command output
|
||||
env (dict, optional): Additional environment variables to set for the command
|
||||
|
||||
Returns:
|
||||
str: Command output if capture_output is True
|
||||
"""
|
||||
# Build the command and get any required environment variables
|
||||
args, cmd_env = SSHHandler._build_command(
|
||||
host, cmd, ssh_user, ssh_key_path, passphrase
|
||||
)
|
||||
# Merge command-specific env with user-provided env
|
||||
if cmd_env:
|
||||
if env is None:
|
||||
env = cmd_env
|
||||
else:
|
||||
env.update(cmd_env)
|
||||
# Execute the command
|
||||
return SSHHandler.execute_command(args, instance_name, capture_output, env)
|
Loading…
Reference in New Issue
Block a user