221 lines
9.0 KiB
Diff
221 lines
9.0 KiB
Diff
From 80272352b3067ebb2cb3011cfbeeef5e9d464fa6 Mon Sep 17 00:00:00 2001
|
|
From: smjiao <smjiao@isoftstone.com>
|
|
Date: Mon, 18 Sep 2023 20:37:50 +0800
|
|
Subject: [PATCH 1/1] fix bash file sync error
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
---
|
|
zeus/config_manager/view.py | 48 ++++++++++++++++++++-----
|
|
zeus/host_manager/ssh.py | 72 +++++++++++++++++++++++++++++++------
|
|
2 files changed, 102 insertions(+), 18 deletions(-)
|
|
|
|
diff --git a/zeus/config_manager/view.py b/zeus/config_manager/view.py
|
|
index baeef7e..6779153 100644
|
|
--- a/zeus/config_manager/view.py
|
|
+++ b/zeus/config_manager/view.py
|
|
@@ -16,6 +16,7 @@ Author:
|
|
Description: Restful APIs for host
|
|
"""
|
|
import json
|
|
+import os
|
|
from typing import List, Dict
|
|
|
|
from vulcanus.multi_thread_handler import MultiThreadHandler
|
|
@@ -26,7 +27,7 @@ from zeus.conf.constant import CERES_COLLECT_FILE, CERES_SYNC_CONF
|
|
from zeus.database.proxy.host import HostProxy
|
|
from zeus.function.model import ClientConnectArgs
|
|
from zeus.function.verify.config import CollectConfigSchema, SyncConfigSchema
|
|
-from zeus.host_manager.ssh import execute_command_and_parse_its_result
|
|
+from zeus.host_manager.ssh import execute_command_and_parse_its_result, execute_command_sftp_result
|
|
|
|
|
|
class CollectConfig(BaseResponse):
|
|
@@ -222,15 +223,46 @@ class CollectConfig(BaseResponse):
|
|
|
|
|
|
class SyncConfig(BaseResponse):
|
|
-
|
|
@staticmethod
|
|
- def sync_config_content(host_info: Dict, sync_config_info: Dict):
|
|
- command = CERES_SYNC_CONF % json.dumps(sync_config_info)
|
|
- status, content = execute_command_and_parse_its_result(
|
|
+ def sync_config_by_execute_command_sftp(host_info: Dict, sync_config_info: Dict, local_path: str,
|
|
+ remote_path: str):
|
|
+ content = sync_config_info.get("content")
|
|
+ with open(local_path, "w", encoding="UTF-8") as f:
|
|
+ f.write(content)
|
|
+ status = execute_command_sftp_result(
|
|
ClientConnectArgs(host_info.get("host_ip"), host_info.get("ssh_port"),
|
|
- host_info.get("ssh_user"), host_info.get("pkey")), command)
|
|
+ host_info.get("ssh_user"), host_info.get("pkey")), local_path, remote_path)
|
|
return status
|
|
|
|
+ @staticmethod
|
|
+ def sync_config_content(host_info: Dict, sync_config_info: Dict):
|
|
+ join_path = "/tmp"
|
|
+ if sync_config_info.get("file_path") == "/etc/profile":
|
|
+ local_path = os.path.join(join_path, "profile")
|
|
+ remote_path = "/etc/profile"
|
|
+ status = SyncConfig.sync_config_by_execute_command_sftp(host_info, sync_config_info, local_path,
|
|
+ remote_path)
|
|
+ return status
|
|
+ elif sync_config_info.get("file_path") == "/etc/rc.local":
|
|
+ local_path = os.path.join(join_path, "rc.local")
|
|
+ remote_path = "/etc/rc.local"
|
|
+ status = SyncConfig.sync_config_by_execute_command_sftp(host_info, sync_config_info, local_path,
|
|
+ remote_path)
|
|
+ return status
|
|
+ elif sync_config_info.get("file_path") == "/etc/bashrc":
|
|
+ local_path = os.path.join(join_path, "bashrc")
|
|
+ remote_path = "/etc/bashrc"
|
|
+ status = SyncConfig.sync_config_by_execute_command_sftp(host_info, sync_config_info, local_path,
|
|
+ remote_path)
|
|
+ return status
|
|
+ else:
|
|
+ command = CERES_SYNC_CONF % json.dumps(sync_config_info)
|
|
+
|
|
+ status, content = execute_command_and_parse_its_result(
|
|
+ ClientConnectArgs(host_info.get("host_ip"), host_info.get("ssh_port"),
|
|
+ host_info.get("ssh_user"), host_info.get("pkey")), command)
|
|
+ return status
|
|
+
|
|
@BaseResponse.handle(schema=SyncConfigSchema, token=False)
|
|
def put(self, **params):
|
|
|
|
@@ -244,13 +276,13 @@ class SyncConfig(BaseResponse):
|
|
}
|
|
|
|
# Query host address from database
|
|
- proxy = HostProxy(configuration)
|
|
+ proxy = HostProxy()
|
|
if not proxy.connect():
|
|
return self.response(code=state.DATABASE_CONNECT_ERROR, data={"resp": sync_result})
|
|
|
|
status, host_list = proxy.get_host_info(
|
|
{"username": "admin", "host_list": [params.get('host_id')]}, True)
|
|
- if status != state.SUCCEED or len(host_list) == 1:
|
|
+ if status != state.SUCCEED:
|
|
return self.response(code=status, data={"resp": sync_result})
|
|
|
|
host_info = host_list[0]
|
|
diff --git a/zeus/host_manager/ssh.py b/zeus/host_manager/ssh.py
|
|
index 4c3a259..11f6383 100644
|
|
--- a/zeus/host_manager/ssh.py
|
|
+++ b/zeus/host_manager/ssh.py
|
|
@@ -15,6 +15,7 @@ from io import StringIO
|
|
from typing import Tuple
|
|
|
|
import paramiko
|
|
+from paramiko import sftp
|
|
|
|
from vulcanus.log.log import LOGGER
|
|
from vulcanus.restful.resp import state
|
|
@@ -57,7 +58,13 @@ class SSH:
|
|
"""
|
|
|
|
def __init__(self, ip, username, port, password=None, pkey=None):
|
|
- self._client_args = {'hostname': ip, 'username': username, 'port': port, "password": password, "pkey": pkey}
|
|
+ self._client_args = {
|
|
+ 'hostname': ip,
|
|
+ 'username': username,
|
|
+ 'port': port,
|
|
+ "password": password,
|
|
+ "pkey": pkey
|
|
+ }
|
|
self._client = self.client()
|
|
|
|
def client(self):
|
|
@@ -71,15 +78,15 @@ class SSH:
|
|
|
|
def execute_command(self, command: str, timeout: float = None) -> tuple:
|
|
"""
|
|
- create a ssh client, execute command and parse result
|
|
+ create a ssh client, execute command and parse result
|
|
|
|
- Args:
|
|
- command(str): shell command
|
|
- timeout(float): the maximum time to wait for the result of command execution
|
|
+ Args:
|
|
+ command(str): shell command
|
|
+ timeout(float): the maximum time to wait for the result of command execution
|
|
|
|
- Returns:
|
|
- tuple:
|
|
- status, result, error message
|
|
+ Returns:
|
|
+ tuple:
|
|
+ status, result, error message
|
|
"""
|
|
open_channel = self._client.get_transport().open_session(timeout=timeout)
|
|
open_channel.set_combine_stderr(False)
|
|
@@ -110,13 +117,14 @@ def execute_command_and_parse_its_result(connect_args: ClientConnectArgs, comman
|
|
status, result
|
|
"""
|
|
if not connect_args.pkey:
|
|
- return state.SSH_AUTHENTICATION_ERROR, f"ssh authentication failed when connect host " f"{connect_args.host_ip}"
|
|
+ return state.SSH_AUTHENTICATION_ERROR, f"ssh authentication failed when connect host " \
|
|
+ f"{connect_args.host_ip}"
|
|
try:
|
|
client = SSH(
|
|
ip=connect_args.host_ip,
|
|
username=connect_args.ssh_user,
|
|
port=connect_args.ssh_port,
|
|
- pkey=paramiko.RSAKey.from_private_key(StringIO(connect_args.pkey)),
|
|
+ pkey=paramiko.RSAKey.from_private_key(StringIO(connect_args.pkey))
|
|
)
|
|
exit_status, stdout, stderr = client.execute_command(command, connect_args.timeout)
|
|
except socket.error as error:
|
|
@@ -131,3 +139,47 @@ def execute_command_and_parse_its_result(connect_args: ClientConnectArgs, comman
|
|
return state.SUCCEED, stdout
|
|
LOGGER.error(stderr)
|
|
return state.EXECUTE_COMMAND_ERROR, stderr
|
|
+
|
|
+
|
|
+def execute_command_sftp_result(connect_args: ClientConnectArgs, local_path=None, remote_path=None):
|
|
+ """
|
|
+ create a ssh client, execute command and parse result
|
|
+
|
|
+ Args:
|
|
+ connect_args(ClientConnectArgs): e.g
|
|
+ ClientArgs(host_ip='127.0.0.1', ssh_port=22, ssh_user='root', pkey=RSAKey string)
|
|
+ command(str): shell command
|
|
+
|
|
+ Returns:
|
|
+ tuple:
|
|
+ status, result
|
|
+ """
|
|
+ global sftp_client, client
|
|
+ if not connect_args.pkey:
|
|
+ return state.SSH_AUTHENTICATION_ERROR, f"ssh authentication failed when connect host " \
|
|
+ f"{connect_args.host_ip}"
|
|
+ try:
|
|
+ client = SSH(
|
|
+ ip=connect_args.host_ip,
|
|
+ username=connect_args.ssh_user,
|
|
+ port=connect_args.ssh_port,
|
|
+ pkey=paramiko.RSAKey.from_private_key(StringIO(connect_args.pkey))
|
|
+ )
|
|
+ sftp_client = client.client().open_sftp()
|
|
+
|
|
+ # Specifies the path to the local file and the remote file
|
|
+ # Upload files to a remote server
|
|
+ sftp_client.put(local_path, remote_path)
|
|
+ return state.SUCCEED
|
|
+ except socket.error as error:
|
|
+ LOGGER.error(error)
|
|
+ return state.SSH_CONNECTION_ERROR, "SSH.Connection.Error"
|
|
+ except paramiko.ssh_exception.SSHException as error:
|
|
+ LOGGER.error(error)
|
|
+ return state.SSH_AUTHENTICATION_ERROR, "SSH.Authentication.Error"
|
|
+ except Exception as error:
|
|
+ LOGGER.error(error)
|
|
+ return state.SSH_AUTHENTICATION_ERROR, "SSH.Authentication.Error"
|
|
+ finally:
|
|
+ sftp_client.close()
|
|
+ client.close()
|
|
--
|
|
2.33.1.windows.1
|
|
|