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.
74 controllerExtraConfig:
77 DEPRECATED use ControllerExtraConfig instead
79 NovaComputeExtraConfig:
82 DEPRECATED use ComputeExtraConfig instead
84 NeutronControlPlaneID:
87 description: Neutron ID or name for ctlplane network.
88 NeutronPublicInterface:
90 description: Which interface to add to the NeutronPhysicalBridge.
95 Control the IP allocation for the ControlVirtualIP port. E.g.
96 [{'ip_address':'1.2.3.4'}]
98 {%- for network in networks if network.vip|default(false) %}
99 {%- if network.name == 'External' %}
100 # TODO (dsneddon) Legacy name, eventually refactor to match network name
101 PublicVirtualFixedIPs:
104 Control the IP allocation for the PublicVirtualInterface port. E.g.
105 [{'ip_address':'1.2.3.4'}]
108 {{network.name}}VirtualFixedIPs:
111 Control the IP allocation for the {{network.name}}VirtualInterface port. E.g.
112 [{'ip_address':'1.2.3.4'}]
119 description: Salt for the rabbit cookie, change this to force the randomly generated rabbit cookie to change.
120 RedisVirtualFixedIPs:
123 Control the IP allocation for the virtual IP used by Redis. E.g.
124 [{'ip_address':'1.2.3.4'}]
127 default: 'localdomain'
130 The DNS domain used for the hosts. This must match the
131 overcloud_domain_name configured on the undercloud.
135 Extra properties or metadata passed to Nova for the created nodes in
136 the overcloud. It's accessible via the Nova metadata API.
139 # Compute-specific params
140 # FIXME(shardy) handle these deprecated names as they don't match compute.yaml
141 HypervisorNeutronPhysicalBridge:
144 An OVS bridge to create on each hypervisor. This defaults to br-ex the
145 same as the control plane nodes, as we have a uniform configuration of
146 the openvswitch agent. Typically should not need to be changed.
148 HypervisorNeutronPublicInterface:
150 description: What interface to add to the HypervisorNeutronPhysicalBridge.
155 description: Maxiumum batch size for creating nodes
158 # Jinja loop for Role in role_data.yaml
159 {% for role in roles %}
160 # Parameters generated for {{role.name}} Role
161 {{role.name}}Services:
162 description: A list of service resources (configured in the Heat
163 resource_registry) which represent nested stacks
164 for each service that should get installed on the {{role.name}} role.
165 type: comma_delimited_list
168 description: Number of {{role.name}} nodes to deploy
170 default: {{role.CountDefault|default(0)}}
172 {{role.name}}HostnameFormat:
175 Format for {{role.name}} node hostnames
176 Note %index% is translated into the index of the node, e.g 0/1/2 etc
177 and %stackname% is replaced with the stack name e.g overcloud
178 {% if role.HostnameFormatDefault %}
179 default: "{{role.HostnameFormatDefault}}"
181 default: "%stackname%-{{role.name.lower()}}-%index%"
183 {{role.name}}RemovalPolicies:
187 List of resources to be removed from {{role.name}} ResourceGroup when
188 doing an update which requires removal of specific resources.
189 Example format ComputeRemovalPolicies: [{'resource_list': ['0']}]
191 {{role.name}}SchedulerHints:
193 description: Optional scheduler hints to pass to nova
195 {%- if role.deprecated_param_scheduler_hints is defined %}
196 {{role.deprecated_param_scheduler_hints}}:
198 description: DEPRECATED - use {{role.name}}SchedulerHints instead
202 {{role.name}}Parameters:
204 description: Optional Role Specific parameters to be provided to service
208 # Identifiers to trigger tasks on nodes
213 Setting to a previously unused value during stack-update will trigger
214 package update on all nodes
219 Setting this to a unique value will re-run any deployment tasks which
220 perform configuration on a Heat stack-update.
225 Set to true to append per network Vips to /etc/hosts on each node.
227 DeploymentServerBlacklist:
229 type: comma_delimited_list
231 List of server hostnames to blacklist from any triggered deployments.
233 {% for role in roles %}
234 {%- if role.deprecated_param_scheduler_hints is defined %}
235 {%- if not parameter_groups_defined|default(false) %}
238 description: Do not use deprecated params, they will be removed.
240 {%- set parameter_groups_defined = true %}
242 - {{role.deprecated_param_scheduler_hints}}
247 add_vips_to_etc_hosts: {equals : [{get_param: AddVipsToEtcHosts}, True]}
252 type: OS::Heat::Value
261 IP: {get_attr: [VipMap, net_ip_map, ctlplane]}
262 HOST: {get_param: CloudNameCtlplane}
263 {%- for network in networks if network.vip|default(false) %}
264 {%- if network.name == 'External' %}
265 # Special case the External hostname param, which is CloudName
269 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
270 HOST: {get_param: CloudName}
271 {%- elif network.name == 'InternalApi' %}
272 # Special case the Internal API hostname param, which is CloudNameInternal
276 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
277 HOST: {get_param: CloudNameInternal}
278 {%- elif network.name == 'StorageMgmt' %}
279 # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
283 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
284 HOST: {get_param: CloudNameStorageManagement}
289 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
290 HOST: {get_param: CloudName{{network.name}}}
294 HeatAuthEncryptionKey:
295 type: OS::TripleO::RandomString
298 type: OS::TripleO::RandomString
303 type: OS::TripleO::RandomString
308 type: OS::Heat::Value
314 - {get_attr: [Networks, net_cidr_map]}
315 - ctlplane: {get_attr: [ControlVirtualIP, subnets, 0, cidr]}
317 ctlplane: {get_param: NeutronControlPlaneID}
319 disabled: {get_attr: [ControlVirtualIP, subnets, 0, cidr]}
322 type: OS::TripleO::ServiceNetMap
325 type: OS::TripleO::EndpointMap
328 ctlplane: {get_param: CloudNameCtlplane}
329 {%- for network in networks if network.vip|default(false) %}
330 {%- if network.name == 'External' %}
331 # Special case the External hostname param, which is CloudName
332 {{network.name_lower}}: {get_param: CloudName}
333 {%- elif network.name == 'InternalApi' %}
334 # Special case the Internal API hostname param, which is CloudNameInternal
335 {{network.name_lower}}: {get_param: CloudNameInternal}
336 {%- elif network.name == 'StorageMgmt' %}
337 # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
338 {{network.name_lower}}: {get_param: CloudNameStorageManagement}
340 {{network.name_lower}}: {get_param: CloudName{{network.name}}}
343 NetIpMap: {get_attr: [VipMap, net_ip_map]}
344 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
347 type: OS::Heat::Value
350 value: {get_attr: [EndpointMap, endpoint_map]}
353 type: OS::TripleO::Ssh::KnownHostsConfig
358 {% for role in roles %}
359 - {get_attr: [{{role.name}}, known_hosts_entry]}
362 # Jinja loop for Role in roles_data.yaml
363 {% for role in roles %}
364 # Resources generated for {{role.name}} Role
365 {{role.name}}ServiceChain:
366 type: OS::TripleO::Services
369 get_param: {{role.name}}Services
370 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
372 net_cidr_map: {get_attr: [NetCidrMapValue, value]}
373 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
374 DefaultPasswords: {get_attr: [DefaultPasswords, passwords]}
375 RoleName: {{role.name}}
376 RoleParameters: {get_param: {{role.name}}Parameters}
378 # Lookup of role_data via heat outputs is slow, so workaround this by caching
379 # the value in an OS::Heat::Value resource
380 {{role.name}}ServiceChainRoleData:
381 type: OS::Heat::Value
384 value: {get_attr: [{{role.name}}ServiceChain, role_data]}
386 {{role.name}}ServiceConfigSettings:
387 type: OS::Heat::Value
392 - get_attr: [{{role.name}}ServiceChainRoleData, value, config_settings]
394 - get_attr: [{{r.name}}ServiceChainRoleData, value, global_config_settings]
396 # This next step combines two yaql passes:
397 # - The inner one does a deep merge on the service_config_settings for all roles
398 # - The outer one filters the map based on the services enabled for the role
399 # then merges the result into one map.
401 expression: let(root => $) -> $.data.map.items().where($[0] in coalesce($root.data.services, [])).select($[1]).reduce($1.mergeWith($2), {})
405 expression: $.data.where($ != null).reduce($1.mergeWith($2), {})
408 - get_attr: [{{r.name}}ServiceChainRoleData, value, service_config_settings]
410 services: {get_attr: [{{role.name}}ServiceNames, value]}
412 {{role.name}}MergedConfigSettings:
413 type: OS::Heat::Value
418 global_config_settings: {}
419 service_config_settings: {}
420 merged_config_settings:
422 - get_attr: [{{role.name}}ServiceConfigSettings, value]
423 - get_param: ExtraConfig
424 {%- if role.name == 'Controller' %}
426 - get_param: controllerExtraConfig
427 - get_param: {{role.name}}ExtraConfig
428 {%- elif role.name == 'Compute' %}
430 - get_param: NovaComputeExtraConfig
431 - get_param: {{role.name}}ExtraConfig
433 - get_param: {{role.name}}ExtraConfig
436 # Filter any null/None service_names which may be present due to mapping
437 # of services to OS::Heat::None
438 {{role.name}}ServiceNames:
439 type: OS::Heat::Value
440 depends_on: {{role.name}}ServiceChain
442 type: comma_delimited_list
445 expression: coalesce($.data, []).where($ != null)
446 data: {get_attr: [{{role.name}}ServiceChainRoleData, value, service_names]}
448 {{role.name}}HostsDeployment:
449 type: OS::Heat::StructuredDeployments
451 name: {{role.name}}HostsDeployment
452 config: {get_attr: [hostsConfig, config_id]}
453 servers: {get_attr: [{{role.name}}Servers, value]}
455 {{role.name}}SshKnownHostsDeployment:
456 type: OS::Heat::StructuredDeployments
458 name: {{role.name}}SshKnownHostsDeployment
459 config: {get_resource: SshKnownHostsConfig}
460 servers: {get_attr: [{{role.name}}Servers, value]}
462 {{role.name}}AllNodesDeployment:
463 type: OS::TripleO::AllNodesDeployment
465 {% for role_inner in roles %}
466 - {{role_inner.name}}HostsDeployment
469 name: {{role.name}}AllNodesDeployment
470 config: {get_attr: [allNodesConfig, config_id]}
471 servers: {get_attr: [{{role.name}}Servers, value]}
473 # Note we have to use yaql to look up the first hostname/ip in the
474 # list because heat path based attributes operate on the attribute
475 # inside the ResourceGroup, not the exposed list ref discussion in
476 # https://bugs.launchpad.net/heat/+bug/1640488
477 # The coalesce is needed because $.data is None during heat validation
480 expression: coalesce($.data, []).first(null)
481 data: {get_attr: [{{role.name}}, hostname]}
484 expression: coalesce($.data, []).first(null)
485 data: {get_attr: [{{role.name}}, ip_address]}
487 {{role.name}}AllNodesValidationDeployment:
488 type: OS::Heat::StructuredDeployments
489 depends_on: {{role.name}}AllNodesDeployment
491 name: {{role.name}}AllNodesValidationDeployment
492 config: {get_resource: AllNodesValidationConfig}
493 servers: {get_attr: [{{role.name}}Servers, value]}
495 {{role.name}}IpListMap:
496 type: OS::TripleO::Network::Ports::NetIpListMap
498 ControlPlaneIpList: {get_attr: [{{role.name}}, ip_address]}
499 {%- for network in networks if network.enabled|default(true) %}
500 {{network.name}}IpList: {get_attr: [{{role.name}}, {{network.name_lower}}_ip_address]}
502 EnabledServices: {get_attr: [{{role.name}}ServiceNames, value]}
503 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
504 ServiceHostnameList: {get_attr: [{{role.name}}, hostname]}
505 NetworkHostnameMap: {get_attr: [{{role.name}}NetworkHostnameMap, value]}
507 {{role.name}}NetworkHostnameMap:
508 type: OS::Heat::Value
512 # Note (shardy) this somewhat complex yaql may be replaced
513 # with a map_deep_merge function in ocata. It merges the
514 # list of maps, but appends to colliding lists so we can
515 # create a map of lists for all nodes for each network
517 expression: dict($.data.where($ != null).flatten().selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
519 - {get_attr: [{{role.name}}, hostname_map]}
522 type: OS::Heat::ResourceGroup
526 max_batch_size: {get_param: NodeCreateBatchSize}
528 count: {get_param: {{role.name}}Count}
529 removal_policies: {get_param: {{role.name}}RemovalPolicies}
531 type: OS::TripleO::{{role.name}}
533 CloudDomain: {get_param: CloudDomain}
534 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
535 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
538 template: {get_param: {{role.name}}HostnameFormat}
540 '%stackname%': {get_param: 'OS::stack_name'}
542 # Note, SchedulerHints must be defined here, not only in the
543 # nested template, as it can contain %index%
544 {{role.name}}SchedulerHints:
546 {%- if role.deprecated_param_scheduler_hints is defined %}
547 - {get_param: {{role.deprecated_param_scheduler_hints}}}
549 - {get_param: {{role.name}}SchedulerHints}
550 ServiceConfigSettings: {get_attr: [{{role.name}}ServiceConfigSettings, value]}
551 ServiceNames: {get_attr: [{{role.name}}ServiceNames, value]}
552 MonitoringSubscriptions: {get_attr: [{{role.name}}ServiceChainRoleData, value, monitoring_subscriptions]}
553 ServiceMetadataSettings: {get_attr: [{{role.name}}ServiceChainRoleData, value, service_metadata_settings]}
554 DeploymentServerBlacklistDict: {get_attr: [DeploymentServerBlacklistDict, value]}
555 RoleParameters: {get_param: {{role.name}}Parameters}
558 {% for role in roles %}
559 {{role.name}}Servers:
560 type: OS::Heat::Value
561 depends_on: {{role.name}}
566 expression: let(servers=>switch(isDict($.data.servers) => $.data.servers, true => {})) -> $servers.deleteAll($servers.keys().where($servers[$] = null))
568 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
571 # This is a different format to *Servers, as it creates a map of lists
572 # whereas *Servers creates a map of maps with keys of the nested resource names
574 type: OS::Heat::Value
578 {% for role in roles %}
579 {{role.name}}: {get_attr: [{{role.name}}, nova_server_resource]}
583 expression: coalesce($.data, []).first(null)
584 data: {get_attr: [{{primary_role_name}}, nova_server_resource]}
586 # This resource just creates a dict out of the DeploymentServerBlacklist,
587 # which is a list. The dict is used in the role templates to set a condition
588 # on whether to create the deployment resources. We can't use the list
589 # directly because there is no way to ask Heat if a list contains a specific
591 DeploymentServerBlacklistDict:
592 type: OS::Heat::Value
601 hostname: {get_param: DeploymentServerBlacklist}
604 type: OS::TripleO::Hosts::SoftwareConfig
610 - add_vips_to_etc_hosts
611 - {get_attr: [VipHosts, value]}
614 {% for role in roles %}
617 - {get_attr: [{{role.name}}, hosts_entry]}
621 type: OS::TripleO::AllNodes::SoftwareConfig
623 {%- for network in networks if network.vip|default(false) %}
624 {%- if network.name == 'External' %}
625 # Special case the External hostname param, which is CloudName
626 cloud_name_{{network.name_lower}}: {get_param: CloudName}
627 {%- elif network.name == 'InternalApi' %}
628 # Special case the Internal API hostname param, which is CloudNameInternal
629 cloud_name_{{network.name_lower}}: {get_param: CloudNameInternal}
630 {%- elif network.name == 'StorageMgmt' %}
631 # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
632 cloud_name_{{network.name_lower}}: {get_param: CloudNameStorageManagement}
634 cloud_name_{{network.name_lower}}: {get_param: CloudName{{network.name}}}
637 cloud_name_ctlplane: {get_param: CloudNameCtlplane}
641 {% for role in roles %}
642 - {get_attr: [{{role.name}}ServiceNames, value]}
647 $.data.groups.flatten()
650 {% for role in roles %}
651 - {get_attr: [{{role.name}}ServiceChainRoleData, value, logging_groups]}
656 $.data.sources.flatten()
659 {% for role in roles %}
660 - {get_attr: [{{role.name}}ServiceChainRoleData, value, logging_sources]}
662 controller_ips: {get_attr: [{{primary_role_name}}, ip_address]}
663 controller_names: {get_attr: [{{primary_role_name}}, hostname]}
665 # Note (shardy) this somewhat complex yaql may be replaced
666 # with a map_deep_merge function in ocata. It merges the
667 # list of maps, but appends to colliding lists when a service
668 # is deployed on more than one role
670 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
673 {% for role in roles %}
674 - {get_attr: [{{role.name}}IpListMap, service_ips]}
678 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
681 {% for role in roles %}
682 - {get_attr: [{{role.name}}IpListMap, service_hostnames]}
684 short_service_node_names:
686 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
689 {% for role in roles %}
690 - {get_attr: [{{role.name}}IpListMap, short_service_hostnames]}
692 short_service_bootstrap_node:
694 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten().first()]))
697 {% for role in roles %}
698 - {get_attr: [{{role.name}}IpListMap, short_service_bootstrap_hostnames]}
700 NetVipMap: {get_attr: [VipMap, net_ip_map]}
701 RedisVirtualIP: {get_attr: [RedisVirtualIP, ip_address]}
702 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
703 DeployIdentifier: {get_param: DeployIdentifier}
704 UpdateIdentifier: {get_param: UpdateIdentifier}
707 type: OS::TripleO::RandomString
712 type: OS::TripleO::RandomString
715 salt: {get_param: RabbitCookieSalt}
718 type: OS::TripleO::DefaultPasswords
720 DefaultMysqlRootPassword: {get_attr: [MysqlRootPassword, value]}
721 DefaultRabbitCookie: {get_attr: [RabbitCookie, value]}
722 DefaultHeatAuthEncryptionKey: {get_attr: [HeatAuthEncryptionKey, value]}
723 DefaultPcsdPassword: {get_attr: [PcsdPassword, value]}
724 DefaultHorizonSecret: {get_attr: [HorizonSecret, value]}
726 # creates the network architecture
728 type: OS::TripleO::Network
731 type: OS::TripleO::Network::Ports::ControlPlaneVipPort
734 name: control_virtual_ip
735 network: {get_param: NeutronControlPlaneID}
736 fixed_ips: {get_param: ControlFixedIPs}
737 replacement_policy: AUTO
741 type: OS::TripleO::Network::Ports::RedisVipPort
743 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
744 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
745 PortName: redis_virtual_ip
746 NetworkName: {get_attr: [ServiceNetMap, service_net_map, RedisNetwork]}
748 FixedIPs: {get_param: RedisVirtualFixedIPs}
750 {%- for network in networks if network.vip|default(false) %}
751 {%- if network.name == 'External' %}
752 # The public VIP is on the External net, falls back to ctlplane
755 type: OS::TripleO::Network::Ports::ExternalVipPort
757 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
758 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
759 PortName: public_virtual_ip
760 FixedIPs: {get_param: PublicVirtualFixedIPs}
761 {%- elif network.name == 'StorageMgmt' %}
762 {{network.name}}VirtualIP:
764 type: OS::TripleO::Network::Ports::{{network.name}}VipPort
766 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
767 PortName: storage_management_virtual_ip
768 FixedIPs: {get_param: {{network.name}}VirtualFixedIPs}
770 {{network.name}}VirtualIP:
772 type: OS::TripleO::Network::Ports::{{network.name}}VipPort
774 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
775 PortName: {{network.name_lower}}_virtual_ip
776 FixedIPs: {get_param: {{network.name}}VirtualFixedIPs}
781 type: OS::TripleO::Network::Ports::NetVipMap
783 ControlPlaneIp: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
784 {%- for network in networks if network.vip|default(false) %}
785 {%- if network.name == 'External' %}
786 ExternalIp: {get_attr: [PublicVirtualIP, ip_address]}
787 ExternalIpUri: {get_attr: [PublicVirtualIP, ip_address_uri]}
789 {{network.name}}Ip: {get_attr: [{{network.name}}VirtualIP, ip_address]}
790 {{network.name}}IpUri: {get_attr: [{{network.name}}VirtualIP, ip_address_uri]}
793 # No tenant or management VIP required
794 # Because of nested get_attr functions in the KeystoneAdminVip output, we
795 # can't determine which attributes of VipMap are used until after
796 # ServiceNetMap's attribute values are available.
797 depends_on: ServiceNetMap
799 # All Nodes Validations
800 AllNodesValidationConfig:
801 type: OS::TripleO::AllNodes::Validation
807 {%- for network in networks if network.enabled|default(true) %}
809 expression: coalesce($.data, []).first(null)
810 data: {get_attr: [{{primary_role_name}}, {{network.name_lower}}_ip_address]}
814 type: OS::TripleO::Tasks::UpdateWorkflow
816 {% for role in roles %}
817 - {{role.name}}AllNodesDeployment
821 {% for role in roles %}
822 {{role.name}}: {get_attr: [{{role.name}}Servers, value]}
825 deploy_identifier: {get_param: DeployIdentifier}
826 update_identifier: {get_param: UpdateIdentifier}
828 # Optional ExtraConfig for all nodes - all roles are passed in here, but
829 # the nested template may configure each role differently (or not at all)
831 type: OS::TripleO::AllNodesExtraConfig
834 {% for role in roles %}
835 - {{role.name}}AllNodesValidationDeployment
839 {% for role in roles %}
840 {{role.name}}: {get_attr: [{{role.name}}Servers, value]}
843 # Post deployment steps for all roles
845 type: OS::TripleO::PostDeploySteps
847 - AllNodesExtraConfig
848 {% for role in roles %}
849 - {{role.name}}AllNodesDeployment
853 {% for role in roles %}
854 {{role.name}}: {get_attr: [{{role.name}}Servers, value]}
856 stack_name: {get_param: 'OS::stack_name'}
857 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
858 ctlplane_service_ips:
859 # Note (shardy) this somewhat complex yaql may be replaced
860 # with a map_deep_merge function in ocata. It merges the
861 # list of maps, but appends to colliding lists when a service
862 # is deployed on more than one role
864 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
867 {% for role in roles %}
868 - {get_attr: [{{role.name}}IpListMap, ctlplane_service_ips]}
871 {% for role in roles %}
874 - {get_attr: [{{role.name}}ServiceChainRoleData, value]}
875 - {get_attr: [{{role.name}}MergedConfigSettings, value]}
878 ServerOsCollectConfigData:
879 type: OS::Heat::Value
883 {% for role in roles %}
884 {{role.name}}: {get_attr: [{{role.name}}, attributes, os_collect_config]}
887 DeployedServerEnvironment:
888 type: OS::TripleO::DeployedServerEnvironment
891 {% for role in roles %}
892 {{role.name}}DeployedServerCount: {get_param: {{role.name}}Count}
896 - {get_attr: [VipMap, net_ip_map]}
897 - redis: {get_attr: [RedisVirtualIP, ip_address]}
898 DeployedServerPortMap:
901 {% for role in roles %}
902 - {get_attr: [{{role.name}}, deployed_server_port_map]}
904 DeployedServerDeploymentSwiftDataMap:
907 {% for role in roles %}
908 - {get_attr: [{{role.name}}, deployed_server_deployment_swift_data_map]}
915 - {get_attr: [ServerOsCollectConfigData, value, {{primary_role_name}}, '0', request, metadata_url]}
921 description: Asserts that the keystone endpoints have been provisioned.
924 description: URL for the Overcloud Keystone service
925 value: {get_attr: [EndpointMapData, value, KeystonePublic, uri]}
927 description: Keystone Admin VIP endpoint
928 # Note that these nested get_attr functions require a dependency
929 # relationship between VipMap and ServiceNetMap, since we can't determine
930 # which attributes of VipMap are used until after ServiceNetMap's attribute
931 # values are available. If this is ever reworked to not use nested
932 # get_attr, that dependency can be removed.
933 value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, KeystoneAdminApiNetwork]}]}
936 Mapping of the resources with the needed info for their endpoints.
937 This includes the protocol used, the IP, port and also a full
938 representation of the URI.
939 value: {get_attr: [EndpointMapData, value]}
942 The content that should be appended to your /etc/hosts if you want to get
943 hostname-based access to the deployed nodes (useful for testing without
948 - - {get_attr: [hostsConfig, hosts_entries]}
949 - - {get_attr: [VipHosts, value]}
951 description: The services enabled on each role
953 {% for role in roles %}
954 {{role.name}}: {get_attr: [{{role.name}}ServiceNames, value]}
957 description: The configuration data associated with each role
959 {% for role in roles %}
962 - {get_attr: [{{role.name}}ServiceChainRoleData, value]}
963 - {get_attr: [{{role.name}}MergedConfigSettings, value]}
966 description: The configuration workflows associated with each role
967 value: {get_attr: [AllNodesDeploySteps, RoleConfig]}
969 description: Mapping of each network to a list of IPs for each role
971 {% for role in roles %}
972 {{role.name}}: {get_attr: [{{role.name}}IpListMap, net_ip_map]}
975 description: Mapping of each network to a list of hostnames for each role
977 {% for role in roles %}
978 {{role.name}}: {get_attr: [{{role.name}}NetworkHostnameMap, value]}
980 ServerOsCollectConfigData:
981 description: The os-collect-config configuration associated with each server resource
982 value: {get_attr: [ServerOsCollectConfigData, value]}
984 description: Mapping of each network to VIP addresses. Also includes the Redis VIP.
987 - {get_attr: [VipMap, net_ip_map]}
988 - redis: {get_attr: [RedisVirtualIP, ip_address]}
990 description: Mapping of each role to a list of nova server IDs and the bootstrap ID
991 value: {get_attr: [ServerIdMap, value]}
992 DeployedServerEnvironment:
994 Environment data that can be used as input into the services stack when
996 value: {get_attr: [DeployedServerEnvironment, deployed_server_environment]}