Guest User

Untitled

a guest
Jan 3rd, 2019
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.28 KB | None | 0 0
  1. # !/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3.  
  4. import paramiko
  5. import os
  6. import subprocess
  7. import json
  8. import logging
  9. import sys
  10. from time import sleep
  11.  
  12. logger = logging.getLogger(__name__)
  13. logfile = "class14_log.log"
  14.  
  15. formatter = logging.Formatter('%(asctime)s - %(name)s : %(levelname)s - %(message)s')
  16. screen_handler = logging.StreamHandler(sys.stdout)
  17. screen_handler.setLevel(logging.DEBUG)
  18. screen_handler.setFormatter(formatter)
  19.  
  20. file_handler = logging.FileHandler(logfile)
  21. file_handler.setLevel(logging.INFO)
  22. file_handler.setFormatter(formatter)
  23.  
  24. logger.addHandler(screen_handler)
  25. logger.addHandler(file_handler)
  26. logger.setLevel(logging.DEBUG)
  27.  
  28.  
  29. class Response(object):
  30. def __init__(self, out="", error="", exitcode=-1, failure_reason=None):
  31. self.out = out
  32. self.error = error
  33. self.exitcode = exitcode
  34. self._failure_reason = failure_reason
  35.  
  36.  
  37. class Config(object):
  38. """
  39. This class represents loading configuration file and parsing it on hosts .
  40. """
  41. def __init__(self, config_file='config.json'):
  42. """
  43. This method is called when we need to take information from configuration file.
  44. """
  45. self.config = config_file
  46. self._loaded = False
  47. self._host_items = {}
  48.  
  49. def load_config(self):
  50. """
  51. This method loads configuration file.
  52. """
  53. assert os.path.isfile(self.config)
  54. with open(self.config) as raw_config:
  55. raw_data = json.load(raw_config)
  56. for host_name, host_details in raw_data['hosts'].iteritems():
  57. self._host_items[host_name] = host_details
  58. self._loaded = True
  59.  
  60. @property
  61. def host_items(self):
  62. """
  63. This method returns dictionary with hosts information in it.
  64. """
  65. if not self._loaded:
  66. self.load_config()
  67. return self._host_items
  68.  
  69. def get_hosts_from_config(self):
  70. """
  71. This method gets hosts attributes from configuration file.
  72. """
  73. return [Host(ip=host["ip"], username=host["username"],
  74. password=host["password"]) for host in self.host_items.values()]
  75.  
  76.  
  77. class Host(object):
  78. """
  79. This class represents actions on remote and local machines.
  80. """
  81. PUBLIC_KEY_FILE_PATH = os.path.expanduser('~/.ssh/id_rsa.pub')
  82. PRIVATE_KEY_FILE_PATH = os.path.expanduser('~/.ssh/id_rsa')
  83. AUTHORIZED_KEY_FILE_PATH = os.path.expanduser('~/.ssh/authorized_keys')
  84. SSH_KEYS_PATH = os.path.expanduser('~/.ssh/')
  85.  
  86. def __init__(self, ip, username, password):
  87. """
  88. This method is called when we need to make commands on remote or local machines.
  89. """
  90. self.ip = ip
  91. self.username = username
  92. self.password = password
  93. self.port = 22
  94. self._ssh = paramiko.SSHClient()
  95. self._ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  96. self._ssh.connect(self.ip, self.port, self.username, self.password)
  97.  
  98. def keys_generating(self):
  99. """
  100. This method generates ssh-keys pair on a local machine.
  101. """
  102. if not os.path.exists(self.PRIVATE_KEY_FILE_PATH) \
  103. or not os.path.exists(self.PUBLIC_KEY_FILE_PATH):
  104. logger.info("There is no SSH keys found, starting 'ssh-keygen'")
  105. proc = subprocess.Popen('ssh-keygen -f ~/.ssh/id_rsa -q -P ""', stderr=subprocess.PIPE, shell=True)
  106. proc.wait()
  107. err = proc.stderr.read()
  108. exit_code = proc.returncode
  109. if not exit_code:
  110. logger.info('The key-pair "{}", "{}" was successfully generated.'.format
  111. (self.PRIVATE_KEY_FILE_PATH, self.PUBLIC_KEY_FILE_PATH))
  112. else:
  113. logger.warn(err)
  114. else:
  115. logger.info("SSH keys are already existing.")
  116.  
  117. def copy_pub_key_to_authorized_keys(self):
  118. """
  119. This method add public key to authorized keys on a local machine.
  120. """
  121. if os.path.exists(self.PUBLIC_KEY_FILE_PATH):
  122. process = subprocess.Popen(['cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys'],
  123. stderr=subprocess.PIPE, shell=True)
  124. process.wait()
  125. err = process.stderr.read()
  126. exit_code = process.returncode
  127. if not exit_code:
  128. logger.info('Public key was successfully copied'
  129. ' to {}.'.format(self.AUTHORIZED_KEY_FILE_PATH))
  130. else:
  131. logger.warn(err)
  132. else:
  133. logger.warn("There is no generated public key, call ssh_keygen")
  134.  
  135. @staticmethod
  136. def run_local_cmd(cmd):
  137. """
  138. This method runs some commands on a local machine.
  139. """
  140. logger.info("Trying to run command on local host")
  141. assert isinstance(cmd, str)
  142. try:
  143. proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
  144. stderr=subprocess.PIPE, shell=True)
  145. out, err = proc.communicate()
  146. exit_code = proc.returncode
  147. logger.info("Success in running local cmd '{}'".format(cmd))
  148. return Response(out, err, exit_code)
  149. except Exception as exc:
  150. return Response(failure_reason=exc)
  151.  
  152. def send_keys(self):
  153. """
  154. This method sends public key to authorized keys on remote machines
  155. and private key to ~/.ssh directory
  156. """
  157. logger.info("Trying to send ssh_keys to remote hosts")
  158. try:
  159. self._ssh.exec_command('mkdir -p ~/.ssh/')
  160. sftp = self._ssh.open_sftp()
  161. sftp.put(self.PUBLIC_KEY_FILE_PATH, self.AUTHORIZED_KEY_FILE_PATH)
  162. sftp.put(self.PRIVATE_KEY_FILE_PATH, self.PRIVATE_KEY_FILE_PATH)
  163. self._ssh.exec_command('chmod 600 ~/.ssh/authorized_keys')
  164. self._ssh.exec_command('chmod 600 ~/.ssh/id_rsa')
  165. self._ssh.exec_command('chmod 700 ~/.ssh/')
  166. logger.info("Ssh-keys were send to remote host {}".format(self.ip))
  167. except Exception as exc:
  168. logger.error('Fail to send ssh_keys to remote hosts. Error: {}'.format(exc))
  169. finally:
  170. self._ssh.close()
  171.  
  172. def remove_keys(self):
  173. """
  174. This method removes public key from authorized keys on remote machines
  175. and private key from ~/.ssh directory
  176. """
  177. logger.info("Trying to remove ssh_keys on remote hosts")
  178. try:
  179. self._ssh.connect(self.ip, self.port, self.username, self.password)
  180. self._ssh.exec_command('rm ~/.ssh/authorized_keys')
  181. self._ssh.exec_command('rm ~/.ssh/id_rsa')
  182. logger.info("Ssh_keys were removed from hosts")
  183. except Exception as exc:
  184. logger.error('Fail to remove ssh_keys from remote hosts. Error: {}'.format(exc))
  185. finally:
  186. self._ssh.close()
  187.  
  188. def run_cmd_remote(self, cmd):
  189. """
  190. This method runs some commands on remote machines.
  191. """
  192. assert isinstance(cmd, str)
  193. logger.info("Trying to run remote cmd")
  194. try:
  195. self._ssh.connect(self.ip, self.port, self.username, self.password)
  196. stdin, stdout, stderr = self._ssh.exec_command(cmd)
  197. exit_code = stdout.channel.recv_exit_status()
  198. stdout = stdout.readlines()
  199. stderr = stderr.read()
  200. logger.info("Success in running remote cmd '{}' ".format(cmd))
  201. return Response(stdout, stderr, exit_code)
  202. except Exception as exc:
  203. logger.error("Fail to run remote cmd. Error {}".format(exc))
  204. return Response(failure_reason=exc)
  205. finally:
  206. self._ssh.close()
  207. logger.info('Connection to {} closed.'.format(self.ip))
  208.  
  209. def reboot_remote_host(self):
  210. """
  211. This method reboots remote machines.
  212. """
  213. logger.info("Trying to reboot host {}".format(self.ip))
  214. try:
  215. self._ssh.connect(self.ip, self.port, self.username, self.password)
  216. stdin, stdout, stderr = self._ssh.exec_command("sudo -S shutdown -r now")
  217. stdin.write('{}\n'.format(self.password))
  218. exit_code = stdout.channel.recv_exit_status()
  219. return Response(stdout, stderr, exit_code)
  220. except Exception as exc:
  221. logger.error('Fail to reboot remote hosts. Error: {}'.format(exc))
  222.  
  223. def host_response(self):
  224. """
  225. This method waits till remote machines will be available.
  226. """
  227. proc = subprocess.Popen('ping -c1 {}'.format(self.ip), stdout=subprocess.PIPE,
  228. stderr=subprocess.PIPE, shell=True)
  229. proc.wait()
  230. exit_code = proc.returncode
  231. if exit_code == 0:
  232. logger.info("Success, host {} available".format(self.ip))
  233. else:
  234. logger.info("Fail, host {} unreachable".format(self.ip))
  235. sleep(5)
  236. self.host_response()
  237.  
  238.  
  239. if __name__ == '__main__':
  240. localhost = Host("192.168.100.8", "iryna", "123")
  241. localhost.keys_generating()
  242. localhost.copy_pub_key_to_authorized_keys()
  243. localhost.run_local_cmd('mkdir -p ~/newdir2')
  244. config = Config()
  245. config.load_config()
  246. hosts = config.get_hosts_from_config()
  247. for hosts in hosts:
  248. hosts.send_keys()
  249. hosts.run_cmd_remote("mkdir -p ~/newdir")
  250. hosts.reboot_remote_host()
  251. sleep(3)
  252. hosts.host_response()
  253. # hosts.remove_keys()
Add Comment
Please, Sign In to add comment