A Python library for code common to TripleO CLI and TripleO UI.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

837 lines
33KB

  1. ---
  2. version: '2.0'
  3. name: tripleo.derive_params_formulas.v1
  4. description: TripleO Workflows to derive deployment parameters from the introspected data
  5. workflows:
  6. dpdk_derive_params:
  7. description: >
  8. Workflow to derive parameters for DPDK service.
  9. input:
  10. - plan
  11. - role_name
  12. - heat_resource_tree
  13. - hw_data # introspection data
  14. - user_inputs
  15. - derived_parameters: {}
  16. output:
  17. derived_parameters: <% $.derived_parameters.mergeWith($.get('dpdk_parameters', {})) %>
  18. tags:
  19. - tripleo-common-managed
  20. tasks:
  21. get_network_config:
  22. action: tripleo.parameters.get_network_config
  23. input:
  24. container: <% $.plan %>
  25. role_name: <% $.role_name %>
  26. publish:
  27. network_configs: <% task().result.get('network_config', []) %>
  28. on-success: get_dpdk_nics_numa_info
  29. on-error: set_status_failed_get_network_config
  30. get_dpdk_nics_numa_info:
  31. action: tripleo.derive_params.get_dpdk_nics_numa_info
  32. input:
  33. network_configs: <% $.network_configs %>
  34. inspect_data: <% $.hw_data %>
  35. publish:
  36. dpdk_nics_numa_info: <% task().result %>
  37. on-success:
  38. # TODO: Need to remove condtions here
  39. # adding condition and throw error in action for empty check
  40. - get_dpdk_nics_numa_nodes: <% $.dpdk_nics_numa_info %>
  41. - set_status_failed_get_dpdk_nics_numa_info: <% not $.dpdk_nics_numa_info %>
  42. on-error: set_status_failed_on_error_get_dpdk_nics_numa_info
  43. get_dpdk_nics_numa_nodes:
  44. publish:
  45. dpdk_nics_numa_nodes: <% $.dpdk_nics_numa_info.groupBy($.numa_node).select($[0]).orderBy($) %>
  46. on-success:
  47. - get_numa_nodes: <% $.dpdk_nics_numa_nodes %>
  48. - set_status_failed_get_dpdk_nics_numa_nodes: <% not $.dpdk_nics_numa_nodes %>
  49. get_numa_nodes:
  50. publish:
  51. numa_nodes: <% $.hw_data.numa_topology.ram.select($.numa_node).orderBy($) %>
  52. on-success:
  53. - get_num_phy_cores_per_numa_for_pmd: <% $.numa_nodes %>
  54. - set_status_failed_get_numa_nodes: <% not $.numa_nodes %>
  55. get_num_phy_cores_per_numa_for_pmd:
  56. publish:
  57. num_phy_cores_per_numa_node_for_pmd: <% $.user_inputs.get('num_phy_cores_per_numa_node_for_pmd', 0) %>
  58. on-success:
  59. - get_num_cores_per_numa_nodes: <% isInteger($.num_phy_cores_per_numa_node_for_pmd) and $.num_phy_cores_per_numa_node_for_pmd > 0 %>
  60. - set_status_failed_get_num_phy_cores_per_numa_for_pmd_invalid: <% not isInteger($.num_phy_cores_per_numa_node_for_pmd) %>
  61. - set_status_failed_get_num_phy_cores_per_numa_for_pmd_not_provided: <% $.num_phy_cores_per_numa_node_for_pmd = 0 %>
  62. # For NUMA node with DPDK nic, number of cores should be used from user input
  63. # For NUMA node without DPDK nic, number of cores should be 1
  64. get_num_cores_per_numa_nodes:
  65. publish:
  66. num_cores_per_numa_nodes: <% let(dpdk_nics_nodes => $.dpdk_nics_numa_nodes, cores => $.num_phy_cores_per_numa_node_for_pmd) -> $.numa_nodes.select(switch($ in $dpdk_nics_nodes => $cores, not $ in $dpdk_nics_nodes => 1)) %>
  67. on-success: get_pmd_cpus
  68. get_pmd_cpus:
  69. action: tripleo.derive_params.get_dpdk_core_list
  70. input:
  71. inspect_data: <% $.hw_data %>
  72. numa_nodes_cores_count: <% $.num_cores_per_numa_nodes %>
  73. publish:
  74. pmd_cpus: <% task().result %>
  75. on-success:
  76. - get_pmd_cpus_range_list: <% $.pmd_cpus %>
  77. - set_status_failed_get_pmd_cpus: <% not $.pmd_cpus %>
  78. on-error: set_status_failed_on_error_get_pmd_cpus
  79. get_pmd_cpus_range_list:
  80. action: tripleo.derive_params.convert_number_to_range_list
  81. input:
  82. num_list: <% $.pmd_cpus %>
  83. publish:
  84. pmd_cpus: <% task().result %>
  85. on-success: get_host_cpus
  86. on-error: set_status_failed_get_pmd_cpus_range_list
  87. get_host_cpus:
  88. workflow: tripleo.derive_params_formulas.v1.get_host_cpus
  89. input:
  90. role_name: <% $.role_name %>
  91. hw_data: <% $.hw_data %>
  92. publish:
  93. host_cpus: <% task().result.get('host_cpus', '') %>
  94. on-success: get_sock_mem
  95. on-error: set_status_failed_get_host_cpus
  96. get_sock_mem:
  97. action: tripleo.derive_params.get_dpdk_socket_memory
  98. input:
  99. dpdk_nics_numa_info: <% $.dpdk_nics_numa_info %>
  100. numa_nodes: <% $.numa_nodes %>
  101. overhead: <% $.user_inputs.get('overhead', 800) %>
  102. packet_size_in_buffer: <% 4096*64 %>
  103. publish:
  104. sock_mem: <% task().result %>
  105. on-success:
  106. - get_neutron_bridge_mappings: <% $.sock_mem %>
  107. - set_status_failed_get_sock_mem: <% not $.sock_mem %>
  108. on-error: set_status_failed_on_error_get_sock_mem
  109. get_neutron_bridge_mappings:
  110. publish:
  111. neutron_bridge_mappings: <% $.heat_resource_tree.parameters.get('NeutronBridgeMappings', {}).get('default', '') %>
  112. on-success:
  113. - get_phy_nw_bridge_mappings: <% $.neutron_bridge_mappings %>
  114. - get_neutron_network_type: <% not $.neutron_bridge_mappings %>
  115. # Gets the physical network and ovs bridge mappings
  116. get_phy_nw_bridge_mappings:
  117. publish:
  118. phy_nw_bridge_mappings: <% $.neutron_bridge_mappings.split(',').select(let(mapping => $.split(':')) -> dict($mapping[0] => $mapping[1])).sum() %>
  119. on-success: get_bridge_numa_nodes_mappings
  120. # Gets the ovs bridge and NUMA nodes mappings
  121. get_bridge_numa_nodes_mappings:
  122. publish:
  123. bridge_numa_nodes_mappings: <% $.dpdk_nics_numa_info.groupBy($.bridge_name).select(dict($[0]=>$[1].select($.numa_node).distinct())).sum() %>
  124. on-success: get_phy_nw_numa_nodes_mappings
  125. # Gets the physical network and NUMA nodes mappings
  126. get_phy_nw_numa_nodes_mappings:
  127. publish:
  128. phy_nw_numa_nodes_mappings: <% let(nw_bridge_mappings => $.phy_nw_bridge_mappings) -> $.bridge_numa_nodes_mappings.items().select(let(br => $[0], nodes => $[1]) -> $nw_bridge_mappings.items().where($[1]=$br).select(dict($[0] => $nodes)).sum()).sum() %>
  129. on-success: get_neutron_network_type
  130. get_neutron_network_type:
  131. publish:
  132. neutron_network_type: <% $.heat_resource_tree.parameters.get('NeutronNetworkType', {}).get('default', '') %>
  133. on-success:
  134. - get_tunnel_numa_nodes_mappings: <% 'vxlan' in $.neutron_network_type %>
  135. - get_dpdk_parameters: <% not 'vxlan' in $.neutron_network_type %>
  136. # Gets the list of NUMA nodes associated to all tunneled networks
  137. # OVS-DPDK on VxLAN tunnel requires Tenant Network IP to be applied on the OVS User Bridge itself.
  138. # With this assumption, if the IP is set on the OVS User Bridge, then OVS-DPDK is used for VxLAN tunnels also.
  139. # Here dpdk_nics_numa_info will have the OVS User Bridges with DPDK ports only.
  140. get_tunnel_numa_nodes_mappings:
  141. publish:
  142. tunnel_numa_nodes_mappings: <% $.dpdk_nics_numa_info.where($.addresses.any($.ip_netmask)).select($.numa_node).distinct() %>
  143. on-success: get_dpdk_parameters
  144. get_dpdk_parameters:
  145. publish:
  146. dpdk_parameters: <% dict(concat($.role_name, 'Parameters') => dict('OvsPmdCoreList' => $.get('pmd_cpus', ''), 'OvsDpdkCoreList' => $.get('host_cpus', ''), 'OvsDpdkSocketMemory' => $.get('sock_mem', ''))) %>
  147. on-success:
  148. - add_phy_nw_numa_nodes_mappings: <% $.get('phy_nw_numa_nodes_mappings', {}) %>
  149. - add_tunnel_numa_nodes_mappings: <% $.get('tunnel_numa_nodes_mappings', []) %>
  150. add_phy_nw_numa_nodes_mappings:
  151. publish:
  152. dpdk_parameters: <% $.dpdk_parameters.mergeWith(dict(concat($.role_name, 'Parameters') => dict('NeutronPhysnetNUMANodesMapping' => $.get('phy_nw_numa_nodes_mappings', {})))) %>
  153. add_tunnel_numa_nodes_mappings:
  154. publish:
  155. dpdk_parameters: <% $.dpdk_parameters.mergeWith(dict(concat($.role_name, 'Parameters') => dict('NeutronTunnelNUMANodes' => $.get('tunnel_numa_nodes_mappings', [])))) %>
  156. set_status_failed_get_network_config:
  157. publish:
  158. status: FAILED
  159. message: <% task(get_network_config).result %>
  160. on-success: fail
  161. set_status_failed_get_dpdk_nics_numa_info:
  162. publish:
  163. status: FAILED
  164. message: "Unable to determine DPDK NIC's NUMA information"
  165. on-success: fail
  166. set_status_failed_on_error_get_dpdk_nics_numa_info:
  167. publish:
  168. status: FAILED
  169. message: <% task(get_dpdk_nics_numa_info).result %>
  170. on-success: fail
  171. set_status_failed_get_dpdk_nics_numa_nodes:
  172. publish:
  173. status: FAILED
  174. message: "Unable to determine DPDK NIC's numa nodes"
  175. on-success: fail
  176. set_status_failed_get_numa_nodes:
  177. publish:
  178. status: FAILED
  179. message: 'Unable to determine available NUMA nodes'
  180. on-success: fail
  181. set_status_failed_get_num_phy_cores_per_numa_for_pmd_invalid:
  182. publish:
  183. status: FAILED
  184. message: <% "num_phy_cores_per_numa_node_for_pmd user input '{0}' is invalid".format($.num_phy_cores_per_numa_node_for_pmd) %>
  185. on-success: fail
  186. set_status_failed_get_num_phy_cores_per_numa_for_pmd_not_provided:
  187. publish:
  188. status: FAILED
  189. message: 'num_phy_cores_per_numa_node_for_pmd user input is not provided'
  190. on-success: fail
  191. set_status_failed_get_pmd_cpus:
  192. publish:
  193. status: FAILED
  194. message: 'Unable to determine OvsPmdCoreList parameter'
  195. on-success: fail
  196. set_status_failed_on_error_get_pmd_cpus:
  197. publish:
  198. status: FAILED
  199. message: <% task(get_pmd_cpus).result %>
  200. on-success: fail
  201. set_status_failed_get_pmd_cpus_range_list:
  202. publish:
  203. status: FAILED
  204. message: <% task(get_pmd_cpus_range_list).result %>
  205. on-success: fail
  206. set_status_failed_get_host_cpus:
  207. publish:
  208. status: FAILED
  209. message: <% task(get_host_cpus).result.get('message', '') %>
  210. on-success: fail
  211. set_status_failed_get_sock_mem:
  212. publish:
  213. status: FAILED
  214. message: 'Unable to determine OvsDpdkSocketMemory parameter'
  215. on-success: fail
  216. set_status_failed_on_error_get_sock_mem:
  217. publish:
  218. status: FAILED
  219. message: <% task(get_sock_mem).result %>
  220. on-success: fail
  221. sriov_derive_params:
  222. description: >
  223. This workflow derives parameters for the SRIOV feature.
  224. input:
  225. - role_name
  226. - hw_data # introspection data
  227. - derived_parameters: {}
  228. output:
  229. derived_parameters: <% $.derived_parameters.mergeWith($.get('sriov_parameters', {})) %>
  230. tags:
  231. - tripleo-common-managed
  232. tasks:
  233. get_host_cpus:
  234. workflow: tripleo.derive_params_formulas.v1.get_host_cpus
  235. input:
  236. role_name: <% $.role_name %>
  237. hw_data: <% $.hw_data %>
  238. publish:
  239. host_cpus: <% task().result.get('host_cpus', '') %>
  240. on-success: get_sriov_parameters
  241. on-error: set_status_failed_get_host_cpus
  242. get_sriov_parameters:
  243. publish:
  244. # SriovHostCpusList parameter is added temporarily and it's removed later from derived parameters result.
  245. sriov_parameters: <% dict(concat($.role_name, 'Parameters') => dict('SriovHostCpusList' => $.get('host_cpus', ''))) %>
  246. set_status_failed_get_host_cpus:
  247. publish:
  248. status: FAILED
  249. message: <% task(get_host_cpus).result.get('message', '') %>
  250. on-success: fail
  251. get_host_cpus:
  252. description: >
  253. Fetching the host CPU list from the introspection data, and then converting the raw list into a range list.
  254. input:
  255. - hw_data # introspection data
  256. output:
  257. host_cpus: <% $.get('host_cpus', '') %>
  258. tags:
  259. - tripleo-common-managed
  260. tasks:
  261. get_host_cpus:
  262. action: tripleo.derive_params.get_host_cpus_list inspect_data=<% $.hw_data %>
  263. publish:
  264. host_cpus: <% task().result %>
  265. on-success:
  266. - get_host_cpus_range_list: <% $.host_cpus %>
  267. - set_status_failed_get_host_cpus: <% not $.host_cpus %>
  268. on-error: set_status_failed_on_error_get_host_cpus
  269. get_host_cpus_range_list:
  270. action: tripleo.derive_params.convert_number_to_range_list
  271. input:
  272. num_list: <% $.host_cpus %>
  273. publish:
  274. host_cpus: <% task().result %>
  275. on-error: set_status_failed_get_host_cpus_range_list
  276. set_status_failed_get_host_cpus:
  277. publish:
  278. status: FAILED
  279. message: 'Unable to determine host cpus'
  280. on-success: fail
  281. set_status_failed_on_error_get_host_cpus:
  282. publish:
  283. status: FAILED
  284. message: <% task(get_host_cpus).result %>
  285. on-success: fail
  286. set_status_failed_get_host_cpus_range_list:
  287. publish:
  288. status: FAILED
  289. message: <% task(get_host_cpus_range_list).result %>
  290. on-success: fail
  291. host_derive_params:
  292. description: >
  293. This workflow derives parameters for the Host process, and is mainly associated with CPU pinning and huge memory pages.
  294. This workflow can be dependent on any feature or also can be invoked individually as well.
  295. input:
  296. - role_name
  297. - hw_data # introspection data
  298. - user_inputs
  299. - derived_parameters: {}
  300. output:
  301. derived_parameters: <% $.derived_parameters.mergeWith($.get('host_parameters', {})) %>
  302. tags:
  303. - tripleo-common-managed
  304. tasks:
  305. get_cpus:
  306. publish:
  307. cpus: <% $.hw_data.numa_topology.cpus %>
  308. on-success:
  309. - get_role_derive_params: <% $.cpus %>
  310. - set_status_failed_get_cpus: <% not $.cpus %>
  311. get_role_derive_params:
  312. publish:
  313. role_derive_params: <% $.derived_parameters.get(concat($.role_name, 'Parameters'), {}) %>
  314. # removing the role parameters (eg. ComputeParameters) in derived_parameters dictionary since already copied in role_derive_params.
  315. derived_parameters: <% $.derived_parameters.delete(concat($.role_name, 'Parameters')) %>
  316. on-success: get_host_cpus
  317. get_host_cpus:
  318. publish:
  319. host_cpus: <% $.role_derive_params.get('OvsDpdkCoreList', '') or $.role_derive_params.get('SriovHostCpusList', '') %>
  320. # SriovHostCpusList parameter is added temporarily for host_cpus and not needed in derived_parameters result.
  321. # SriovHostCpusList parameter is deleted in derived_parameters list and adding the updated role parameters
  322. # back in the derived_parameters.
  323. derived_parameters: <% $.derived_parameters + dict(concat($.role_name, 'Parameters') => $.role_derive_params.delete('SriovHostCpusList')) %>
  324. on-success: get_host_dpdk_combined_cpus
  325. get_host_dpdk_combined_cpus:
  326. publish:
  327. host_dpdk_combined_cpus: <% let(pmd_cpus => $.role_derive_params.get('OvsPmdCoreList', '')) -> switch($pmd_cpus => concat($pmd_cpus, ',', $.host_cpus), not $pmd_cpus => $.host_cpus) %>
  328. reserved_cpus: []
  329. on-success:
  330. - get_host_dpdk_combined_cpus_num_list: <% $.host_dpdk_combined_cpus %>
  331. - set_status_failed_get_host_dpdk_combined_cpus: <% not $.host_dpdk_combined_cpus %>
  332. get_host_dpdk_combined_cpus_num_list:
  333. action: tripleo.derive_params.convert_range_to_number_list
  334. input:
  335. range_list: <% $.host_dpdk_combined_cpus %>
  336. publish:
  337. host_dpdk_combined_cpus: <% task().result %>
  338. reserved_cpus: <% task().result.split(',') %>
  339. on-success: get_nova_cpus
  340. on-error: set_status_failed_get_host_dpdk_combined_cpus_num_list
  341. get_nova_cpus:
  342. publish:
  343. nova_cpus: <% let(reserved_cpus => $.reserved_cpus) -> $.cpus.select($.thread_siblings).flatten().where(not (str($) in $reserved_cpus)).join(',') %>
  344. on-success:
  345. - get_isol_cpus: <% $.nova_cpus %>
  346. - set_status_failed_get_nova_cpus: <% not $.nova_cpus %>
  347. # concatinates OvsPmdCoreList range format and NovaVcpuPinSet in range format. it may not be in perfect range format.
  348. # example: concatinates '12-15,19' and 16-18' ranges '12-15,19,16-18'
  349. get_isol_cpus:
  350. publish:
  351. isol_cpus: <% let(pmd_cpus => $.role_derive_params.get('OvsPmdCoreList','')) -> switch($pmd_cpus => concat($pmd_cpus, ',', $.nova_cpus), not $pmd_cpus => $.nova_cpus) %>
  352. on-success: get_isol_cpus_num_list
  353. # Gets the isol_cpus in the number list
  354. # example: '12-15,19,16-18' into '12,13,14,15,16,17,18,19'
  355. get_isol_cpus_num_list:
  356. action: tripleo.derive_params.convert_range_to_number_list
  357. input:
  358. range_list: <% $.isol_cpus %>
  359. publish:
  360. isol_cpus: <% task().result %>
  361. on-success: get_nova_cpus_range_list
  362. on-error: set_status_failed_get_isol_cpus_num_list
  363. get_nova_cpus_range_list:
  364. action: tripleo.derive_params.convert_number_to_range_list
  365. input:
  366. num_list: <% $.nova_cpus %>
  367. publish:
  368. nova_cpus: <% task().result %>
  369. on-success: get_isol_cpus_range_list
  370. on-error: set_status_failed_get_nova_cpus_range_list
  371. # converts number format isol_cpus into range format
  372. # example: '12,13,14,15,16,17,18,19' into '12-19'
  373. get_isol_cpus_range_list:
  374. action: tripleo.derive_params.convert_number_to_range_list
  375. input:
  376. num_list: <% $.isol_cpus %>
  377. publish:
  378. isol_cpus: <% task().result %>
  379. on-success: get_host_mem
  380. on-error: set_status_failed_get_isol_cpus_range_list
  381. get_host_mem:
  382. publish:
  383. host_mem: <% $.user_inputs.get('host_mem_default', 4096) %>
  384. on-success: check_default_hugepage_supported
  385. check_default_hugepage_supported:
  386. publish:
  387. default_hugepage_supported: <% $.hw_data.get('inventory', {}).get('cpu', {}).get('flags', []).contains('pdpe1gb') %>
  388. on-success:
  389. - get_total_memory: <% $.default_hugepage_supported %>
  390. - set_status_failed_check_default_hugepage_supported: <% not $.default_hugepage_supported %>
  391. get_total_memory:
  392. publish:
  393. total_memory: <% $.hw_data.get('inventory', {}).get('memory', {}).get('physical_mb', 0) %>
  394. on-success:
  395. - get_hugepage_allocation_percentage: <% $.total_memory %>
  396. - set_status_failed_get_total_memory: <% not $.total_memory %>
  397. get_hugepage_allocation_percentage:
  398. publish:
  399. huge_page_allocation_percentage: <% $.user_inputs.get('huge_page_allocation_percentage', 0) %>
  400. on-success:
  401. - get_hugepages: <% isInteger($.huge_page_allocation_percentage) and $.huge_page_allocation_percentage > 0 %>
  402. - set_status_failed_get_hugepage_allocation_percentage_invalid: <% not isInteger($.huge_page_allocation_percentage) %>
  403. - set_status_failed_get_hugepage_allocation_percentage_not_provided: <% $.huge_page_allocation_percentage = 0 %>
  404. get_hugepages:
  405. publish:
  406. hugepages: <% let(huge_page_perc => float($.huge_page_allocation_percentage)/100)-> int((($.total_memory/1024)-4) * $huge_page_perc) %>
  407. on-success:
  408. - get_cpu_model: <% $.hugepages %>
  409. - set_status_failed_get_hugepages: <% not $.hugepages %>
  410. get_cpu_model:
  411. publish:
  412. intel_cpu_model: <% $.hw_data.get('inventory', {}).get('cpu', {}).get('model_name', '').startsWith('Intel') %>
  413. on-success: get_iommu_info
  414. get_iommu_info:
  415. publish:
  416. iommu_info: <% switch($.intel_cpu_model => 'intel_iommu=on iommu=pt', not $.intel_cpu_model => '') %>
  417. on-success: get_kernel_args
  418. get_kernel_args:
  419. publish:
  420. kernel_args: <% concat('default_hugepagesz=1GB hugepagesz=1G ', 'hugepages=', str($.hugepages), ' ', $.iommu_info, ' isolcpus=', $.isol_cpus) %>
  421. on-success: get_host_parameters
  422. get_host_parameters:
  423. publish:
  424. host_parameters: <% dict(concat($.role_name, 'Parameters') => dict('NovaVcpuPinSet' => $.get('nova_cpus', ''), 'NovaReservedHostMemory' => $.get('host_mem', ''), 'KernelArgs' => $.get('kernel_args', ''), 'IsolCpusList' => $.get('isol_cpus', ''))) %>
  425. set_status_failed_get_cpus:
  426. publish:
  427. status: FAILED
  428. message: "Unable to determine CPU's on NUMA nodes"
  429. on-success: fail
  430. set_status_failed_get_host_dpdk_combined_cpus:
  431. publish:
  432. status: FAILED
  433. message: 'Unable to combine host and dpdk cpus list'
  434. on-success: fail
  435. set_status_failed_get_host_dpdk_combined_cpus_num_list:
  436. publish:
  437. status: FAILED
  438. message: <% task(get_host_dpdk_combined_cpus_num_list).result %>
  439. on-success: fail
  440. set_status_failed_get_nova_cpus:
  441. publish:
  442. status: FAILED
  443. message: 'Unable to determine nova vcpu pin set'
  444. on-success: fail
  445. set_status_failed_get_nova_cpus_range_list:
  446. publish:
  447. status: FAILED
  448. message: <% task(get_nova_cpus_range_list).result %>
  449. on-success: fail
  450. set_status_failed_get_isol_cpus_num_list:
  451. publish:
  452. status: FAILED
  453. message: <% task(get_isol_cpus_num_list).result %>
  454. on-success: fail
  455. set_status_failed_get_isol_cpus_range_list:
  456. publish:
  457. status: FAILED
  458. message: <% task(get_isol_cpus_range_list).result %>
  459. on-success: fail
  460. set_status_failed_check_default_hugepage_supported:
  461. publish:
  462. status: FAILED
  463. message: 'default huge page size 1GB is not supported'
  464. on-success: fail
  465. set_status_failed_get_total_memory:
  466. publish:
  467. status: FAILED
  468. message: 'Unable to determine total memory'
  469. on-success: fail
  470. set_status_failed_get_hugepage_allocation_percentage_invalid:
  471. publish:
  472. status: FAILED
  473. message: <% "huge_page_allocation_percentage user input '{0}' is invalid".format($.huge_page_allocation_percentage) %>
  474. on-success: fail
  475. set_status_failed_get_hugepage_allocation_percentage_not_provided:
  476. publish:
  477. status: FAILED
  478. message: 'huge_page_allocation_percentage user input is not provided'
  479. on-success: fail
  480. set_status_failed_get_hugepages:
  481. publish:
  482. status: FAILED
  483. message: 'Unable to determine huge pages'
  484. on-success: fail
  485. hci_derive_params:
  486. description: Derive the deployment parameters for HCI
  487. input:
  488. - role_name
  489. - environment_parameters
  490. - heat_resource_tree
  491. - introspection_data
  492. - user_inputs
  493. - derived_parameters: {}
  494. output:
  495. derived_parameters: <% $.derived_parameters.mergeWith($.get('hci_parameters', {})) %>
  496. tags:
  497. - tripleo-common-managed
  498. tasks:
  499. get_hci_inputs:
  500. publish:
  501. hci_profile: <% $.user_inputs.get('hci_profile', '') %>
  502. hci_profile_config: <% $.user_inputs.get('hci_profile_config', {}) %>
  503. MB_PER_GB: 1024
  504. on-success:
  505. - get_average_guest_memory_size_in_mb: <% $.hci_profile and $.hci_profile_config.get($.hci_profile, {}) %>
  506. - set_failed_invalid_hci_profile: <% $.hci_profile and not $.hci_profile_config.get($.hci_profile, {}) %>
  507. # When no hci_profile is specified, the workflow terminates without deriving any HCI parameters.
  508. get_average_guest_memory_size_in_mb:
  509. publish:
  510. average_guest_memory_size_in_mb: <% $.hci_profile_config.get($.hci_profile, {}).get('average_guest_memory_size_in_mb', 0) %>
  511. on-success:
  512. - get_average_guest_cpu_utilization_percentage: <% isInteger($.average_guest_memory_size_in_mb) %>
  513. - set_failed_invalid_average_guest_memory_size_in_mb: <% not isInteger($.average_guest_memory_size_in_mb) %>
  514. get_average_guest_cpu_utilization_percentage:
  515. publish:
  516. average_guest_cpu_utilization_percentage: <% $.hci_profile_config.get($.hci_profile, {}).get('average_guest_cpu_utilization_percentage', 0) %>
  517. on-success:
  518. - get_gb_overhead_per_guest: <% isInteger($.average_guest_cpu_utilization_percentage) %>
  519. - set_failed_invalid_average_guest_cpu_utilization_percentage: <% not isInteger($.average_guest_cpu_utilization_percentage) %>
  520. get_gb_overhead_per_guest:
  521. publish:
  522. gb_overhead_per_guest: <% $.user_inputs.get('gb_overhead_per_guest', 0.5) %>
  523. on-success:
  524. - get_gb_per_osd: <% isNumber($.gb_overhead_per_guest) %>
  525. - set_failed_invalid_gb_overhead_per_guest: <% not isNumber($.gb_overhead_per_guest) %>
  526. get_gb_per_osd:
  527. publish:
  528. gb_per_osd: <% $.user_inputs.get('gb_per_osd', 5) %>
  529. on-success:
  530. - get_cores_per_osd: <% isNumber($.gb_per_osd) %>
  531. - set_failed_invalid_gb_per_osd: <% not isNumber($.gb_per_osd) %>
  532. get_cores_per_osd:
  533. publish:
  534. cores_per_osd: <% $.user_inputs.get('cores_per_osd', 1.0) %>
  535. on-success:
  536. - get_extra_configs: <% isNumber($.cores_per_osd) %>
  537. - set_failed_invalid_cores_per_osd: <% not isNumber($.cores_per_osd) %>
  538. get_extra_configs:
  539. publish:
  540. extra_config: <% $.environment_parameters.get('ExtraConfig', {}) %>
  541. role_extra_config: <% $.environment_parameters.get(concat($.role_name, 'ExtraConfig'), {}) %>
  542. role_env_params: <% $.environment_parameters.get(concat($.role_name, 'Parameters'), {}) %>
  543. role_derive_params: <% $.derived_parameters.get(concat($.role_name, 'Parameters'), {}) %>
  544. on-success: calc_osds
  545. calc_osds:
  546. publish:
  547. num_dev: <% $.heat_resource_tree.parameters.get('CephAnsibleDisksConfig', {}).get('default', {}).get('devices', []).count() %>
  548. num_lvm: <% $.heat_resource_tree.parameters.get('CephAnsibleDisksConfig', {}).get('default', {}).get('lvm_volumes', []).count() %>
  549. on-success: get_num_osds
  550. get_num_osds:
  551. publish:
  552. num_osds: <% int($.num_dev + $.num_lvm) %>
  553. on-success:
  554. - get_memory_mb: <% $.num_osds %>
  555. # If there's no CephAnsibleDisksConfig then look for OSD configuration in hiera data
  556. - get_num_osds_from_hiera: <% not $.num_osds %>
  557. get_num_osds_from_hiera:
  558. publish:
  559. num_osds: <% $.role_extra_config.get('ceph::profile::params::osds', $.extra_config.get('ceph::profile::params::osds', {})).keys().count() %>
  560. on-success:
  561. - get_memory_mb: <% $.num_osds %>
  562. - set_failed_no_osds: <% not $.num_osds %>
  563. get_memory_mb:
  564. publish:
  565. memory_mb: <% $.introspection_data.get('memory_mb', 0) %>
  566. on-success:
  567. - get_nova_vcpu_pin_set: <% $.memory_mb %>
  568. - set_failed_get_memory_mb: <% not $.memory_mb %>
  569. # Determine the number of CPU cores available to Nova and Ceph. If
  570. # NovaVcpuPinSet is defined then use the number of vCPUs in the set,
  571. # otherwise use all of the cores identified in the introspection data.
  572. get_nova_vcpu_pin_set:
  573. publish:
  574. # NovaVcpuPinSet can be defined in multiple locations, and it's
  575. # important to select the value in order of precedence:
  576. #
  577. # 1) User specified value for this role
  578. # 2) User specified default value for all roles
  579. # 3) Value derived by another derived parameters workflow
  580. nova_vcpu_pin_set: <% $.role_env_params.get('NovaVcpuPinSet', $.environment_parameters.get('NovaVcpuPinSet', $.role_derive_params.get('NovaVcpuPinSet', ''))) %>
  581. on-success:
  582. - get_nova_vcpu_count: <% $.nova_vcpu_pin_set %>
  583. - get_num_cores: <% not $.nova_vcpu_pin_set %>
  584. get_nova_vcpu_count:
  585. action: tripleo.derive_params.convert_range_to_number_list
  586. input:
  587. range_list: <% $.nova_vcpu_pin_set %>
  588. publish:
  589. num_cores: <% task().result.split(',').count() %>
  590. on-success: calculate_nova_parameters
  591. on-error: set_failed_get_nova_vcpu_count
  592. get_num_cores:
  593. publish:
  594. num_cores: <% $.introspection_data.get('cpus', 0) %>
  595. on-success:
  596. - calculate_nova_parameters: <% $.num_cores %>
  597. - set_failed_get_num_cores: <% not $.num_cores %>
  598. # HCI calculations are broken into multiple steps. This is necessary
  599. # because variables published by a Mistral task are not available
  600. # for use by that same task. Variables computed and published in a task
  601. # are only available in subsequent tasks.
  602. #
  603. # The HCI calculations compute two Nova parameters:
  604. # - reserved_host_memory
  605. # - cpu_allocation_ratio
  606. #
  607. # The reserved_host_memory calculation computes the amount of memory
  608. # that needs to be reserved for Ceph and the total amount of "guest
  609. # overhead" memory that is based on the anticipated number of guests.
  610. # Psuedo-code for the calculation (disregarding MB and GB units) is
  611. # as follows:
  612. #
  613. # ceph_memory = mem_per_osd * num_osds
  614. # nova_memory = total_memory - ceph_memory
  615. # num_guests = nova_memory /
  616. # (average_guest_memory_size + overhead_per_guest)
  617. # reserved_memory = ceph_memory + (num_guests * overhead_per_guest)
  618. #
  619. # The cpu_allocation_ratio calculation is similar in that it takes into
  620. # account the number of cores that must be reserved for Ceph.
  621. #
  622. # ceph_cores = cores_per_osd * num_osds
  623. # guest_cores = num_cores - ceph_cores
  624. # guest_vcpus = guest_cores / average_guest_utilization
  625. # cpu_allocation_ratio = guest_vcpus / num_cores
  626. calculate_nova_parameters:
  627. publish:
  628. avg_guest_util: <% $.average_guest_cpu_utilization_percentage / 100.0 %>
  629. avg_guest_size_gb: <% $.average_guest_memory_size_in_mb / float($.MB_PER_GB) %>
  630. memory_gb: <% $.memory_mb / float($.MB_PER_GB) %>
  631. ceph_mem_gb: <% $.gb_per_osd * $.num_osds %>
  632. nonceph_cores: <% $.num_cores - int($.cores_per_osd * $.num_osds) %>
  633. on-success: calc_step_2
  634. calc_step_2:
  635. publish:
  636. num_guests: <% int(($.memory_gb - $.ceph_mem_gb) / ($.avg_guest_size_gb + $.gb_overhead_per_guest)) %>
  637. guest_vcpus: <% $.nonceph_cores / $.avg_guest_util %>
  638. on-success: calc_step_3
  639. calc_step_3:
  640. publish:
  641. reserved_host_memory: <% $.MB_PER_GB * int($.ceph_mem_gb + ($.num_guests * $.gb_overhead_per_guest)) %>
  642. cpu_allocation_ratio: <% $.guest_vcpus / $.num_cores %>
  643. on-success: validate_results
  644. validate_results:
  645. publish:
  646. # Verify whether HCI is viable:
  647. # - At least 80% of the memory is reserved for Ceph and guest overhead
  648. # - At least half of the CPU cores must be available to Nova
  649. mem_ok: <% $.reserved_host_memory <= ($.memory_mb * 0.8) %>
  650. cpu_ok: <% $.cpu_allocation_ratio >= 0.5 %>
  651. on-success:
  652. - set_failed_insufficient_mem: <% not $.mem_ok %>
  653. - set_failed_insufficient_cpu: <% not $.cpu_ok %>
  654. - publish_hci_parameters: <% $.mem_ok and $.cpu_ok %>
  655. publish_hci_parameters:
  656. publish:
  657. # TODO(abishop): Update this when the cpu_allocation_ratio can be set
  658. # via a THT parameter (no such parameter currently exists). Until a
  659. # THT parameter exists, use hiera data to set the cpu_allocation_ratio.
  660. hci_parameters: <% dict(concat($.role_name, 'Parameters') => dict('NovaReservedHostMemory' => $.reserved_host_memory)) + dict(concat($.role_name, 'ExtraConfig') => dict('nova::cpu_allocation_ratio' => $.cpu_allocation_ratio)) %>
  661. set_failed_invalid_hci_profile:
  662. publish:
  663. message: "'<% $.hci_profile %>' is not a valid HCI profile."
  664. on-success: fail
  665. set_failed_invalid_average_guest_memory_size_in_mb:
  666. publish:
  667. message: "'<% $.average_guest_memory_size_in_mb %>' is not a valid average_guest_memory_size_in_mb value."
  668. on-success: fail
  669. set_failed_invalid_gb_overhead_per_guest:
  670. publish:
  671. message: "'<% $.gb_overhead_per_guest %>' is not a valid gb_overhead_per_guest value."
  672. on-success: fail
  673. set_failed_invalid_gb_per_osd:
  674. publish:
  675. message: "'<% $.gb_per_osd %>' is not a valid gb_per_osd value."
  676. on-success: fail
  677. set_failed_invalid_cores_per_osd:
  678. publish:
  679. message: "'<% $.cores_per_osd %>' is not a valid cores_per_osd value."
  680. on-success: fail
  681. set_failed_invalid_average_guest_cpu_utilization_percentage:
  682. publish:
  683. message: "'<% $.average_guest_cpu_utilization_percentage %>' is not a valid average_guest_cpu_utilization_percentage value."
  684. on-success: fail
  685. set_failed_no_osds:
  686. publish:
  687. message: "No Ceph OSDs found in the overcloud definition ('ceph::profile::params::osds')."
  688. on-success: fail
  689. set_failed_get_memory_mb:
  690. publish:
  691. message: "Unable to determine the amount of physical memory (no 'memory_mb' found in introspection_data)."
  692. on-success: fail
  693. set_failed_get_nova_vcpu_count:
  694. publish:
  695. message: <% task(get_nova_vcpu_count).result %>
  696. on-success: fail
  697. set_failed_get_num_cores:
  698. publish:
  699. message: "Unable to determine the number of CPU cores (no 'cpus' found in introspection_data)."
  700. on-success: fail
  701. set_failed_insufficient_mem:
  702. publish:
  703. message: "<% $.memory_mb %> MB is not enough memory to run hyperconverged."
  704. on-success: fail
  705. set_failed_insufficient_cpu:
  706. publish:
  707. message: "<% $.num_cores %> CPU cores are not enough to run hyperconverged."
  708. on-success: fail