Guest User

Untitled

a guest
Jan 20th, 2018
339
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.67 KB | None | 0 0
  1. #!/usr/bin/env python
  2. ## Gavin Purcell
  3. ## Gather system resource info from VMware ESXi hosts and create totals by vSphere cluster.
  4.  
  5. import paramiko
  6. import socket
  7. import sys
  8. import os
  9. import base64
  10. from multiprocessing import Process, Queue
  11. import resource
  12. from datetime import date
  13. import pickle
  14. from shutil import copyfile
  15.  
  16. dir_path = os.path.dirname(os.path.abspath(__file__)) + '/'
  17. hosts_by_cluster_pickle = dir_path + 'hosts_by_cluster.pkl'
  18. html_head_file = dir_path + 'html_head.txt'
  19.  
  20. port = 22
  21. user = 'root'
  22. password = base64.b64decode('') ## PASSWORD REMOVED
  23. get_sysinfo = 'timeout -t 3 esxcli hardware cpu global get | grep CPU | awk \'{print $3}\'; timeout -t 3 esxcli hardware memory get | grep "Physical Memory" | awk \'{print $3}\''
  24. expected_itmes_returned = 4
  25.  
  26. html_title_placeholder = 'title not set'
  27. html_title = 'Vsphere Cluster Info'
  28. html_colors = ['#ffddcc', '#e6ccff', '#ffffcc', '#cce6ff']
  29. webpage_dir = '/var/www/html/'
  30. favicon_file_name = 'cloudopsvcli_icon.png'
  31. favicon_file = webpage_dir + favicon_file_name
  32. html_file_name = 'cluster_info'
  33. html_file = webpage_dir + html_file_name
  34. csv_file_name = 'cluster_info.csv'
  35. csv_file = webpage_dir + csv_file_name
  36.  
  37. class color:
  38. red = '\033[91m'
  39. end = '\033[0m'
  40.  
  41. ## For converting from bytes to gigabytes.
  42. gigabyte_divisor = 1073741824
  43.  
  44. ## Check that the hosts_by_cluster_pickle file exists.
  45. if os.path.exists(hosts_by_cluster_pickle) == False:
  46. print hosts_by_cluster_pickle, "does not exist."
  47. sys.exit(1)
  48.  
  49. ## Output files to local directory if webpage_dir doesn't exist.
  50. if os.path.exists(webpage_dir) == False:
  51. print webpage_dir, 'does not exist. Outputting to local directory.'
  52. csv_file = dir_path + csv_file_name
  53. html_file = dir_path + html_file_name
  54.  
  55. ## Set the ulimit to 2048
  56. soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
  57. resource.setrlimit(resource.RLIMIT_NOFILE, (2048, hard))
  58.  
  59. def ssh_run_cmd(q, user, host, cmd):
  60. """Connect and run the command on the host."""
  61. ssh = paramiko.SSHClient()
  62. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  63. try:
  64. ssh.connect(host, port, user, password, timeout=3)
  65. stdin, stdout, stderr = ssh.exec_command(cmd)
  66. error_msg = stderr.read()
  67. vms_on_host = stdout.read().split()
  68. q.put(vms_on_host)
  69. if error_msg: print error_msg
  70. except (socket.error, paramiko.ssh_exception.BadAuthenticationType, paramiko.ssh_exception.SSHException) as e:
  71. print '%sCannot connect to %s: %s%s' % (color.red, host, e, color.end)
  72. q.put('')
  73. finally:
  74. ssh.close()
  75.  
  76. ## Get hosts by cluster:
  77. hosts_by_cluster = {}
  78. with open(hosts_by_cluster_pickle, 'r') as pickle_file:
  79. hosts_by_cluster = pickle.load(pickle_file)
  80.  
  81. ## Create and start processes for getting sysinfo by cluster in parallel.
  82. jobs = []
  83. sysinfo_by_host = {}
  84. for cluster in hosts_by_cluster.keys():
  85. for host in hosts_by_cluster[cluster]:
  86. sysinfo_by_host[host] = []
  87. q = Queue()
  88. process = Process(target=ssh_run_cmd, args=(q,user,host,get_sysinfo))
  89. jobs.append((process,q,cluster,host))
  90. process.start()
  91.  
  92. ## Wait for the processes to finish and append to the lists of vm's.
  93. for job in jobs:
  94. process,q,cluster,host = job[0],job[1],job[2],job[3]
  95. print "Waiting for:", cluster, host
  96. sysinfo = q.get()
  97. process.join()
  98. sysinfo_by_host[host].extend(sysinfo)
  99.  
  100. ## Create a table of clusters.
  101. table_header = ['Cluster','Hosts(up)','Sockets','Cores','Threads','Memory(gigibytes)', 'Hosts(down)']
  102. table = []
  103.  
  104. for cluster in hosts_by_cluster.keys():
  105. host_cnt,socket_cnt,core_cnt,thread_cnt,memory_cnt,host_down_cnt = [0,0,0,0,0,0]
  106. for host in hosts_by_cluster[cluster]:
  107. if len(sysinfo_by_host[host]) >= expected_itmes_returned: ## Some hosts are down and don't return anyting.
  108. sockets,cores,threads,memory = sysinfo_by_host[host]
  109. host_cnt += 1
  110. socket_cnt += int(sockets)
  111. core_cnt += int(cores)
  112. thread_cnt += int(threads)
  113. memory_cnt += int(round(float(memory) / gigabyte_divisor))
  114. else:
  115. host_down_cnt += 1
  116. table.append([cluster,host_cnt,socket_cnt,core_cnt,thread_cnt,memory_cnt,host_down_cnt])
  117.  
  118. table.sort()
  119.  
  120. ## Map html colors to clusters.
  121. cluster_colors = {}
  122. for row in table:
  123. cluster = row[0]
  124. cluster_colors[cluster] = html_colors[0]
  125. if 'C02' in cluster:
  126. cluster_colors[cluster] = html_colors[1]
  127. if 'C03' in cluster:
  128. cluster_colors[cluster] = html_colors[2]
  129. if 'C09' in cluster:
  130. cluster_colors[cluster] = html_colors[3]
  131.  
  132. ## Write out csv file.
  133. with open(csv_file, 'w') as out_file:
  134. table_csv = [table_header] + table
  135. for row in table_csv:
  136. cluster,host_cnt,socket_cnt,core_cnt,thread_cnt,memory_cnt,host_down_cnt = row
  137. line = '%s,%s,%s,%s,%s,%s,%s\n' % (cluster,host_cnt,socket_cnt,core_cnt,thread_cnt,memory_cnt,host_down_cnt)
  138. out_file.write(line)
  139.  
  140. ## Check that the html_head file exists:
  141. if os.path.exists(html_head_file) == False:
  142. print html_head_file, "does not exist."
  143. sys.exit(2)
  144.  
  145. ## Read in the html head file and set the title.
  146. with open(html_head_file, 'r') as in_file:
  147. html = in_file.read()
  148. html = html.replace(html_title_placeholder, html_title, 1)
  149.  
  150. ## Create the html for output.
  151. date = str(date.today())
  152. html = html + '<body>\n\n'
  153. html = html + '<table>\n'
  154. cluster,host_cnt,socket_cnt,core_cnt,thread_cnt,memory_cnt,host_down_cnt = table_header
  155. html = html + '<tr>\n'
  156. html = html + '<th>' + cluster + '</th>\n'
  157. html = html + '<th>' + host_cnt + '</th>\n'
  158. html = html + '<th>' + socket_cnt + '</th>\n'
  159. html = html + '<th>' + core_cnt + '</th>\n'
  160. html = html + '<th>' + thread_cnt + '</th>\n'
  161. html = html + '<th>' + memory_cnt + '</th>\n'
  162. html = html + '<th>' + host_down_cnt + '</th>\n'
  163. html = html + '</tr>\n'
  164. for row in table:
  165. cluster,host_cnt,socket_cnt,core_cnt,thread_cnt,memory_cnt,host_down_cnt = row
  166. html = html + '<tr bgcolor="' + cluster_colors[cluster] + '">\n'
  167. html = html + '<td>' + cluster + '</td>\n'
  168. html = html + '<td>' + str(host_cnt) + '</td>\n'
  169. html = html + '<td>' + str(socket_cnt) + '</td>\n'
  170. html = html + '<td>' + str(core_cnt) + '</td>\n'
  171. html = html + '<td>' + str(thread_cnt) + '</td>\n'
  172. html = html + '<td>' + str(memory_cnt) + '</td>\n'
  173. html = html + '<td>' + str(host_down_cnt) + '</td>\n'
  174. html = html + '</tr>\n'
  175. html = html + '</table>\n\n'
  176. html = html + '<br>\n'
  177. html = html + '<a href="' + csv_file_name + '">' + csv_file_name + '</a>\n'
  178. html = html + '<br>\n'
  179. html = html + '<p>' + 'Last updated ' + date + '</p>\n'
  180. html = html + '</body>\n'
  181. html = html + '</html>'
  182.  
  183. ## Check that the favicon file exists and copy it to the web page directory:
  184. if os.path.exists(favicon_file_name) == False:
  185. print favicon_file_name, "does not exist."
  186. else:
  187. copyfile(favicon_file_name, favicon_file)
  188.  
  189. ## Write out html file.
  190. with open(html_file, 'w') as out_file:
  191. out_file.write(html)
Add Comment
Please, Sign In to add comment