aops-zeus/0003-fix-bash-file-sync-error.patch
rabbitali c9da01ed40 修复bash文件同步问题,更新回调接口身份验证逻辑
(cherry picked from commit ae8a36e4cfc5dab70b9d71b2a2c84735f9acabb8)
2023-09-19 11:21:37 +08:00

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