7f6a4b4385
When using `ManageNetworks: false` the gateway IPs are empty string instead of `null` when not set. The YAQL expression filters `null` values, but the empty string value is included in the list. The ping gateway test end up trying to run "ping $args $empty_string" which fails. This change improves the yaql expression to also filter strings with 0 lenght. Closes-Bug: #1973866 Change-Id: I7d8712223d077ab8e25239b891bd03a1324e01a8
1425 lines
56 KiB
YAML
1425 lines
56 KiB
YAML
{%- set primary_role_name = roles[0].name -%}
|
|
{%- for role in roles if ('primary' in role.tags and 'controller' in role.tags) -%}
|
|
{%- if loop.first -%}
|
|
{%- set primary_role_name = role.name -%}
|
|
{%- endif -%}
|
|
{%- endfor -%}
|
|
# primary role is: {{primary_role_name}}
|
|
heat_template_version: wallaby
|
|
|
|
description: >
|
|
Deploy an OpenStack environment, consisting of several node types (roles),
|
|
Controller, Compute, BlockStorage, SwiftStorage and CephStorage. The Storage
|
|
roles enable independent scaling of the storage components, but the minimal
|
|
deployment is one Controller and one Compute node.
|
|
|
|
|
|
# TODO(shadower): we should probably use the parameter groups to put
|
|
# some order in here.
|
|
parameters:
|
|
ExtraAnsibleHostVars:
|
|
default: {}
|
|
description: Mapping of Ansible host variable overrides.
|
|
type: json
|
|
|
|
# Common parameters (not specific to
|
|
{%- for network in networks if network.vip|default(false) and network.enabled|default(true) %}
|
|
{%- if network.name == 'External' %}
|
|
# Special case the External hostname param, which is CloudName
|
|
CloudName:
|
|
default: overcloud.localdomain
|
|
description: The DNS name of this cloud. E.g. ci-overcloud.tripleo.org
|
|
type: string
|
|
# TODO (dsneddon) Legacy name, eventually refactor to match network name
|
|
PublicVirtualFixedIPs:
|
|
default: []
|
|
description: >
|
|
Control the IP allocation for the PublicVirtualInterface port. E.g.
|
|
[{'ip_address':'1.2.3.4'}]
|
|
type: json
|
|
{%- elif network.name == 'InternalApi' %}
|
|
# Special case the Internal API hostname param, which is CloudNameInternal
|
|
CloudNameInternal:
|
|
default: overcloud.{{network.name.lower()}}.localdomain
|
|
description: >
|
|
The DNS name of this cloud's {{network.name_lower}} endpoint. E.g.
|
|
'ci-overcloud.{{network.name.lower()}}.tripleo.org'.
|
|
type: string
|
|
{%- elif network.name == 'StorageMgmt' %}
|
|
# Special case StorageMgmt hostname param, which is CloudNameStorageManagement
|
|
CloudNameStorageManagement:
|
|
default: overcloud.{{network.name.lower()}}.localdomain
|
|
description: >
|
|
The DNS name of this cloud's {{network.name_lower}} endpoint. E.g.
|
|
'ci-overcloud.{{network.name.lower()}}.tripleo.org'.
|
|
type: string
|
|
{%- else %}
|
|
CloudName{{network.name}}:
|
|
default: overcloud.{{network.name.lower()}}.localdomain
|
|
description: >
|
|
The DNS name of this cloud's {{network.name_lower}} endpoint. E.g.
|
|
'ci-overcloud.{{network.name.lower()}}.tripleo.org'.
|
|
type: string
|
|
{%- endif %}
|
|
{{network.name}}VirtualFixedIPs:
|
|
default: []
|
|
description: >
|
|
Control the IP allocation for the {{network.name}}VirtualInterface port. E.g.
|
|
[{'ip_address':'1.2.3.4'}]
|
|
type: json
|
|
{%- endfor %}
|
|
CloudNameCtlplane:
|
|
default: overcloud.ctlplane.localdomain
|
|
description: >
|
|
The DNS name of this cloud's provisioning network endpoint. E.g.
|
|
'ci-overcloud.ctlplane.tripleo.org'.
|
|
type: string
|
|
ExtraHostFileEntries:
|
|
default: []
|
|
description: List of extra hosts entries to be appended to /etc/hosts
|
|
type: comma_delimited_list
|
|
UndercloudHostsEntries:
|
|
default: []
|
|
description: >
|
|
List of undercloud hosts entries to be appended to /etc/hosts. The
|
|
value is populated with the HEAT_HOSTS entries on the undercloud by
|
|
tripleoclient when running deploy.
|
|
type: comma_delimited_list
|
|
EndpointMapOverride:
|
|
default: {}
|
|
description: Can be used to override the calcluated EndpointMap
|
|
type: json
|
|
ExtraConfig:
|
|
default: {}
|
|
description: |
|
|
Additional hiera configuration to inject into the cluster.
|
|
type: json
|
|
DeployedServerPortMap:
|
|
default: {}
|
|
type: json
|
|
NeutronControlPlaneID:
|
|
default: 'ctlplane'
|
|
type: string
|
|
description: Neutron ID or name for ctlplane network.
|
|
NeutronPhysicalBridge:
|
|
default: 'br-ex'
|
|
description: An OVS bridge to create for accessing external networks.
|
|
type: string
|
|
NeutronPublicInterface:
|
|
default: nic1
|
|
description: Which interface to add to the NeutronPhysicalBridge.
|
|
type: string
|
|
ControlPlaneSubnet:
|
|
description: The name of the undercloud Neutron control plane subnet
|
|
default: ctlplane-subnet
|
|
type: string
|
|
ControlPlaneSubnetCidr:
|
|
default: ''
|
|
description: >
|
|
The subnet CIDR of the control plane network. (The parameter is
|
|
automatically resolved from the ctlplane subnet's cidr attribute.)
|
|
type: string
|
|
DnsSearchDomains: # Override this via parameter_defaults
|
|
default: []
|
|
description: A list of DNS search domains to be added (in order) to resolv.conf.
|
|
type: comma_delimited_list
|
|
ControlFixedIPs:
|
|
default: []
|
|
description: >
|
|
Control the IP allocation for the ControlVirtualIP port. E.g.
|
|
[{'ip_address':'1.2.3.4'}]
|
|
type: json
|
|
RabbitCookieSalt:
|
|
type: string
|
|
default: unset
|
|
description: Salt for the rabbit cookie, change this to force the randomly generated rabbit cookie to change.
|
|
CloudDomain:
|
|
default: 'localdomain'
|
|
type: string
|
|
description: >
|
|
The DNS domain used for the hosts. This must match the
|
|
overcloud_domain_name configured on the undercloud.
|
|
ServerMetadata:
|
|
default: {}
|
|
description: >
|
|
Extra properties or metadata passed to Nova for the created nodes in
|
|
the overcloud. It's accessible via the Nova metadata API.
|
|
type: json
|
|
# Compute-specific params
|
|
# FIXME(shardy) handle these deprecated names as they don't match compute.yaml
|
|
HypervisorNeutronPhysicalBridge:
|
|
default: 'br-ex'
|
|
description: >
|
|
An OVS bridge to create on each hypervisor. This defaults to br-ex the
|
|
same as the control plane nodes, as we have a uniform configuration of
|
|
the openvswitch agent. Typically should not need to be changed.
|
|
type: string
|
|
HypervisorNeutronPublicInterface:
|
|
default: nic1
|
|
description: What interface to add to the HypervisorNeutronPhysicalBridge.
|
|
type: string
|
|
|
|
NodeCreateBatchSize:
|
|
default: 30
|
|
description: Maxiumum batch size for creating nodes
|
|
type: number
|
|
|
|
NovaAdditionalCell:
|
|
default: false
|
|
description: Whether this is an cell additional to the default cell.
|
|
type: boolean
|
|
|
|
NovaLocalMetadataPerCell:
|
|
default: false
|
|
description: >
|
|
Indicates that the nova-metadata API service has been deployed
|
|
per-cell, so that we can have better performance and data isolation in a
|
|
multi-cell deployment. Users should consider the use of this configuration
|
|
depending on how neutron is setup. If networks span cells, you might need
|
|
to run nova-metadata API service globally. If your networks are segmented
|
|
along cell boundaries, then you can run nova-metadata API service per cell.
|
|
When running nova-metadata API service per cell, you should also configure
|
|
each Neutron metadata-agent to point to the corresponding nova-metadata API
|
|
service.
|
|
type: boolean
|
|
|
|
BondInterfaceOvsOptions:
|
|
default: ''
|
|
description: The ovs_options or bonding_options string for the bond
|
|
interface. Set things like lacp=active and/or bond_mode=balance-slb
|
|
for OVS bonds or like mode=4 for Linux bonds using this option.
|
|
type: string
|
|
constraints:
|
|
- allowed_pattern: ^((?!balance.tcp).)*$
|
|
description: The balance-tcp bond mode is known to cause packet loss and
|
|
should not be used in BondInterfaceOvsOptions.
|
|
|
|
NetworkConfigWithAnsible:
|
|
description: NetworkConfig with ansible flag
|
|
type: boolean
|
|
default: True
|
|
|
|
# Jinja loop for Role in role_data.yaml
|
|
{% for role in roles %}
|
|
|
|
{%- if role.name == 'ComputeOvsDpdk' %}
|
|
NumDpdkInterfaceRxQueues:
|
|
description: Number of Rx Queues required for DPDK bond or DPDK ports
|
|
default: 1
|
|
type: number
|
|
{%- endif %}
|
|
|
|
{{role.name}}LocalMtu: # Override this via parameter_defaults
|
|
default: 1500
|
|
description: MTU to use for the Undercloud local_interface.
|
|
type: number
|
|
constraints:
|
|
- range: { min: 1000, max: 65536 }
|
|
{{role.name}}NetworkConfigTemplate:
|
|
description: {{role.name}} NetworkConfig Template
|
|
type: string
|
|
{%- if 'external_bridge' in role.tags|default([]) %}
|
|
default: 'templates/net_config_bridge.j2'
|
|
{%- else %}
|
|
default: ''
|
|
{%- endif %}
|
|
{{role.name}}ExtraConfig:
|
|
default: {}
|
|
description: |
|
|
Role specific additional hiera configuration to inject into the cluster.
|
|
type: json
|
|
{%- if role.deprecated_param_extraconfig is defined %}
|
|
{{role.deprecated_param_extraconfig}}:
|
|
default: {}
|
|
description: |
|
|
DEPRECATED use {{role.name}}ExtraConfig instead
|
|
type: json
|
|
{%- endif %}
|
|
# Parameters generated for {{role.name}} Role
|
|
{{role.name}}Services:
|
|
description: A list of service resources (configured in the Heat
|
|
resource_registry) which represent nested stacks
|
|
for each service that should get installed on the {{role.name}} role.
|
|
type: comma_delimited_list
|
|
{{role.name}}NetworkConfigUpdate:
|
|
type: boolean
|
|
description: >
|
|
When set to "True", existing networks will be updated on the overcloud.
|
|
This parameter replaces the functionality previously provided by
|
|
NetworkDeploymentActions. Defaults to "False" so that only new nodes will
|
|
have their networks configured. This is a role based parameter.
|
|
default: False
|
|
{{role.name}}AnyErrorsFatal:
|
|
default: true
|
|
type: boolean
|
|
{{role.name}}MaxFailPercentage:
|
|
default: 0
|
|
type: number
|
|
{{role.name}}Count:
|
|
description: Number of {{role.name}} nodes to deploy
|
|
type: number
|
|
default: {{role.CountDefault|default(0)}}
|
|
|
|
{{role.name}}HostnameFormat:
|
|
type: string
|
|
description: >
|
|
Format for {{role.name}} node hostnames
|
|
Note %index% is translated into the index of the node, e.g 0/1/2 etc
|
|
and %stackname% is replaced with the stack name e.g overcloud
|
|
{% if role.HostnameFormatDefault %}
|
|
default: "{{role.HostnameFormatDefault}}"
|
|
{% else %}
|
|
default: "%stackname%-{{role.name.lower()}}-%index%"
|
|
{% endif %}
|
|
{{role.name}}RemovalPolicies:
|
|
default: []
|
|
type: json
|
|
description: >
|
|
List of resources to be removed from {{role.name}} ResourceGroup when
|
|
doing an update which requires removal of specific resources.
|
|
Example format ComputeRemovalPolicies: [{'resource_list': ['0']}]
|
|
|
|
{{role.name}}RemovalPoliciesMode:
|
|
default: append
|
|
type: string
|
|
description: >
|
|
How to handle change to RemovalPolicies for {{role.name}}
|
|
ResourceGroup when doing an update. Default mode 'append' will
|
|
append to the existing blacklist and 'update' would replace
|
|
the blacklist.
|
|
|
|
{{role.name}}SchedulerHints:
|
|
type: json
|
|
description: Optional scheduler hints to pass to nova
|
|
default: {}
|
|
{%- if role.deprecated_param_scheduler_hints is defined %}
|
|
{{role.deprecated_param_scheduler_hints}}:
|
|
type: json
|
|
description: DEPRECATED - use {{role.name}}SchedulerHints instead
|
|
default: {}
|
|
{%- endif %}
|
|
|
|
{{role.name}}Parameters:
|
|
type: json
|
|
description: Optional Role Specific parameters to be provided to service
|
|
default: {}
|
|
|
|
{{role.name}}ExtraGroupVars:
|
|
type: json
|
|
description: Optional extra Ansible group vars
|
|
default: {}
|
|
|
|
{{role.name}}ControlPlaneSubnet:
|
|
default: ctlplane-subnet
|
|
description: |
|
|
Name of the subnet on ctlplane network for this role.
|
|
type: string
|
|
|
|
{{role.name}}ServiceNetMap:
|
|
default: {}
|
|
description: |
|
|
Role specific ServiceNetMap overrides, the map provided will be merged
|
|
with the global ServiceNetMap when passing the ServiceNetMap to the
|
|
{{role.name}}ServiceChain resource and the {{role.name}} resource group.
|
|
For example:
|
|
{{role.name}}ServiceNetMap:
|
|
NovaLibvirtNetwork: internal_api_leaf2
|
|
type: json
|
|
|
|
{{role.name}}NetConfigOverride:
|
|
default: {}
|
|
description: |
|
|
Custom JSON data to be used to override the os-net-config config.
|
|
This is meant to be used by net_config_override parameter in tripleoclient
|
|
to provide an easy means to pass in custom net configs for the Undercloud.
|
|
type: json
|
|
|
|
{% endfor %}
|
|
|
|
# Identifiers to trigger tasks on nodes
|
|
UpdateIdentifier:
|
|
default: ''
|
|
type: string
|
|
description: >
|
|
Setting to a previously unused value during stack-update will trigger
|
|
package update on all nodes
|
|
DeployIdentifier:
|
|
default: ''
|
|
type: string
|
|
description: >
|
|
Setting this to a unique value will re-run any deployment tasks which
|
|
perform configuration on a Heat stack-update.
|
|
AddVipsToEtcHosts:
|
|
default: True
|
|
type: boolean
|
|
description: >
|
|
Set to true to append per network Vips to /etc/hosts on each node.
|
|
|
|
DeploymentServerBlacklist:
|
|
default: []
|
|
type: comma_delimited_list
|
|
description: >
|
|
List of server hostnames to blacklist from any triggered deployments.
|
|
|
|
GlobalConfigExtraMapData:
|
|
type: json
|
|
default: {}
|
|
description: Map of extra global_config_settings data to set on each node.
|
|
|
|
NetConfigDataLookup:
|
|
type: json
|
|
default: {}
|
|
description: >
|
|
Configure os-net-config mappings for specific nodes
|
|
Your environment file needs to look like:
|
|
parameter_defaults:
|
|
NetConfigDataLookup:
|
|
node1:
|
|
nic1: "00:c8:7c:e6:f0:2e"
|
|
node2:
|
|
nic1: "00:18:7d:99:0c:b6"
|
|
node3:
|
|
dmiString: 'system-uuid'
|
|
id: 'A8C85861-1B16-4803-8689-AFC62984F8F6'
|
|
nic1: em3
|
|
# Dell PowerEdge
|
|
nodegroup1:
|
|
dmiString: "system-product-name"
|
|
id: "PowerEdge R630"
|
|
nic1: em3
|
|
nic2: em1
|
|
nic3: em2
|
|
# Cisco UCS B200-M4"
|
|
nodegroup2:
|
|
dmiString: "system-product-name"
|
|
id: "UCSB-B200-M4"
|
|
nic1: enp7s0
|
|
nic2: enp6s0
|
|
|
|
This will result in the first node* entry where either a mac matches a
|
|
local device or a DMI String matches the specified id being written as a
|
|
mapping file for os-net-config. (/etc/os-net-config/mapping.yaml)
|
|
|
|
DnsServers: # Override this via parameter_defaults
|
|
default: []
|
|
description: >
|
|
DNS servers to use for the Overcloud (2 max for some implementations).
|
|
If not set the nameservers configured in the ctlplane subnet's
|
|
dns_nameservers attribute will be used.
|
|
type: comma_delimited_list
|
|
|
|
RootStackName:
|
|
description: The name of the stack/plan.
|
|
type: string
|
|
|
|
AdminPassword:
|
|
description: The password for the keystone admin account, used for monitoring, querying neutron etc.
|
|
type: string
|
|
hidden: true
|
|
|
|
KeystoneRegion:
|
|
type: string
|
|
default: 'regionOne'
|
|
description: Keystone region for endpoint
|
|
|
|
{% for role in roles %}
|
|
{%- if role.deprecated_param_scheduler_hints is defined or role.deprecated_param_extraconfig is defined %}
|
|
{%- if not parameter_groups_defined|default(false) %}
|
|
parameter_groups:
|
|
- label: deprecated
|
|
description: Do not use deprecated params, they will be removed.
|
|
parameters:
|
|
- DnsServers
|
|
{%- set parameter_groups_defined = true %}
|
|
{%- endif %}
|
|
{%- endif %}
|
|
{%- if role.deprecated_param_scheduler_hints is defined %}
|
|
- {{role.deprecated_param_scheduler_hints}}
|
|
{%- endif %}
|
|
{%- if role.deprecated_param_extraconfig is defined %}
|
|
- {{role.deprecated_param_extraconfig}}
|
|
{%- endif %}
|
|
{%- endfor %}
|
|
|
|
conditions:
|
|
add_vips_to_etc_hosts: {equals : [{get_param: AddVipsToEtcHosts}, True]}
|
|
control_fixed_ip_not_set: {equals : [{get_param: ControlFixedIPs}, []]}
|
|
{%- for network in networks if network.name != 'External' %}
|
|
{{network.name_lower}}_virtual_fixed_ip_set:
|
|
not:
|
|
equals:
|
|
- get_param: {{network.name}}VirtualFixedIPs
|
|
- []
|
|
{%- endfor %}
|
|
public_virtual_fixed_ip_set:
|
|
not:
|
|
equals:
|
|
- get_param: PublicVirtualFixedIPs
|
|
- []
|
|
set_default_mysql_cell_internal:
|
|
or:
|
|
- equals:
|
|
- get_param: NovaAdditionalCell
|
|
- true
|
|
- and:
|
|
- equals:
|
|
- get_param: NovaAdditionalCell
|
|
- false
|
|
- equals:
|
|
- get_param: [EndpointMapOverride, MysqlCellInternal]
|
|
- ''
|
|
set_default_nova_vnc_proxy_cell_public:
|
|
or:
|
|
- equals:
|
|
- get_param: NovaAdditionalCell
|
|
- true
|
|
- and:
|
|
- equals:
|
|
- get_param: NovaAdditionalCell
|
|
- false
|
|
- equals:
|
|
- get_param: [EndpointMapOverride, NovaVNCProxyCellPublic]
|
|
- ''
|
|
set_default_nova_metadata_cell_internal:
|
|
or:
|
|
- equals:
|
|
- get_param: NovaLocalMetadataPerCell
|
|
- true
|
|
- and:
|
|
- equals:
|
|
- get_param: NovaLocalMetadataPerCell
|
|
- false
|
|
- equals:
|
|
- get_param: [EndpointMapOverride, NovaMetadataCellInternal]
|
|
- ''
|
|
dnsservers_set:
|
|
not:
|
|
equals: [{get_param: DnsServers}, []]
|
|
|
|
resources:
|
|
|
|
VipHosts:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
type: comma_delimited_list
|
|
value:
|
|
- str_replace:
|
|
template: IP HOST
|
|
params:
|
|
IP: {get_attr: [VipMap, net_ip_map, ctlplane]}
|
|
HOST: {get_param: CloudNameCtlplane}
|
|
{%- for network in networks if network.vip|default(false) and network.enabled|default(true) %}
|
|
{%- if network.name == 'External' %}
|
|
# Special case the External hostname param, which is CloudName
|
|
- str_replace:
|
|
template: IP HOST
|
|
params:
|
|
IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
|
|
HOST: {get_param: CloudName}
|
|
{%- elif network.name == 'InternalApi' %}
|
|
# Special case the Internal API hostname param, which is CloudNameInternal
|
|
- str_replace:
|
|
template: IP HOST
|
|
params:
|
|
IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
|
|
HOST: {get_param: CloudNameInternal}
|
|
{%- elif network.name == 'StorageMgmt' %}
|
|
# Special case StorageMgmt hostname param, which is CloudNameStorageManagement
|
|
- str_replace:
|
|
template: IP HOST
|
|
params:
|
|
IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
|
|
HOST: {get_param: CloudNameStorageManagement}
|
|
{%- else %}
|
|
- str_replace:
|
|
template: IP HOST
|
|
params:
|
|
IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
|
|
HOST: {get_param: CloudName{{network.name}}}
|
|
{%- endif %}
|
|
{%- endfor %}
|
|
|
|
NetCidrMapValue:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
type: json
|
|
value:
|
|
map_replace:
|
|
- map_merge:
|
|
- {get_attr: [Networks, net_cidr_map]}
|
|
# NOTE(hjensas): When ctlplane network and subnets are created by the
|
|
# undercloud installer, the subnet cidrs are added as tags.
|
|
- ctlplane: {get_attr: [ControlVirtualIP, network, tags]}
|
|
- keys:
|
|
ctlplane: {get_param: NeutronControlPlaneID}
|
|
|
|
NetIpVersionMapValue:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
type: json
|
|
value:
|
|
map_replace:
|
|
- map_merge:
|
|
- {get_attr: [Networks, net_ip_version_map]}
|
|
- ctlplane: {get_attr: [ControlVirtualIP, subnets, 0, ip_version]}
|
|
- keys:
|
|
ctlplane: {get_param: NeutronControlPlaneID}
|
|
|
|
ServiceNetMap:
|
|
type: OS::TripleO::ServiceNetMap
|
|
|
|
EndpointMap:
|
|
type: OS::TripleO::EndpointMap
|
|
properties:
|
|
CloudEndpoints:
|
|
ctlplane: {get_param: CloudNameCtlplane}
|
|
{%- for network in networks if network.vip|default(false) and network.enabled|default(true) %}
|
|
{%- if network.name == 'External' %}
|
|
# Special case the External hostname param, which is CloudName
|
|
{{network.name_lower}}: {get_param: CloudName}
|
|
{%- elif network.name == 'InternalApi' %}
|
|
# Special case the Internal API hostname param, which is CloudNameInternal
|
|
{{network.name_lower}}: {get_param: CloudNameInternal}
|
|
{%- elif network.name == 'StorageMgmt' %}
|
|
# Special case StorageMgmt hostname param, which is CloudNameStorageManagement
|
|
{{network.name_lower}}: {get_param: CloudNameStorageManagement}
|
|
{%- else %}
|
|
{{network.name_lower}}: {get_param: CloudName{{network.name}}}
|
|
{%- endif %}
|
|
{%- endfor %}
|
|
NetIpMap: {get_attr: [VipMap, net_ip_map]}
|
|
ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
|
|
|
|
EndpointMapData:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
type: json
|
|
value:
|
|
map_merge:
|
|
- {get_attr: [EndpointMap, endpoint_map]}
|
|
- {get_param: EndpointMapOverride}
|
|
# For parent stack we must set these to the local endpoints
|
|
# For split-controlplane stacks that are nova cells we must set
|
|
# these to the local endpoints
|
|
# For split-controlplane stacks that are not nova cells we should
|
|
# take these from EndpointMapOverride (i.e the parent stack)
|
|
- if:
|
|
- set_default_mysql_cell_internal
|
|
- MysqlCellInternal: {get_attr: [EndpointMap, endpoint_map, MysqlInternal]}
|
|
- {}
|
|
- if:
|
|
- set_default_nova_vnc_proxy_cell_public
|
|
- NovaVNCProxyCellPublic: {get_attr: [EndpointMap, endpoint_map, NovaVNCProxyPublic]}
|
|
- {}
|
|
- if:
|
|
- set_default_nova_metadata_cell_internal
|
|
- NovaMetadataCellInternal: {get_attr: [EndpointMap, endpoint_map, NovaMetadataInternal]}
|
|
- {}
|
|
|
|
# Creates the "heat-admin" user if configured via the environment
|
|
# Should return a OS::Heat::MultipartMime reference via OS::stack_id
|
|
NodeAdminUserData:
|
|
type: OS::TripleO::NodeAdminUserData
|
|
|
|
# Bootstraps an ntp configuration and includes a hardware clock sync to
|
|
# for containers.
|
|
# Should return a OS::Heat::MultipartMime reference via OS::stack_id
|
|
NodeTimesyncUserData:
|
|
type: OS::TripleO::NodeTimesyncUserData
|
|
|
|
# For optional operator additional userdata
|
|
# Should return a OS::Heat::MultipartMime reference via OS::stack_id
|
|
NodeUserData:
|
|
type: OS::TripleO::NodeUserData
|
|
|
|
# Jinja loop for Role in roles_data.yaml
|
|
{% for role in roles %}
|
|
# Resources generated for {{role.name}} Role
|
|
{{role.name}}ServiceChain:
|
|
type: OS::TripleO::{{role.name}}Services
|
|
properties:
|
|
Services:
|
|
get_param: {{role.name}}Services
|
|
ServiceNetMap:
|
|
map_merge:
|
|
- {get_attr: [ServiceNetMap, service_net_map]}
|
|
- {get_param: {{role.name}}ServiceNetMap}
|
|
ServiceData:
|
|
net_cidr_map: {get_attr: [NetCidrMapValue, value]}
|
|
net_vip_map: {get_attr: [VipMap, net_ip_map]}
|
|
net_ip_version_map: {get_attr: [NetIpVersionMapValue, value]}
|
|
vip_subnet_map: {get_attr: [ServiceNetMap, vip_subnet_map]}
|
|
EndpointMap: {get_attr: [EndpointMapData, value]}
|
|
RoleName: {{role.name}}
|
|
RoleParameters:
|
|
map_merge:
|
|
- {{role.RoleParametersDefault|default({})}}
|
|
- get_param: {{role.name}}Parameters
|
|
|
|
# Lookup of role_data via heat outputs is slow, so workaround this by caching
|
|
# the value in an OS::Heat::Value resource
|
|
{{role.name}}ServiceChainRoleData:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
type: json
|
|
value: {get_attr: [{{role.name}}ServiceChain, role_data]}
|
|
|
|
{{role.name}}ConfigData:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
type: json
|
|
value:
|
|
service_configs: {get_attr: [{{role.name}}ServiceConfigSettings, value]}
|
|
service_names: {get_attr: [{{role.name}}ServiceNames, value]}
|
|
role_extraconfig:
|
|
map_merge:
|
|
- tripleo::profile::base::metrics::collectd::sensubility::subscriptions: {get_attr: [{{role.name}}ServiceChainRoleData, value, monitoring_subscriptions]}
|
|
- tripleo_collectd_sensubility_subscriptions: {get_attr: [{{role.name}}ServiceChainRoleData, value, monitoring_subscriptions]}
|
|
{%- if role.deprecated_param_extraconfig is defined %}
|
|
- {get_param: {{role.deprecated_param_extraconfig}}}
|
|
{%- endif %}
|
|
- {get_param: {{role.name}}ExtraConfig}
|
|
extraconfig: {get_param: ExtraConfig}
|
|
hieradata_files:
|
|
- '%{::uuid}'
|
|
- fqdn
|
|
- docker_puppet # Optionally provided by container-puppet.sh
|
|
- ansible_managed
|
|
- heat_config_%{::deploy_config_name}
|
|
- config_step
|
|
- role_extraconfig
|
|
- extraconfig
|
|
- pci_passthrough_whitelist
|
|
- service_names
|
|
- service_configs
|
|
- cloud_domain
|
|
- bootstrap_node # provided by tripleo_hieradata
|
|
- all_nodes # provided by tripleo_hieradata
|
|
- vip_data # provided by tripleo_hieradata
|
|
- net_ip_map
|
|
- ovn_chassis_mac_map # provided by tripleo_hieradata
|
|
- '%{::osfamily}'
|
|
# Special variable for upgrade
|
|
- upgrade
|
|
|
|
{{role.name}}ServiceConfigSettings:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
type: json
|
|
value:
|
|
map_merge:
|
|
- get_param: GlobalConfigExtraMapData
|
|
- get_attr: [{{role.name}}ServiceChainRoleData, value, config_settings]
|
|
{% for r in roles %}
|
|
- get_attr: [{{r.name}}ServiceChainRoleData, value, global_config_settings]
|
|
{% endfor %}
|
|
# This next step combines two yaql passes:
|
|
# - The inner one does a deep merge on the service_config_settings for all roles
|
|
# - The outer one filters the map based on the services enabled for the role
|
|
# then merges the result into one map.
|
|
- yaql:
|
|
expression: let(root => $) -> $.data.map.items().where($[0] in coalesce($root.data.services, [])).select($[1]).reduce($1.mergeWith($2), {})
|
|
data:
|
|
map:
|
|
yaql:
|
|
expression: $.data.where($ != null).reduce($1.mergeWith($2), {})
|
|
data:
|
|
{% for r in roles %}
|
|
- get_attr: [{{r.name}}ServiceChainRoleData, value, service_config_settings]
|
|
{% endfor %}
|
|
services: {get_attr: [{{role.name}}ServiceNames, value]}
|
|
|
|
# Filter any null/None service_names which may be present due to mapping
|
|
# of services to OS::Heat::None
|
|
{{role.name}}ServiceNames:
|
|
type: OS::Heat::Value
|
|
depends_on: {{role.name}}ServiceChain
|
|
properties:
|
|
type: comma_delimited_list
|
|
value:
|
|
yaql:
|
|
expression: let(root => $) -> distinct($.data.extra_services.items().where($[0] in coalesce($root.data.enabled_services, [])).select($[1]).flatten() + coalesce($root.data.enabled_services, []))
|
|
data:
|
|
enabled_services: {get_attr: [{{role.name}}ServiceChainRoleData, value, service_names]}
|
|
extra_services:
|
|
# If anything other than keystone needs this
|
|
# then we should add an extra_networks interface
|
|
# to the service templates role_data but for
|
|
# now we hard-code the keystone special case
|
|
keystone:
|
|
- keystone_admin_api
|
|
- keystone_public_api
|
|
|
|
{{role.name}}IpListMap:
|
|
type: OS::TripleO::Network::Ports::NetIpListMap
|
|
properties:
|
|
ControlPlaneIpList: {get_attr: [{{role.name}}, ip_address]}
|
|
{%- for network in networks if network.enabled|default(true) and network.name in role.networks|default([]) %}
|
|
{{network.name}}IpList: {get_attr: [{{role.name}}, {{network.name_lower}}_ip_address]}
|
|
{%- endfor %}
|
|
RoleNetworks:
|
|
- ctlplane
|
|
{%- for network in networks if network.enabled|default(true) and network.name in role.networks|default([]) %}
|
|
- {{network.name_lower}}
|
|
{%- endfor %}
|
|
EnabledServices: {get_attr: [{{role.name}}ServiceNames, value]}
|
|
ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
|
|
ServiceHostnameList: {get_attr: [{{role.name}}, hostname]}
|
|
NetworkHostnameMap: {get_attr: [{{role.name}}NetworkHostnameMap, value]}
|
|
|
|
{{role.name}}NetworkHostnameMap:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
type: json
|
|
value:
|
|
# Note (shardy) this somewhat complex yaql may be replaced
|
|
# with a map_deep_merge function in ocata. It merges the
|
|
# list of maps, but appends to colliding lists so we can
|
|
# create a map of lists for all nodes for each network
|
|
yaql:
|
|
expression: dict($.data.where($ != null).flatten().selectMany($.items()).groupBy($[0], $[1]).select([$[0], $[1].flatten()]))
|
|
data:
|
|
- {get_attr: [{{role.name}}, hostname_map]}
|
|
|
|
# Combine the NodeAdminUserData and NodeUserData mime archives
|
|
{{role.name}}UserData:
|
|
type: OS::Heat::MultipartMime
|
|
properties:
|
|
parts:
|
|
- config: {get_resource: NodeAdminUserData}
|
|
type: multipart
|
|
- config: {get_resource: NodeTimesyncUserData}
|
|
type: multipart
|
|
- config: {get_resource: NodeUserData}
|
|
type: multipart
|
|
- config: {get_resource: {{role.name}}RoleUserData}
|
|
type: multipart
|
|
|
|
# For optional operator role-specific userdata
|
|
# Should return a OS::Heat::MultipartMime reference via OS::stack_id
|
|
{{role.name}}RoleUserData:
|
|
type: OS::TripleO::{{role.name}}::NodeUserData
|
|
|
|
{{role.name}}:
|
|
type: OS::Heat::ResourceGroup
|
|
depends_on: Networks
|
|
update_policy:
|
|
batch_create:
|
|
max_batch_size: {get_param: NodeCreateBatchSize}
|
|
properties:
|
|
count: {get_param: {{role.name}}Count}
|
|
removal_policies: {get_param: {{role.name}}RemovalPolicies}
|
|
removal_policies_mode: {get_param: {{role.name}}RemovalPoliciesMode}
|
|
resource_def:
|
|
type: OS::TripleO::{{role.name}}
|
|
properties:
|
|
CloudDomain: {get_param: CloudDomain}
|
|
ServiceNetMap:
|
|
map_merge:
|
|
- {get_attr: [ServiceNetMap, service_net_map]}
|
|
- {get_param: {{role.name}}ServiceNetMap}
|
|
EndpointMap: {get_attr: [EndpointMapData, value]}
|
|
Hostname:
|
|
str_replace:
|
|
template: {get_param: {{role.name}}HostnameFormat}
|
|
params:
|
|
'%stackname%': {get_param: 'OS::stack_name'}
|
|
NodeIndex: '%index%'
|
|
# Note, SchedulerHints must be defined here, not only in the
|
|
# nested template, as it can contain %index%
|
|
{{role.name}}SchedulerHints:
|
|
map_merge:
|
|
{%- if role.deprecated_param_scheduler_hints is defined %}
|
|
- {get_param: {{role.deprecated_param_scheduler_hints}}}
|
|
{%- endif %}
|
|
- {get_param: {{role.name}}SchedulerHints}
|
|
ServiceNames: {get_attr: [{{role.name}}ServiceNames, value]}
|
|
ServiceMetadataSettings: {get_attr: [{{role.name}}ServiceChainRoleData, value, service_metadata_settings]}
|
|
OVNBridgeMappings: {get_attr: [{{role.name}}ServiceChainRoleData, value, config_settings, 'ovn::controller::ovn_bridge_mappings']}
|
|
DeploymentServerBlacklistDict: {get_attr: [DeploymentServerBlacklistDict, value]}
|
|
RoleParameters:
|
|
map_merge:
|
|
- {{role.RoleParametersDefault|default({})}}
|
|
- get_param: {{role.name}}Parameters
|
|
UserData: {get_resource: {{role.name}}UserData}
|
|
{%- endfor %}
|
|
|
|
{%- for role in roles %}
|
|
{{role.name}}Servers:
|
|
type: OS::Heat::Value
|
|
depends_on: {{role.name}}
|
|
properties:
|
|
type: json
|
|
value:
|
|
yaql:
|
|
expression: let(servers=>switch(isDict($.data.servers) => $.data.servers, true => {})) -> $servers.deleteAll($servers.keys().where($servers[$] = null))
|
|
data:
|
|
servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
|
|
{%- endfor %}
|
|
|
|
# This is a different format to *Servers, as it creates a map of lists
|
|
# whereas *Servers creates a map of maps with keys of the nested resource names
|
|
ServerIdMap:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
value:
|
|
server_ids:
|
|
{%- for role in roles %}
|
|
{{role.name}}: {get_attr: [{{role.name}}, nova_server_resource]}
|
|
{%- endfor %}
|
|
bootstrap_server_id:
|
|
yaql:
|
|
expression: coalesce($.data, []).first(null)
|
|
data: {get_attr: [{{primary_role_name}}, nova_server_resource]}
|
|
|
|
# This resource just creates a dict out of the DeploymentServerBlacklist,
|
|
# which is a list. The dict is used in the role templates to set a condition
|
|
# on whether to create the deployment resources. We can't use the list
|
|
# directly because there is no way to ask Heat if a list contains a specific
|
|
# value.
|
|
DeploymentServerBlacklistDict:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
type: json
|
|
value:
|
|
map_merge:
|
|
repeat:
|
|
template:
|
|
hostname: 1
|
|
for_each:
|
|
hostname: {get_param: DeploymentServerBlacklist}
|
|
|
|
HostsEntryValue:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
type: comma_delimited_list
|
|
value:
|
|
list_concat_unique:
|
|
list_concat:
|
|
- - {get_param: UndercloudHostsEntries}
|
|
- - if:
|
|
- add_vips_to_etc_hosts
|
|
- {get_attr: [VipHosts, value]}
|
|
- []
|
|
{%- for role in roles %}
|
|
- {get_attr: [{{role.name}}, hosts_entry]}
|
|
{%- endfor %}
|
|
- - {get_param: ExtraHostFileEntries}
|
|
|
|
CloudNames:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
value:
|
|
{%- for network in networks if network.vip|default(false) and network.enabled|default(true) %}
|
|
{%- if network.name == 'External' %}
|
|
# Special case the External hostname param, which is CloudName
|
|
cloud_name_{{network.name_lower}}: {get_param: CloudName}
|
|
{%- elif network.name == 'InternalApi' %}
|
|
# Special case the Internal API hostname param, which is CloudNameInternal
|
|
cloud_name_{{network.name_lower}}: {get_param: CloudNameInternal}
|
|
{%- elif network.name == 'StorageMgmt' %}
|
|
# Special case StorageMgmt hostname param, which is CloudNameStorageManagement
|
|
cloud_name_{{network.name_lower}}: {get_param: CloudNameStorageManagement}
|
|
{%- else %}
|
|
cloud_name_{{network.name_lower}}: {get_param: CloudName{{network.name}}}
|
|
{%- endif %}
|
|
{%- endfor %}
|
|
cloud_name_ctlplane: {get_param: CloudNameCtlplane}
|
|
|
|
GlobalConfig:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
type: json
|
|
value:
|
|
map_merge:
|
|
{% for role in roles %}
|
|
- get_attr: [{{role.name}}ServiceChainRoleData, value, global_config_settings]
|
|
{% endfor %}
|
|
|
|
# creates the network architecture
|
|
Networks:
|
|
type: OS::TripleO::Network
|
|
properties:
|
|
CtlplaneNetworkCidrs: {get_attr: [ControlVirtualIP, network, tags]}
|
|
|
|
# NOTE(tkajinam): Backend services and haproxy might be running in different
|
|
# nodes, so we need to gather all frontend firewall rules
|
|
# across all roles and pass the combined data to firewall
|
|
# configuration task in the node where haproxy (or edge
|
|
# haproxy) is assigned to.
|
|
FirewallFrontendRules:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
type: json
|
|
value:
|
|
frontend:
|
|
map_merge:
|
|
{% for role in roles %}
|
|
- get_attr: [{{role.name}}ServiceChainRoleData, value, firewall_frontend_rules]
|
|
{% endfor %}
|
|
ssl_frontend:
|
|
map_merge:
|
|
{% for role in roles %}
|
|
- get_attr: [{{role.name}}ServiceChainRoleData, value, firewall_ssl_frontend_rules]
|
|
{% endfor %}
|
|
edge_frontend:
|
|
map_merge:
|
|
{% for role in roles %}
|
|
- get_attr: [{{role.name}}ServiceChainRoleData, value, firewall_edge_frontend_rules]
|
|
{% endfor %}
|
|
edge_ssl_frontend:
|
|
map_merge:
|
|
{% for role in roles %}
|
|
- get_attr: [{{role.name}}ServiceChainRoleData, value, firewall_edge_ssl_frontend_rules]
|
|
{% endfor %}
|
|
|
|
{%- for role in roles %}
|
|
{{role.name}}GroupVars:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
value:
|
|
ctlplane_mtu: {get_attr: [Networks, net_attributes_map, ctlplane, network, mtu]}
|
|
ctlplane_gateway_ip: {get_attr: [Networks, net_attributes_map, ctlplane, subnets, {get_param: {{role.name}}ControlPlaneSubnet}, gateway_ip]}
|
|
ctlplane_dns_nameservers:
|
|
if:
|
|
- dnsservers_set
|
|
- {get_param: DnsServers}
|
|
- {get_attr: [Networks, net_attributes_map, ctlplane, subnets, {get_param: {{role.name}}ControlPlaneSubnet}, dns_nameservers]}
|
|
ctlplane_subnet_cidr: {str_split: ['/', {get_attr: [Networks, net_attributes_map, ctlplane, subnets, {get_param: {{role.name}}ControlPlaneSubnet}, cidr]}, 1]}
|
|
ctlplane_host_routes:
|
|
list_concat_unique:
|
|
- {get_attr: [Networks, net_attributes_map, ctlplane, subnets, {get_param: {{role.name}}ControlPlaneSubnet}, host_routes]}
|
|
{%- if role.default_route_networks is not defined or 'ControlPlane' in role.default_route_networks %}
|
|
- - default: true
|
|
next_hop: {get_attr: [Networks, net_attributes_map, ctlplane, subnets, {get_param: {{role.name}}ControlPlaneSubnet}, gateway_ip]}
|
|
{%- endif %}
|
|
# MTU is not filtered on role.networks, for DVR we need the External MTU on the exteranl_bridge
|
|
{% for network in networks if network.enabled|default(true) %}
|
|
{{network.name_lower}}_mtu: {get_attr: [Networks, net_attributes_map, {{network.name_lower}}, network, mtu]}
|
|
{%- endfor %}
|
|
{%- for network in networks if network.enabled|default(true) and network.name in role.networks|default([]) %}
|
|
{%- if role.networks is mapping %}
|
|
{%- set _role_net_subnet = role.networks[network.name]['subnet'] %}
|
|
{%- else %}
|
|
{%- set _role_net_subnet = network.name_lower + '_subnet' %}
|
|
{%- endif %}
|
|
{{network.name_lower}}_gateway_ip: {get_attr: [Networks, net_attributes_map, {{network.name_lower}}, subnets, {{_role_net_subnet}}, gateway_ip]}
|
|
{{network.name_lower}}_host_routes:
|
|
list_concat_unique:
|
|
- {get_attr: [Networks, net_attributes_map, {{network.name_lower}}, subnets, {{_role_net_subnet}}, host_routes]}
|
|
{%- if role.default_route_networks is defined and network.name in role.default_route_networks %}
|
|
- - default: true
|
|
next_hop: {get_attr: [Networks, net_attributes_map, {{network.name_lower}}, subnets, {{_role_net_subnet}}, gateway_ip]}
|
|
{%- endif %}
|
|
{{network.name_lower}}_cidr: {str_split: ['/', {get_attr: [Networks, net_attributes_map, {{network.name_lower}}, subnets, {{_role_net_subnet}}, cidr]}, 1]}
|
|
{{network.name_lower}}_vlan_id:
|
|
yaql:
|
|
expression: >
|
|
switch(not isList($.data) => 1,
|
|
not $.data.where($.startsWith('tripleo_vlan_id')).len() => 1,
|
|
true => int($.data.where($.startsWith('tripleo_vlan_id')).first().split('=').last()))
|
|
data: {get_attr: [Networks, net_attributes_map, {{network.name_lower}}, subnets, {{_role_net_subnet}}, tags]}
|
|
{%- endfor %}
|
|
network_cidrs:
|
|
{%- for network in networks if network.enabled|default(true) and network.name in role.networks|default([]) %}
|
|
{%- if role.networks is mapping %}
|
|
{%- set _role_net_subnet = role.networks[network.name]['subnet'] %}
|
|
{%- else %}
|
|
{%- set _role_net_subnet = network.name_lower + '_subnet' %}
|
|
{%- endif %}
|
|
{{network.name}}_cidr: {str_split: ['/', {get_attr: [Networks, net_attributes_map, {{network.name_lower}}, subnets, {{_role_net_subnet}}, cidr]}, 1]}
|
|
{%- endfor %}
|
|
dns_search_domains: {get_param: DnsSearchDomains}
|
|
bond_interface_ovs_options: {get_param: BondInterfaceOvsOptions}
|
|
local_mtu: {get_param: {{role.name}}LocalMtu}
|
|
role_networks:
|
|
{%- for network in networks if network.enabled|default(true) and network.name in role.networks|default([]) %}
|
|
- {{network.name}}
|
|
{%- endfor %}
|
|
networks_lower:
|
|
{%- for network in networks if network.enabled|default(true) %}
|
|
{{network.name}}: {{network.name_lower}}
|
|
{%- endfor %}
|
|
networks_all:
|
|
{%- for network in networks if network.enabled|default(true) %}
|
|
- {{network.name}}
|
|
{%- endfor %}
|
|
service_metadata_settings: {get_attr: [{{role.name}}ServiceChainRoleData, value, service_metadata_settings]}
|
|
tripleo_network_config_template: {get_param: {{role.name}}NetworkConfigTemplate}
|
|
tripleo_network_config_with_ansible: {get_param: NetworkConfigWithAnsible}
|
|
default_route_networks: {{role.default_route_networks|default(['ControlPlane'])}}
|
|
networks_skip_config: {{ role.networks_skip_config|default([]) }}
|
|
tripleo_firewall_rules: {get_attr: [{{role.name}}ServiceChainRoleData, value, firewall_rules]}
|
|
tripleo_firewall_frontend_rules: {get_attr: [FirewallFrontendRules, value, frontend]}
|
|
tripleo_firewall_ssl_frontend_rules: {get_attr: [FirewallFrontendRules, value, ssl_frontend]}
|
|
tripleo_firewall_edge_frontend_rules: {get_attr: [FirewallFrontendRules, value, edge_frontend]}
|
|
tripleo_firewall_edge_ssl_frontend_rules: {get_attr: [FirewallFrontendRules, value, edge_ssl_frontend]}
|
|
role_tags: {{role.tags}}
|
|
|
|
{{role.name}}NetworkConfig:
|
|
type: OS::TripleO::{{role.name}}::Net::SoftwareConfig
|
|
properties:
|
|
ControlPlaneIp: "{{ '{{' }} ctlplane_ip {{ '}}' }}"
|
|
ControlPlaneSubnetCidr: {str_split: ['/', {get_attr: [Networks, net_attributes_map, ctlplane, subnets, {get_param: {{role.name}}ControlPlaneSubnet}, cidr]}, 1]}
|
|
ControlPlaneDefaultRoute: {get_attr: [Networks, net_attributes_map, ctlplane, subnets, {get_param: {{role.name}}ControlPlaneSubnet}, gateway_ip]}
|
|
ControlPlaneStaticRoutes:
|
|
list_concat_unique:
|
|
- {get_attr: [Networks, net_attributes_map, ctlplane, subnets, {get_param: {{role.name}}ControlPlaneSubnet}, host_routes]}
|
|
{%- if role.default_route_networks is not defined or 'ControlPlane' in role.default_route_networks %}
|
|
- - default: true
|
|
next_hop: {get_attr: [Networks, net_attributes_map, ctlplane, subnets, {get_param: {{role.name}}ControlPlaneSubnet}, gateway_ip]}
|
|
{%- endif %}
|
|
ControlPlaneMtu: {get_attr: [Networks, net_attributes_map, ctlplane, network, mtu]}
|
|
DnsServers:
|
|
if:
|
|
- dnsservers_set
|
|
- {get_param: DnsServers}
|
|
- {get_attr: [Networks, net_attributes_map, ctlplane, subnets, {get_param: {{role.name}}ControlPlaneSubnet}, dns_nameservers]}
|
|
{%- for network in networks if network.enabled|default(true) and network.name in role.networks|default([]) %}
|
|
{%- if role.networks is mapping %}
|
|
{%- set _role_net_subnet = role.networks[network.name]['subnet'] %}
|
|
{%- else %}
|
|
{%- set _role_net_subnet = network.name_lower + '_subnet' %}
|
|
{%- endif %}
|
|
{{network.name}}IpSubnet: "{{ '{{' }} {{network.name_lower}}_ip ~ '/' ~ {{network.name_lower}}_cidr {{ '}}' }}"
|
|
{{network.name}}InterfaceRoutes:
|
|
list_concat_unique:
|
|
- {get_attr: [Networks, net_attributes_map, {{network.name_lower}}, subnets, {{_role_net_subnet}}, host_routes]}
|
|
{%- if role.default_route_networks is defined and network.name in role.default_route_networks %}
|
|
- - default: true
|
|
next_hop: {get_attr: [Networks, net_attributes_map, {{network.name_lower}}, subnets, {{_role_net_subnet}}, gateway_ip]}
|
|
{%- endif %}
|
|
{{network.name}}Mtu: {get_attr: [Networks, net_attributes_map, {{network.name_lower}}, network, mtu]}
|
|
{{network.name}}NetworkVlanID:
|
|
yaql:
|
|
expression: >
|
|
switch(not isList($.data) => 1,
|
|
not $.data.where($.startsWith('tripleo_vlan_id')).len() => 1,
|
|
true => int($.data.where($.startsWith('tripleo_vlan_id')).first().split('=').last()))
|
|
data: {get_attr: [Networks, net_attributes_map, {{network.name_lower}}, subnets, {{_role_net_subnet}}, tags]}
|
|
{%- if role.default_route_networks is defined and network.name in role.default_route_networks %}
|
|
{{network.name}}InterfaceDefaultRoute: {get_attr: [Networks, net_attributes_map, {{network.name_lower}}, subnets, {{_role_net_subnet}}, gateway_ip]}
|
|
{%- endif %}
|
|
{%- endfor %}
|
|
{%- endfor %}
|
|
|
|
ControlVirtualIP:
|
|
depends_on: ServiceNetMap
|
|
type: OS::TripleO::Network::Ports::ControlPlaneVipPort
|
|
properties:
|
|
name: control_virtual_ip
|
|
dns_name: {str_split: ['.', {get_param: CloudNameCtlplane}, 0]}
|
|
network: {get_param: NeutronControlPlaneID}
|
|
fixed_ips:
|
|
if:
|
|
- control_fixed_ip_not_set
|
|
- [{subnet: {get_attr: [ServiceNetMap, vip_subnet_map, ctlplane]}}]
|
|
- get_param: ControlFixedIPs
|
|
replacement_policy: AUTO
|
|
tags:
|
|
- tripleo_vip_net=ctlplane
|
|
- str_replace:
|
|
template: tripleo_stack_name=$STACK_NAME
|
|
params:
|
|
$STACK_NAME: {get_param: 'OS::stack_name'}
|
|
|
|
{%- for network in networks if network.vip|default(false) and network.enabled|default(true) %}
|
|
{%- if network.name == 'External' %}
|
|
# The public VIP is on the External net, falls back to ctlplane
|
|
PublicVirtualIP:
|
|
{%- else %}
|
|
{{network.name}}VirtualIP:
|
|
{%- endif %}
|
|
depends_on: [Networks, ServiceNetMap]
|
|
type: OS::TripleO::Network::Ports::{{network.name}}VipPort
|
|
properties:
|
|
ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
|
|
ControlPlaneSubnetCidr: {str_split: ['/', {get_attr: [Networks, net_attributes_map, ctlplane, subnets, {get_attr: [ServiceNetMap, vip_subnet_map, ctlplane]}, cidr]}, 1]}
|
|
PortName: {{network.name_lower}}_virtual_ip
|
|
{%- if network.name == 'External' %}
|
|
DnsName: {str_split: ['.', {get_param: CloudName}, 0]}
|
|
{%- elif network.name == 'InternalApi' %}
|
|
DnsName: {str_split: ['.', {get_param: CloudNameInternal}, 0]}
|
|
{%- elif network.name == 'StorageMgmt' %}
|
|
DnsName: {str_split: ['.', {get_param: CloudNameStorageManagement}, 0]}
|
|
{%- elif network.name not in ['External', 'InternalApi', 'StorageMgmt'] %}
|
|
DnsName: {str_split: ['.', {get_param: CloudName{{network.name}}}, 0]}
|
|
{%- endif %}
|
|
FixedIPs:
|
|
if:
|
|
{%- if network.name == 'External' %}
|
|
- public_virtual_fixed_ip_set
|
|
- {get_param: PublicVirtualFixedIPs}
|
|
{%- else %}
|
|
- {{network.name_lower}}_virtual_fixed_ip_set
|
|
- {get_param: {{network.name}}VirtualFixedIPs}
|
|
{%- endif %}
|
|
- [{subnet: {get_attr: [ServiceNetMap, vip_subnet_map, {{network.name}}]}}]
|
|
IsVirtualIP: true
|
|
{%- endfor %}
|
|
|
|
VipMap:
|
|
type: OS::TripleO::Network::Ports::NetVipMap
|
|
properties:
|
|
ControlPlaneIp: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
|
|
ControlPlaneSubnetCidr: {str_split: ['/', {get_attr: [Networks, net_attributes_map, ctlplane, subnets, {get_attr: [ServiceNetMap, vip_subnet_map, ctlplane]}, cidr]}, 1]}
|
|
{%- for network in networks if network.vip|default(false) and network.enabled|default(true) %}
|
|
{%- if network.name == 'External' %}
|
|
ExternalIp: {get_attr: [PublicVirtualIP, ip_address]}
|
|
ExternalIpUri: {get_attr: [PublicVirtualIP, ip_address_uri]}
|
|
{%- else %}
|
|
{{network.name}}Ip: {get_attr: [{{network.name}}VirtualIP, ip_address]}
|
|
{{network.name}}IpUri: {get_attr: [{{network.name}}VirtualIP, ip_address_uri]}
|
|
{%- endif %}
|
|
{%- endfor %}
|
|
# No tenant or management VIP required
|
|
# Because of nested get_attr functions in the KeystoneAdminVip output, we
|
|
# can't determine which attributes of VipMap are used until after
|
|
# ServiceNetMap's attribute values are available.
|
|
depends_on: ServiceNetMap
|
|
|
|
# Optional ExtraConfig for all nodes - all roles are passed in here, but
|
|
# the nested template may configure each role differently (or not at all)
|
|
AllNodesExtraConfig:
|
|
type: OS::TripleO::AllNodesExtraConfig
|
|
properties:
|
|
servers:
|
|
{%- for role in roles %}
|
|
{{role.name}}: {get_attr: [{{role.name}}Servers, value]}
|
|
{%- endfor %}
|
|
|
|
BlacklistedIpAddresses:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
value:
|
|
list_concat:
|
|
{%- for role in roles %}
|
|
- {get_attr: [{{role.name}}, blacklist_ip_address]}
|
|
{%- endfor %}
|
|
|
|
AnsibleHostVars:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
type: json
|
|
value:
|
|
{%- for role in roles %}
|
|
{{role.name}}:
|
|
map_merge:
|
|
list_concat:
|
|
- {get_attr: [{{role.name}}, ansible_host_vars_map]}
|
|
{%- endfor %}
|
|
|
|
BlacklistedHostnames:
|
|
type: OS::Heat::Value
|
|
properties:
|
|
value:
|
|
list_concat:
|
|
{%- for role in roles %}
|
|
- {get_attr: [{{role.name}}, blacklist_hostname]}
|
|
{%- endfor %}
|
|
|
|
# Post deployment steps for all roles
|
|
AllNodesDeploySteps:
|
|
type: OS::TripleO::PostDeploySteps
|
|
depends_on:
|
|
- AllNodesExtraConfig
|
|
properties:
|
|
servers:
|
|
{%- for role in roles %}
|
|
{{role.name}}: {get_attr: [{{role.name}}Servers, value]}
|
|
{%- endfor %}
|
|
EndpointMap: {get_attr: [EndpointMapData, value]}
|
|
role_data:
|
|
{%- for role in roles %}
|
|
{{role.name}}: {get_attr: [{{role.name}}ServiceChainRoleData, value]}
|
|
{%- endfor %}
|
|
{%- for role in roles %}
|
|
{{role.name}}Count: {get_param: {{role.name}}Count}
|
|
{%- endfor %}
|
|
ServiceNetMapLower: {get_attr: [ServiceNetMap, service_net_map_lower]}
|
|
PingTestGatewayIPsMap:
|
|
{%- for role in roles %}
|
|
{{role.name}}:
|
|
yaql:
|
|
expression: list($.data.where($ != null and len($) > 0)).flatten()
|
|
data:
|
|
- {get_attr: [Networks, net_attributes_map, ctlplane, subnets, {get_param: {{role.name}}ControlPlaneSubnet}, gateway_ip]}
|
|
{%- for network in networks %}
|
|
{%- if network.enabled|default(true) and network.name in role.networks|default([]) %}
|
|
{%- if role.networks is mapping %}
|
|
{%- set _role_net_subnet = role.networks[network.name]['subnet'] %}
|
|
{%- else %}
|
|
{%- set _role_net_subnet = network.name_lower + '_subnet' %}
|
|
{%- endif %}
|
|
- {get_attr: [Networks, net_attributes_map, {{network.name_lower}}, subnets, {{ _role_net_subnet }}, gateway_ip]}
|
|
{%- endif %}
|
|
{%- endfor %}
|
|
{%- endfor %}
|
|
PingTestIpsMap:
|
|
{%- for role in roles %}
|
|
{{role.name}}:
|
|
list_join:
|
|
- ' '
|
|
- - yaql:
|
|
expression: coalesce($.data, []).first(null)
|
|
data: {get_attr: [{{role.name}}, ip_address]}
|
|
{%- for network in networks %}
|
|
{%- if network.enabled|default(true) and network.name in role.networks|default([]) %}
|
|
- yaql:
|
|
expression: coalesce($.data, []).first(null)
|
|
data: {get_attr: [{{role.name}}, {{network.name_lower}}_ip_address]}
|
|
{%- endif %}
|
|
{%- endfor %}
|
|
{%- endfor %}
|
|
HostsEntry: {get_attr: [HostsEntryValue, value]}
|
|
EnabledServices:
|
|
list_concat:
|
|
{%- for role in roles %}
|
|
- {get_attr: [{{role.name}}ServiceNames, value]}
|
|
{%- endfor %}
|
|
ControlVirtualIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
|
|
EnabledNetworks:
|
|
{%- for network in networks if network.enabled|default(true) %}
|
|
- {{ network.name }}
|
|
{%- endfor %}
|
|
NetVipMap: {get_attr: [VipMap, net_ip_map]}
|
|
CloudNames: {get_attr: [CloudNames, value]}
|
|
UndercloudHostsEntries: {get_param: UndercloudHostsEntries}
|
|
ExtraHostsEntries: {get_param: ExtraHostFileEntries}
|
|
VipHostsEntries:
|
|
if:
|
|
- add_vips_to_etc_hosts
|
|
- {get_attr: [VipHosts, value]}
|
|
- []
|
|
KeystoneResourcesConfigs:
|
|
map_merge:
|
|
{% for role in roles %}
|
|
- get_attr: [{{role.name}}ServiceChainRoleData, value, keystone_resources]
|
|
{% endfor %}
|
|
NetCidrMap: {get_attr: [NetCidrMapValue, value]}
|
|
|
|
outputs:
|
|
ManagedEndpoints:
|
|
description: Asserts that the keystone endpoints have been provisioned.
|
|
value: true
|
|
KeystoneURL:
|
|
description: URL for the Overcloud Keystone service
|
|
value: {get_attr: [EndpointMapData, value, KeystonePublic, uri_no_suffix]}
|
|
KeystoneAdminVip:
|
|
description: Keystone Admin VIP endpoint
|
|
# Note that these nested get_attr functions require a dependency
|
|
# relationship between VipMap and ServiceNetMap, since we can't determine
|
|
# which attributes of VipMap are used until after ServiceNetMap's attribute
|
|
# values are available. If this is ever reworked to not use nested
|
|
# get_attr, that dependency can be removed.
|
|
value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, KeystoneAdminApiNetwork]}]}
|
|
EndpointMap:
|
|
description: |
|
|
Mapping of the resources with the needed info for their endpoints.
|
|
This includes the protocol used, the IP, port and also a full
|
|
representation of the URI.
|
|
value: {get_attr: [EndpointMapData, value]}
|
|
HostsEntry:
|
|
description: |
|
|
The content that should be appended to your /etc/hosts if you want to get
|
|
hostname-based access to the deployed nodes (useful for testing without
|
|
setting up a DNS).
|
|
value:
|
|
list_concat_unique:
|
|
- {get_attr: [HostsEntryValue, value]}
|
|
- {get_attr: [VipHosts, value]}
|
|
EnabledServices:
|
|
description: The services enabled on each role
|
|
value:
|
|
{%- for role in roles %}
|
|
{{role.name}}: {get_attr: [{{role.name}}ServiceNames, value]}
|
|
{%- endfor %}
|
|
RoleData:
|
|
description: The configuration data associated with each role
|
|
value:
|
|
{%- for role in roles %}
|
|
{{role.name}}: {get_attr: [{{role.name}}ServiceChainRoleData, value]}
|
|
{%- endfor %}
|
|
RoleConfig:
|
|
description: The configuration workflows associated with each role
|
|
value: {get_attr: [AllNodesDeploySteps, RoleConfig]}
|
|
RoleNetIpMap:
|
|
description: Mapping of each network to a list of IPs for each role
|
|
value:
|
|
{%- for role in roles %}
|
|
{{role.name}}: {get_attr: [{{role.name}}IpListMap, net_ip_map]}
|
|
{%- endfor %}
|
|
RoleGroupVars:
|
|
description: Mapping of roles to ansible group_vars to be applied config in those roles
|
|
value:
|
|
{%- for role in roles %}
|
|
{{role.name}}:
|
|
map_merge:
|
|
- {get_attr: [{{role.name}}ServiceChainRoleData, value, ansible_group_vars]}
|
|
- {get_attr: [{{role.name}}GroupVars, value]}
|
|
- {get_attr: [{{role.name}}ConfigData, value]}
|
|
- any_errors_fatal: {get_param: {{role.name}}AnyErrorsFatal}
|
|
max_fail_percentage: {get_param: {{role.name}}MaxFailPercentage}
|
|
neutron_physical_bridge_name: {get_param: NeutronPhysicalBridge}
|
|
neutron_public_interface_name: {get_param: NeutronPublicInterface}
|
|
network_config_update: {get_param: {{role.name}}NetworkConfigUpdate}
|
|
tripleo_network_config_os_net_config_mappings: {get_param: NetConfigDataLookup}
|
|
deployed_server_port_map: {get_param: DeployedServerPortMap}
|
|
tripleo_network_config_override: {get_param: {{role.name}}NetConfigOverride}
|
|
tripleo_stack_name: {get_param: RootStackName}
|
|
{%- if role.name == 'ComputeOvsDpdk' %}
|
|
num_dpdk_interface_rx_queues: {get_param: NumDpdkInterfaceRxQueues}
|
|
{%- endif %}
|
|
- {get_param: {{role.name}}ExtraGroupVars}
|
|
{%- endfor %}
|
|
RoleNetHostnameMap:
|
|
description: Mapping of each network to a list of hostnames for each role
|
|
value:
|
|
{%- for role in roles %}
|
|
{{role.name}}: {get_attr: [{{role.name}}NetworkHostnameMap, value]}
|
|
{%- endfor %}
|
|
RoleTags:
|
|
description: Tags for each role, as defined in roles_data.yaml
|
|
value:
|
|
{%- for role in roles %}
|
|
{{role.name}}: {{role.tags|default([])}}
|
|
{%- endfor %}
|
|
VipMap:
|
|
description: Mapping of each network to VIP addresses. Also includes the Redis and OVN DBs VIPs.
|
|
value: {get_attr: [VipMap, net_ip_map]}
|
|
ServerIdData:
|
|
description: Mapping of each role to a list of nova server IDs and the bootstrap ID
|
|
value: {get_attr: [ServerIdMap, value]}
|
|
BlacklistedHostnames:
|
|
description: List of blacklisted hostnames
|
|
value: {get_attr: [BlacklistedHostnames, value]}
|
|
BlacklistedIpAddresses:
|
|
description: List of blacklisted ctlplane IP addresses
|
|
value: {get_attr: [BlacklistedIpAddresses, value]}
|
|
GlobalConfig:
|
|
description: The global_config (hieradata).
|
|
value: {get_attr: [GlobalConfig, value]}
|
|
RoleNetworkConfigMap:
|
|
description: Mapping of roles to network config
|
|
value:
|
|
{%- for role in roles %}
|
|
{{role.name}}: {get_attr: [{{role.name}}NetworkConfig, config]}
|
|
{%- endfor %}
|
|
AnsibleHostVarsMap:
|
|
description: Map of Ansible Host variables per role
|
|
value:
|
|
map_merge:
|
|
- {get_attr: [AnsibleHostVars, value]}
|
|
- {get_param: ExtraAnsibleHostVars}
|
|
TripleoHeatTemplatesJinja2RenderingDataSources:
|
|
description: The role_data and the network_data used when rendering the THT Jinja2 templates
|
|
value:
|
|
roles_data: {{ roles }}
|
|
networks_data: {{ networks }}
|
|
AdminPassword:
|
|
description: The password for the keystone admin account, used for monitoring, querying neutron etc.
|
|
value: {get_param: AdminPassword}
|
|
KeystoneRegion:
|
|
description: Keystone region for endpoint
|
|
value: {get_param: KeystoneRegion}
|