Guest User

Untitled

a guest
Apr 4th, 2018
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.82 KB | None | 0 0
  1. #!/usr/bin/python
  2. import numa_dict
  3. import os
  4. import sys
  5. import time
  6. import subprocess
  7. import string
  8. from novaclient.v2 import aggregates
  9. from novaclient.v2 import hosts
  10. from novaclient.v2 import servers
  11. from credential_helper import CredentialHelper
  12. from datetime import datetime
  13. import novaclient.client as nova_client
  14. from novaclient import client as nvclient
  15. from ironic_helper import IronicHelper
  16. from dracclient import client
  17. import requests
  18. from requests.packages.urllib3.exceptions import InsecureRequestWarning
  19. requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
  20.  
  21. home_dir = os.path.expanduser('~')
  22. DELL_AGGREGATE_METADATA = {"Dell_Aggr": {'pinned': 'False' , 'hugepages': 'False'}}
  23.  
  24. # Dell nfv configuration global values
  25. undercloudrc_file_name = "stackrc"
  26. UC_USERNAME = UC_PASSWORD = UC_PROJECT_ID = UC_AUTH_URL = ''
  27.  
  28. class ConfigOvercloud(object):
  29. """
  30. Description: Class responsible for overcloud configurations.
  31. """
  32.  
  33. # These are not parameters. So defined as class variables
  34. ironic = IronicHelper()
  35. ironic_client = ironic.get_ironic_client()
  36. nodes = ironic_client.node.list()
  37. get_drac_credentail = CredentialHelper()
  38.  
  39. def __init__(self, overcloud_name):
  40. self.overcloud_name = overcloud_name
  41. self.source_stackrc = "source ~/stackrc;"
  42. self.overcloudrc = "source " + home_dir + "/" + self.overcloud_name + "rc;"
  43.  
  44. @classmethod
  45. def get_undercloud_details(cls):
  46. try:
  47. global UC_USERNAME, UC_PASSWORD, UC_PROJECT_ID, UC_AUTH_URL
  48. file_path = home_dir + '/' + undercloudrc_file_name
  49. if not os.path.isfile(file_path):
  50. raise Exception("The Undercloud rc file does not exist {}".format(file_path))
  51.  
  52. with open(file_path) as rc_file:
  53. for line in rc_file:
  54. if 'OS_USERNAME=' in line:
  55. UC_USERNAME = line.split('OS_USERNAME=')[1].strip("\n").strip("'")
  56. elif 'OS_PASSWORD=' in line:
  57. cmd = 'sudo hiera admin_password'
  58. proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
  59. stderr=subprocess.PIPE)
  60. output = proc.communicate()
  61. output = output[0]
  62. UC_PASSWORD = output[:-1]
  63. elif 'OS_TENANT_NAME=' in line:
  64. UC_PROJECT_ID = line.split('OS_TENANT_NAME=')[1].strip("\n").strip("'")
  65. elif 'OS_AUTH_URL=' in line:
  66. UC_AUTH_URL = line.split('OS_AUTH_URL=')[1].strip("\n").strip("'")
  67. except Exception as error:
  68. message = "Exception {}: {}".format(type(error).__name__, str(error))
  69. print "{}".format(message)
  70. raise Exception("Failed to get undercloud details from the undercloud rc file {}".format(file_path))
  71.  
  72.  
  73. @classmethod
  74. def get_overcloud_details(cls, overcloud_name):
  75. try:
  76. global UC_USERNAME, UC_PASSWORD, UC_PROJECT_ID, UC_AUTH_URL
  77. file_path = home_dir + '/' + overcloud_name + "rc"
  78. if not os.path.isfile(file_path):
  79. raise Exception("The Overcloud rc file does not exist {}".format(file_path))
  80.  
  81. with open(file_path) as rc_file:
  82. for line in rc_file:
  83. if 'OS_USERNAME' in line:
  84. UC_USERNAME = line.split('OS_USERNAME=')[1].strip("\n").strip("'")
  85. elif 'OS_PASSWORD' in line:
  86. UC_PASSWORD = line.split('OS_PASSWORD=')[1].strip("\n").strip("'")
  87. elif 'OS_PROJECT_NAME' in line:
  88. UC_PROJECT_ID = line.split('OS_PROJECT_NAME=')[1].strip("\n").strip("'")
  89. elif 'OS_AUTH_URL' in line:
  90. UC_AUTH_URL = line.split('OS_AUTH_URL=')[1].strip("\n").strip("'")
  91. except Exception as error:
  92. message = "Exception {}: {}".format(type(error).__name__, str(error))
  93. print "{}".format(message)
  94. raise Exception("Failed to get overcloud details from the overcloud rc file {}".format(file_path))
  95.  
  96. def reboot_dell_nfv_nodes(self):
  97. try:
  98. print "Rebooting dellnfv nodes"
  99. ConfigOvercloud.get_undercloud_details()
  100. # Create servers object
  101. nova = nvclient.Client(2, UC_USERNAME, UC_PASSWORD, UC_PROJECT_ID, UC_AUTH_URL)
  102. server_obj = servers.ServerManager(nova)
  103. for server in server_obj.list():
  104. if "dell-nfv-compute" in str(server):
  105. server_obj.reboot(server)
  106. except Exception as error:
  107. message = "Exception {}: {}".format(type(error).__name__, str(error))
  108. print "Failed to reboot dell nfv nodes with error {}".format(message)
  109.  
  110.  
  111.  
  112. @classmethod
  113. def calculate_hostos_cpus(self,number_of_host_os_cpu):
  114. try:
  115. cpu_count_list = []
  116. for node in ConfigOvercloud.nodes:
  117. # for every compute node get the corresponding drac credentials to fetch the cpu details
  118. node_uuid = node.uuid
  119. node_details=ConfigOvercloud.ironic_client.node.get(node_uuid)
  120. node_type=node_details.properties['capabilities'].split(',')[0].split(':')[1]
  121. if 'dell-nfv-compute' not in node_type:
  122. # filter for getting compute node
  123. continue
  124. drac_ip, drac_user, drac_password = ConfigOvercloud.get_drac_credentail.get_drac_creds(ConfigOvercloud.ironic_client, node_uuid)
  125. stor = client.DRACClient(drac_ip, drac_user, drac_password)
  126. sockets = stor.list_cpus() # cpu socket information for every compute node
  127. cpu_count = 0
  128. for socket in sockets :
  129. if socket.ht_enabled :
  130. cpu_count += socket.cores*2
  131. else:
  132. print "Hyperthreading is not enabled in " + str(node_uuid) + ". So exiting the code execution."
  133. sys.exit()
  134. cpu_count_list.append(cpu_count)
  135.  
  136. min_cpu_count = min(cpu_count_list)
  137. if min_cpu_count not in [40,48,56,64,72] :
  138. print "CPU count should be one of these values : [40,48,56,64,72]. But number of cpu is " + str(min_cpu_count)
  139. sys.exit()
  140. number_of_host_os_cpu=int(number_of_host_os_cpu)
  141. print "Host OS CPUs : {}".format(numa_dict.numa_info[min_cpu_count][number_of_host_os_cpu]["List of host os cpu"])
  142. print "vCPUs : {}".format(numa_dict.numa_info[min_cpu_count][number_of_host_os_cpu]["List of vcpu"])
  143. return numa_dict.numa_info[min_cpu_count][number_of_host_os_cpu]["List of vcpu"]
  144. except Exception as error:
  145. message = "Exception {}: {}".format(type(error).__name__, str(error))
  146. print "Failed to calculate Numa Vcpu list {}".format(message)
  147.  
  148.  
  149. @classmethod
  150. def calculate_hugepage_count(self,hugepage_size):
  151. try:
  152.  
  153. pages = []
  154.  
  155. for node in ConfigOvercloud.nodes:
  156. node_uuid = node.uuid # uuid of a node
  157. node_details = ConfigOvercloud.ironic_client.node.get(node_uuid) # details of a node
  158. memory_count = node_details.properties['memory_mb']
  159. node_properties_capabilities = node_details.properties['capabilities'].split(',')[0].split(':')[1]
  160. if 'dell-nfv-compute' in node_properties_capabilities:
  161. if hugepage_size == "2MB":
  162. pages.append((memory_count / 2))
  163. if hugepage_size == "1GB":
  164. pages.append((memory_count / 1024))
  165.  
  166. return min(pages)
  167. except Exception as error:
  168. message = "Exception {}: {}".format(type(error).__name__, str(error))
  169. print "Failed to calculate hugepage count {}".format(message)
  170.  
  171. def edit_dellnfv_environment_file(self, enable_hugepage, enable_numa, hugepage_size, hostos_cpu_count, dell_nfv_compute_count=0):
  172. try:
  173. print "Editing dellnfv environment file"
  174. file_path = home_dir + '/pilot/templates/overcloud/dellnfv_environment.yaml'
  175. if not os.path.isfile(file_path):
  176. raise Exception("The dellnfv_environment.yaml file does not exist")
  177. cmds = ['sed -i "s|dellnfv::hugepages::enable:.*|dellnfv::hugepages::enable: ' + str(
  178. enable_hugepage) + '|" ' + file_path,
  179. 'sed -i "s|dellnfv::numa::enable:.*|dellnfv::numa::enable: ' + str(enable_numa) + '|" ' + file_path]
  180.  
  181. if dell_nfv_compute_count > 0:
  182. cmds.append('sed -i "s|DellNfvComputeCount:.*|DellNfvComputeCount: ' + str(
  183. dell_nfv_compute_count) + '|" ' + file_path)
  184.  
  185. if enable_hugepage:
  186. hugepage_number = ConfigOvercloud.calculate_hugepage_count(hugepage_size)
  187. cmds.append(
  188. 'sed -i "s|dellnfv::hugepages::hugepagesize:.*|dellnfv::hugepages::hugepagesize: ' + hugepage_size[
  189. 0:-1] + '|" ' + file_path)
  190. cmds.append('sed -i "s|dellnfv::hugepages::hugepagecount:.*|dellnfv::hugepages::hugepagecount: ' + str(
  191. hugepage_number) + '|" ' + file_path)
  192. if enable_numa:
  193. vcpu_pin_set = ConfigOvercloud.calculate_hostos_cpus(hostos_cpu_count)
  194. cmds.append(
  195. 'sed -i "s|dellnfv::numa::vcpu_pin_set:.*|dellnfv::numa::vcpu_pin_set: \\\\\\\\\\"' + vcpu_pin_set + '\\\\\\\\\\"|" ' + file_path)
  196.  
  197. for cmd in cmds:
  198. status = os.system(cmd)
  199. print "cmd: {}".format(cmd)
  200. if status != 0:
  201. raise Exception("Failed to execute the command {} with error code {}".format(cmd, status))
  202. except Exception as error:
  203. message = "Exception {}: {}".format(type(error).__name__, str(error))
  204. print
  205. "{}".format(message)
  206. raise Exception("Failed to modify the dellnfv_environment.yaml at location {}".format(file_path))
  207.  
  208.  
  209. def get_dell_nfv_compute_nodes_hostnames(self, nova):
  210. try:
  211. print "Getting dellnfv compute node hostnames"
  212.  
  213. # Create host object
  214. host_obj = hosts.HostManager(nova)
  215.  
  216. # Get list of dell nfv nodes
  217. dell_nfv_hosts = []
  218.  
  219. for host in host_obj.list():
  220. if "dell-nfv-compute" in host.host_name:
  221. hostname = str(host.host_name)
  222. dell_nfv_hosts.append(hostname)
  223. return dell_nfv_hosts
  224. except Exception as error:
  225. message = "Exception {}: {}".format(type(error).__name__, str(error))
  226. print "{}".format(message)
  227. raise Exception("Failed to get the Dell Nfv Compute nodes.")
  228.  
  229.  
  230. def edit_aggregate_environment_file(self, aggr_name, aggr_metadata, hostname_list):
  231. print "Editing create aggregate environment file"
  232. file_path = home_dir + '/pilot/templates/overcloud/create_aggregate_environment.yaml'
  233. if not os.path.isfile(file_path):
  234. raise Exception("The create_aggregate_environment.yaml file does not exist")
  235. cmds = list()
  236. cmds.append(
  237. 'sed -i "s|aggregate_name:.*|aggregate_name: ' + str(aggr_name) + '|" ' + file_path)
  238. cmds.append(
  239. 'sed -i "s|aggregate_metadata:.*|aggregate_metadata: ' + str(aggr_metadata) + '|" ' + file_path)
  240. cmds.append(
  241. 'sed -i "s|hosts:.*|hosts: ' + str(hostname_list) + '|" ' + file_path)
  242. for cmd in cmds:
  243. status = os.system(cmd)
  244. print "cmd: {}".format(cmd)
  245. if status != 0:
  246. raise Exception("Failed to execute the command {} with error code {}".format(cmd, status))
  247.  
  248.  
  249. def create_aggregates(self, aggr_name):
  250. env_opts = " -e ~/pilot/templates/overcloud/create_aggregate_environment.yaml"
  251.  
  252. cmd = self.overcloudrc + "openstack stack create " \
  253. " {}" \
  254. " --template ~/pilot/templates/overcloud/puppet/services/DellNfv/createaggregate.yaml" \
  255. " {}" \
  256. "".format(aggr_name,
  257. env_opts)
  258. aggregate_create_status = os.system(cmd)
  259. if aggregate_create_status == 0:
  260. print "Aggregate {} created".format(aggr_name)
  261. else:
  262. print "Aggregate {} could not be created... Exiting post deployment tasks".format(aggr_name)
  263. sys.exit(0)
  264.  
  265.  
  266. def set_aggregate_metadata(self):
  267. try:
  268. # Get the overcloud details
  269. ConfigOvercloud.get_overcloud_details(self.overcloud_name)
  270.  
  271. # Create nova client object
  272. nova = nvclient.Client(2, UC_USERNAME, UC_PASSWORD, UC_PROJECT_ID, UC_AUTH_URL)
  273. aggregate_dict = dict()
  274. hostname_list = self.get_dell_nfv_compute_nodes_hostnames(nova)
  275.  
  276. aggregate_dict.update(DELL_AGGREGATE_METADATA)
  277.  
  278. for aggregate_name, aggregate_metadata in aggregate_dict.items():
  279. self.edit_aggregate_environment_file(aggregate_name, aggregate_metadata, hostname_list)
  280. self.create_aggregates(aggregate_name)
  281. except Exception as error:
  282. message = "Exception {}: {}".format(type(error).__name__, str(error))
  283. print message
  284. print "Unable to set aggregate metadata. Exiting post deployment task..."
  285. sys.exit(0)
  286.  
  287.  
  288. def post_deployment_tasks(self, enable_hugepage, enable_numa, hpg_size):
  289. try:
  290. # Reboot all the Dell NFV compute nodes
  291. self.reboot_dell_nfv_nodes()
  292.  
  293. # Wait for 5 mins to let dll nfv nodes boot up
  294. time.sleep(300)
  295.  
  296. print "Initiating post deployment tasks"
  297.  
  298. # create aggregate
  299. self.set_aggregate_metadata()
  300.  
  301. except Exception as error:
  302. message = "Exception {}: {}".format(type(error).__name__, str(error))
  303. print
  304. "{}".format(message)
Add Comment
Please, Sign In to add comment