Advertisement
Guest User

Untitled

a guest
Jul 6th, 2016
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.11 KB | None | 0 0
  1. #!/usr/bin/python
  2. # Author: akbhat@juniper.net
  3. # Version 1.0 20150803
  4.  
  5. from jnpr_cmds import *
  6. from jutil import *
  7.  
  8. def run_cmds(node, logger, uname, rpwd):
  9. cmd_set_shell_Q = {"EX4300" : ex4300_cmds_shell_Q,
  10. "QFX5100" : qfx5100_cmds_shell_Q,
  11. "QFX5100_VXLAN":qfx5100_vxlan_cmds_shell_Q}
  12. #"QFX10002" : qfx10002_cmds_shell_Q}
  13. #"SRX_BRANCH" : srx_cmds_shell_Q,
  14. #"SRX_HIGHEND": srx_cmds_shell_Q,
  15. #"MX" : mx_cmds_shell_Q}
  16.  
  17. cmd_set_shell_D = {"EX4300" : ex4300_cmds_shell_D,
  18. "QFX5100" : qfx5100_cmds_shell_D,
  19. "QFX5100_VXLAN":qfx5100_vxlan_cmds_shell_D}
  20. #"QFX10002" : qfx10002_cmds_shell_D}
  21. #"SRX_BRANCH" : srx_cmds_shell_D,
  22. #"SRX_HIGHEND": srx_cmds_shell_D,
  23. #"MX" : mx_cmds_shell_D}
  24.  
  25. # TODO: Check if user belongs to either ENG_CLASS or ADMIN_CLASS. User CLASS stored locally?
  26.  
  27. #Check free space on filesystem for logging
  28. if not check_free_space(node, args, logger):
  29. sys.exit(1)
  30.  
  31. fs = FS(node)
  32. try:
  33. res = fs.mkdir('/var/tmp/data')
  34. except:
  35. logger.error('Could not create directory on device: %s', sys.exc_info()[0])
  36. sys.exit(1)
  37.  
  38. if not args.nocmd:
  39. logfile = "/var/tmp/data/data_collection@" + datetime.datetime.now().strftime("%y-%m-%d-%H-%M") + ".log"
  40. fs.mkfile(logfile)
  41. if args.cmdfile:
  42. if args.detail:
  43. logger.info("--detail ignored as --cmdfile specified")
  44. try:
  45. with open(args.cmdfile, 'r') as cmdfile, StartShell(node) as sh:
  46. record_banner(args, node, sh, uname, node.facts['hostname'],logfile)
  47. become_root(sh, uname, rpwd,logger)
  48. cmd_type = ''
  49. for index, comd in enumerate(cmdfile):
  50. if comd.strip() == 'cli':
  51. cmd_type = 'cli'
  52. continue
  53. elif comd.strip() == 'shell':
  54. cmd_type = 'shell'
  55. continue
  56. elif comd.strip() == 'vty':
  57. cmd_type = 'vty'
  58. continue
  59. else:
  60. if cmd_type == 'cli':
  61. element = "cli -c '" + comd.strip() + "'"
  62. elif cmd_type == 'shell':
  63. element = comd.strip()
  64. elif cmd_type == 'vty':
  65. element = "cprod -A fpc0 -c '" + comd.strip() + "'"
  66. run_cmd(node, sh, index , element, logger, args.force, logfile)
  67. cmdfile.close()
  68. except IOError as e:
  69. logger.error('Operation failed: %s', e.strerror)
  70. sys.exit(1)
  71. except:
  72. logger.error('Unexpected error: %s', sys.exc_info()[0])
  73. sys.exit(1)
  74. else:
  75. # TODO: Verify SRX cluster
  76. person_platform = {'MX', 'SRX_BRANCH', 'SRX_HIGHEND'}
  77. if node.facts['personality'] in person_platform:
  78. cmd_set = node.facts['personality']
  79. elif node.facts['model'] == 'Virtual Chassis':
  80. rsp = node.rpc.get_chassis_inventory()
  81. for element in rsp.iter('name'):
  82. if element.text == 'FPC 0':
  83. for elem in element.getparent().getchildren():
  84. if elem.tag == 'model-number':
  85. cmd_set = elem.text.split('-')[0]
  86. else:
  87. cmd_set = node.facts['model'].split('-')[0]
  88.  
  89. with StartShell(node) as sh:
  90. record_banner(args, node, sh, uname, node.facts['hostname'], logfile)
  91. become_root(sh, uname, rpwd, logger)
  92.  
  93. if cmd_set in ('QFX5100', 'QFX5100_VXLAN', 'QFX10002'):
  94. try:
  95. collect_host_logs(node, sh, logger)
  96. except:
  97. logger.error("Could not retrieve host logs")
  98.  
  99. try:
  100. for index, element in enumerate(cmd_set_shell_Q[cmd_set]):
  101. run_cmd(node, sh, index, element, logger, args.force, logfile)
  102.  
  103. if args.vxlan:
  104. if cmd_set == 'QFX5100':
  105. cmd_set = 'QFX5100_VXLAN'
  106. for index, element in enumerate(cmd_set_shell_Q[cmd_set]):
  107. run_cmd(node, sh, index, element, logger, args.force, logfile)
  108. else:
  109. logger.error("VXLAN data collection supported only for QFX5100")
  110. except KeyError:
  111. logger.error('Unsupported platform')
  112. sys.exit(1)
  113.  
  114. if args.detail:
  115. logger.info('######################################################')
  116. logger.info("Sleeping for 30 seconds before initiating detailed command set on {}".format(node.facts['hostname']))
  117. logger.info('######################################################')
  118. time.sleep(30)
  119.  
  120. logger.info('######################################################')
  121. logger.info('Executing detailed command set on...{}'.format(node.facts['hostname']))
  122. logger.info('######################################################')
  123.  
  124. for index, element in enumerate(cmd_set_shell_D[cmd_set]):
  125. run_cmd(node, sh, index, element, logger, args.force, logfile)
  126. #time.sleep(2)
  127.  
  128. # Collect requested cores
  129. if args.core and verify_load(node, logger, 0.75):
  130. #TODO: No need of 100M for smaller platforms. %age of /var/tmp?
  131. if not free_space_avail(node, '/var/tmp', 100):
  132. logging.error("Less than 100M available in /var/tmp")
  133. else:
  134. logger.info('Collecting {} core on {}....'.format(args.core, node.facts['hostname']))
  135. if args.core=='live':
  136. with StartShell(node) as sh:
  137. become_root(sh, uname, rpwd, logger)
  138.  
  139. #Remove all exisiting live cores
  140. #TODO: Can accidentally delete useful kernel core
  141. rt = fs.stat('/var/tmp/vmcore.*')
  142. while rt is not None:
  143. logger.info("Removing %s", rt['path'])
  144. sh.run("rm " + rt['path'])
  145. rt = fs.stat('/var/tmp/vmcore.*')
  146.  
  147. logging.debug('Dumping live core')
  148. # Dump the live core
  149. sh.run("cli -c 'request system live-core'")
  150. tm = 0
  151. # Loop until stat is successful for new vmcore file
  152. while fs.stat('/var/tmp/vmcore.*') is None:
  153. # Break from loop if core not available after 5 mins
  154. if tm >= 300:
  155. logger.info("Skipping live core after waiting 5 mins")
  156. break
  157. logger.info('Waiting 15 seconds while live core is generated')
  158. tm += 15
  159. time.sleep(15)
  160. logger.debug('Moving live core to /var/tmp/data')
  161. sh.run("mv /var/tmp/vmcore.* /var/tmp/data/")
  162. else:
  163. with StartShell(node) as sh:
  164. result = sh.run("ps -auxw | grep -w " + args.core.strip() + " | grep /usr/sbin | awk '{print $2}' >> /var/tmp/data/pids.log")
  165. pids = fs.cat('/var/tmp/data/pids.log').splitlines()
  166. if pids:
  167. become_root(sh, uname, rpwd, logger)
  168. # In case multiple pids returned
  169. for index, pd in enumerate(pids):
  170. if pd:
  171. filename = "/var/tmp/data/" + args.core.strip() + ".gcore." + str(index)
  172. element = "gcore -c " + filename + ' ' + pd.strip()
  173. sh.run(element)
  174.  
  175. # Gzip generated core file to save disk space
  176. sh.run("gzip " + filename)
  177. logging.info("Core collection completed on {}".format(node.facts['hostname']))
  178. fs.rm('/var/tmp/data/pids.log')
  179. else:
  180. logging.error("Invalid process")
  181. else:
  182. logging.error("Skipping gcore")
  183.  
  184. # Archive RSI & /var/log
  185. if not args.norsi and verify_load(node, logger, 1.5):
  186. logger.info("Collecting {} RSI.....".format(node.facts['hostname']))
  187. with StartShell(node) as sh:
  188. become_root(sh, uname, rpwd, logger)
  189. sh.run("cli -c 'request support information | no-more | save /var/tmp/data/" + node.facts['hostname'] + '_' + \
  190. datetime.datetime.now().strftime("%y-%m-%d-%H-%M") + "_rsi.log'")
  191. logging.info("RSI Completed")
  192.  
  193. logger.info("Archiving {} /var/log.....".format(node.facts['hostname']))
  194. msglog = fs.tgz('/var/log', '/var/tmp/data/varlog_' + node.facts['hostname'] + '_' + datetime.datetime.now().strftime("%y-%m-%d-%H-%M"))
  195. logging.info("/var/log Completed")
  196. else:
  197. logging.info("Skipping RSI and /var/log")
  198.  
  199. # Zipping collected data
  200. ufname = '/var/tmp/' + node.facts['hostname'] + '_' + datetime.datetime.now().strftime("%y-%m-%d-%H-%M")
  201. msglog = fs.tgz('/var/tmp/data', ufname)
  202.  
  203. logger.info("Transferring {} back to server....".format(ufname.split('/')[3] + '.tgz'))
  204. with SCP(node) as scp:
  205. scp.get(remote_path= ufname + '.tgz', local_path='./', preserve_times=True)
  206. logging.info("Done")
  207.  
  208. # Removing on device log files
  209. fs.rmdir('/var/tmp/data')
  210. fs.rm(ufname + '.tgz')
  211. node.close()
  212.  
  213. # Transfer collected data to Juniper FTP
  214. if args.case:
  215. t = paramiko.Transport(('sftp.juniper.net', 22))
  216. t.connect(username = 'anonymous', password = 'anonymous')
  217. sftp = paramiko.SFTPClient.from_transport(t)
  218. try:
  219. sftp.chdir('/pub/incoming/' + args.case) # Test if remote_path exists
  220. except IOError:
  221. sftp.mkdir('/pub/incoming/' + args.case) # Create remote_path
  222. sftp.chdir('/pub/incoming/' + args.case)
  223.  
  224. filename = ufname.split('/')[3] + '.tgz'
  225. logging.info("Uploading {} to Juniper SFTP.....".format(filename))
  226.  
  227. #Upload files individually for JCATS detection
  228. tout = tarfile.open(filename, 'r')
  229. tout.extractall()
  230. for item in os.listdir('var/tmp/data'):
  231. sftp.put('var/tmp/data/' + item, './' + item)
  232. rmtree('var')
  233. logging.info("File upload completed")
  234. sftp.close()
  235. else:
  236. logging.info("Unable to upload log files to Juniper FTP as case# not provided")
  237.  
  238. def main():
  239. logging.getLogger("paramiko").setLevel(logging.WARNING)
  240. logging.getLogger("ncclient").setLevel(logging.WARNING)
  241.  
  242. logger = logging.getLogger('JCOLLECT')
  243. logger.propagate = False
  244. formatter = '%(message)s'
  245.  
  246. if args.log:
  247. numeric_level = getattr(logging, args.log.upper(), None)
  248. if not isinstance(numeric_level, int):
  249. raise ValueError('Invalid log level: %s' % args.log)
  250. logging.basicConfig(format=formatter, level=numeric_level)
  251. else:
  252. logging.basicConfig(format=formatter, level=logging.INFO)
  253. #Supress traceback
  254. #sys.tracebacklimit = 0
  255.  
  256. console = logging.StreamHandler()
  257. console.setLevel (logging.INFO)
  258. logger.addHandler(console)
  259.  
  260. #os.system ('eval "$(register-python-argcomplete jcollect.py)"')
  261.  
  262. jobs = []
  263. if args.ipfile != sys.stdin:
  264. devices = args.ipfile
  265. elif args.host:
  266. devices = list(set(args.host))
  267. else:
  268. logger.error("argument --host or --ipfile required")
  269. sys.exit(1)
  270.  
  271. uname = raw_input("Username: ")
  272. pwd = getpass.getpass()
  273. rpwd = getpass.getpass(prompt="Root Password:")
  274.  
  275. for dev in devices:
  276. try:
  277. node = Device (host = dev.strip(), user = uname.strip(), passwd = pwd.strip())
  278. node.open(auto_probe = True)
  279. node.timeout = 60
  280. except Exception as err:
  281. sys.stderr.write('Cannot connect to device: {0}\n'.format(err))
  282.  
  283. if node.connected:
  284. #TODO: If cluster or VC, append to devices
  285. t = Thread(target=run_cmds, args=(node,logger,uname,rpwd.strip()))
  286. jobs.append(t)
  287.  
  288. for j in jobs:
  289. j.start()
  290.  
  291. for j in jobs:
  292. j.join()
  293.  
  294. if __name__ == "__main__":
  295. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement