DPDK and Host derive parameters workflows
This change is specific to DPDK and Host derive parameters to apply the DPDK and Host specific formulas. this change also updates the derive parameters in the plan environment once derived. Implements: blueprint tripleo-derive-parameters Change-Id: I8c94f6d576ddd1c98729a70107f48871c40aba53
This commit is contained in:
parent
619239e907
commit
2537440a9b
@ -74,6 +74,10 @@ mistral.actions =
|
||||
tripleo.deployment.config = tripleo_common.actions.deployment:OrchestrationDeployAction
|
||||
tripleo.deployment.deploy = tripleo_common.actions.deployment:DeployStackAction
|
||||
tripleo.deployment.overcloudrc = tripleo_common.actions.deployment:OvercloudRcAction
|
||||
tripleo.derive_params.get_dpdk_nics_numa_info = tripleo_common.actions.derive_params:GetDpdkNicsNumaInfoAction
|
||||
tripleo.derive_params.get_dpdk_core_list = tripleo_common.actions.derive_params:GetDpdkCoreListAction
|
||||
tripleo.derive_params.get_dpdk_socket_memory = tripleo_common.actions.derive_params:GetDpdkSocketMemoryAction
|
||||
tripleo.derive_params.get_host_cpus_list = tripleo_common.actions.derive_params:GetHostCpusListAction
|
||||
tripleo.git.clean = tripleo_common.actions.vcs:GitCleanupAction
|
||||
tripleo.git.clone = tripleo_common.actions.vcs:GitCloneAction
|
||||
tripleo.heat_capabilities.get = tripleo_common.actions.heat_capabilities:GetCapabilitiesAction
|
||||
@ -82,6 +86,7 @@ mistral.actions =
|
||||
tripleo.package_update.update_stack = tripleo_common.actions.package_update:UpdateStackAction
|
||||
tripleo.parameters.get = tripleo_common.actions.parameters:GetParametersAction
|
||||
tripleo.parameters.get_flatten = tripleo_common.actions.parameters:GetFlattenedParametersAction
|
||||
tripleo.parameters.get_network_config = tripleo_common.actions.parameters:GetNetworkConfigAction
|
||||
tripleo.parameters.reset = tripleo_common.actions.parameters:ResetParametersAction
|
||||
tripleo.parameters.update = tripleo_common.actions.parameters:UpdateParametersAction
|
||||
tripleo.parameters.update_role = tripleo_common.actions.parameters:UpdateRoleParametersAction
|
||||
|
329
tripleo_common/actions/derive_params.py
Normal file
329
tripleo_common/actions/derive_params.py
Normal file
@ -0,0 +1,329 @@
|
||||
# Copyright 2017 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import re
|
||||
|
||||
from mistral_lib import actions
|
||||
|
||||
from tripleo_common.actions import base
|
||||
|
||||
|
||||
class GetDpdkNicsNumaInfoAction(base.TripleOAction):
|
||||
"""Gets the DPDK NICs with MTU for NUMA nodes.
|
||||
|
||||
Find the DPDK interface names from the network config and
|
||||
translate it to phsical interface names using the introspection
|
||||
data. And then find the NUMA node associated with the DPDK
|
||||
interface and the MTU value.
|
||||
|
||||
:param network_configs: network config list
|
||||
:param inspect_data: introspection data
|
||||
:param mtu_default: mtu default value for NICs
|
||||
|
||||
:return: DPDK NICs NUMA nodes info
|
||||
"""
|
||||
|
||||
def __init__(self, network_configs, inspect_data, mtu_default=1500):
|
||||
super(GetDpdkNicsNumaInfoAction, self).__init__()
|
||||
self.network_configs = network_configs
|
||||
self.inspect_data = inspect_data
|
||||
self.mtu_default = mtu_default
|
||||
|
||||
# TODO(jpalanis): Expose this utility from os-net-config to sort
|
||||
# active nics
|
||||
def _natural_sort_key(self, s):
|
||||
nsre = re.compile('([0-9]+)')
|
||||
return [int(text) if text.isdigit() else text
|
||||
for text in re.split(nsre, s)]
|
||||
|
||||
# TODO(jpalanis): Expose this utility from os-net-config to sort
|
||||
# active nics
|
||||
def _is_embedded_nic(self, nic):
|
||||
if (nic.startswith('em') or nic.startswith('eth') or
|
||||
nic.startswith('eno')):
|
||||
return True
|
||||
return False
|
||||
|
||||
# TODO(jpalanis): Expose this utility from os-net-config to sort
|
||||
# active nics
|
||||
def _ordered_nics(self, interfaces):
|
||||
embedded_nics = []
|
||||
nics = []
|
||||
for iface in interfaces:
|
||||
nic = iface.get('name', '')
|
||||
if self._is_embedded_nic(nic):
|
||||
embedded_nics.append(nic)
|
||||
else:
|
||||
nics.append(nic)
|
||||
active_nics = (sorted(
|
||||
embedded_nics, key=self._natural_sort_key) +
|
||||
sorted(nics, key=self._natural_sort_key))
|
||||
return active_nics
|
||||
|
||||
# Gets numa node id for physical NIC name
|
||||
def find_numa_node_id(self, numa_nics, nic_name):
|
||||
for nic_info in numa_nics:
|
||||
if nic_info.get('name', '') == nic_name:
|
||||
return nic_info.get('numa_node', None)
|
||||
return None
|
||||
|
||||
# Get physical interface name for NIC name
|
||||
def get_physical_iface_name(self, ordered_nics, nic_name):
|
||||
if nic_name.startswith('nic'):
|
||||
# Nic numbering, find the actual interface name
|
||||
nic_number = int(nic_name.replace('nic', ''))
|
||||
if nic_number > 0:
|
||||
iface_name = ordered_nics[nic_number - 1]
|
||||
return iface_name
|
||||
return nic_name
|
||||
|
||||
# Gets dpdk interfaces and mtu info for dpdk config
|
||||
# Default mtu(recommended 1500) is used if no MTU is set for DPDK NIC
|
||||
def get_dpdk_interfaces(self, dpdk_objs):
|
||||
mtu = self.mtu_default
|
||||
dpdk_ifaces = []
|
||||
for dpdk_obj in dpdk_objs:
|
||||
obj_type = dpdk_obj.get('type')
|
||||
mtu = dpdk_obj.get('mtu', self.mtu_default)
|
||||
if obj_type == 'ovs_dpdk_port':
|
||||
# Member interfaces of ovs_dpdk_port
|
||||
dpdk_ifaces.extend(dpdk_obj.get('members', []))
|
||||
elif obj_type == 'ovs_dpdk_bond':
|
||||
# ovs_dpdk_bond will have multiple ovs_dpdk_ports
|
||||
for bond_member in dpdk_obj.get('members', []):
|
||||
if bond_member.get('type') == 'ovs_dpdk_port':
|
||||
dpdk_ifaces.extend(bond_member.get('members', []))
|
||||
return (dpdk_ifaces, mtu)
|
||||
|
||||
def run(self, context):
|
||||
interfaces = self.inspect_data.get('inventory',
|
||||
{}).get('interfaces', [])
|
||||
# Checks whether inventory interfaces information is not available
|
||||
# in introspection data.
|
||||
if not interfaces:
|
||||
msg = 'Introspection data does not have inventory.interfaces'
|
||||
return actions.Result(error=msg)
|
||||
|
||||
numa_nics = self.inspect_data.get('numa_topology',
|
||||
{}).get('nics', [])
|
||||
# Checks whether numa topology nics information is not available
|
||||
# in introspection data.
|
||||
if not numa_nics:
|
||||
msg = 'Introspection data does not have numa_topology.nics'
|
||||
return actions.Result(error=msg)
|
||||
|
||||
active_interfaces = [iface for iface in interfaces
|
||||
if iface.get('has_carrier', False)]
|
||||
# Checks whether active interfaces are not available
|
||||
if not active_interfaces:
|
||||
msg = 'Unable to determine active interfaces (has_carrier)'
|
||||
return actions.Result(error=msg)
|
||||
|
||||
dpdk_nics_numa_info = []
|
||||
ordered_nics = self._ordered_nics(active_interfaces)
|
||||
# Gets DPDK network config and parses to get DPDK NICs
|
||||
# with mtu and numa node id
|
||||
for config in self.network_configs:
|
||||
if config.get('type', '') == 'ovs_user_bridge':
|
||||
members = config.get('members', [])
|
||||
dpdk_ifaces, mtu = self.get_dpdk_interfaces(members)
|
||||
for dpdk_iface in dpdk_ifaces:
|
||||
name = dpdk_iface.get('name', '')
|
||||
phy_name = self.get_physical_iface_name(
|
||||
ordered_nics, name)
|
||||
node = self.find_numa_node_id(numa_nics, phy_name)
|
||||
if not node:
|
||||
msg = ('Unable to determine NUMA node for '
|
||||
'DPDK NIC: %s' % phy_name)
|
||||
return actions.Result(error=msg)
|
||||
|
||||
dpdk_nic_info = {'name': phy_name,
|
||||
'numa_node': node,
|
||||
'mtu': mtu}
|
||||
dpdk_nics_numa_info.append(dpdk_nic_info)
|
||||
return dpdk_nics_numa_info
|
||||
|
||||
|
||||
class GetDpdkCoreListAction(base.TripleOAction):
|
||||
"""Gets the DPDK PMD Core List.
|
||||
|
||||
With input as the number of physical cores for each NUMA node,
|
||||
find the right logical CPUs to be allocated along with its
|
||||
siblings for the PMD core list.
|
||||
|
||||
:param inspect_data: introspection data
|
||||
:param numa_nodes_cores_count: physical cores count for each NUMA
|
||||
|
||||
:return: DPDK Core List
|
||||
"""
|
||||
|
||||
def __init__(self, inspect_data, numa_nodes_cores_count):
|
||||
super(GetDpdkCoreListAction, self).__init__()
|
||||
self.inspect_data = inspect_data
|
||||
self.numa_nodes_cores_count = numa_nodes_cores_count
|
||||
|
||||
def run(self, context):
|
||||
dpdk_core_list = []
|
||||
numa_cpus_info = self.inspect_data.get('numa_topology',
|
||||
{}).get('cpus', [])
|
||||
|
||||
# Checks whether numa topology cpus information is not available
|
||||
# in introspection data.
|
||||
if not numa_cpus_info:
|
||||
msg = 'Introspection data does not have numa_topology.cpus'
|
||||
return actions.Result(error=msg)
|
||||
|
||||
# Checks whether CPU physical cores count for each NUMA nodes is
|
||||
# not available
|
||||
if not self.numa_nodes_cores_count:
|
||||
msg = ('CPU physical cores count for each NUMA nodes '
|
||||
'is not available')
|
||||
return actions.Result(error=msg)
|
||||
|
||||
numa_nodes_threads = {}
|
||||
# Creates list for all available threads in each NUMA node
|
||||
for cpu in numa_cpus_info:
|
||||
if not cpu['numa_node'] in numa_nodes_threads:
|
||||
numa_nodes_threads[cpu['numa_node']] = []
|
||||
numa_nodes_threads[cpu['numa_node']].extend(cpu['thread_siblings'])
|
||||
|
||||
for node_cores_count in self.numa_nodes_cores_count:
|
||||
node = self.numa_nodes_cores_count.index(node_cores_count)
|
||||
# Gets least thread in NUMA node
|
||||
numa_node_min = min(numa_nodes_threads[node])
|
||||
cores_count = node_cores_count
|
||||
for cpu in numa_cpus_info:
|
||||
if cpu['numa_node'] == node:
|
||||
# Adds threads from core which is not having least thread
|
||||
if numa_node_min not in cpu['thread_siblings']:
|
||||
dpdk_core_list.extend(cpu['thread_siblings'])
|
||||
cores_count -= 1
|
||||
if cores_count == 0:
|
||||
break
|
||||
return ','.join([str(thread) for thread in dpdk_core_list])
|
||||
|
||||
|
||||
class GetHostCpusListAction(base.TripleOAction):
|
||||
"""Gets the Host CPUs List.
|
||||
|
||||
CPU threads from first physical core is allocated for host processes
|
||||
on each NUMA nodes.
|
||||
|
||||
:param inspect_data: introspection data
|
||||
|
||||
:return: Host CPUs List
|
||||
"""
|
||||
|
||||
def __init__(self, inspect_data):
|
||||
super(GetHostCpusListAction, self).__init__()
|
||||
self.inspect_data = inspect_data
|
||||
|
||||
def run(self, context):
|
||||
host_cpus_list = []
|
||||
numa_cpus_info = self.inspect_data.get('numa_topology',
|
||||
{}).get('cpus', [])
|
||||
|
||||
# Checks whether numa topology cpus information is not available
|
||||
# in introspection data.
|
||||
if not numa_cpus_info:
|
||||
msg = 'Introspection data does not have numa_topology.cpus'
|
||||
return actions.Result(error=msg)
|
||||
|
||||
numa_nodes_threads = {}
|
||||
# Creates a list for all available threads in each NUMA nodes
|
||||
for cpu in numa_cpus_info:
|
||||
if not cpu['numa_node'] in numa_nodes_threads:
|
||||
numa_nodes_threads[cpu['numa_node']] = []
|
||||
numa_nodes_threads[cpu['numa_node']].extend(
|
||||
cpu['thread_siblings'])
|
||||
|
||||
for numa_node in numa_nodes_threads.keys():
|
||||
node = int(numa_node)
|
||||
# Gets least thread in NUMA node
|
||||
numa_node_min = min(numa_nodes_threads[numa_node])
|
||||
for cpu in numa_cpus_info:
|
||||
if cpu['numa_node'] == node:
|
||||
# Adds threads from core which is having least thread
|
||||
if numa_node_min in cpu['thread_siblings']:
|
||||
host_cpus_list.extend(cpu['thread_siblings'])
|
||||
break
|
||||
|
||||
return ','.join([str(thread) for thread in host_cpus_list])
|
||||
|
||||
|
||||
class GetDpdkSocketMemoryAction(base.TripleOAction):
|
||||
"""Gets the DPDK Socket Memory List.
|
||||
|
||||
For NUMA node with DPDK nic, socket memory is calculated
|
||||
based on MTU, Overhead and Packet size in buffer.
|
||||
|
||||
For NUMA node without DPDK nic, minimum socket memory is
|
||||
assigned (recommended 1GB)
|
||||
|
||||
:param dpdk_nics_numa_info: DPDK nics numa info
|
||||
:param numa_nodes: list of numa nodes
|
||||
:param overhead: overhead value
|
||||
:param packet_size_in_buffer: packet size in buffer
|
||||
:param minimum_socket_memory: minimum socket memory
|
||||
|
||||
:return: DPDK Socket Memory List
|
||||
"""
|
||||
def __init__(self, dpdk_nics_numa_info, numa_nodes,
|
||||
overhead, packet_size_in_buffer,
|
||||
minimum_socket_memory=1024):
|
||||
super(GetDpdkSocketMemoryAction, self).__init__()
|
||||
self.dpdk_nics_numa_info = dpdk_nics_numa_info
|
||||
self.numa_nodes = numa_nodes
|
||||
self.overhead = overhead
|
||||
self.packet_size_in_buffer = packet_size_in_buffer
|
||||
self.minimum_socket_memory = minimum_socket_memory
|
||||
|
||||
# Calculates socket memory for a NUMA node
|
||||
def calculate_node_socket_memory(
|
||||
self, numa_node, dpdk_nics_numa_info, overhead,
|
||||
packet_size_in_buffer, minimum_socket_memory):
|
||||
distinct_mtu_per_node = []
|
||||
socket_memory = 0
|
||||
|
||||
# For DPDK numa node
|
||||
for nics_info in dpdk_nics_numa_info:
|
||||
if (numa_node == nics_info['numa_node'] and
|
||||
not nics_info['mtu'] in distinct_mtu_per_node):
|
||||
distinct_mtu_per_node.append(nics_info['mtu'])
|
||||
socket_memory += (((nics_info['mtu'] + overhead)
|
||||
* packet_size_in_buffer) /
|
||||
(1024 * 1024))
|
||||
|
||||
# For Non DPDK numa node
|
||||
if socket_memory == 0:
|
||||
socket_memory = minimum_socket_memory
|
||||
# For DPDK numa node
|
||||
else:
|
||||
socket_memory += 500
|
||||
|
||||
socket_memory_in_gb = int(socket_memory / 1024)
|
||||
if socket_memory % 1024 > 0:
|
||||
socket_memory_in_gb += 1
|
||||
return (socket_memory_in_gb * 1024)
|
||||
|
||||
def run(self, context):
|
||||
dpdk_socket_memory_list = []
|
||||
for node in self.numa_nodes:
|
||||
socket_mem = self.calculate_node_socket_memory(
|
||||
node, self.dpdk_nics_numa_info, self.overhead,
|
||||
self.packet_size_in_buffer,
|
||||
self.minimum_socket_memory)
|
||||
dpdk_socket_memory_list.append(socket_mem)
|
||||
|
||||
return ','.join([str(sm) for sm in dpdk_socket_memory_list])
|
@ -26,6 +26,7 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import json
|
||||
import logging
|
||||
import uuid
|
||||
|
||||
@ -101,9 +102,11 @@ class GetParametersAction(templates.ProcessTemplatesAction):
|
||||
class ResetParametersAction(base.TripleOAction):
|
||||
"""Provides method to delete user set parameters."""
|
||||
|
||||
def __init__(self, container=constants.DEFAULT_CONTAINER_NAME):
|
||||
def __init__(self, container=constants.DEFAULT_CONTAINER_NAME,
|
||||
key=constants.DEFAULT_PLAN_ENV_KEY):
|
||||
super(ResetParametersAction, self).__init__()
|
||||
self.container = container
|
||||
self.key = key
|
||||
|
||||
def run(self, context):
|
||||
swift = self.get_object_client(context)
|
||||
@ -117,7 +120,7 @@ class ResetParametersAction(base.TripleOAction):
|
||||
return actions.Result(error=err_msg)
|
||||
|
||||
try:
|
||||
plan_utils.update_in_env(swift, env, 'parameter_defaults',
|
||||
plan_utils.update_in_env(swift, env, self.key,
|
||||
delete_key=True)
|
||||
except swiftexceptions.ClientException as err:
|
||||
err_msg = ("Error updating environment for plan %s: %s" % (
|
||||
@ -135,10 +138,12 @@ class UpdateParametersAction(base.TripleOAction):
|
||||
"""Updates plan environment with parameters."""
|
||||
|
||||
def __init__(self, parameters,
|
||||
container=constants.DEFAULT_CONTAINER_NAME):
|
||||
container=constants.DEFAULT_CONTAINER_NAME,
|
||||
key=constants.DEFAULT_PLAN_ENV_KEY):
|
||||
super(UpdateParametersAction, self).__init__()
|
||||
self.container = container
|
||||
self.parameters = parameters
|
||||
self.key = key
|
||||
|
||||
def run(self, context):
|
||||
swift = self.get_object_client(context)
|
||||
@ -152,7 +157,7 @@ class UpdateParametersAction(base.TripleOAction):
|
||||
return actions.Result(error=err_msg)
|
||||
|
||||
try:
|
||||
plan_utils.update_in_env(swift, env, 'parameter_defaults',
|
||||
plan_utils.update_in_env(swift, env, self.key,
|
||||
self.parameters)
|
||||
except swiftexceptions.ClientException as err:
|
||||
err_msg = ("Error updating environment for plan %s: %s" % (
|
||||
@ -546,3 +551,65 @@ class RotateFernetKeysAction(GetPasswordsAction):
|
||||
for key_path in key_paths[1:keys_to_be_purged + 1]:
|
||||
del keys_map[key_path]
|
||||
return keys_map
|
||||
|
||||
|
||||
class GetNetworkConfigAction(templates.ProcessTemplatesAction):
|
||||
"""Gets network configuration details from available heat parameters."""
|
||||
|
||||
def __init__(self, role_name, container=constants.DEFAULT_CONTAINER_NAME):
|
||||
super(GetNetworkConfigAction, self).__init__(container=container)
|
||||
self.role_name = role_name
|
||||
|
||||
def run(self, context):
|
||||
|
||||
processed_data = super(GetNetworkConfigAction, self).run(context)
|
||||
|
||||
# If we receive a 'Result' instance it is because the parent action
|
||||
# had an error.
|
||||
if isinstance(processed_data, actions.Result):
|
||||
return processed_data
|
||||
|
||||
fields = {
|
||||
'template': processed_data['template'],
|
||||
'files': processed_data['files'],
|
||||
'environment': processed_data['environment'],
|
||||
'stack_name': self.container,
|
||||
}
|
||||
orc = self.get_orchestration_client(context)
|
||||
preview_data = orc.stacks.preview(**fields)
|
||||
result = self.get_network_config(preview_data, self.container,
|
||||
self.role_name)
|
||||
return result
|
||||
|
||||
def get_network_config(self, preview_data, stack_name, role_name):
|
||||
result = None
|
||||
if preview_data:
|
||||
for res in preview_data.resources:
|
||||
net_script = self.process_preview_list(res,
|
||||
stack_name,
|
||||
role_name)
|
||||
if net_script:
|
||||
ns_len = len(net_script)
|
||||
start_index = (net_script.find(
|
||||
"echo '{\"network_config\"", 0, ns_len) + 6)
|
||||
end_index = net_script.find("'", start_index, ns_len)
|
||||
if (end_index > start_index):
|
||||
net_config = net_script[start_index:end_index]
|
||||
if net_config:
|
||||
result = json.loads(net_config)
|
||||
break
|
||||
return result
|
||||
|
||||
def process_preview_list(self, res, stack_name, role_name):
|
||||
if type(res) == list:
|
||||
for item in res:
|
||||
out = self.process_preview_list(item, stack_name, role_name)
|
||||
if out:
|
||||
return out
|
||||
elif type(res) == dict:
|
||||
res_stack_name = stack_name + '-' + role_name
|
||||
if res['resource_name'] == "OsNetConfigImpl" and \
|
||||
res['resource_identity'] and \
|
||||
res_stack_name in res['resource_identity']['stack_name']:
|
||||
return res['properties']['config']
|
||||
return None
|
||||
|
@ -299,10 +299,17 @@ class ProcessTemplatesAction(base.TripleOAction):
|
||||
# merge generated passwords into params first
|
||||
passwords = plan_env.get('passwords', {})
|
||||
merged_params.update(passwords)
|
||||
|
||||
# derived parameters are merged before 'parameter defaults'
|
||||
# so that user-specified values can override the derived values.
|
||||
derived_params = plan_env.get('derived_parameters', {})
|
||||
merged_params.update(derived_params)
|
||||
|
||||
# handle user set parameter values next in case a user has set
|
||||
# a new value for a password parameter
|
||||
params = plan_env.get('parameter_defaults', {})
|
||||
merged_params.update(params)
|
||||
merged_params = template_utils.deep_update(merged_params, params)
|
||||
|
||||
if merged_params:
|
||||
env_temp_file = _create_temp_file(
|
||||
{'parameter_defaults': merged_params})
|
||||
|
@ -41,6 +41,9 @@ STACK_TIMEOUT_DEFAULT = 240
|
||||
#: The default name to use for a plan container
|
||||
DEFAULT_CONTAINER_NAME = 'overcloud'
|
||||
|
||||
#: The default key to use for updating parameters in plan environment.
|
||||
DEFAULT_PLAN_ENV_KEY = 'parameter_defaults'
|
||||
|
||||
#: The path to the tripleo heat templates installed on the undercloud
|
||||
DEFAULT_TEMPLATES_PATH = '/usr/share/openstack-tripleo-heat-templates/'
|
||||
|
||||
|
424
tripleo_common/tests/actions/test_derive_params.py
Normal file
424
tripleo_common/tests/actions/test_derive_params.py
Normal file
@ -0,0 +1,424 @@
|
||||
# Copyright 2017 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from mistral_lib import actions
|
||||
|
||||
from tripleo_common.actions import derive_params
|
||||
from tripleo_common.tests import base
|
||||
|
||||
|
||||
class GetDpdkNicsNumaInfoActionTest(base.TestCase):
|
||||
|
||||
def test_run_dpdk_port(self):
|
||||
network_configs = [{
|
||||
"members": [{
|
||||
"members": [{"name": "nic5", "type": "interface"}],
|
||||
"name": "dpdk0",
|
||||
"type": "ovs_dpdk_port",
|
||||
"mtu": 8192,
|
||||
"rx_queue": 4}],
|
||||
"name": "br-link",
|
||||
"type": "ovs_user_bridge"}]
|
||||
|
||||
inspect_data = {
|
||||
"numa_topology": {
|
||||
"nics": [{"name": "ens802f1", "numa_node": 1},
|
||||
{"name": "ens802f0", "numa_node": 1},
|
||||
{"name": "eno1", "numa_node": 0},
|
||||
{"name": "eno2", "numa_node": 0},
|
||||
{"name": "enp12s0f1", "numa_node": 0},
|
||||
{"name": "enp12s0f0", "numa_node": 0},
|
||||
{"name": "enp13s0f0", "numa_node": 0},
|
||||
{"name": "enp13s0f1", "numa_node": 0}]
|
||||
},
|
||||
"inventory": {
|
||||
"interfaces": [{"has_carrier": True,
|
||||
"name": "ens802f1"},
|
||||
{"has_carrier": True,
|
||||
"name": "ens802f0"},
|
||||
{"has_carrier": True,
|
||||
"name": "eno1"},
|
||||
{"has_carrier": True,
|
||||
"name": "eno2"},
|
||||
{"has_carrier": True,
|
||||
"name": "enp12s0f0"},
|
||||
{"has_carrier": False,
|
||||
"name": "enp13s0f0"},
|
||||
{"has_carrier": False,
|
||||
"name": "enp13s0f1"}]
|
||||
}
|
||||
}
|
||||
|
||||
expected_result = [{'name': 'ens802f1', 'mtu': 8192, 'numa_node': 1}]
|
||||
|
||||
mock_ctx = mock.MagicMock()
|
||||
action = derive_params.GetDpdkNicsNumaInfoAction(network_configs,
|
||||
inspect_data)
|
||||
result = action.run(mock_ctx)
|
||||
self.assertEqual(result, expected_result)
|
||||
|
||||
def test_run_dpdk_bond(self):
|
||||
network_configs = [{
|
||||
"members": [{"type": "ovs_dpdk_bond", "name": "dpdkbond0",
|
||||
"mtu": 9000, "rx_queue": 4,
|
||||
"members": [{"type": "ovs_dpdk_port",
|
||||
"name": "dpdk0",
|
||||
"members": [{"type": "interface",
|
||||
"name": "nic4"}]},
|
||||
{"type": "ovs_dpdk_port",
|
||||
"name": "dpdk1",
|
||||
"members": [{"type": "interface",
|
||||
"name": "nic5"}]}]}],
|
||||
"name": "br-link",
|
||||
"type": "ovs_user_bridge"}]
|
||||
inspect_data = {
|
||||
"numa_topology": {
|
||||
"nics": [{"name": "ens802f1", "numa_node": 1},
|
||||
{"name": "ens802f0", "numa_node": 1},
|
||||
{"name": "eno1", "numa_node": 0},
|
||||
{"name": "eno2", "numa_node": 0},
|
||||
{"name": "enp12s0f1", "numa_node": 0},
|
||||
{"name": "enp12s0f0", "numa_node": 0},
|
||||
{"name": "enp13s0f0", "numa_node": 0},
|
||||
{"name": "enp13s0f1", "numa_node": 0}]
|
||||
},
|
||||
"inventory": {
|
||||
"interfaces": [{"has_carrier": True,
|
||||
"name": "ens802f1"},
|
||||
{"has_carrier": True,
|
||||
"name": "ens802f0"},
|
||||
{"has_carrier": True,
|
||||
"name": "eno1"},
|
||||
{"has_carrier": True,
|
||||
"name": "eno2"},
|
||||
{"has_carrier": True,
|
||||
"name": "enp12s0f0"},
|
||||
{"has_carrier": False,
|
||||
"name": "enp13s0f0"},
|
||||
{"has_carrier": False,
|
||||
"name": "enp13s0f1"}]
|
||||
}
|
||||
}
|
||||
expected_result = [{'mtu': 9000, 'numa_node': 1, 'name': 'ens802f0'},
|
||||
{'mtu': 9000, 'numa_node': 1, 'name': 'ens802f1'}]
|
||||
|
||||
mock_ctx = mock.MagicMock()
|
||||
action = derive_params.GetDpdkNicsNumaInfoAction(network_configs,
|
||||
inspect_data)
|
||||
result = action.run(mock_ctx)
|
||||
self.assertEqual(result, expected_result)
|
||||
|
||||
@mock.patch.object(actions, 'Result', autospec=True)
|
||||
def test_run_no_inspect_nics(self, mock_actions):
|
||||
|
||||
network_configs = [{
|
||||
"members": [{
|
||||
"members": [{"name": "nic5", "type": "interface"}],
|
||||
"name": "dpdk0",
|
||||
"type": "ovs_dpdk_port",
|
||||
"mtu": 8192,
|
||||
"rx_queue": 4}],
|
||||
"name": "br-link",
|
||||
"type": "ovs_user_bridge"}]
|
||||
|
||||
inspect_data = {
|
||||
"numa_topology": {
|
||||
"nics": []
|
||||
},
|
||||
"inventory": {
|
||||
"interfaces": [{"has_carrier": True,
|
||||
"name": "ens802f1"},
|
||||
{"has_carrier": True,
|
||||
"name": "ens802f0"},
|
||||
{"has_carrier": True,
|
||||
"name": "eno1"},
|
||||
{"has_carrier": True,
|
||||
"name": "eno2"},
|
||||
{"has_carrier": True,
|
||||
"name": "enp12s0f0"},
|
||||
{"has_carrier": False,
|
||||
"name": "enp13s0f0"},
|
||||
{"has_carrier": False,
|
||||
"name": "enp13s0f1"}]
|
||||
}
|
||||
}
|
||||
|
||||
mock_ctx = mock.MagicMock()
|
||||
action = derive_params.GetDpdkNicsNumaInfoAction(network_configs,
|
||||
inspect_data)
|
||||
action.run(mock_ctx)
|
||||
msg = 'Introspection data does not have numa_topology.nics'
|
||||
mock_actions.assert_called_once_with(error=msg)
|
||||
|
||||
@mock.patch.object(actions, 'Result', autospec=True)
|
||||
def test_run_no_inspect_interfaces(self, mock_actions):
|
||||
|
||||
network_configs = [{
|
||||
"members": [{
|
||||
"members": [{"name": "nic5", "type": "interface"}],
|
||||
"name": "dpdk0",
|
||||
"type": "ovs_dpdk_port",
|
||||
"mtu": 8192,
|
||||
"rx_queue": 4}],
|
||||
"name": "br-link",
|
||||
"type": "ovs_user_bridge"}]
|
||||
|
||||
inspect_data = {
|
||||
"numa_topology": {
|
||||
"nics": []
|
||||
},
|
||||
"inventory": {
|
||||
"interfaces": []
|
||||
}
|
||||
}
|
||||
|
||||
mock_ctx = mock.MagicMock()
|
||||
action = derive_params.GetDpdkNicsNumaInfoAction(network_configs,
|
||||
inspect_data)
|
||||
action.run(mock_ctx)
|
||||
msg = 'Introspection data does not have inventory.interfaces'
|
||||
mock_actions.assert_called_once_with(error=msg)
|
||||
|
||||
@mock.patch.object(actions, 'Result', autospec=True)
|
||||
def test_run_no_inspect_active_interfaces(self, mock_actions):
|
||||
|
||||
network_configs = [{
|
||||
"members": [{
|
||||
"members": [{"name": "nic5", "type": "interface"}],
|
||||
"name": "dpdk0",
|
||||
"type": "ovs_dpdk_port",
|
||||
"mtu": 8192,
|
||||
"rx_queue": 4}],
|
||||
"name": "br-link",
|
||||
"type": "ovs_user_bridge"}]
|
||||
|
||||
inspect_data = {
|
||||
"numa_topology": {
|
||||
"nics": [{"name": "ens802f1", "numa_node": 1},
|
||||
{"name": "ens802f0", "numa_node": 1},
|
||||
{"name": "eno1", "numa_node": 0},
|
||||
{"name": "eno2", "numa_node": 0},
|
||||
{"name": "enp12s0f1", "numa_node": 0},
|
||||
{"name": "enp12s0f0", "numa_node": 0},
|
||||
{"name": "enp13s0f0", "numa_node": 0},
|
||||
{"name": "enp13s0f1", "numa_node": 0}]
|
||||
},
|
||||
"inventory": {
|
||||
"interfaces": [{"has_carrier": False,
|
||||
"name": "enp13s0f0"},
|
||||
{"has_carrier": False,
|
||||
"name": "enp13s0f1"}]
|
||||
}
|
||||
}
|
||||
|
||||
mock_ctx = mock.MagicMock()
|
||||
action = derive_params.GetDpdkNicsNumaInfoAction(network_configs,
|
||||
inspect_data)
|
||||
action.run(mock_ctx)
|
||||
msg = 'Unable to determine active interfaces (has_carrier)'
|
||||
mock_actions.assert_called_once_with(error=msg)
|
||||
|
||||
@mock.patch.object(actions, 'Result', autospec=True)
|
||||
def test_run_no_numa_node(self, mock_actions):
|
||||
network_configs = [{
|
||||
"members": [{
|
||||
"members": [{"name": "nic5", "type": "interface"}],
|
||||
"name": "dpdk0",
|
||||
"type": "ovs_dpdk_port",
|
||||
"mtu": 8192,
|
||||
"rx_queue": 4}],
|
||||
"name": "br-link",
|
||||
"type": "ovs_user_bridge"}]
|
||||
|
||||
inspect_data = {
|
||||
"numa_topology": {
|
||||
"nics": [{"name": "ens802f1"},
|
||||
{"name": "ens802f0", "numa_node": 1},
|
||||
{"name": "eno1", "numa_node": 0},
|
||||
{"name": "eno2", "numa_node": 0},
|
||||
{"name": "enp12s0f1", "numa_node": 0},
|
||||
{"name": "enp12s0f0", "numa_node": 0},
|
||||
{"name": "enp13s0f0", "numa_node": 0},
|
||||
{"name": "enp13s0f1", "numa_node": 0}]
|
||||
},
|
||||
"inventory": {
|
||||
"interfaces": [{"has_carrier": True,
|
||||
"name": "ens802f1"},
|
||||
{"has_carrier": True,
|
||||
"name": "ens802f0"},
|
||||
{"has_carrier": True,
|
||||
"name": "eno1"},
|
||||
{"has_carrier": True,
|
||||
"name": "eno2"},
|
||||
{"has_carrier": True,
|
||||
"name": "enp12s0f0"},
|
||||
{"has_carrier": False,
|
||||
"name": "enp13s0f0"},
|
||||
{"has_carrier": False,
|
||||
"name": "enp13s0f1"}]
|
||||
}
|
||||
}
|
||||
|
||||
mock_ctx = mock.MagicMock()
|
||||
action = derive_params.GetDpdkNicsNumaInfoAction(network_configs,
|
||||
inspect_data)
|
||||
action.run(mock_ctx)
|
||||
msg = 'Unable to determine NUMA node for DPDK NIC: ens802f1'
|
||||
mock_actions.assert_called_once_with(error=msg)
|
||||
|
||||
|
||||
class GetDpdkCoreListActionTest(base.TestCase):
|
||||
|
||||
def test_run(self):
|
||||
inspect_data = {
|
||||
"numa_topology": {
|
||||
"cpus": [{"cpu": 21, "numa_node": 1,
|
||||
"thread_siblings": [38, 82]},
|
||||
{"cpu": 27, "numa_node": 0,
|
||||
"thread_siblings": [20, 64]},
|
||||
{"cpu": 3, "numa_node": 1,
|
||||
"thread_siblings": [25, 69]},
|
||||
{"cpu": 20, "numa_node": 0,
|
||||
"thread_siblings": [15, 59]},
|
||||
{"cpu": 17, "numa_node": 1,
|
||||
"thread_siblings": [34, 78]},
|
||||
{"cpu": 16, "numa_node": 0,
|
||||
"thread_siblings": [11, 55]}]
|
||||
}
|
||||
}
|
||||
|
||||
numa_nodes_cores_count = [2, 1]
|
||||
|
||||
expected_result = "20,64,15,59,38,82"
|
||||
|
||||
mock_ctx = mock.MagicMock()
|
||||
action = derive_params.GetDpdkCoreListAction(inspect_data,
|
||||
numa_nodes_cores_count)
|
||||
result = action.run(mock_ctx)
|
||||
self.assertEqual(result, expected_result)
|
||||
|
||||
@mock.patch.object(actions, 'Result', autospec=True)
|
||||
def test_run_invalid_inspect_data(self, mock_actions):
|
||||
inspect_data = {"numa_topology": {"cpus": []}}
|
||||
|
||||
numa_nodes_cores_count = [2, 1]
|
||||
|
||||
mock_ctx = mock.MagicMock()
|
||||
action = derive_params.GetDpdkCoreListAction(inspect_data,
|
||||
numa_nodes_cores_count)
|
||||
action.run(mock_ctx)
|
||||
msg = 'Introspection data does not have numa_topology.cpus'
|
||||
mock_actions.assert_called_once_with(error=msg)
|
||||
|
||||
@mock.patch.object(actions, 'Result', autospec=True)
|
||||
def test_run_invalid_numa_nodes_cores_count(self, mock_actions):
|
||||
inspect_data = {"numa_topology": {
|
||||
"cpus": [{"cpu": 21, "numa_node": 1, "thread_siblings": [38, 82]},
|
||||
{"cpu": 27, "numa_node": 0, "thread_siblings": [20, 64]}]
|
||||
}}
|
||||
|
||||
numa_nodes_cores_count = []
|
||||
|
||||
mock_ctx = mock.MagicMock()
|
||||
action = derive_params.GetDpdkCoreListAction(inspect_data,
|
||||
numa_nodes_cores_count)
|
||||
action.run(mock_ctx)
|
||||
msg = 'CPU physical cores count for each NUMA nodes is not available'
|
||||
mock_actions.assert_called_once_with(error=msg)
|
||||
|
||||
|
||||
class GetHostCpusListActionTest(base.TestCase):
|
||||
|
||||
def test_run_valid_inspect_data(self):
|
||||
inspect_data = {
|
||||
"numa_topology": {
|
||||
"cpus": [{"cpu": 21, "numa_node": 1,
|
||||
"thread_siblings": [38, 82]},
|
||||
{"cpu": 27, "numa_node": 0,
|
||||
"thread_siblings": [20, 64]},
|
||||
{"cpu": 3, "numa_node": 1,
|
||||
"thread_siblings": [25, 69]},
|
||||
{"cpu": 20, "numa_node": 0,
|
||||
"thread_siblings": [15, 59]}]
|
||||
}
|
||||
}
|
||||
expected_result = "15,59,25,69"
|
||||
|
||||
mock_ctx = mock.MagicMock()
|
||||
action = derive_params.GetHostCpusListAction(inspect_data)
|
||||
result = action.run(mock_ctx)
|
||||
self.assertEqual(result, expected_result)
|
||||
|
||||
@mock.patch.object(actions, 'Result', autospec=True)
|
||||
def test_run_invalid_inspect_data(self, mock_actions):
|
||||
inspect_data = {"numa_topology": {"cpus": []}}
|
||||
|
||||
mock_ctx = mock.MagicMock()
|
||||
action = derive_params.GetHostCpusListAction(inspect_data)
|
||||
action.run(mock_ctx)
|
||||
msg = 'Introspection data does not have numa_topology.cpus'
|
||||
mock_actions.assert_called_once_with(error=msg)
|
||||
|
||||
|
||||
class GetDpdkSocketMemoryActionTest(base.TestCase):
|
||||
|
||||
def test_run_valid_dpdk_nics_numa_info(self):
|
||||
dpdk_nics_numa_info = [{"name": "ens802f1", "numa_node": 1,
|
||||
"mtu": 8192}]
|
||||
numa_nodes = [0, 1]
|
||||
overhead = 800
|
||||
packet_size_in_buffer = (4096 * 64)
|
||||
|
||||
expected_result = "1024,3072"
|
||||
mock_ctx = mock.MagicMock()
|
||||
action = derive_params.GetDpdkSocketMemoryAction(
|
||||
dpdk_nics_numa_info, numa_nodes, overhead,
|
||||
packet_size_in_buffer)
|
||||
result = action.run(mock_ctx)
|
||||
self.assertEqual(result, expected_result)
|
||||
|
||||
def test_run_multiple_mtu_in_same_numa_node(self):
|
||||
dpdk_nics_numa_info = [{"name": "ens802f1", "numa_node": 1,
|
||||
"mtu": 1500},
|
||||
{"name": "ens802f2", "numa_node": 1,
|
||||
"mtu": 2048}]
|
||||
numa_nodes = [0, 1]
|
||||
overhead = 800
|
||||
packet_size_in_buffer = (4096 * 64)
|
||||
|
||||
expected_result = "1024,2048"
|
||||
mock_ctx = mock.MagicMock()
|
||||
action = derive_params.GetDpdkSocketMemoryAction(
|
||||
dpdk_nics_numa_info, numa_nodes, overhead, packet_size_in_buffer)
|
||||
result = action.run(mock_ctx)
|
||||
self.assertEqual(result, expected_result)
|
||||
|
||||
def test_run_duplicate_mtu_in_same_numa_node(self):
|
||||
dpdk_nics_numa_info = [{"name": "ens802f1", "numa_node": 1,
|
||||
"mtu": 4096},
|
||||
{"name": "ens802f2", "numa_node": 1,
|
||||
"mtu": 4096}]
|
||||
numa_nodes = [0, 1]
|
||||
overhead = 800
|
||||
packet_size_in_buffer = (4096 * 64)
|
||||
|
||||
expected_result = "1024,2048"
|
||||
mock_ctx = mock.MagicMock()
|
||||
action = derive_params.GetDpdkSocketMemoryAction(
|
||||
dpdk_nics_numa_info, numa_nodes, overhead, packet_size_in_buffer)
|
||||
result = action.run(mock_ctx)
|
||||
self.assertEqual(result, expected_result)
|
@ -293,6 +293,48 @@ class UpdateParametersActionTest(base.TestCase):
|
||||
"tripleo.parameters.get"
|
||||
)
|
||||
|
||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||
'cache_delete')
|
||||
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||
def test_run_new_key(self, mock_get_object_client, mock_cache):
|
||||
|
||||
mock_ctx = mock.MagicMock()
|
||||
|
||||
swift = mock.MagicMock(url="http://test.com")
|
||||
mock_env = yaml.safe_dump({
|
||||
'name': constants.DEFAULT_CONTAINER_NAME,
|
||||
'temp_environment': 'temp_environment',
|
||||
'template': 'template',
|
||||
'environments': [{u'path': u'environments/test.yaml'}],
|
||||
}, default_flow_style=False)
|
||||
swift.get_object.return_value = ({}, mock_env)
|
||||
mock_get_object_client.return_value = swift
|
||||
|
||||
# Test
|
||||
test_parameters = {'SomeTestParameter': 42}
|
||||
action = parameters.UpdateParametersAction(test_parameters,
|
||||
key='test_key')
|
||||
action.run(mock_ctx)
|
||||
|
||||
mock_env_updated = yaml.safe_dump({
|
||||
'name': constants.DEFAULT_CONTAINER_NAME,
|
||||
'temp_environment': 'temp_environment',
|
||||
'test_key': {'SomeTestParameter': 42},
|
||||
'template': 'template',
|
||||
'environments': [{u'path': u'environments/test.yaml'}]
|
||||
}, default_flow_style=False)
|
||||
|
||||
swift.put_object.assert_called_once_with(
|
||||
constants.DEFAULT_CONTAINER_NAME,
|
||||
constants.PLAN_ENVIRONMENT,
|
||||
mock_env_updated
|
||||
)
|
||||
mock_cache.assert_called_once_with(
|
||||
mock_ctx,
|
||||
"overcloud",
|
||||
"tripleo.parameters.get"
|
||||
)
|
||||
|
||||
|
||||
class UpdateRoleParametersActionTest(base.TestCase):
|
||||
|
||||
@ -966,3 +1008,127 @@ class RotateFernetKeysActionTest(base.TestCase):
|
||||
max_keys = 3
|
||||
keys_map = action.purge_excess_keys(max_keys, keys_map)
|
||||
self.assertEqual(2, len(keys_map))
|
||||
|
||||
|
||||
class GetNetworkConfigActionTest(base.TestCase):
|
||||
|
||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||
'cache_set')
|
||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||
'cache_get')
|
||||
@mock.patch('heatclient.common.template_utils.'
|
||||
'process_multiple_environments_and_files')
|
||||
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||
'get_orchestration_client')
|
||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||
'get_workflow_client')
|
||||
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||
def test_run_valid_network_config(
|
||||
self, mock_get_object_client, mock_get_workflow_client,
|
||||
mock_get_orchestration_client, mock_get_template_contents,
|
||||
mock_process_multiple_environments_and_files,
|
||||
mock_cache_get,
|
||||
mock_cache_set):
|
||||
|
||||
mock_ctx = mock.MagicMock()
|
||||
swift = mock.MagicMock(url="http://test.com")
|
||||
mock_env = yaml.safe_dump({
|
||||
'temp_environment': 'temp_environment',
|
||||
'template': 'template',
|
||||
'environments': [{u'path': u'environments/test.yaml'}]
|
||||
}, default_flow_style=False)
|
||||
swift.get_object.side_effect = (
|
||||
({}, mock_env),
|
||||
swiftexceptions.ClientException('atest2'),
|
||||
({}, mock_env)
|
||||
)
|
||||
mock_get_object_client.return_value = swift
|
||||
|
||||
mock_get_template_contents.return_value = ({}, {
|
||||
'heat_template_version': '2016-04-30'
|
||||
})
|
||||
mock_process_multiple_environments_and_files.return_value = ({}, {})
|
||||
|
||||
mock_heat = mock.MagicMock()
|
||||
mock_heat.stacks.preview.return_value = mock.Mock(resources=[{
|
||||
"resource_identity": {"stack_name": "overcloud-Compute-0"},
|
||||
"resource_name": "OsNetConfigImpl",
|
||||
"properties": {"config": "echo \'{\"network_config\": {}}\'"}
|
||||
}])
|
||||
|
||||
mock_get_orchestration_client.return_value = mock_heat
|
||||
|
||||
mock_cache_get.return_value = None
|
||||
expected = {"network_config": {}}
|
||||
# Test
|
||||
action = parameters.GetNetworkConfigAction(container='overcloud',
|
||||
role_name='Compute')
|
||||
result = action.run(mock_ctx)
|
||||
self.assertEqual(expected, result)
|
||||
mock_heat.stacks.preview.assert_called_once_with(
|
||||
environment={},
|
||||
files={},
|
||||
template={'heat_template_version': '2016-04-30'},
|
||||
stack_name='overcloud',
|
||||
)
|
||||
|
||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||
'cache_set')
|
||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||
'cache_get')
|
||||
@mock.patch('heatclient.common.template_utils.'
|
||||
'process_multiple_environments_and_files')
|
||||
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||
'get_orchestration_client')
|
||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||
'get_workflow_client')
|
||||
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||
def test_run_invalid_network_config(
|
||||
self, mock_get_object_client,
|
||||
mock_get_workflow_client, mock_get_orchestration_client,
|
||||
mock_get_template_contents,
|
||||
mock_process_multiple_environments_and_files,
|
||||
mock_cache_get, mock_cache_set):
|
||||
|
||||
mock_ctx = mock.MagicMock()
|
||||
swift = mock.MagicMock(url="http://test.com")
|
||||
mock_env = yaml.safe_dump({
|
||||
'temp_environment': 'temp_environment',
|
||||
'template': 'template',
|
||||
'environments': [{u'path': u'environments/test.yaml'}]
|
||||
}, default_flow_style=False)
|
||||
swift.get_object.side_effect = (
|
||||
({}, mock_env),
|
||||
swiftexceptions.ClientException('atest2'),
|
||||
({}, mock_env)
|
||||
)
|
||||
mock_get_object_client.return_value = swift
|
||||
|
||||
mock_get_template_contents.return_value = ({}, {
|
||||
'heat_template_version': '2016-04-30'
|
||||
})
|
||||
mock_process_multiple_environments_and_files.return_value = ({}, {})
|
||||
|
||||
mock_heat = mock.MagicMock()
|
||||
mock_heat.stacks.preview.return_value = mock.Mock(resources=[{
|
||||
"resource_identity": {"stack_name": "overcloud-Compute-0"},
|
||||
"resource_name": "OsNetConfigImpl",
|
||||
"properties": {"config": ""}
|
||||
}])
|
||||
|
||||
mock_get_orchestration_client.return_value = mock_heat
|
||||
|
||||
mock_cache_get.return_value = None
|
||||
# Test
|
||||
action = parameters.GetNetworkConfigAction(container='overcloud',
|
||||
role_name='Compute')
|
||||
result = action.run(mock_ctx)
|
||||
self.assertIsNone(result)
|
||||
mock_heat.stacks.preview.assert_called_once_with(
|
||||
environment={},
|
||||
files={},
|
||||
template={'heat_template_version': '2016-04-30'},
|
||||
stack_name='overcloud',
|
||||
)
|
||||
|
@ -47,13 +47,35 @@ workflows:
|
||||
concurrency: 1
|
||||
workflow: _derive_parameters_per_role
|
||||
input:
|
||||
plan: <% $.plan %>
|
||||
role_name: <% $.role_name %>
|
||||
environment_parameters: <% $.environment_parameters %>
|
||||
heat_resource_tree: <% $.heat_resource_tree %>
|
||||
user_inputs: <% $.user_inputs %>
|
||||
on-success: send_message
|
||||
publish:
|
||||
# Gets all the roles derived parameters as dictionary
|
||||
result: <% task().result.select($.get('derived_parameters', {})).sum() %>
|
||||
on-success: reset_derive_parameters_in_plan
|
||||
on-error: set_status_failed_for_each_role
|
||||
|
||||
reset_derive_parameters_in_plan:
|
||||
action: tripleo.parameters.reset
|
||||
input:
|
||||
container: <% $.plan %>
|
||||
key: 'derived_parameters'
|
||||
on-success:
|
||||
- update_derive_parameters_in_plan: <% $.result %>
|
||||
on-error: set_status_failed_reset_derive_parameters_in_plan
|
||||
|
||||
update_derive_parameters_in_plan:
|
||||
action: tripleo.parameters.update
|
||||
input:
|
||||
container: <% $.plan %>
|
||||
key: 'derived_parameters'
|
||||
parameters: <% $.get('result', {}) %>
|
||||
on-success: send_message
|
||||
on-error: set_status_failed_update_derive_parameters_in_plan
|
||||
|
||||
set_status_failed_get_flattened_parameters:
|
||||
on-success: send_message
|
||||
publish:
|
||||
@ -84,6 +106,18 @@ workflows:
|
||||
status: FAILED
|
||||
message: <% task(for_each_role).result.select(dict('role_name' => $.role_name, 'status' => $.get('status', 'SUCCESS'), 'message' => $.get('message', ''))) %>
|
||||
|
||||
set_status_failed_reset_derive_parameters_in_plan:
|
||||
on-success: send_message
|
||||
publish:
|
||||
status: FAILED
|
||||
message: <% task(reset_derive_parameters_in_plan).result %>
|
||||
|
||||
set_status_failed_update_derive_parameters_in_plan:
|
||||
on-success: send_message
|
||||
publish:
|
||||
status: FAILED
|
||||
message: <% task(update_derive_parameters_in_plan).result %>
|
||||
|
||||
send_message:
|
||||
action: zaqar.queue_post
|
||||
retry: count=5 delay=1
|
||||
@ -95,6 +129,7 @@ workflows:
|
||||
payload:
|
||||
status: <% $.get('status', 'SUCCESS') %>
|
||||
message: <% $.get('message', '') %>
|
||||
result: <% $.get('result', '') %>
|
||||
execution: <% execution() %>
|
||||
on-success:
|
||||
- fail: <% $.get('status') = 'FAILED' %>
|
||||
@ -105,11 +140,17 @@ workflows:
|
||||
Workflow which runs per role to get the introspection data on the first matching node assigned to role.
|
||||
Once introspection data is fetched, this worklow will trigger the actual derive parameters workflow
|
||||
input:
|
||||
- plan
|
||||
- role_name
|
||||
- environment_parameters
|
||||
- heat_resource_tree
|
||||
- user_inputs
|
||||
|
||||
output:
|
||||
derived_parameters: <% $.get('derived_parameters', {}) %>
|
||||
# Need role_name in output parameter to display the status for all roles in main workflow when any role fails here.
|
||||
role_name: <% $.role_name %>
|
||||
|
||||
tasks:
|
||||
get_role_info:
|
||||
workflow: _get_role_info
|
||||
@ -155,11 +196,37 @@ workflows:
|
||||
on-error: set_status_failed_on_error_get_profile_node
|
||||
|
||||
get_introspection_data:
|
||||
on-error: set_status_failed_get_introspection_data
|
||||
action: baremetal_introspection.get_data uuid=<% $.profile_node_uuid %>
|
||||
publish:
|
||||
introspection_data: <% task().result %>
|
||||
# TODO-Follow up patches workflows will actually be used here to derive parameters for each role
|
||||
hw_data: <% task().result %>
|
||||
on-success:
|
||||
- get_dpdk_derive_params: <% $.role_features.contains("DPDK") %>
|
||||
# TODO: Needs to include condition to call other service derive params if DPDK is not available.
|
||||
on-error: set_status_failed_get_introspection_data
|
||||
|
||||
get_dpdk_derive_params:
|
||||
workflow: tripleo.derive_params_formulas.v1.dpdk_derive_params
|
||||
input:
|
||||
plan: <% $.plan %>
|
||||
role_name: <% $.role_name %>
|
||||
hw_data: <% $.hw_data %>
|
||||
user_inputs: <% $.user_inputs %>
|
||||
publish:
|
||||
derived_parameters: <% task().result.get('derived_parameters', {}) %>
|
||||
on-success: get_host_derive_params
|
||||
on-error: set_status_failed_get_dpdk_derive_params
|
||||
|
||||
get_host_derive_params:
|
||||
workflow: tripleo.derive_params_formulas.v1.host_derive_params
|
||||
input:
|
||||
role_name: <% $.role_name %>
|
||||
hw_data: <% $.hw_data %>
|
||||
user_inputs: <% $.user_inputs %>
|
||||
derived_parameters: <% $.derived_parameters %>
|
||||
publish:
|
||||
derived_parameters: <% task().result.get('derived_parameters', {}) %>
|
||||
on-error: set_status_failed_get_host_derive_params
|
||||
# Workflow ends here because there are no more algorithms.
|
||||
|
||||
set_status_failed_get_role_info:
|
||||
publish:
|
||||
@ -203,6 +270,21 @@ workflows:
|
||||
message: <% task(get_introspection_data).result %>
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_get_dpdk_derive_params:
|
||||
publish:
|
||||
role_name: <% $.role_name %>
|
||||
status: FAILED
|
||||
message: <% task(get_dpdk_derive_params).result %>
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_get_host_derive_params:
|
||||
publish:
|
||||
role_name: <% $.role_name %>
|
||||
status: FAILED
|
||||
message: <% task(get_host_derive_params).result %>
|
||||
on-success: fail
|
||||
|
||||
|
||||
_get_role_info:
|
||||
description: >
|
||||
Workflow that determines the list of derived parameter features (DPDK,
|
||||
@ -244,8 +326,9 @@ workflows:
|
||||
check_features:
|
||||
on-success: build_feature_dict
|
||||
publish:
|
||||
# The role supports the DPDK feature if the NeutronDpdkCoreList parameter is present.
|
||||
dpdk: <% $.role_services.any($.get('parameters', []).contains('NeutronDpdkCoreList')) %>
|
||||
# TODO: Need to update this logic for ODL integration.
|
||||
# The role supports the DPDK feature if the NeutronDatapathType parameter is present.
|
||||
dpdk: <% $.role_services.any($.get('parameters', []).contains('NeutronDatapathType')) %>
|
||||
|
||||
# The role supports the HCI feature if it includes both NovaCompute and CephOSD services.
|
||||
hci: <% $.role_services.any($.get('type', '').endsWith('::NovaCompute')) and $.role_services.any($.get('type', '').endsWith('::CephOSD')) %>
|
||||
|
342
workbooks/derive_params_formulas.yaml
Normal file
342
workbooks/derive_params_formulas.yaml
Normal file
@ -0,0 +1,342 @@
|
||||
---
|
||||
version: '2.0'
|
||||
name: tripleo.derive_params_formulas.v1
|
||||
description: TripleO Workflows to derive deployment parameters from the introspected data
|
||||
|
||||
workflows:
|
||||
|
||||
|
||||
dpdk_derive_params:
|
||||
description: >
|
||||
Workflow to derive parameters for DPDK service.
|
||||
input:
|
||||
- plan
|
||||
- role_name
|
||||
- hw_data # introspection data
|
||||
- user_inputs
|
||||
- derived_parameters: {}
|
||||
|
||||
output:
|
||||
derived_parameters: <% $.derived_parameters.mergeWith($.get('dpdk_parameters', {})) %>
|
||||
|
||||
tasks:
|
||||
get_network_config:
|
||||
action: tripleo.parameters.get_network_config
|
||||
input:
|
||||
container: <% $.plan %>
|
||||
role_name: <% $.role_name %>
|
||||
publish:
|
||||
network_configs: <% task().result.get('network_config', []) %>
|
||||
on-success: get_dpdk_nics_numa_info
|
||||
on-error: set_status_failed_get_network_config
|
||||
|
||||
get_dpdk_nics_numa_info:
|
||||
action: tripleo.derive_params.get_dpdk_nics_numa_info
|
||||
input:
|
||||
network_configs: <% $.network_configs %>
|
||||
inspect_data: <% $.hw_data %>
|
||||
publish:
|
||||
dpdk_nics_numa_info: <% task().result %>
|
||||
on-success:
|
||||
# TODO: Need to remove condtions here
|
||||
# adding condition and trhow error in action for empty check
|
||||
- get_dpdk_nics_numa_nodes: <% $.dpdk_nics_numa_info %>
|
||||
- set_status_failed_get_dpdk_nics_numa_info: <% not $.dpdk_nics_numa_info %>
|
||||
on-error: set_status_failed_on_error_get_dpdk_nics_numa_info
|
||||
|
||||
get_dpdk_nics_numa_nodes:
|
||||
publish:
|
||||
dpdk_nics_numa_nodes: <% $.dpdk_nics_numa_info.groupBy($.numa_node).select($[0]).orderBy($) %>
|
||||
on-success:
|
||||
- get_numa_nodes: <% $.dpdk_nics_numa_nodes %>
|
||||
- set_status_failed_get_dpdk_nics_numa_nodes: <% not $.dpdk_nics_numa_nodes %>
|
||||
|
||||
get_numa_nodes:
|
||||
publish:
|
||||
numa_nodes: <% $.hw_data.numa_topology.ram.select($.numa_node).orderBy($) %>
|
||||
on-success:
|
||||
- get_num_cores_per_numa_nodes: <% $.numa_nodes %>
|
||||
- set_status_failed_get_numa_nodes: <% not $.numa_nodes %>
|
||||
|
||||
# For NUMA node with DPDK nic, number of cores should be used from user input (defaults to 2)
|
||||
# For NUMA node without DPDK nic, number of cores should be 1
|
||||
get_num_cores_per_numa_nodes:
|
||||
publish:
|
||||
num_cores_per_numa_nodes: <% let(dpdk_nics_nodes => $.dpdk_nics_numa_nodes, cores => $.user_inputs.get('num_phy_cores_per_numa_node_for_pmd', 2)) -> $.numa_nodes.select(switch($ in $dpdk_nics_nodes => $cores, not $ in $dpdk_nics_nodes => 1)) %>
|
||||
on-success: get_pmd_cpus
|
||||
|
||||
get_pmd_cpus:
|
||||
action: tripleo.derive_params.get_dpdk_core_list
|
||||
input:
|
||||
inspect_data: <% $.hw_data %>
|
||||
numa_nodes_cores_count: <% $.num_cores_per_numa_nodes %>
|
||||
publish:
|
||||
pmd_cpus: <% task().result %>
|
||||
on-success:
|
||||
- get_host_cpus: <% $.pmd_cpus %>
|
||||
- set_status_failed_get_pmd_cpus: <% not $.pmd_cpus %>
|
||||
on-error: set_status_failed_on_error_get_pmd_cpus
|
||||
|
||||
get_host_cpus:
|
||||
action: tripleo.derive_params.get_host_cpus_list inspect_data=<% $.hw_data %>
|
||||
publish:
|
||||
host_cpus: <% task().result %>
|
||||
on-success:
|
||||
- get_sock_mem: <% $.host_cpus %>
|
||||
- set_status_failed_get_host_cpus: <% not $.host_cpus %>
|
||||
on-error: set_status_failed_on_error_get_host_cpus
|
||||
|
||||
get_sock_mem:
|
||||
action: tripleo.derive_params.get_dpdk_socket_memory
|
||||
input:
|
||||
dpdk_nics_numa_info: <% $.dpdk_nics_numa_info %>
|
||||
numa_nodes: <% $.numa_nodes %>
|
||||
overhead: <% $.user_inputs.get('overhead', 800) %>
|
||||
packet_size_in_buffer: <% 4096*64 %>
|
||||
publish:
|
||||
sock_mem: <% task().result %>
|
||||
on-success:
|
||||
- get_memory_slot_info: <% $.sock_mem %>
|
||||
- set_status_failed_get_sock_mem: <% not $.sock_mem %>
|
||||
on-error: set_status_failed_on_error_get_sock_mem
|
||||
|
||||
get_memory_slot_info:
|
||||
publish:
|
||||
memory_slot_info: <% $.hw_data.extra.memory.values().select($.get("slot")).where($) %>
|
||||
on-success:
|
||||
- remove_slots_prefix_string: <% $.memory_slot_info %>
|
||||
- set_status_failed_get_memory_slot_info: <% not $.memory_slot_info %>
|
||||
|
||||
# Memory channels are identified by the number of memory slots to the NUMA node
|
||||
# Memory slots will be off different formats in the introspection data, like P1-DIMMA1, DIMM_A1, etc
|
||||
# This task removes the prefix string format like 'P1-DIMM' or 'DIMM_' and provides the list with only slot names like 'A1'
|
||||
remove_slots_prefix_string:
|
||||
publish:
|
||||
updated_mem_slot_info: <% $.memory_slot_info.select($.replaceBy(regex("[A-Z0-9]*[-_]*DIMM{1}[-_]*"), '')) %>
|
||||
on-success: remove_slots_suffix_number
|
||||
|
||||
# In the above list of slot names, this task removes the suffix number like '1' in 'A1' and provide the list with slot name as 'A'
|
||||
remove_slots_suffix_number:
|
||||
publish:
|
||||
updated_mem_slot_info: <% $.updated_mem_slot_info.select($.replaceBy(regex("[0-9]"), '')) %>
|
||||
on-success: get_memory_channels_per_node
|
||||
|
||||
# The total memory slot names list will have both NUMA nodes slot.
|
||||
# Average out the length of slot name list with number of NUMA nodes to get the final value
|
||||
get_memory_channels_per_node:
|
||||
publish:
|
||||
mem_channel: <% $.updated_mem_slot_info.distinct().len() / $.numa_nodes.len() %>
|
||||
on-success:
|
||||
- get_dpdk_parameters: <% $.mem_channel %>
|
||||
- set_status_failed_get_memory_channels_per_node: <% not $.mem_channel %>
|
||||
|
||||
get_dpdk_parameters:
|
||||
publish:
|
||||
dpdk_parameters: <% dict(concat($.role_name, 'Parameters') => dict('OvsPmdCoreList' => $.get('pmd_cpus', ''), 'OvsDpdkCoreList' => $.get('host_cpus', ''), 'OvsDpdkSocketMemory' => $.get('sock_mem', ''), 'OvsDpdkMemoryChannels' => $.get('mem_channel', ''))) %>
|
||||
|
||||
set_status_failed_get_network_config:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: <% task(get_network_config).result %>
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_get_dpdk_nics_numa_info:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: "Unable to determine DPDK NIC's NUMA information"
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_on_error_get_dpdk_nics_numa_info:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: <% task(get_dpdk_nics_numa_info).result %>
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_get_dpdk_nics_numa_nodes:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: "Unable to determine DPDK NIC's numa nodes"
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_get_numa_nodes:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: 'Unable to determine available NUMA nodes'
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_get_pmd_cpus:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: 'Unable to determine OvsPmdCoreList parameter'
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_on_error_get_pmd_cpus:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: <% task(get_pmd_cpus).result %>
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_get_host_cpus:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: 'Unable to determine OvsDpdkCoreList parameter'
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_on_error_get_host_cpus:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: <% task(get_host_cpus).result %>
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_get_sock_mem:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: 'Unable to determine OvsDpdkSocketMemory parameter'
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_on_error_get_sock_mem:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: <% task(get_sock_mem).result %>
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_get_memory_slot_info:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: 'Unable to determine memory slot name on NUMA nodes'
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_get_memory_channels_per_node:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: 'Unable to determine OvsDpdkMemoryChannels parameter'
|
||||
on-success: fail
|
||||
|
||||
|
||||
host_derive_params:
|
||||
description: >
|
||||
This workflow derives parameters for the Host process, and is mainly associated with CPU pinning and huge memory pages.
|
||||
This workflow can be dependent on any feature or also can be invoked individually as well.
|
||||
|
||||
input:
|
||||
- role_name
|
||||
- hw_data # introspection data
|
||||
- user_inputs
|
||||
- derived_parameters: {}
|
||||
|
||||
output:
|
||||
derived_parameters: <% $.derived_parameters.mergeWith($.get('host_parameters', {})) %>
|
||||
|
||||
tasks:
|
||||
|
||||
get_cpus:
|
||||
publish:
|
||||
cpus: <% $.hw_data.numa_topology.cpus %>
|
||||
on-success:
|
||||
- get_role_derive_params: <% $.cpus %>
|
||||
- set_status_failed_get_cpus: <% not $.cpus %>
|
||||
|
||||
get_role_derive_params:
|
||||
publish:
|
||||
role_derive_params: <% $.derived_parameters.get(concat($.role_name, 'Parameters'), {}) %>
|
||||
on-success: get_host_dpdk_combined_cpus
|
||||
|
||||
get_host_dpdk_combined_cpus:
|
||||
publish:
|
||||
host_dpdk_combined_cpus: <% let(params => $.role_derive_params) -> concat($params.get('OvsPmdCoreList', ''), ',', $params.get('OvsDpdkCoreList', '')).split(",").select(int($)) %>
|
||||
on-success:
|
||||
- get_nova_cpus: <% $.host_dpdk_combined_cpus %>
|
||||
- set_status_failed_get_host_dpdk_combined_cpus: <% not $.host_dpdk_combined_cpus %>
|
||||
|
||||
get_nova_cpus:
|
||||
publish:
|
||||
nova_cpus: <% let(invalid_threads => $.host_dpdk_combined_cpus) -> $.cpus.select($.thread_siblings).flatten().where(not $ in $invalid_threads).join(',') %>
|
||||
on-success:
|
||||
- get_isol_cpus: <% $.nova_cpus %>
|
||||
- set_status_failed_get_nova_cpus: <% not $.nova_cpus %>
|
||||
|
||||
get_isol_cpus:
|
||||
publish:
|
||||
isol_cpus: <% let(params => $.role_derive_params) -> concat($params.get('OvsPmdCoreList',''), ',', $.nova_cpus) %>
|
||||
on-success: get_host_mem
|
||||
|
||||
get_host_mem:
|
||||
publish:
|
||||
host_mem: <% $.user_inputs.get('host_mem_default', 4096) %>
|
||||
on-success: check_default_hugepage_supported
|
||||
|
||||
check_default_hugepage_supported:
|
||||
publish:
|
||||
default_hugepage_supported: <% $.hw_data.get('inventory', {}).get('cpu', {}).get('flags', []).contains('cpu_hugepages_1g') %>
|
||||
on-success:
|
||||
- get_total_memory: <% $.default_hugepage_supported %>
|
||||
- set_status_failed_check_default_hugepage_supported: <% not $.default_hugepage_supported %>
|
||||
|
||||
get_total_memory:
|
||||
publish:
|
||||
total_memory: <% $.hw_data.get('inventory', {}).get('memory', {}).get('physical_mb', 0) %>
|
||||
on-success:
|
||||
- get_hugepages: <% $.total_memory %>
|
||||
- set_status_failed_get_total_memory: <% not $.total_memory %>
|
||||
|
||||
get_hugepages:
|
||||
publish:
|
||||
hugepages: <% let(huge_page_perc => float($.user_inputs.get('huge_page_allocation_percentage', 90))/100)-> int((($.total_memory/1024)-4) * $huge_page_perc) %>
|
||||
on-success:
|
||||
- get_cpu_model: <% $.hugepages %>
|
||||
- set_status_failed_get_hugepages: <% not $.hugepages %>
|
||||
|
||||
get_cpu_model:
|
||||
publish:
|
||||
intel_cpu_model: <% $.hw_data.get('inventory', {}).get('cpu', {}).get('model_name', '').startsWith('Intel') %>
|
||||
on-success: get_iommu_info
|
||||
|
||||
get_iommu_info:
|
||||
publish:
|
||||
iommu_info: <% switch($.intel_cpu_model => 'intel_iommu=on iommu=pt', not $.intel_cpu_model => '') %>
|
||||
on-success: get_kernel_args
|
||||
|
||||
get_kernel_args:
|
||||
publish:
|
||||
kernel_args: <% concat('default_hugepagesz=1GB hugepagesz=1G ', 'hugepages=', str($.hugepages), ' ', $.iommu_info, ' isolcpus=', $.isol_cpus) %>
|
||||
on-success: get_host_parameters
|
||||
|
||||
get_host_parameters:
|
||||
publish:
|
||||
host_parameters: <% dict(concat($.role_name, 'Parameters') => dict('NovaVcpuPinSet' => $.get('nova_cpus', ''), 'NovaReservedHostMemory' => $.get('host_mem', ''), 'KernelArgs' => $.get('kernel_args', ''), 'IsolCpusList' => $.get('isol_cpus', ''))) %>
|
||||
|
||||
set_status_failed_get_cpus:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: "Unable to determine CPU's on NUMA nodes"
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_get_host_dpdk_combined_cpus:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: 'Unable to combine host and dpdk cpus list'
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_get_nova_cpus:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: 'Unable to determine nova vcpu pin set'
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_check_default_hugepage_supported:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: 'default huge page size 1GB is not supported'
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_get_total_memory:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: 'Unable to determine total memory'
|
||||
on-success: fail
|
||||
|
||||
set_status_failed_get_hugepages:
|
||||
publish:
|
||||
status: FAILED
|
||||
message: 'Unable to determine huge pages'
|
||||
on-success: fail
|
Loading…
x
Reference in New Issue
Block a user