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:
193 description: Optional scheduler hints to pass to nova
195 NovaComputeSchedulerHints:
196 description: DEPRECATED - use ComputeSchedulerHints instead
201 {{role.name}}Parameters:
203 description: Optional Role Specific parameters to be provided to service
207 # Identifiers to trigger tasks on nodes
212 Setting to a previously unused value during stack-update will trigger
213 package update on all nodes
218 Setting this to a unique value will re-run any deployment tasks which
219 perform configuration on a Heat stack-update.
224 Set to true to append per network Vips to /etc/hosts on each node.
226 DeploymentServerBlacklist:
228 type: comma_delimited_list
230 List of server hostnames to blacklist from any triggered deployments.
233 add_vips_to_etc_hosts: {equals : [{get_param: AddVipsToEtcHosts}, True]}
238 type: OS::Heat::Value
247 IP: {get_attr: [VipMap, net_ip_map, ctlplane]}
248 HOST: {get_param: CloudNameCtlplane}
249 {%- for network in networks if network.vip|default(false) %}
250 {%- if network.name == 'External' %}
251 # Special case the External hostname param, which is CloudName
255 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
256 HOST: {get_param: CloudName}
257 {%- elif network.name == 'InternalApi' %}
258 # Special case the Internal API hostname param, which is CloudNameInternal
262 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
263 HOST: {get_param: CloudNameInternal}
264 {%- elif network.name == 'StorageMgmt' %}
265 # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
269 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
270 HOST: {get_param: CloudNameStorageManagement}
275 IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
276 HOST: {get_param: CloudName{{network.name}}}
280 HeatAuthEncryptionKey:
281 type: OS::TripleO::RandomString
284 type: OS::TripleO::RandomString
289 type: OS::TripleO::RandomString
294 type: OS::Heat::Value
300 - {get_attr: [Networks, net_cidr_map]}
301 - ctlplane: {get_attr: [ControlVirtualIP, subnets, 0, cidr]}
303 ctlplane: {get_param: NeutronControlPlaneID}
305 disabled: {get_attr: [ControlVirtualIP, subnets, 0, cidr]}
308 type: OS::TripleO::ServiceNetMap
311 type: OS::TripleO::EndpointMap
314 ctlplane: {get_param: CloudNameCtlplane}
315 {%- for network in networks if network.vip|default(false) %}
316 {%- if network.name == 'External' %}
317 # Special case the External hostname param, which is CloudName
318 {{network.name_lower}}: {get_param: CloudName}
319 {%- elif network.name == 'InternalApi' %}
320 # Special case the Internal API hostname param, which is CloudNameInternal
321 {{network.name_lower}}: {get_param: CloudNameInternal}
322 {%- elif network.name == 'StorageMgmt' %}
323 # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
324 {{network.name_lower}}: {get_param: CloudNameStorageManagement}
326 {{network.name_lower}}: {get_param: CloudName{{network.name}}}
329 NetIpMap: {get_attr: [VipMap, net_ip_map]}
330 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
333 type: OS::Heat::Value
336 value: {get_attr: [EndpointMap, endpoint_map]}
339 type: OS::TripleO::Ssh::KnownHostsConfig
344 {% for role in roles %}
345 - {get_attr: [{{role.name}}, known_hosts_entry]}
348 # Jinja loop for Role in roles_data.yaml
349 {% for role in roles %}
350 # Resources generated for {{role.name}} Role
351 {{role.name}}ServiceChain:
352 type: OS::TripleO::Services
355 get_param: {{role.name}}Services
356 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
358 net_cidr_map: {get_attr: [NetCidrMapValue, value]}
359 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
360 DefaultPasswords: {get_attr: [DefaultPasswords, passwords]}
361 RoleName: {{role.name}}
362 RoleParameters: {get_param: {{role.name}}Parameters}
364 # Lookup of role_data via heat outputs is slow, so workaround this by caching
365 # the value in an OS::Heat::Value resource
366 {{role.name}}ServiceChainRoleData:
367 type: OS::Heat::Value
370 value: {get_attr: [{{role.name}}ServiceChain, role_data]}
372 {{role.name}}ServiceConfigSettings:
373 type: OS::Heat::Value
378 - get_attr: [{{role.name}}ServiceChainRoleData, value, config_settings]
380 - get_attr: [{{r.name}}ServiceChainRoleData, value, global_config_settings]
382 # This next step combines two yaql passes:
383 # - The inner one does a deep merge on the service_config_settings for all roles
384 # - The outer one filters the map based on the services enabled for the role
385 # then merges the result into one map.
387 expression: let(root => $) -> $.data.map.items().where($[0] in coalesce($root.data.services, [])).select($[1]).reduce($1.mergeWith($2), {})
391 expression: $.data.where($ != null).reduce($1.mergeWith($2), {})
394 - get_attr: [{{r.name}}ServiceChainRoleData, value, service_config_settings]
396 services: {get_attr: [{{role.name}}ServiceNames, value]}
398 {{role.name}}MergedConfigSettings:
399 type: OS::Heat::Value
404 global_config_settings: {}
405 service_config_settings: {}
406 merged_config_settings:
408 - get_attr: [{{role.name}}ServiceConfigSettings, value]
409 - get_param: ExtraConfig
410 {%- if role.name == 'Controller' %}
412 - get_param: controllerExtraConfig
413 - get_param: {{role.name}}ExtraConfig
414 {%- elif role.name == 'Compute' %}
416 - get_param: NovaComputeExtraConfig
417 - get_param: {{role.name}}ExtraConfig
419 - get_param: {{role.name}}ExtraConfig
422 # Filter any null/None service_names which may be present due to mapping
423 # of services to OS::Heat::None
424 {{role.name}}ServiceNames:
425 type: OS::Heat::Value
426 depends_on: {{role.name}}ServiceChain
428 type: comma_delimited_list
431 expression: coalesce($.data, []).where($ != null)
432 data: {get_attr: [{{role.name}}ServiceChainRoleData, value, service_names]}
434 {{role.name}}HostsDeployment:
435 type: OS::Heat::StructuredDeployments
437 name: {{role.name}}HostsDeployment
438 config: {get_attr: [hostsConfig, config_id]}
439 servers: {get_attr: [{{role.name}}Servers, value]}
441 {{role.name}}SshKnownHostsDeployment:
442 type: OS::Heat::StructuredDeployments
444 name: {{role.name}}SshKnownHostsDeployment
445 config: {get_resource: SshKnownHostsConfig}
446 servers: {get_attr: [{{role.name}}Servers, value]}
448 {{role.name}}AllNodesDeployment:
449 type: OS::TripleO::AllNodesDeployment
451 {% for role_inner in roles %}
452 - {{role_inner.name}}HostsDeployment
455 name: {{role.name}}AllNodesDeployment
456 config: {get_attr: [allNodesConfig, config_id]}
457 servers: {get_attr: [{{role.name}}Servers, value]}
459 # Note we have to use yaql to look up the first hostname/ip in the
460 # list because heat path based attributes operate on the attribute
461 # inside the ResourceGroup, not the exposed list ref discussion in
462 # https://bugs.launchpad.net/heat/+bug/1640488
463 # The coalesce is needed because $.data is None during heat validation
466 expression: coalesce($.data, []).first(null)
467 data: {get_attr: [{{role.name}}, hostname]}
470 expression: coalesce($.data, []).first(null)
471 data: {get_attr: [{{role.name}}, ip_address]}
473 {{role.name}}AllNodesValidationDeployment:
474 type: OS::Heat::StructuredDeployments
475 depends_on: {{role.name}}AllNodesDeployment
477 name: {{role.name}}AllNodesValidationDeployment
478 config: {get_resource: AllNodesValidationConfig}
479 servers: {get_attr: [{{role.name}}Servers, value]}
481 {{role.name}}IpListMap:
482 type: OS::TripleO::Network::Ports::NetIpListMap
484 ControlPlaneIpList: {get_attr: [{{role.name}}, ip_address]}
485 {%- for network in networks if network.enabled|default(true) %}
486 {{network.name}}IpList: {get_attr: [{{role.name}}, {{network.name_lower}}_ip_address]}
488 EnabledServices: {get_attr: [{{role.name}}ServiceNames, value]}
489 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
490 ServiceHostnameList: {get_attr: [{{role.name}}, hostname]}
491 NetworkHostnameMap: {get_attr: [{{role.name}}NetworkHostnameMap, value]}
493 {{role.name}}NetworkHostnameMap:
494 type: OS::Heat::Value
498 # Note (shardy) this somewhat complex yaql may be replaced
499 # with a map_deep_merge function in ocata. It merges the
500 # list of maps, but appends to colliding lists so we can
501 # create a map of lists for all nodes for each network
503 expression: dict($.data.where($ != null).flatten().selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
505 - {get_attr: [{{role.name}}, hostname_map]}
508 type: OS::Heat::ResourceGroup
512 max_batch_size: {get_param: NodeCreateBatchSize}
514 count: {get_param: {{role.name}}Count}
515 removal_policies: {get_param: {{role.name}}RemovalPolicies}
517 type: OS::TripleO::{{role.name}}
519 CloudDomain: {get_param: CloudDomain}
520 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
521 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
524 template: {get_param: {{role.name}}HostnameFormat}
526 '%stackname%': {get_param: 'OS::stack_name'}
528 {% if role.name != 'Compute' %}
529 {{role.name}}SchedulerHints: {get_param: {{role.name}}SchedulerHints}
531 NovaComputeSchedulerHints: {get_param: NovaComputeSchedulerHints}
533 ServiceConfigSettings: {get_attr: [{{role.name}}ServiceConfigSettings, value]}
534 ServiceNames: {get_attr: [{{role.name}}ServiceNames, value]}
535 MonitoringSubscriptions: {get_attr: [{{role.name}}ServiceChainRoleData, value, monitoring_subscriptions]}
536 ServiceMetadataSettings: {get_attr: [{{role.name}}ServiceChainRoleData, value, service_metadata_settings]}
537 DeploymentServerBlacklistDict: {get_attr: [DeploymentServerBlacklistDict, value]}
538 RoleParameters: {get_param: {{role.name}}Parameters}
541 {% for role in roles %}
542 {{role.name}}Servers:
543 type: OS::Heat::Value
544 depends_on: {{role.name}}
549 expression: let(servers=>switch(isDict($.data.servers) => $.data.servers, true => {})) -> $servers.deleteAll($servers.keys().where($servers[$] = null))
551 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
554 # This is a different format to *Servers, as it creates a map of lists
555 # whereas *Servers creates a map of maps with keys of the nested resource names
557 type: OS::Heat::Value
561 {% for role in roles %}
562 {{role.name}}: {get_attr: [{{role.name}}, nova_server_resource]}
566 expression: coalesce($.data, []).first(null)
567 data: {get_attr: [{{primary_role_name}}, nova_server_resource]}
569 # This resource just creates a dict out of the DeploymentServerBlacklist,
570 # which is a list. The dict is used in the role templates to set a condition
571 # on whether to create the deployment resources. We can't use the list
572 # directly because there is no way to ask Heat if a list contains a specific
574 DeploymentServerBlacklistDict:
575 type: OS::Heat::Value
584 hostname: {get_param: DeploymentServerBlacklist}
587 type: OS::TripleO::Hosts::SoftwareConfig
593 - add_vips_to_etc_hosts
594 - {get_attr: [VipHosts, value]}
597 {% for role in roles %}
600 - {get_attr: [{{role.name}}, hosts_entry]}
604 type: OS::TripleO::AllNodes::SoftwareConfig
606 {%- for network in networks if network.vip|default(false) %}
607 {%- if network.name == 'External' %}
608 # Special case the External hostname param, which is CloudName
609 cloud_name_{{network.name_lower}}: {get_param: CloudName}
610 {%- elif network.name == 'InternalApi' %}
611 # Special case the Internal API hostname param, which is CloudNameInternal
612 cloud_name_{{network.name_lower}}: {get_param: CloudNameInternal}
613 {%- elif network.name == 'StorageMgmt' %}
614 # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
615 cloud_name_{{network.name_lower}}: {get_param: CloudNameStorageManagement}
617 cloud_name_{{network.name_lower}}: {get_param: CloudName{{network.name}}}
620 cloud_name_ctlplane: {get_param: CloudNameCtlplane}
624 {% for role in roles %}
625 - {get_attr: [{{role.name}}ServiceNames, value]}
630 $.data.groups.flatten()
633 {% for role in roles %}
634 - {get_attr: [{{role.name}}ServiceChainRoleData, value, logging_groups]}
639 $.data.sources.flatten()
642 {% for role in roles %}
643 - {get_attr: [{{role.name}}ServiceChainRoleData, value, logging_sources]}
645 controller_ips: {get_attr: [{{primary_role_name}}, ip_address]}
646 controller_names: {get_attr: [{{primary_role_name}}, hostname]}
648 # Note (shardy) this somewhat complex yaql may be replaced
649 # with a map_deep_merge function in ocata. It merges the
650 # list of maps, but appends to colliding lists when a service
651 # is deployed on more than one role
653 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
656 {% for role in roles %}
657 - {get_attr: [{{role.name}}IpListMap, service_ips]}
661 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
664 {% for role in roles %}
665 - {get_attr: [{{role.name}}IpListMap, service_hostnames]}
667 short_service_node_names:
669 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
672 {% for role in roles %}
673 - {get_attr: [{{role.name}}IpListMap, short_service_hostnames]}
675 short_service_bootstrap_node:
677 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten().first()]))
680 {% for role in roles %}
681 - {get_attr: [{{role.name}}IpListMap, short_service_bootstrap_hostnames]}
683 NetVipMap: {get_attr: [VipMap, net_ip_map]}
684 RedisVirtualIP: {get_attr: [RedisVirtualIP, ip_address]}
685 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
686 DeployIdentifier: {get_param: DeployIdentifier}
687 UpdateIdentifier: {get_param: UpdateIdentifier}
690 type: OS::TripleO::RandomString
695 type: OS::TripleO::RandomString
698 salt: {get_param: RabbitCookieSalt}
701 type: OS::TripleO::DefaultPasswords
703 DefaultMysqlRootPassword: {get_attr: [MysqlRootPassword, value]}
704 DefaultRabbitCookie: {get_attr: [RabbitCookie, value]}
705 DefaultHeatAuthEncryptionKey: {get_attr: [HeatAuthEncryptionKey, value]}
706 DefaultPcsdPassword: {get_attr: [PcsdPassword, value]}
707 DefaultHorizonSecret: {get_attr: [HorizonSecret, value]}
709 # creates the network architecture
711 type: OS::TripleO::Network
714 type: OS::TripleO::Network::Ports::ControlPlaneVipPort
717 name: control_virtual_ip
718 network: {get_param: NeutronControlPlaneID}
719 fixed_ips: {get_param: ControlFixedIPs}
720 replacement_policy: AUTO
724 type: OS::TripleO::Network::Ports::RedisVipPort
726 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
727 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
728 PortName: redis_virtual_ip
729 NetworkName: {get_attr: [ServiceNetMap, service_net_map, RedisNetwork]}
731 FixedIPs: {get_param: RedisVirtualFixedIPs}
733 {%- for network in networks if network.vip|default(false) %}
734 {%- if network.name == 'External' %}
735 # The public VIP is on the External net, falls back to ctlplane
738 type: OS::TripleO::Network::Ports::ExternalVipPort
740 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
741 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
742 PortName: public_virtual_ip
743 FixedIPs: {get_param: PublicVirtualFixedIPs}
744 {%- elif network.name == 'StorageMgmt' %}
745 {{network.name}}VirtualIP:
747 type: OS::TripleO::Network::Ports::{{network.name}}VipPort
749 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
750 PortName: storage_management_virtual_ip
751 FixedIPs: {get_param: {{network.name}}VirtualFixedIPs}
753 {{network.name}}VirtualIP:
755 type: OS::TripleO::Network::Ports::{{network.name}}VipPort
757 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
758 PortName: {{network.name_lower}}_virtual_ip
759 FixedIPs: {get_param: {{network.name}}VirtualFixedIPs}
764 type: OS::TripleO::Network::Ports::NetVipMap
766 ControlPlaneIp: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
767 {%- for network in networks if network.vip|default(false) %}
768 {%- if network.name == 'External' %}
769 ExternalIp: {get_attr: [PublicVirtualIP, ip_address]}
770 ExternalIpUri: {get_attr: [PublicVirtualIP, ip_address_uri]}
772 {{network.name}}Ip: {get_attr: [{{network.name}}VirtualIP, ip_address]}
773 {{network.name}}IpUri: {get_attr: [{{network.name}}VirtualIP, ip_address_uri]}
776 # No tenant or management VIP required
777 # Because of nested get_attr functions in the KeystoneAdminVip output, we
778 # can't determine which attributes of VipMap are used until after
779 # ServiceNetMap's attribute values are available.
780 depends_on: ServiceNetMap
782 # All Nodes Validations
783 AllNodesValidationConfig:
784 type: OS::TripleO::AllNodes::Validation
790 {%- for network in networks if network.enabled|default(true) %}
792 expression: coalesce($.data, []).first(null)
793 data: {get_attr: [{{primary_role_name}}, {{network.name_lower}}_ip_address]}
797 type: OS::TripleO::Tasks::UpdateWorkflow
799 {% for role in roles %}
800 - {{role.name}}AllNodesDeployment
804 {% for role in roles %}
805 {{role.name}}: {get_attr: [{{role.name}}Servers, value]}
808 deploy_identifier: {get_param: DeployIdentifier}
809 update_identifier: {get_param: UpdateIdentifier}
811 # Optional ExtraConfig for all nodes - all roles are passed in here, but
812 # the nested template may configure each role differently (or not at all)
814 type: OS::TripleO::AllNodesExtraConfig
817 {% for role in roles %}
818 - {{role.name}}AllNodesValidationDeployment
822 {% for role in roles %}
823 {{role.name}}: {get_attr: [{{role.name}}Servers, value]}
826 # Post deployment steps for all roles
828 type: OS::TripleO::PostDeploySteps
830 - AllNodesExtraConfig
831 {% for role in roles %}
832 - {{role.name}}AllNodesDeployment
836 {% for role in roles %}
837 {{role.name}}: {get_attr: [{{role.name}}Servers, value]}
839 stack_name: {get_param: 'OS::stack_name'}
840 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
841 ctlplane_service_ips:
842 # Note (shardy) this somewhat complex yaql may be replaced
843 # with a map_deep_merge function in ocata. It merges the
844 # list of maps, but appends to colliding lists when a service
845 # is deployed on more than one role
847 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
850 {% for role in roles %}
851 - {get_attr: [{{role.name}}IpListMap, ctlplane_service_ips]}
854 {% for role in roles %}
857 - {get_attr: [{{role.name}}ServiceChainRoleData, value]}
858 - {get_attr: [{{role.name}}MergedConfigSettings, value]}
861 ServerOsCollectConfigData:
862 type: OS::Heat::Value
866 {% for role in roles %}
867 {{role.name}}: {get_attr: [{{role.name}}, attributes, os_collect_config]}
870 DeployedServerEnvironment:
871 type: OS::TripleO::DeployedServerEnvironment
874 {% for role in roles %}
875 {{role.name}}DeployedServerCount: {get_param: {{role.name}}Count}
879 - {get_attr: [VipMap, net_ip_map]}
880 - redis: {get_attr: [RedisVirtualIP, ip_address]}
881 DeployedServerPortMap:
884 {% for role in roles %}
885 - {get_attr: [{{role.name}}, deployed_server_port_map]}
887 DeployedServerDeploymentSwiftDataMap:
890 {% for role in roles %}
891 - {get_attr: [{{role.name}}, deployed_server_deployment_swift_data_map]}
898 - {get_attr: [ServerOsCollectConfigData, value, {{primary_role_name}}, '0', request, metadata_url]}
904 description: Asserts that the keystone endpoints have been provisioned.
907 description: URL for the Overcloud Keystone service
908 value: {get_attr: [EndpointMapData, value, KeystonePublic, uri]}
910 description: Keystone Admin VIP endpoint
911 # Note that these nested get_attr functions require a dependency
912 # relationship between VipMap and ServiceNetMap, since we can't determine
913 # which attributes of VipMap are used until after ServiceNetMap's attribute
914 # values are available. If this is ever reworked to not use nested
915 # get_attr, that dependency can be removed.
916 value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, KeystoneAdminApiNetwork]}]}
919 Mapping of the resources with the needed info for their endpoints.
920 This includes the protocol used, the IP, port and also a full
921 representation of the URI.
922 value: {get_attr: [EndpointMapData, value]}
925 The content that should be appended to your /etc/hosts if you want to get
926 hostname-based access to the deployed nodes (useful for testing without
931 - - {get_attr: [hostsConfig, hosts_entries]}
932 - - {get_attr: [VipHosts, value]}
934 description: The services enabled on each role
936 {% for role in roles %}
937 {{role.name}}: {get_attr: [{{role.name}}ServiceNames, value]}
940 description: The configuration data associated with each role
942 {% for role in roles %}
945 - {get_attr: [{{role.name}}ServiceChainRoleData, value]}
946 - {get_attr: [{{role.name}}MergedConfigSettings, value]}
949 description: The configuration workflows associated with each role
950 value: {get_attr: [AllNodesDeploySteps, RoleConfig]}
952 description: Mapping of each network to a list of IPs for each role
954 {% for role in roles %}
955 {{role.name}}: {get_attr: [{{role.name}}IpListMap, net_ip_map]}
958 description: Mapping of each network to a list of hostnames for each role
960 {% for role in roles %}
961 {{role.name}}: {get_attr: [{{role.name}}NetworkHostnameMap, value]}
963 ServerOsCollectConfigData:
964 description: The os-collect-config configuration associated with each server resource
965 value: {get_attr: [ServerOsCollectConfigData, value]}
967 description: Mapping of each network to VIP addresses. Also includes the Redis VIP.
970 - {get_attr: [VipMap, net_ip_map]}
971 - redis: {get_attr: [RedisVirtualIP, ip_address]}
973 description: Mapping of each role to a list of nova server IDs and the bootstrap ID
974 value: {get_attr: [ServerIdMap, value]}
975 DeployedServerEnvironment:
977 Environment data that can be used as input into the services stack when
979 value: {get_attr: [DeployedServerEnvironment, deployed_server_environment]}