1 {%- set primary_role = [roles[0]] -%}
2 {%- for role in roles -%}
3 {%- if 'primary' in role.tags and 'controller' in role.tags -%}
4 {%- set _ = primary_role.pop() -%}
5 {%- set _ = primary_role.append(role) -%}
8 {%- set primary_role_name = primary_role[0].name -%}
9 # primary role is: {{primary_role_name}}
10 heat_template_version: pike
13 Deploy an OpenStack environment, consisting of several node types (roles),
14 Controller, Compute, BlockStorage, SwiftStorage and CephStorage. The Storage
15 roles enable independent scaling of the storage components, but the minimal
16 deployment is one Controller and one Compute node.
19 # TODO(shadower): we should probably use the parameter groups to put
23 # Common parameters (not specific to a role)
24 {%- for network in networks if network.vip|default(false) %}
25 {%- if network.name == 'External' %}
26 # Special case the External hostname param, which is CloudName
28 default: overcloud.localdomain
29 description: The DNS name of this cloud. E.g. ci-overcloud.tripleo.org
31 {%- elif network.name == 'InternalApi' %}
32 # Special case the Internal API hostname param, which is CloudNameInternal
34 default: overcloud.{{network.name.lower()}}.localdomain
36 The DNS name of this cloud's {{network.name_lower}} endpoint. E.g.
37 'ci-overcloud.{{network.name.lower()}}.tripleo.org'.
39 {%- elif network.name == 'StorageMgmt' %}
40 # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
41 CloudNameStorageManagement:
42 default: overcloud.{{network.name.lower()}}.localdomain
44 The DNS name of this cloud's {{network.name_lower}} endpoint. E.g.
45 'ci-overcloud.{{network.name.lower()}}.tripleo.org'.
48 CloudName{{network.name}}:
49 default: overcloud.{{network.name.lower()}}.localdomain
51 The DNS name of this cloud's {{network.name_lower}} endpoint. E.g.
52 'ci-overcloud.{{network.name.lower()}}.tripleo.org'.
57 default: overcloud.ctlplane.localdomain
59 The DNS name of this cloud's provisioning network endpoint. E.g.
60 'ci-overcloud.ctlplane.tripleo.org'.
65 Additional hiera configuration to inject into the cluster.
67 {%- for role in roles %}
68 {{role.name}}ExtraConfig:
71 Role specific additional hiera configuration to inject into the cluster.
73 {%- if role.deprecated_param_extraconfig is defined %}
74 {{role.deprecated_param_extraconfig}}:
77 DEPRECATED use {{role.name}}ExtraConfig instead
81 NeutronControlPlaneID:
84 description: Neutron ID or name for ctlplane network.
85 NeutronPublicInterface:
87 description: Which interface to add to the NeutronPhysicalBridge.
92 Control the IP allocation for the ControlVirtualIP port. E.g.
93 [{'ip_address':'1.2.3.4'}]
95 {%- for network in networks if network.vip|default(false) %}
96 {%- if network.name == 'External' %}
97 # TODO (dsneddon) Legacy name, eventually refactor to match network name
98 PublicVirtualFixedIPs:
101 Control the IP allocation for the PublicVirtualInterface port. E.g.
102 [{'ip_address':'1.2.3.4'}]
105 {{network.name}}VirtualFixedIPs:
108 Control the IP allocation for the {{network.name}}VirtualInterface port. E.g.
109 [{'ip_address':'1.2.3.4'}]
116 description: Salt for the rabbit cookie, change this to force the randomly generated rabbit cookie to change.
117 RedisVirtualFixedIPs:
120 Control the IP allocation for the virtual IP used by Redis. E.g.
121 [{'ip_address':'1.2.3.4'}]
124 default: 'localdomain'
127 The DNS domain used for the hosts. This must match the
128 overcloud_domain_name configured on the undercloud.
132 Extra properties or metadata passed to Nova for the created nodes in
133 the overcloud. It's accessible via the Nova metadata API.
136 # Compute-specific params
137 # FIXME(shardy) handle these deprecated names as they don't match compute.yaml
138 HypervisorNeutronPhysicalBridge:
141 An OVS bridge to create on each hypervisor. This defaults to br-ex the
142 same as the control plane nodes, as we have a uniform configuration of
143 the openvswitch agent. Typically should not need to be changed.
145 HypervisorNeutronPublicInterface:
147 description: What interface to add to the HypervisorNeutronPhysicalBridge.
152 description: Maxiumum batch size for creating nodes
155 # Jinja loop for Role in role_data.yaml
156 {% for role in roles %}
157 # Parameters generated for {{role.name}} Role
158 {{role.name}}Services:
159 description: A list of service resources (configured in the Heat
160 resource_registry) which represent nested stacks
161 for each service that should get installed on the {{role.name}} role.
162 type: comma_delimited_list
165 description: Number of {{role.name}} nodes to deploy
167 default: {{role.CountDefault|default(0)}}
169 {{role.name}}HostnameFormat:
172 Format for {{role.name}} node hostnames
173 Note %index% is translated into the index of the node, e.g 0/1/2 etc
174 and %stackname% is replaced with the stack name e.g overcloud
175 {% if role.HostnameFormatDefault %}
176 default: "{{role.HostnameFormatDefault}}"
178 default: "%stackname%-{{role.name.lower()}}-%index%"
180 {{role.name}}RemovalPolicies:
184 List of resources to be removed from {{role.name}} ResourceGroup when
185 doing an update which requires removal of specific resources.
186 Example format ComputeRemovalPolicies: [{'resource_list': ['0']}]
188 {{role.name}}SchedulerHints:
190 description: Optional scheduler hints to pass to nova
192 {%- if role.deprecated_param_scheduler_hints is defined %}
193 {{role.deprecated_param_scheduler_hints}}:
195 description: DEPRECATED - use {{role.name}}SchedulerHints instead
199 {{role.name}}Parameters:
201 description: Optional Role Specific parameters to be provided to service
205 # Identifiers to trigger tasks on nodes
210 Setting to a previously unused value during stack-update will trigger
211 package update on all nodes
216 Setting this to a unique value will re-run any deployment tasks which
217 perform configuration on a Heat stack-update.
222 Set to true to append per network Vips to /etc/hosts on each node.
224 DeploymentServerBlacklist:
226 type: comma_delimited_list
228 List of server hostnames to blacklist from any triggered deployments.
230 {% for role in roles %}
231 {%- if role.deprecated_param_scheduler_hints is defined or role.deprecated_param_extraconfig is defined %}
232 {%- if not parameter_groups_defined|default(false) %}
235 description: Do not use deprecated params, they will be removed.
237 {%- set parameter_groups_defined = true %}
240 {%- if role.deprecated_param_scheduler_hints is defined %}
241 - {{role.deprecated_param_scheduler_hints}}
243 {%- if role.deprecated_param_extraconfig is defined %}
244 - {{role.deprecated_param_extraconfig}}
249 add_vips_to_etc_hosts: {equals : [{get_param: AddVipsToEtcHosts}, True]}
254 type: OS::Heat::Value
263 IP: {get_attr: [VipMap, net_ip_map, ctlplane]}
264 HOST: {get_param: CloudNameCtlplane}
265 {%- for network in networks if network.vip|default(false) %}
266 {%- if network.name == 'External' %}
267 # Special case the External hostname param, which is CloudName
271 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
272 HOST: {get_param: CloudName}
273 {%- elif network.name == 'InternalApi' %}
274 # Special case the Internal API hostname param, which is CloudNameInternal
278 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
279 HOST: {get_param: CloudNameInternal}
280 {%- elif network.name == 'StorageMgmt' %}
281 # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
285 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
286 HOST: {get_param: CloudNameStorageManagement}
291 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
292 HOST: {get_param: CloudName{{network.name}}}
296 HeatAuthEncryptionKey:
297 type: OS::TripleO::RandomString
300 type: OS::TripleO::RandomString
305 type: OS::TripleO::RandomString
310 type: OS::Heat::Value
316 - {get_attr: [Networks, net_cidr_map]}
317 - ctlplane: {get_attr: [ControlVirtualIP, subnets, 0, cidr]}
319 ctlplane: {get_param: NeutronControlPlaneID}
321 disabled: {get_attr: [ControlVirtualIP, subnets, 0, cidr]}
324 type: OS::TripleO::ServiceNetMap
327 type: OS::TripleO::EndpointMap
330 ctlplane: {get_param: CloudNameCtlplane}
331 {%- for network in networks if network.vip|default(false) %}
332 {%- if network.name == 'External' %}
333 # Special case the External hostname param, which is CloudName
334 {{network.name_lower}}: {get_param: CloudName}
335 {%- elif network.name == 'InternalApi' %}
336 # Special case the Internal API hostname param, which is CloudNameInternal
337 {{network.name_lower}}: {get_param: CloudNameInternal}
338 {%- elif network.name == 'StorageMgmt' %}
339 # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
340 {{network.name_lower}}: {get_param: CloudNameStorageManagement}
342 {{network.name_lower}}: {get_param: CloudName{{network.name}}}
345 NetIpMap: {get_attr: [VipMap, net_ip_map]}
346 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
349 type: OS::Heat::Value
352 value: {get_attr: [EndpointMap, endpoint_map]}
355 type: OS::TripleO::Ssh::KnownHostsConfig
360 {% for role in roles %}
361 - {get_attr: [{{role.name}}, known_hosts_entry]}
364 # Jinja loop for Role in roles_data.yaml
365 {% for role in roles %}
366 # Resources generated for {{role.name}} Role
367 {{role.name}}ServiceChain:
368 type: OS::TripleO::Services
371 get_param: {{role.name}}Services
372 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
374 net_cidr_map: {get_attr: [NetCidrMapValue, value]}
375 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
376 DefaultPasswords: {get_attr: [DefaultPasswords, passwords]}
377 RoleName: {{role.name}}
378 RoleParameters: {get_param: {{role.name}}Parameters}
380 # Lookup of role_data via heat outputs is slow, so workaround this by caching
381 # the value in an OS::Heat::Value resource
382 {{role.name}}ServiceChainRoleData:
383 type: OS::Heat::Value
386 value: {get_attr: [{{role.name}}ServiceChain, role_data]}
388 {{role.name}}ServiceConfigSettings:
389 type: OS::Heat::Value
394 - get_attr: [{{role.name}}ServiceChainRoleData, value, config_settings]
396 - get_attr: [{{r.name}}ServiceChainRoleData, value, global_config_settings]
398 # This next step combines two yaql passes:
399 # - The inner one does a deep merge on the service_config_settings for all roles
400 # - The outer one filters the map based on the services enabled for the role
401 # then merges the result into one map.
403 expression: let(root => $) -> $.data.map.items().where($[0] in coalesce($root.data.services, [])).select($[1]).reduce($1.mergeWith($2), {})
407 expression: $.data.where($ != null).reduce($1.mergeWith($2), {})
410 - get_attr: [{{r.name}}ServiceChainRoleData, value, service_config_settings]
412 services: {get_attr: [{{role.name}}ServiceNames, value]}
414 {{role.name}}MergedConfigSettings:
415 type: OS::Heat::Value
420 global_config_settings: {}
421 service_config_settings: {}
422 merged_config_settings:
424 - get_attr: [{{role.name}}ServiceConfigSettings, value]
425 - get_param: ExtraConfig
426 {%- if role.deprecated_param_extraconfig is defined %}
427 - get_param: {{role.deprecated_param_extraconfig}}
429 - get_param: {{role.name}}ExtraConfig
431 # Filter any null/None service_names which may be present due to mapping
432 # of services to OS::Heat::None
433 {{role.name}}ServiceNames:
434 type: OS::Heat::Value
435 depends_on: {{role.name}}ServiceChain
437 type: comma_delimited_list
440 expression: coalesce($.data, []).where($ != null)
441 data: {get_attr: [{{role.name}}ServiceChainRoleData, value, service_names]}
443 {{role.name}}HostsDeployment:
444 type: OS::Heat::StructuredDeployments
446 name: {{role.name}}HostsDeployment
447 config: {get_attr: [hostsConfig, config_id]}
448 servers: {get_attr: [{{role.name}}Servers, value]}
450 {{role.name}}SshKnownHostsDeployment:
451 type: OS::Heat::StructuredDeployments
453 name: {{role.name}}SshKnownHostsDeployment
454 config: {get_resource: SshKnownHostsConfig}
455 servers: {get_attr: [{{role.name}}Servers, value]}
457 {{role.name}}AllNodesDeployment:
458 type: OS::TripleO::AllNodesDeployment
460 {% for role_inner in roles %}
461 - {{role_inner.name}}HostsDeployment
464 name: {{role.name}}AllNodesDeployment
465 config: {get_attr: [allNodesConfig, config_id]}
466 servers: {get_attr: [{{role.name}}Servers, value]}
468 # Note we have to use yaql to look up the first hostname/ip in the
469 # list because heat path based attributes operate on the attribute
470 # inside the ResourceGroup, not the exposed list ref discussion in
471 # https://bugs.launchpad.net/heat/+bug/1640488
472 # The coalesce is needed because $.data is None during heat validation
475 expression: coalesce($.data, []).first(null)
476 data: {get_attr: [{{role.name}}, hostname]}
479 expression: coalesce($.data, []).first(null)
480 data: {get_attr: [{{role.name}}, ip_address]}
482 {{role.name}}AllNodesValidationDeployment:
483 type: OS::Heat::StructuredDeployments
484 depends_on: {{role.name}}AllNodesDeployment
486 name: {{role.name}}AllNodesValidationDeployment
487 config: {get_resource: AllNodesValidationConfig}
488 servers: {get_attr: [{{role.name}}Servers, value]}
490 {{role.name}}IpListMap:
491 type: OS::TripleO::Network::Ports::NetIpListMap
493 ControlPlaneIpList: {get_attr: [{{role.name}}, ip_address]}
494 {%- for network in networks if network.enabled|default(true) %}
495 {{network.name}}IpList: {get_attr: [{{role.name}}, {{network.name_lower}}_ip_address]}
497 EnabledServices: {get_attr: [{{role.name}}ServiceNames, value]}
498 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
499 ServiceHostnameList: {get_attr: [{{role.name}}, hostname]}
500 NetworkHostnameMap: {get_attr: [{{role.name}}NetworkHostnameMap, value]}
502 {{role.name}}NetworkHostnameMap:
503 type: OS::Heat::Value
507 # Note (shardy) this somewhat complex yaql may be replaced
508 # with a map_deep_merge function in ocata. It merges the
509 # list of maps, but appends to colliding lists so we can
510 # create a map of lists for all nodes for each network
512 expression: dict($.data.where($ != null).flatten().selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
514 - {get_attr: [{{role.name}}, hostname_map]}
517 type: OS::Heat::ResourceGroup
521 max_batch_size: {get_param: NodeCreateBatchSize}
523 count: {get_param: {{role.name}}Count}
524 removal_policies: {get_param: {{role.name}}RemovalPolicies}
526 type: OS::TripleO::{{role.name}}
528 CloudDomain: {get_param: CloudDomain}
529 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
530 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
533 template: {get_param: {{role.name}}HostnameFormat}
535 '%stackname%': {get_param: 'OS::stack_name'}
537 # Note, SchedulerHints must be defined here, not only in the
538 # nested template, as it can contain %index%
539 {{role.name}}SchedulerHints:
541 {%- if role.deprecated_param_scheduler_hints is defined %}
542 - {get_param: {{role.deprecated_param_scheduler_hints}}}
544 - {get_param: {{role.name}}SchedulerHints}
545 ServiceConfigSettings: {get_attr: [{{role.name}}ServiceConfigSettings, value]}
546 ServiceNames: {get_attr: [{{role.name}}ServiceNames, value]}
547 MonitoringSubscriptions: {get_attr: [{{role.name}}ServiceChainRoleData, value, monitoring_subscriptions]}
548 ServiceMetadataSettings: {get_attr: [{{role.name}}ServiceChainRoleData, value, service_metadata_settings]}
549 DeploymentServerBlacklistDict: {get_attr: [DeploymentServerBlacklistDict, value]}
550 RoleParameters: {get_param: {{role.name}}Parameters}
553 {% for role in roles %}
554 {{role.name}}Servers:
555 type: OS::Heat::Value
556 depends_on: {{role.name}}
561 expression: let(servers=>switch(isDict($.data.servers) => $.data.servers, true => {})) -> $servers.deleteAll($servers.keys().where($servers[$] = null))
563 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
566 # This is a different format to *Servers, as it creates a map of lists
567 # whereas *Servers creates a map of maps with keys of the nested resource names
569 type: OS::Heat::Value
573 {% for role in roles %}
574 {{role.name}}: {get_attr: [{{role.name}}, nova_server_resource]}
578 expression: coalesce($.data, []).first(null)
579 data: {get_attr: [{{primary_role_name}}, nova_server_resource]}
581 # This resource just creates a dict out of the DeploymentServerBlacklist,
582 # which is a list. The dict is used in the role templates to set a condition
583 # on whether to create the deployment resources. We can't use the list
584 # directly because there is no way to ask Heat if a list contains a specific
586 DeploymentServerBlacklistDict:
587 type: OS::Heat::Value
596 hostname: {get_param: DeploymentServerBlacklist}
599 type: OS::TripleO::Hosts::SoftwareConfig
605 - add_vips_to_etc_hosts
606 - {get_attr: [VipHosts, value]}
609 {% for role in roles %}
612 - {get_attr: [{{role.name}}, hosts_entry]}
616 type: OS::TripleO::AllNodes::SoftwareConfig
618 {%- for network in networks if network.vip|default(false) %}
619 {%- if network.name == 'External' %}
620 # Special case the External hostname param, which is CloudName
621 cloud_name_{{network.name_lower}}: {get_param: CloudName}
622 {%- elif network.name == 'InternalApi' %}
623 # Special case the Internal API hostname param, which is CloudNameInternal
624 cloud_name_{{network.name_lower}}: {get_param: CloudNameInternal}
625 {%- elif network.name == 'StorageMgmt' %}
626 # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
627 cloud_name_{{network.name_lower}}: {get_param: CloudNameStorageManagement}
629 cloud_name_{{network.name_lower}}: {get_param: CloudName{{network.name}}}
632 cloud_name_ctlplane: {get_param: CloudNameCtlplane}
636 {% for role in roles %}
637 - {get_attr: [{{role.name}}ServiceNames, value]}
642 $.data.groups.flatten()
645 {% for role in roles %}
646 - {get_attr: [{{role.name}}ServiceChainRoleData, value, logging_groups]}
651 $.data.sources.flatten()
654 {% for role in roles %}
655 - {get_attr: [{{role.name}}ServiceChainRoleData, value, logging_sources]}
657 controller_ips: {get_attr: [{{primary_role_name}}, ip_address]}
658 controller_names: {get_attr: [{{primary_role_name}}, hostname]}
660 # Note (shardy) this somewhat complex yaql may be replaced
661 # with a map_deep_merge function in ocata. It merges the
662 # list of maps, but appends to colliding lists when a service
663 # is deployed on more than one role
665 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
668 {% for role in roles %}
669 - {get_attr: [{{role.name}}IpListMap, service_ips]}
673 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
676 {% for role in roles %}
677 - {get_attr: [{{role.name}}IpListMap, service_hostnames]}
679 short_service_node_names:
681 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
684 {% for role in roles %}
685 - {get_attr: [{{role.name}}IpListMap, short_service_hostnames]}
687 short_service_bootstrap_node:
689 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten().first()]))
692 {% for role in roles %}
693 - {get_attr: [{{role.name}}IpListMap, short_service_bootstrap_hostnames]}
695 NetVipMap: {get_attr: [VipMap, net_ip_map]}
696 RedisVirtualIP: {get_attr: [RedisVirtualIP, ip_address]}
697 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
698 DeployIdentifier: {get_param: DeployIdentifier}
699 UpdateIdentifier: {get_param: UpdateIdentifier}
702 type: OS::TripleO::RandomString
707 type: OS::TripleO::RandomString
710 salt: {get_param: RabbitCookieSalt}
713 type: OS::TripleO::DefaultPasswords
715 DefaultMysqlRootPassword: {get_attr: [MysqlRootPassword, value]}
716 DefaultRabbitCookie: {get_attr: [RabbitCookie, value]}
717 DefaultHeatAuthEncryptionKey: {get_attr: [HeatAuthEncryptionKey, value]}
718 DefaultPcsdPassword: {get_attr: [PcsdPassword, value]}
719 DefaultHorizonSecret: {get_attr: [HorizonSecret, value]}
721 # creates the network architecture
723 type: OS::TripleO::Network
726 type: OS::TripleO::Network::Ports::ControlPlaneVipPort
729 name: control_virtual_ip
730 network: {get_param: NeutronControlPlaneID}
731 fixed_ips: {get_param: ControlFixedIPs}
732 replacement_policy: AUTO
736 type: OS::TripleO::Network::Ports::RedisVipPort
738 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
739 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
740 PortName: redis_virtual_ip
741 NetworkName: {get_attr: [ServiceNetMap, service_net_map, RedisNetwork]}
743 FixedIPs: {get_param: RedisVirtualFixedIPs}
745 {%- for network in networks if network.vip|default(false) %}
746 {%- if network.name == 'External' %}
747 # The public VIP is on the External net, falls back to ctlplane
750 type: OS::TripleO::Network::Ports::ExternalVipPort
752 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
753 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
754 PortName: public_virtual_ip
755 FixedIPs: {get_param: PublicVirtualFixedIPs}
756 {%- elif network.name == 'StorageMgmt' %}
757 {{network.name}}VirtualIP:
759 type: OS::TripleO::Network::Ports::{{network.name}}VipPort
761 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
762 PortName: storage_management_virtual_ip
763 FixedIPs: {get_param: {{network.name}}VirtualFixedIPs}
765 {{network.name}}VirtualIP:
767 type: OS::TripleO::Network::Ports::{{network.name}}VipPort
769 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
770 PortName: {{network.name_lower}}_virtual_ip
771 FixedIPs: {get_param: {{network.name}}VirtualFixedIPs}
776 type: OS::TripleO::Network::Ports::NetVipMap
778 ControlPlaneIp: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
779 {%- for network in networks if network.vip|default(false) %}
780 {%- if network.name == 'External' %}
781 ExternalIp: {get_attr: [PublicVirtualIP, ip_address]}
782 ExternalIpUri: {get_attr: [PublicVirtualIP, ip_address_uri]}
784 {{network.name}}Ip: {get_attr: [{{network.name}}VirtualIP, ip_address]}
785 {{network.name}}IpUri: {get_attr: [{{network.name}}VirtualIP, ip_address_uri]}
788 # No tenant or management VIP required
789 # Because of nested get_attr functions in the KeystoneAdminVip output, we
790 # can't determine which attributes of VipMap are used until after
791 # ServiceNetMap's attribute values are available.
792 depends_on: ServiceNetMap
794 # All Nodes Validations
795 AllNodesValidationConfig:
796 type: OS::TripleO::AllNodes::Validation
802 {%- for network in networks if network.enabled|default(true) %}
804 expression: coalesce($.data, []).first(null)
805 data: {get_attr: [{{primary_role_name}}, {{network.name_lower}}_ip_address]}
809 type: OS::TripleO::Tasks::UpdateWorkflow
811 {% for role in roles %}
812 - {{role.name}}AllNodesDeployment
816 {% for role in roles %}
817 {{role.name}}: {get_attr: [{{role.name}}Servers, value]}
820 deploy_identifier: {get_param: DeployIdentifier}
821 update_identifier: {get_param: UpdateIdentifier}
823 # Optional ExtraConfig for all nodes - all roles are passed in here, but
824 # the nested template may configure each role differently (or not at all)
826 type: OS::TripleO::AllNodesExtraConfig
829 {% for role in roles %}
830 - {{role.name}}AllNodesValidationDeployment
834 {% for role in roles %}
835 {{role.name}}: {get_attr: [{{role.name}}Servers, value]}
838 # Post deployment steps for all roles
840 type: OS::TripleO::PostDeploySteps
842 - AllNodesExtraConfig
843 {% for role in roles %}
844 - {{role.name}}AllNodesDeployment
848 {% for role in roles %}
849 {{role.name}}: {get_attr: [{{role.name}}Servers, value]}
851 stack_name: {get_param: 'OS::stack_name'}
852 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
853 ctlplane_service_ips:
854 # Note (shardy) this somewhat complex yaql may be replaced
855 # with a map_deep_merge function in ocata. It merges the
856 # list of maps, but appends to colliding lists when a service
857 # is deployed on more than one role
859 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
862 {% for role in roles %}
863 - {get_attr: [{{role.name}}IpListMap, ctlplane_service_ips]}
866 {% for role in roles %}
869 - {get_attr: [{{role.name}}ServiceChainRoleData, value]}
870 - {get_attr: [{{role.name}}MergedConfigSettings, value]}
873 ServerOsCollectConfigData:
874 type: OS::Heat::Value
878 {% for role in roles %}
879 {{role.name}}: {get_attr: [{{role.name}}, attributes, os_collect_config]}
882 DeployedServerEnvironment:
883 type: OS::TripleO::DeployedServerEnvironment
886 {% for role in roles %}
887 {{role.name}}DeployedServerCount: {get_param: {{role.name}}Count}
891 - {get_attr: [VipMap, net_ip_map]}
892 - redis: {get_attr: [RedisVirtualIP, ip_address]}
893 DeployedServerPortMap:
896 {% for role in roles %}
897 - {get_attr: [{{role.name}}, deployed_server_port_map]}
899 DeployedServerDeploymentSwiftDataMap:
902 {% for role in roles %}
903 - {get_attr: [{{role.name}}, deployed_server_deployment_swift_data_map]}
910 - {get_attr: [ServerOsCollectConfigData, value, {{primary_role_name}}, '0', request, metadata_url]}
916 description: Asserts that the keystone endpoints have been provisioned.
919 description: URL for the Overcloud Keystone service
920 value: {get_attr: [EndpointMapData, value, KeystonePublic, uri]}
922 description: Keystone Admin VIP endpoint
923 # Note that these nested get_attr functions require a dependency
924 # relationship between VipMap and ServiceNetMap, since we can't determine
925 # which attributes of VipMap are used until after ServiceNetMap's attribute
926 # values are available. If this is ever reworked to not use nested
927 # get_attr, that dependency can be removed.
928 value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, KeystoneAdminApiNetwork]}]}
931 Mapping of the resources with the needed info for their endpoints.
932 This includes the protocol used, the IP, port and also a full
933 representation of the URI.
934 value: {get_attr: [EndpointMapData, value]}
937 The content that should be appended to your /etc/hosts if you want to get
938 hostname-based access to the deployed nodes (useful for testing without
943 - - {get_attr: [hostsConfig, hosts_entries]}
944 - - {get_attr: [VipHosts, value]}
946 description: The services enabled on each role
948 {% for role in roles %}
949 {{role.name}}: {get_attr: [{{role.name}}ServiceNames, value]}
952 description: The configuration data associated with each role
954 {% for role in roles %}
957 - {get_attr: [{{role.name}}ServiceChainRoleData, value]}
958 - {get_attr: [{{role.name}}MergedConfigSettings, value]}
961 description: The configuration workflows associated with each role
962 value: {get_attr: [AllNodesDeploySteps, RoleConfig]}
964 description: Mapping of each network to a list of IPs for each role
966 {% for role in roles %}
967 {{role.name}}: {get_attr: [{{role.name}}IpListMap, net_ip_map]}
970 description: Mapping of each network to a list of hostnames for each role
972 {% for role in roles %}
973 {{role.name}}: {get_attr: [{{role.name}}NetworkHostnameMap, value]}
975 ServerOsCollectConfigData:
976 description: The os-collect-config configuration associated with each server resource
977 value: {get_attr: [ServerOsCollectConfigData, value]}
979 description: Mapping of each network to VIP addresses. Also includes the Redis VIP.
982 - {get_attr: [VipMap, net_ip_map]}
983 - redis: {get_attr: [RedisVirtualIP, ip_address]}
985 description: Mapping of each role to a list of nova server IDs and the bootstrap ID
986 value: {get_attr: [ServerIdMap, value]}
987 DeployedServerEnvironment:
989 Environment data that can be used as input into the services stack when
991 value: {get_attr: [DeployedServerEnvironment, deployed_server_environment]}