mirror of https://github.com/openspug/spug
U api add ssh lib
parent
5a225ae9fd
commit
0b36aaf6c1
|
@ -0,0 +1,65 @@
|
||||||
|
from paramiko.client import SSHClient, AutoAddPolicy
|
||||||
|
from paramiko.config import SSH_PORT
|
||||||
|
from paramiko.rsakey import RSAKey
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
|
|
||||||
|
class SSH:
|
||||||
|
def __init__(self, host, port=SSH_PORT, username='root', pkey=None, password=None, connect_timeout=10):
|
||||||
|
if pkey is None and password is None:
|
||||||
|
raise Exception('public key and password must have one is not None')
|
||||||
|
self.client = None
|
||||||
|
self.arguments = {
|
||||||
|
'hostname': host,
|
||||||
|
'port': port,
|
||||||
|
'username': username,
|
||||||
|
'password': password,
|
||||||
|
'pkey': pkey,
|
||||||
|
'timeout': connect_timeout,
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def generate_key():
|
||||||
|
key_obj = StringIO()
|
||||||
|
key = RSAKey.generate(2048)
|
||||||
|
key.write_private_key(key_obj)
|
||||||
|
return key_obj.getvalue(), 'ssh-rsa ' + key.get_base64()
|
||||||
|
|
||||||
|
def add_public_key(self, public_key):
|
||||||
|
command = f'mkdir -p -m 700 ~/.ssh && \
|
||||||
|
echo {public_key!r} >> ~/.ssh/authorized_keys && \
|
||||||
|
chmod 600 ~/.ssh/authorized_keys'
|
||||||
|
code, stdout, stderr = self.exec_command(command)
|
||||||
|
if code != 0:
|
||||||
|
raise Exception(stdout + stderr)
|
||||||
|
|
||||||
|
def ping(self):
|
||||||
|
with self:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def exec_command(self, command):
|
||||||
|
with self as cli:
|
||||||
|
_, stdout, stderr = cli.exec_command(command)
|
||||||
|
return stdout.channel.recv_exit_status(), ''.join(stdout), ''.join(stderr)
|
||||||
|
|
||||||
|
def exec_command_with_stream(self, command):
|
||||||
|
with self as cli:
|
||||||
|
_, stdout, _ = cli.exec_command(command, get_pty=True)
|
||||||
|
while True:
|
||||||
|
message = stdout.readline()
|
||||||
|
if not message:
|
||||||
|
break
|
||||||
|
yield message
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
if self.client is not None:
|
||||||
|
raise RuntimeError('Already connected')
|
||||||
|
client = SSHClient()
|
||||||
|
client.set_missing_host_key_policy(AutoAddPolicy)
|
||||||
|
client.connect(**self.arguments)
|
||||||
|
self.client = client
|
||||||
|
return self.client
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
|
self.client.close()
|
||||||
|
self.client = None
|
Loading…
Reference in New Issue