Use python package instead of sshpass to execute remote commands.
Use python package instead of sshpass to execute remote commands. Fixing this issue, by using paramiko. Closes-bug: #1511658 Change-Id: I102d178b2fb1f621f2a61b26a939e69613156c19
This commit is contained in:
parent
814c9509e6
commit
a362aadaaa
|
@ -0,0 +1,104 @@
|
|||
# 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.
|
||||
|
||||
import paramiko
|
||||
import socket
|
||||
|
||||
|
||||
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, ip, port=22, con_timeout=10):
|
||||
self.__ip = ip
|
||||
self.__port = port
|
||||
self.__user = user
|
||||
self.__password = password
|
||||
self.__paramiko_conn = None
|
||||
self.__sock = None
|
||||
self.__con_timeout = con_timeout
|
||||
self.__connect()
|
||||
|
||||
def __connect(self):
|
||||
self.__sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.__sock.settimeout(self.__con_timeout)
|
||||
self.__sock.connect((self.__ip, self.__port))
|
||||
self.__paramiko_conn = paramiko.Transport(self.__sock)
|
||||
self.__paramiko_conn.start_client()
|
||||
if not self.__paramiko_conn.is_active():
|
||||
self.__paramiko_conn.close()
|
||||
raise Exception('client negotiation failed with %s' % self.__ip)
|
||||
|
||||
self.__paramiko_conn.auth_password(self.__user, self.__password)
|
||||
if not self.__paramiko_conn.is_authenticated():
|
||||
self.__paramiko_conn.close()
|
||||
raise Exception('Authentication failed: %s' % self.__ip)
|
||||
|
||||
def close_session(self):
|
||||
self.__paramiko_conn.close()
|
||||
|
||||
def reconnect(self):
|
||||
try:
|
||||
self.close_session()
|
||||
except Exception:
|
||||
pass
|
||||
self.__connect()
|
||||
|
||||
def execute_command(self, cmd, input_data=None, timeout=None):
|
||||
channel = self.__paramiko_conn.open_session()
|
||||
if channel is None:
|
||||
raise Exception("Channel already closed")
|
||||
if timeout:
|
||||
channel.settimeout(timeout)
|
||||
channel.exec_command(cmd)
|
||||
try:
|
||||
if input_data:
|
||||
stdin = channel.makefile('wb')
|
||||
stdin.write(input_data)
|
||||
stdout = channel.makefile('rb')
|
||||
stderr = channel.makefile_stderr()
|
||||
cmd_err = stderr.readlines()
|
||||
cmd_out = stdout.readlines()
|
||||
return_code = channel.recv_exit_status()
|
||||
stdin.close()
|
||||
stdout.close()
|
||||
except socket.timeout:
|
||||
raise
|
||||
result = CommandResult(cmd, cmd_out, cmd_err, return_code)
|
||||
return result
|
|
@ -19,7 +19,7 @@
|
|||
from oslo_config import cfg
|
||||
import yaml
|
||||
|
||||
from tacker.agent.linux import utils
|
||||
from tacker.common import cmd_executer
|
||||
from tacker.common import log
|
||||
from tacker.openstack.common import jsonutils
|
||||
from tacker.openstack.common import log as logging
|
||||
|
@ -53,11 +53,11 @@ class DeviceMgmtOpenWRT(abstract_driver.DeviceMGMTAbstractDriver):
|
|||
def _config_service(self, mgmt_ip_address, service, config):
|
||||
user = cfg.CONF.openwrt.user
|
||||
password = cfg.CONF.openwrt.password
|
||||
cmd = ["sshpass", "-p", "%s" % password,
|
||||
"ssh", "-o", "StrictHostKeyChecking=no",
|
||||
"%s@%s" % (user, mgmt_ip_address),
|
||||
"uci import %s; /etc/init.d/%s restart" % (service, service)]
|
||||
utils.execute(cmd, process_input=config)
|
||||
commander = cmd_executer.RemoteCommandExecutor(user,
|
||||
password,
|
||||
mgmt_ip_address)
|
||||
cmd = "uci import %s; /etc/init.d/%s restart" % (service, service)
|
||||
commander.execute_command(cmd, input_data=config)
|
||||
|
||||
@log.log
|
||||
def mgmt_call(self, plugin, context, device, kwargs):
|
||||
|
|
Loading…
Reference in New Issue