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 {% if role.name != 'Compute' %}
192 {{role.name}}SchedulerHints:
194 NovaComputeSchedulerHints:
197 description: Optional scheduler hints to pass to nova
200 {{role.name}}Parameters:
202 description: Optional Role Specific parameters to be provided to service
206 # Identifiers to trigger tasks on nodes
211 Setting to a previously unused value during stack-update will trigger
212 package update on all nodes
217 Setting this to a unique value will re-run any deployment tasks which
218 perform configuration on a Heat stack-update.
223 Set to true to append per network Vips to /etc/hosts on each node.
225 DeploymentServerBlacklist:
227 type: comma_delimited_list
229 List of server hostnames to blacklist from any triggered deployments.
233 description: Do not use deprecated params, they will be removed.
235 - controllerExtraConfig
236 - NovaComputeExtraConfig
239 add_vips_to_etc_hosts: {equals : [{get_param: AddVipsToEtcHosts}, True]}
244 type: OS::Heat::Value
253 IP: {get_attr: [VipMap, net_ip_map, ctlplane]}
254 HOST: {get_param: CloudNameCtlplane}
255 {%- for network in networks if network.vip|default(false) %}
256 {%- if network.name == 'External' %}
257 # Special case the External hostname param, which is CloudName
261 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
262 HOST: {get_param: CloudName}
263 {%- elif network.name == 'InternalApi' %}
264 # Special case the Internal API hostname param, which is CloudNameInternal
268 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
269 HOST: {get_param: CloudNameInternal}
270 {%- elif network.name == 'StorageMgmt' %}
271 # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
275 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
276 HOST: {get_param: CloudNameStorageManagement}
281 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
282 HOST: {get_param: CloudName{{network.name}}}
286 HeatAuthEncryptionKey:
287 type: OS::TripleO::RandomString
290 type: OS::TripleO::RandomString
295 type: OS::TripleO::RandomString
300 type: OS::Heat::Value
306 - {get_attr: [Networks, net_cidr_map]}
307 - ctlplane: {get_attr: [ControlVirtualIP, subnets, 0, cidr]}
309 ctlplane: {get_param: NeutronControlPlaneID}
311 disabled: {get_attr: [ControlVirtualIP, subnets, 0, cidr]}
314 type: OS::TripleO::ServiceNetMap
317 type: OS::TripleO::EndpointMap
320 ctlplane: {get_param: CloudNameCtlplane}
321 {%- for network in networks if network.vip|default(false) %}
322 {%- if network.name == 'External' %}
323 # Special case the External hostname param, which is CloudName
324 {{network.name_lower}}: {get_param: CloudName}
325 {%- elif network.name == 'InternalApi' %}
326 # Special case the Internal API hostname param, which is CloudNameInternal
327 {{network.name_lower}}: {get_param: CloudNameInternal}
328 {%- elif network.name == 'StorageMgmt' %}
329 # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
330 {{network.name_lower}}: {get_param: CloudNameStorageManagement}
332 {{network.name_lower}}: {get_param: CloudName{{network.name}}}
335 NetIpMap: {get_attr: [VipMap, net_ip_map]}
336 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
339 type: OS::Heat::Value
342 value: {get_attr: [EndpointMap, endpoint_map]}
345 type: OS::TripleO::Ssh::KnownHostsConfig
350 {% for role in roles %}
351 - {get_attr: [{{role.name}}, known_hosts_entry]}
354 # Jinja loop for Role in roles_data.yaml
355 {% for role in roles %}
356 # Resources generated for {{role.name}} Role
357 {{role.name}}ServiceChain:
358 type: OS::TripleO::Services
361 get_param: {{role.name}}Services
362 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
364 net_cidr_map: {get_attr: [NetCidrMapValue, value]}
365 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
366 DefaultPasswords: {get_attr: [DefaultPasswords, passwords]}
367 RoleName: {{role.name}}
368 RoleParameters: {get_param: {{role.name}}Parameters}
370 # Lookup of role_data via heat outputs is slow, so workaround this by caching
371 # the value in an OS::Heat::Value resource
372 {{role.name}}ServiceChainRoleData:
373 type: OS::Heat::Value
376 value: {get_attr: [{{role.name}}ServiceChain, role_data]}
378 {{role.name}}ServiceConfigSettings:
379 type: OS::Heat::Value
384 - get_attr: [{{role.name}}ServiceChainRoleData, value, config_settings]
386 - get_attr: [{{r.name}}ServiceChainRoleData, value, global_config_settings]
388 # This next step combines two yaql passes:
389 # - The inner one does a deep merge on the service_config_settings for all roles
390 # - The outer one filters the map based on the services enabled for the role
391 # then merges the result into one map.
393 expression: let(root => $) -> $.data.map.items().where($[0] in coalesce($root.data.services, [])).select($[1]).reduce($1.mergeWith($2), {})
397 expression: $.data.where($ != null).reduce($1.mergeWith($2), {})
400 - get_attr: [{{r.name}}ServiceChainRoleData, value, service_config_settings]
402 services: {get_attr: [{{role.name}}ServiceNames, value]}
404 {{role.name}}MergedConfigSettings:
405 type: OS::Heat::Value
410 global_config_settings: {}
411 service_config_settings: {}
412 merged_config_settings:
414 - get_attr: [{{role.name}}ServiceConfigSettings, value]
415 - get_param: ExtraConfig
416 {%- if role.name == 'Controller' %}
418 - get_param: controllerExtraConfig
419 - get_param: {{role.name}}ExtraConfig
420 {%- elif role.name == 'Compute' %}
422 - get_param: NovaComputeExtraConfig
423 - get_param: {{role.name}}ExtraConfig
425 - get_param: {{role.name}}ExtraConfig
428 # Filter any null/None service_names which may be present due to mapping
429 # of services to OS::Heat::None
430 {{role.name}}ServiceNames:
431 type: OS::Heat::Value
432 depends_on: {{role.name}}ServiceChain
434 type: comma_delimited_list
437 expression: coalesce($.data, []).where($ != null)
438 data: {get_attr: [{{role.name}}ServiceChainRoleData, value, service_names]}
440 {{role.name}}HostsDeployment:
441 type: OS::Heat::StructuredDeployments
443 name: {{role.name}}HostsDeployment
444 config: {get_attr: [hostsConfig, config_id]}
445 servers: {get_attr: [{{role.name}}Servers, value]}
447 {{role.name}}SshKnownHostsDeployment:
448 type: OS::Heat::StructuredDeployments
450 name: {{role.name}}SshKnownHostsDeployment
451 config: {get_resource: SshKnownHostsConfig}
452 servers: {get_attr: [{{role.name}}Servers, value]}
454 {{role.name}}AllNodesDeployment:
455 type: OS::TripleO::AllNodesDeployment
457 {% for role_inner in roles %}
458 - {{role_inner.name}}HostsDeployment
461 name: {{role.name}}AllNodesDeployment
462 config: {get_attr: [allNodesConfig, config_id]}
463 servers: {get_attr: [{{role.name}}Servers, value]}
465 # Note we have to use yaql to look up the first hostname/ip in the
466 # list because heat path based attributes operate on the attribute
467 # inside the ResourceGroup, not the exposed list ref discussion in
468 # https://bugs.launchpad.net/heat/+bug/1640488
469 # The coalesce is needed because $.data is None during heat validation
472 expression: coalesce($.data, []).first(null)
473 data: {get_attr: [{{role.name}}, hostname]}
476 expression: coalesce($.data, []).first(null)
477 data: {get_attr: [{{role.name}}, ip_address]}
479 {{role.name}}AllNodesValidationDeployment:
480 type: OS::Heat::StructuredDeployments
481 depends_on: {{role.name}}AllNodesDeployment
483 name: {{role.name}}AllNodesValidationDeployment
484 config: {get_resource: AllNodesValidationConfig}
485 servers: {get_attr: [{{role.name}}Servers, value]}
487 {{role.name}}IpListMap:
488 type: OS::TripleO::Network::Ports::NetIpListMap
490 ControlPlaneIpList: {get_attr: [{{role.name}}, ip_address]}
491 {%- for network in networks if network.enabled|default(true) %}
492 {{network.name}}IpList: {get_attr: [{{role.name}}, {{network.name_lower}}_ip_address]}
494 EnabledServices: {get_attr: [{{role.name}}ServiceNames, value]}
495 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
496 ServiceHostnameList: {get_attr: [{{role.name}}, hostname]}
497 NetworkHostnameMap: {get_attr: [{{role.name}}NetworkHostnameMap, value]}
499 {{role.name}}NetworkHostnameMap:
500 type: OS::Heat::Value
504 # Note (shardy) this somewhat complex yaql may be replaced
505 # with a map_deep_merge function in ocata. It merges the
506 # list of maps, but appends to colliding lists so we can
507 # create a map of lists for all nodes for each network
509 expression: dict($.data.where($ != null).flatten().selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
511 - {get_attr: [{{role.name}}, hostname_map]}
514 type: OS::Heat::ResourceGroup
518 max_batch_size: {get_param: NodeCreateBatchSize}
520 count: {get_param: {{role.name}}Count}
521 removal_policies: {get_param: {{role.name}}RemovalPolicies}
523 type: OS::TripleO::{{role.name}}
525 CloudDomain: {get_param: CloudDomain}
526 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
527 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
530 template: {get_param: {{role.name}}HostnameFormat}
532 '%stackname%': {get_param: 'OS::stack_name'}
534 {% if role.name != 'Compute' %}
535 {{role.name}}SchedulerHints: {get_param: {{role.name}}SchedulerHints}
537 NovaComputeSchedulerHints: {get_param: NovaComputeSchedulerHints}
539 ServiceConfigSettings: {get_attr: [{{role.name}}ServiceConfigSettings, value]}
540 ServiceNames: {get_attr: [{{role.name}}ServiceNames, value]}
541 MonitoringSubscriptions: {get_attr: [{{role.name}}ServiceChainRoleData, value, monitoring_subscriptions]}
542 ServiceMetadataSettings: {get_attr: [{{role.name}}ServiceChainRoleData, value, service_metadata_settings]}
543 DeploymentServerBlacklistDict: {get_attr: [DeploymentServerBlacklistDict, value]}
544 RoleParameters: {get_param: {{role.name}}Parameters}
547 {% for role in roles %}
548 {{role.name}}Servers:
549 type: OS::Heat::Value
550 depends_on: {{role.name}}
555 expression: let(servers=>switch(isDict($.data.servers) => $.data.servers, true => {})) -> $servers.deleteAll($servers.keys().where($servers[$] = null))
557 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
560 # This is a different format to *Servers, as it creates a map of lists
561 # whereas *Servers creates a map of maps with keys of the nested resource names
563 type: OS::Heat::Value
567 {% for role in roles %}
568 {{role.name}}: {get_attr: [{{role.name}}, nova_server_resource]}
572 expression: coalesce($.data, []).first(null)
573 data: {get_attr: [{{primary_role_name}}, nova_server_resource]}
575 # This resource just creates a dict out of the DeploymentServerBlacklist,
576 # which is a list. The dict is used in the role templates to set a condition
577 # on whether to create the deployment resources. We can't use the list
578 # directly because there is no way to ask Heat if a list contains a specific
580 DeploymentServerBlacklistDict:
581 type: OS::Heat::Value
590 hostname: {get_param: DeploymentServerBlacklist}
593 type: OS::TripleO::Hosts::SoftwareConfig
599 - add_vips_to_etc_hosts
600 - {get_attr: [VipHosts, value]}
603 {% for role in roles %}
606 - {get_attr: [{{role.name}}, hosts_entry]}
610 type: OS::TripleO::AllNodes::SoftwareConfig
612 {%- for network in networks if network.vip|default(false) %}
613 {%- if network.name == 'External' %}
614 # Special case the External hostname param, which is CloudName
615 cloud_name_{{network.name_lower}}: {get_param: CloudName}
616 {%- elif network.name == 'InternalApi' %}
617 # Special case the Internal API hostname param, which is CloudNameInternal
618 cloud_name_{{network.name_lower}}: {get_param: CloudNameInternal}
619 {%- elif network.name == 'StorageMgmt' %}
620 # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
621 cloud_name_{{network.name_lower}}: {get_param: CloudNameStorageManagement}
623 cloud_name_{{network.name_lower}}: {get_param: CloudName{{network.name}}}
626 cloud_name_ctlplane: {get_param: CloudNameCtlplane}
630 {% for role in roles %}
631 - {get_attr: [{{role.name}}ServiceNames, value]}
636 $.data.groups.flatten()
639 {% for role in roles %}
640 - {get_attr: [{{role.name}}ServiceChainRoleData, value, logging_groups]}
645 $.data.sources.flatten()
648 {% for role in roles %}
649 - {get_attr: [{{role.name}}ServiceChainRoleData, value, logging_sources]}
651 controller_ips: {get_attr: [{{primary_role_name}}, ip_address]}
652 controller_names: {get_attr: [{{primary_role_name}}, hostname]}
654 # Note (shardy) this somewhat complex yaql may be replaced
655 # with a map_deep_merge function in ocata. It merges the
656 # list of maps, but appends to colliding lists when a service
657 # is deployed on more than one role
659 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
662 {% for role in roles %}
663 - {get_attr: [{{role.name}}IpListMap, service_ips]}
667 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
670 {% for role in roles %}
671 - {get_attr: [{{role.name}}IpListMap, service_hostnames]}
673 short_service_node_names:
675 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
678 {% for role in roles %}
679 - {get_attr: [{{role.name}}IpListMap, short_service_hostnames]}
681 short_service_bootstrap_node:
683 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten().first()]))
686 {% for role in roles %}
687 - {get_attr: [{{role.name}}IpListMap, short_service_bootstrap_hostnames]}
689 NetVipMap: {get_attr: [VipMap, net_ip_map]}
690 RedisVirtualIP: {get_attr: [RedisVirtualIP, ip_address]}
691 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
692 DeployIdentifier: {get_param: DeployIdentifier}
693 UpdateIdentifier: {get_param: UpdateIdentifier}
696 type: OS::TripleO::RandomString
701 type: OS::TripleO::RandomString
704 salt: {get_param: RabbitCookieSalt}
707 type: OS::TripleO::DefaultPasswords
709 DefaultMysqlRootPassword: {get_attr: [MysqlRootPassword, value]}
710 DefaultRabbitCookie: {get_attr: [RabbitCookie, value]}
711 DefaultHeatAuthEncryptionKey: {get_attr: [HeatAuthEncryptionKey, value]}
712 DefaultPcsdPassword: {get_attr: [PcsdPassword, value]}
713 DefaultHorizonSecret: {get_attr: [HorizonSecret, value]}
715 # creates the network architecture
717 type: OS::TripleO::Network
720 type: OS::TripleO::Network::Ports::ControlPlaneVipPort
723 name: control_virtual_ip
724 network: {get_param: NeutronControlPlaneID}
725 fixed_ips: {get_param: ControlFixedIPs}
726 replacement_policy: AUTO
730 type: OS::TripleO::Network::Ports::RedisVipPort
732 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
733 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
734 PortName: redis_virtual_ip
735 NetworkName: {get_attr: [ServiceNetMap, service_net_map, RedisNetwork]}
737 FixedIPs: {get_param: RedisVirtualFixedIPs}
739 {%- for network in networks if network.vip|default(false) %}
740 {%- if network.name == 'External' %}
741 # The public VIP is on the External net, falls back to ctlplane
744 type: OS::TripleO::Network::Ports::ExternalVipPort
746 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
747 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
748 PortName: public_virtual_ip
749 FixedIPs: {get_param: PublicVirtualFixedIPs}
750 {%- elif network.name == 'StorageMgmt' %}
751 {{network.name}}VirtualIP:
753 type: OS::TripleO::Network::Ports::{{network.name}}VipPort
755 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
756 PortName: storage_management_virtual_ip
757 FixedIPs: {get_param: {{network.name}}VirtualFixedIPs}
759 {{network.name}}VirtualIP:
761 type: OS::TripleO::Network::Ports::{{network.name}}VipPort
763 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
764 PortName: {{network.name_lower}}_virtual_ip
765 FixedIPs: {get_param: {{network.name}}VirtualFixedIPs}
770 type: OS::TripleO::Network::Ports::NetVipMap
772 ControlPlaneIp: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
773 {%- for network in networks if network.vip|default(false) %}
774 {%- if network.name == 'External' %}
775 ExternalIp: {get_attr: [PublicVirtualIP, ip_address]}
776 ExternalIpUri: {get_attr: [PublicVirtualIP, ip_address_uri]}
778 {{network.name}}Ip: {get_attr: [{{network.name}}VirtualIP, ip_address]}
779 {{network.name}}IpUri: {get_attr: [{{network.name}}VirtualIP, ip_address_uri]}
782 # No tenant or management VIP required
783 # Because of nested get_attr functions in the KeystoneAdminVip output, we
784 # can't determine which attributes of VipMap are used until after
785 # ServiceNetMap's attribute values are available.
786 depends_on: ServiceNetMap
788 # All Nodes Validations
789 AllNodesValidationConfig:
790 type: OS::TripleO::AllNodes::Validation
796 {%- for network in networks if network.enabled|default(true) %}
798 expression: coalesce($.data, []).first(null)
799 data: {get_attr: [{{primary_role_name}}, {{network.name_lower}}_ip_address]}
803 type: OS::TripleO::Tasks::UpdateWorkflow
805 {% for role in roles %}
806 - {{role.name}}AllNodesDeployment
810 {% for role in roles %}
811 {{role.name}}: {get_attr: [{{role.name}}Servers, value]}
814 deploy_identifier: {get_param: DeployIdentifier}
815 update_identifier: {get_param: UpdateIdentifier}
817 # Optional ExtraConfig for all nodes - all roles are passed in here, but
818 # the nested template may configure each role differently (or not at all)
820 type: OS::TripleO::AllNodesExtraConfig
823 {% for role in roles %}
824 - {{role.name}}AllNodesValidationDeployment
828 {% for role in roles %}
829 {{role.name}}: {get_attr: [{{role.name}}Servers, value]}
832 # Post deployment steps for all roles
834 type: OS::TripleO::PostDeploySteps
836 - AllNodesExtraConfig
837 {% for role in roles %}
838 - {{role.name}}AllNodesDeployment
842 {% for role in roles %}
843 {{role.name}}: {get_attr: [{{role.name}}Servers, value]}
845 stack_name: {get_param: 'OS::stack_name'}
846 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
847 ctlplane_service_ips:
848 # Note (shardy) this somewhat complex yaql may be replaced
849 # with a map_deep_merge function in ocata. It merges the
850 # list of maps, but appends to colliding lists when a service
851 # is deployed on more than one role
853 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
856 {% for role in roles %}
857 - {get_attr: [{{role.name}}IpListMap, ctlplane_service_ips]}
860 {% for role in roles %}
863 - {get_attr: [{{role.name}}ServiceChainRoleData, value]}
864 - {get_attr: [{{role.name}}MergedConfigSettings, value]}
867 ServerOsCollectConfigData:
868 type: OS::Heat::Value
872 {% for role in roles %}
873 {{role.name}}: {get_attr: [{{role.name}}, attributes, os_collect_config]}
876 DeployedServerEnvironment:
877 type: OS::TripleO::DeployedServerEnvironment
880 {% for role in roles %}
881 {{role.name}}DeployedServerCount: {get_param: {{role.name}}Count}
885 - {get_attr: [VipMap, net_ip_map]}
886 - redis: {get_attr: [RedisVirtualIP, ip_address]}
887 DeployedServerPortMap:
890 {% for role in roles %}
891 - {get_attr: [{{role.name}}, deployed_server_port_map]}
893 DeployedServerDeploymentSwiftDataMap:
896 {% for role in roles %}
897 - {get_attr: [{{role.name}}, deployed_server_deployment_swift_data_map]}
904 - {get_attr: [ServerOsCollectConfigData, value, {{primary_role_name}}, '0', request, metadata_url]}
910 description: Asserts that the keystone endpoints have been provisioned.
913 description: URL for the Overcloud Keystone service
914 value: {get_attr: [EndpointMapData, value, KeystonePublic, uri]}
916 description: Keystone Admin VIP endpoint
917 # Note that these nested get_attr functions require a dependency
918 # relationship between VipMap and ServiceNetMap, since we can't determine
919 # which attributes of VipMap are used until after ServiceNetMap's attribute
920 # values are available. If this is ever reworked to not use nested
921 # get_attr, that dependency can be removed.
922 value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, KeystoneAdminApiNetwork]}]}
925 Mapping of the resources with the needed info for their endpoints.
926 This includes the protocol used, the IP, port and also a full
927 representation of the URI.
928 value: {get_attr: [EndpointMapData, value]}
931 The content that should be appended to your /etc/hosts if you want to get
932 hostname-based access to the deployed nodes (useful for testing without
937 - - {get_attr: [hostsConfig, hosts_entries]}
938 - - {get_attr: [VipHosts, value]}
940 description: The services enabled on each role
942 {% for role in roles %}
943 {{role.name}}: {get_attr: [{{role.name}}ServiceNames, value]}
946 description: The configuration data associated with each role
948 {% for role in roles %}
951 - {get_attr: [{{role.name}}ServiceChainRoleData, value]}
952 - {get_attr: [{{role.name}}MergedConfigSettings, value]}
955 description: Mapping of each network to a list of IPs for each role
957 {% for role in roles %}
958 {{role.name}}: {get_attr: [{{role.name}}IpListMap, net_ip_map]}
961 description: Mapping of each network to a list of hostnames for each role
963 {% for role in roles %}
964 {{role.name}}: {get_attr: [{{role.name}}NetworkHostnameMap, value]}
966 ServerOsCollectConfigData:
967 description: The os-collect-config configuration associated with each server resource
968 value: {get_attr: [ServerOsCollectConfigData, value]}
970 description: Mapping of each network to VIP addresses. Also includes the Redis VIP.
973 - {get_attr: [VipMap, net_ip_map]}
974 - redis: {get_attr: [RedisVirtualIP, ip_address]}
976 description: Mapping of each role to a list of nova server IDs and the bootstrap ID
977 value: {get_attr: [ServerIdMap, value]}
978 DeployedServerEnvironment:
980 Environment data that can be used as input into the services stack when
982 value: {get_attr: [DeployedServerEnvironment, deployed_server_environment]}