Files
tacker/tacker/common/cmd_executer.py
Shuwen Cai 0c69e122b2 Refactor for Performance Improvement
In order to improve the performance of Tacker in commercial systems,
This patch provides the following code refactoring to improve system
performance.

1. Reduce transaction of getting OpenStack resource from Heat
   (for Tacker v2 API)
2. Support subscription filter of vnfdId (for Tacker v1 API)
3. Refactor the Tacker Output Logs (for Tacker v1/v2 API)

Implement: blueprint system-performance-management
Change-Id: I8879a690e455fb196c2e28a251bf46cea7376b56
2022-09-14 14:16:33 +09:00

108 lines
3.8 KiB
Python

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log as logging
import paramiko
from tacker.common import exceptions
LOG = logging.getLogger(__name__)
class CommandResult(object):
"""Result class contains command, stdout, stderror and return code."""
def __init__(self, cmd, stdout, stderr, return_code):
self.__cmd = cmd
self.__stdout = stdout
self.__stderr = stderr
self.__return_code = return_code
def get_command(self):
return self.__cmd
def get_stdout(self):
return self.__stdout
def get_stderr(self):
return self.__stderr
def get_return_code(self):
return self.__return_code
def __str__(self):
return "cmd: %s, stdout: %s, stderr: %s, return code: %s" \
% (self.__cmd, self.__stdout, self.__stderr, self.__return_code)
def __repr__(self):
return "cmd: %s, stdout: %s, stderr: %s, return code: %s" \
% (self.__cmd, self.__stdout, self.__stderr, self.__return_code)
class RemoteCommandExecutor(object):
"""Class to execute a command on remote location"""
def __init__(self, user, password, host, timeout=10):
self.__user = user
self.__password = password
self.__host = host
self.__paramiko_conn = None
self.__ssh = None
self.__timeout = timeout
self.__connect()
def __connect(self):
try:
self.__ssh = paramiko.SSHClient()
self.__ssh.set_missing_host_key_policy(paramiko.WarningPolicy())
self.__ssh.connect(self.__host, username=self.__user,
password=self.__password, timeout=self.__timeout)
LOG.info("Connected to %s", self.__host)
except paramiko.AuthenticationException:
LOG.error("Authentication failed when connecting to %s",
self.__host)
raise exceptions.NotAuthorized
except paramiko.SSHException:
LOG.error("Could not connect to %s. Giving up", self.__host)
raise
def close_session(self):
self.__ssh.close()
LOG.info(f"The SSH connection to the remote"
f" host {self.__host} has been closed.")
def execute_command(self, cmd, input_data=None):
try:
stdin, stdout, stderr = self.__ssh.exec_command(cmd)
if input_data:
stdin.write(input_data)
LOG.debug("Input data written successfully")
stdin.flush()
LOG.debug("Input data flushed")
stdin.channel.shutdown_write()
# NOTE (dkushwaha): There might be a case, when server can take
# too long time to write data in stdout buffer or sometimes hang
# itself, in that case readlines() will stuck for long/infinite
# time. To handle such cases, timeout logic should be introduce
# here.
cmd_out = stdout.readlines()
cmd_err = stderr.readlines()
return_code = stdout.channel.recv_exit_status()
except paramiko.SSHException:
LOG.error("Command execution failed at %s. Giving up", self.__host)
raise
result = CommandResult(cmd, cmd_out, cmd_err, return_code)
LOG.debug("Remote command execution result: %s", result)
return result
def __del__(self):
self.close_session()