Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # !/usr/bin/env python
- # -*- coding: utf-8 -*-
- import paramiko
- import os
- import subprocess
- import json
- import logging
- import sys
- from time import sleep
- logger = logging.getLogger(__name__)
- logfile = "class14_log.log"
- formatter = logging.Formatter('%(asctime)s - %(name)s : %(levelname)s - %(message)s')
- screen_handler = logging.StreamHandler(sys.stdout)
- screen_handler.setLevel(logging.DEBUG)
- screen_handler.setFormatter(formatter)
- file_handler = logging.FileHandler(logfile)
- file_handler.setLevel(logging.INFO)
- file_handler.setFormatter(formatter)
- logger.addHandler(screen_handler)
- logger.addHandler(file_handler)
- logger.setLevel(logging.DEBUG)
- class Response(object):
- def __init__(self, out="", error="", exitcode=-1, failure_reason=None):
- self.out = out
- self.error = error
- self.exitcode = exitcode
- self._failure_reason = failure_reason
- class Config(object):
- """
- This class represents loading configuration file and parsing it on hosts .
- """
- def __init__(self, config_file='config.json'):
- """
- This method is called when we need to take information from configuration file.
- """
- self.config = config_file
- self._loaded = False
- self._host_items = {}
- def load_config(self):
- """
- This method loads configuration file.
- """
- assert os.path.isfile(self.config)
- with open(self.config) as raw_config:
- raw_data = json.load(raw_config)
- for host_name, host_details in raw_data['hosts'].iteritems():
- self._host_items[host_name] = host_details
- self._loaded = True
- @property
- def host_items(self):
- """
- This method returns dictionary with hosts information in it.
- """
- if not self._loaded:
- self.load_config()
- return self._host_items
- def get_hosts_from_config(self):
- """
- This method gets hosts attributes from configuration file.
- """
- return [Host(ip=host["ip"], username=host["username"],
- password=host["password"]) for host in self.host_items.values()]
- class Host(object):
- """
- This class represents actions on remote and local machines.
- """
- PUBLIC_KEY_FILE_PATH = os.path.expanduser('~/.ssh/id_rsa.pub')
- PRIVATE_KEY_FILE_PATH = os.path.expanduser('~/.ssh/id_rsa')
- AUTHORIZED_KEY_FILE_PATH = os.path.expanduser('~/.ssh/authorized_keys')
- SSH_KEYS_PATH = os.path.expanduser('~/.ssh/')
- def __init__(self, ip, username, password):
- """
- This method is called when we need to make commands on remote or local machines.
- """
- self.ip = ip
- self.username = username
- self.password = password
- self.port = 22
- self._ssh = paramiko.SSHClient()
- self._ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- self._ssh.connect(self.ip, self.port, self.username, self.password)
- def keys_generating(self):
- """
- This method generates ssh-keys pair on a local machine.
- """
- if not os.path.exists(self.PRIVATE_KEY_FILE_PATH) \
- or not os.path.exists(self.PUBLIC_KEY_FILE_PATH):
- logger.info("There is no SSH keys found, starting 'ssh-keygen'")
- proc = subprocess.Popen('ssh-keygen -f ~/.ssh/id_rsa -q -P ""', stderr=subprocess.PIPE, shell=True)
- proc.wait()
- err = proc.stderr.read()
- exit_code = proc.returncode
- if not exit_code:
- logger.info('The key-pair "{}", "{}" was successfully generated.'.format
- (self.PRIVATE_KEY_FILE_PATH, self.PUBLIC_KEY_FILE_PATH))
- else:
- logger.warn(err)
- else:
- logger.info("SSH keys are already existing.")
- def copy_pub_key_to_authorized_keys(self):
- """
- This method add public key to authorized keys on a local machine.
- """
- if os.path.exists(self.PUBLIC_KEY_FILE_PATH):
- process = subprocess.Popen(['cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys'],
- stderr=subprocess.PIPE, shell=True)
- process.wait()
- err = process.stderr.read()
- exit_code = process.returncode
- if not exit_code:
- logger.info('Public key was successfully copied'
- ' to {}.'.format(self.AUTHORIZED_KEY_FILE_PATH))
- else:
- logger.warn(err)
- else:
- logger.warn("There is no generated public key, call ssh_keygen")
- @staticmethod
- def run_local_cmd(cmd):
- """
- This method runs some commands on a local machine.
- """
- logger.info("Trying to run command on local host")
- assert isinstance(cmd, str)
- try:
- proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE, shell=True)
- out, err = proc.communicate()
- exit_code = proc.returncode
- logger.info("Success in running local cmd '{}'".format(cmd))
- return Response(out, err, exit_code)
- except Exception as exc:
- return Response(failure_reason=exc)
- def send_keys(self):
- """
- This method sends public key to authorized keys on remote machines
- and private key to ~/.ssh directory
- """
- logger.info("Trying to send ssh_keys to remote hosts")
- try:
- self._ssh.exec_command('mkdir -p ~/.ssh/')
- sftp = self._ssh.open_sftp()
- sftp.put(self.PUBLIC_KEY_FILE_PATH, self.AUTHORIZED_KEY_FILE_PATH)
- sftp.put(self.PRIVATE_KEY_FILE_PATH, self.PRIVATE_KEY_FILE_PATH)
- self._ssh.exec_command('chmod 600 ~/.ssh/authorized_keys')
- self._ssh.exec_command('chmod 600 ~/.ssh/id_rsa')
- self._ssh.exec_command('chmod 700 ~/.ssh/')
- logger.info("Ssh-keys were send to remote host {}".format(self.ip))
- except Exception as exc:
- logger.error('Fail to send ssh_keys to remote hosts. Error: {}'.format(exc))
- finally:
- self._ssh.close()
- def remove_keys(self):
- """
- This method removes public key from authorized keys on remote machines
- and private key from ~/.ssh directory
- """
- logger.info("Trying to remove ssh_keys on remote hosts")
- try:
- self._ssh.connect(self.ip, self.port, self.username, self.password)
- self._ssh.exec_command('rm ~/.ssh/authorized_keys')
- self._ssh.exec_command('rm ~/.ssh/id_rsa')
- logger.info("Ssh_keys were removed from hosts")
- except Exception as exc:
- logger.error('Fail to remove ssh_keys from remote hosts. Error: {}'.format(exc))
- finally:
- self._ssh.close()
- def run_cmd_remote(self, cmd):
- """
- This method runs some commands on remote machines.
- """
- assert isinstance(cmd, str)
- logger.info("Trying to run remote cmd")
- try:
- self._ssh.connect(self.ip, self.port, self.username, self.password)
- stdin, stdout, stderr = self._ssh.exec_command(cmd)
- exit_code = stdout.channel.recv_exit_status()
- stdout = stdout.readlines()
- stderr = stderr.read()
- logger.info("Success in running remote cmd '{}' ".format(cmd))
- return Response(stdout, stderr, exit_code)
- except Exception as exc:
- logger.error("Fail to run remote cmd. Error {}".format(exc))
- return Response(failure_reason=exc)
- finally:
- self._ssh.close()
- logger.info('Connection to {} closed.'.format(self.ip))
- def reboot_remote_host(self):
- """
- This method reboots remote machines.
- """
- logger.info("Trying to reboot host {}".format(self.ip))
- try:
- self._ssh.connect(self.ip, self.port, self.username, self.password)
- stdin, stdout, stderr = self._ssh.exec_command("sudo -S shutdown -r now")
- stdin.write('{}\n'.format(self.password))
- exit_code = stdout.channel.recv_exit_status()
- return Response(stdout, stderr, exit_code)
- except Exception as exc:
- logger.error('Fail to reboot remote hosts. Error: {}'.format(exc))
- def host_response(self):
- """
- This method waits till remote machines will be available.
- """
- proc = subprocess.Popen('ping -c1 {}'.format(self.ip), stdout=subprocess.PIPE,
- stderr=subprocess.PIPE, shell=True)
- proc.wait()
- exit_code = proc.returncode
- if exit_code == 0:
- logger.info("Success, host {} available".format(self.ip))
- else:
- logger.info("Fail, host {} unreachable".format(self.ip))
- sleep(5)
- self.host_response()
- if __name__ == '__main__':
- localhost = Host("192.168.100.8", "iryna", "123")
- localhost.keys_generating()
- localhost.copy_pub_key_to_authorized_keys()
- localhost.run_local_cmd('mkdir -p ~/newdir2')
- config = Config()
- config.load_config()
- hosts = config.get_hosts_from_config()
- for hosts in hosts:
- hosts.send_keys()
- hosts.run_cmd_remote("mkdir -p ~/newdir")
- hosts.reboot_remote_host()
- sleep(3)
- hosts.host_response()
- # hosts.remove_keys()
Add Comment
Please, Sign In to add comment