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 LoggingSources: {get_attr: [{{role.name}}ServiceChainRoleData, value, logging_sources]}
549 LoggingGroups: {get_attr: [{{role.name}}ServiceChainRoleData, value, logging_groups]}
550 ServiceMetadataSettings: {get_attr: [{{role.name}}ServiceChainRoleData, value, service_metadata_settings]}
551 DeploymentServerBlacklistDict: {get_attr: [DeploymentServerBlacklistDict, value]}
552 RoleParameters: {get_param: {{role.name}}Parameters}
555 {% for role in roles %}
556 {{role.name}}Servers:
557 type: OS::Heat::Value
558 depends_on: {{role.name}}
563 expression: let(servers=>switch(isDict($.data.servers) => $.data.servers, true => {})) -> $servers.deleteAll($servers.keys().where($servers[$] = null))
565 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
568 # This is a different format to *Servers, as it creates a map of lists
569 # whereas *Servers creates a map of maps with keys of the nested resource names
571 type: OS::Heat::Value
575 {% for role in roles %}
576 {{role.name}}: {get_attr: [{{role.name}}, nova_server_resource]}
580 expression: coalesce($.data, []).first(null)
581 data: {get_attr: [{{primary_role_name}}, nova_server_resource]}
583 # This resource just creates a dict out of the DeploymentServerBlacklist,
584 # which is a list. The dict is used in the role templates to set a condition
585 # on whether to create the deployment resources. We can't use the list
586 # directly because there is no way to ask Heat if a list contains a specific
588 DeploymentServerBlacklistDict:
589 type: OS::Heat::Value
598 hostname: {get_param: DeploymentServerBlacklist}
601 type: OS::TripleO::Hosts::SoftwareConfig
607 - add_vips_to_etc_hosts
608 - {get_attr: [VipHosts, value]}
611 {% for role in roles %}
614 - {get_attr: [{{role.name}}, hosts_entry]}
618 type: OS::TripleO::AllNodes::SoftwareConfig
620 {%- for network in networks if network.vip|default(false) %}
621 {%- if network.name == 'External' %}
622 # Special case the External hostname param, which is CloudName
623 cloud_name_{{network.name_lower}}: {get_param: CloudName}
624 {%- elif network.name == 'InternalApi' %}
625 # Special case the Internal API hostname param, which is CloudNameInternal
626 cloud_name_{{network.name_lower}}: {get_param: CloudNameInternal}
627 {%- elif network.name == 'StorageMgmt' %}
628 # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
629 cloud_name_{{network.name_lower}}: {get_param: CloudNameStorageManagement}
631 cloud_name_{{network.name_lower}}: {get_param: CloudName{{network.name}}}
634 cloud_name_ctlplane: {get_param: CloudNameCtlplane}
638 {% for role in roles %}
639 - {get_attr: [{{role.name}}ServiceNames, value]}
641 controller_ips: {get_attr: [{{primary_role_name}}, ip_address]}
642 controller_names: {get_attr: [{{primary_role_name}}, hostname]}
644 # Note (shardy) this somewhat complex yaql may be replaced
645 # with a map_deep_merge function in ocata. It merges the
646 # list of maps, but appends to colliding lists when a service
647 # is deployed on more than one role
649 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
652 {% for role in roles %}
653 - {get_attr: [{{role.name}}IpListMap, service_ips]}
657 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
660 {% for role in roles %}
661 - {get_attr: [{{role.name}}IpListMap, service_hostnames]}
663 short_service_node_names:
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, short_service_hostnames]}
671 short_service_bootstrap_node:
673 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten().first()]))
676 {% for role in roles %}
677 - {get_attr: [{{role.name}}IpListMap, short_service_bootstrap_hostnames]}
679 NetVipMap: {get_attr: [VipMap, net_ip_map]}
680 RedisVirtualIP: {get_attr: [RedisVirtualIP, ip_address]}
681 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
682 DeployIdentifier: {get_param: DeployIdentifier}
683 UpdateIdentifier: {get_param: UpdateIdentifier}
686 type: OS::TripleO::RandomString
691 type: OS::TripleO::RandomString
694 salt: {get_param: RabbitCookieSalt}
697 type: OS::TripleO::DefaultPasswords
699 DefaultMysqlRootPassword: {get_attr: [MysqlRootPassword, value]}
700 DefaultRabbitCookie: {get_attr: [RabbitCookie, value]}
701 DefaultHeatAuthEncryptionKey: {get_attr: [HeatAuthEncryptionKey, value]}
702 DefaultPcsdPassword: {get_attr: [PcsdPassword, value]}
703 DefaultHorizonSecret: {get_attr: [HorizonSecret, value]}
705 # creates the network architecture
707 type: OS::TripleO::Network
710 type: OS::TripleO::Network::Ports::ControlPlaneVipPort
713 name: control_virtual_ip
714 network: {get_param: NeutronControlPlaneID}
715 fixed_ips: {get_param: ControlFixedIPs}
716 replacement_policy: AUTO
720 type: OS::TripleO::Network::Ports::RedisVipPort
722 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
723 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
724 PortName: redis_virtual_ip
725 NetworkName: {get_attr: [ServiceNetMap, service_net_map, RedisNetwork]}
727 FixedIPs: {get_param: RedisVirtualFixedIPs}
729 {%- for network in networks if network.vip|default(false) %}
730 {%- if network.name == 'External' %}
731 # The public VIP is on the External net, falls back to ctlplane
734 type: OS::TripleO::Network::Ports::ExternalVipPort
736 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
737 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
738 PortName: public_virtual_ip
739 FixedIPs: {get_param: PublicVirtualFixedIPs}
740 {%- elif network.name == 'StorageMgmt' %}
741 {{network.name}}VirtualIP:
743 type: OS::TripleO::Network::Ports::{{network.name}}VipPort
745 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
746 PortName: storage_management_virtual_ip
747 FixedIPs: {get_param: {{network.name}}VirtualFixedIPs}
749 {{network.name}}VirtualIP:
751 type: OS::TripleO::Network::Ports::{{network.name}}VipPort
753 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
754 PortName: {{network.name_lower}}_virtual_ip
755 FixedIPs: {get_param: {{network.name}}VirtualFixedIPs}
760 type: OS::TripleO::Network::Ports::NetVipMap
762 ControlPlaneIp: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
763 {%- for network in networks if network.vip|default(false) %}
764 {%- if network.name == 'External' %}
765 ExternalIp: {get_attr: [PublicVirtualIP, ip_address]}
766 ExternalIpUri: {get_attr: [PublicVirtualIP, ip_address_uri]}
768 {{network.name}}Ip: {get_attr: [{{network.name}}VirtualIP, ip_address]}
769 {{network.name}}IpUri: {get_attr: [{{network.name}}VirtualIP, ip_address_uri]}
772 # No tenant or management VIP required
773 # Because of nested get_attr functions in the KeystoneAdminVip output, we
774 # can't determine which attributes of VipMap are used until after
775 # ServiceNetMap's attribute values are available.
776 depends_on: ServiceNetMap
778 # All Nodes Validations
779 AllNodesValidationConfig:
780 type: OS::TripleO::AllNodes::Validation
786 {%- for network in networks if network.enabled|default(true) %}
788 expression: coalesce($.data, []).first(null)
789 data: {get_attr: [{{primary_role_name}}, {{network.name_lower}}_ip_address]}
793 type: OS::TripleO::Tasks::UpdateWorkflow
795 {% for role in roles %}
796 - {{role.name}}AllNodesDeployment
800 {% for role in roles %}
801 {{role.name}}: {get_attr: [{{role.name}}Servers, value]}
804 deploy_identifier: {get_param: DeployIdentifier}
805 update_identifier: {get_param: UpdateIdentifier}
807 # Optional ExtraConfig for all nodes - all roles are passed in here, but
808 # the nested template may configure each role differently (or not at all)
810 type: OS::TripleO::AllNodesExtraConfig
813 {% for role in roles %}
814 - {{role.name}}AllNodesValidationDeployment
818 {% for role in roles %}
819 {{role.name}}: {get_attr: [{{role.name}}Servers, value]}
822 # Post deployment steps for all roles
824 type: OS::TripleO::PostDeploySteps
826 - AllNodesExtraConfig
827 {% for role in roles %}
828 - {{role.name}}AllNodesDeployment
832 {% for role in roles %}
833 {{role.name}}: {get_attr: [{{role.name}}Servers, value]}
835 stack_name: {get_param: 'OS::stack_name'}
836 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
837 ctlplane_service_ips:
838 # Note (shardy) this somewhat complex yaql may be replaced
839 # with a map_deep_merge function in ocata. It merges the
840 # list of maps, but appends to colliding lists when a service
841 # is deployed on more than one role
843 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
846 {% for role in roles %}
847 - {get_attr: [{{role.name}}IpListMap, ctlplane_service_ips]}
850 {% for role in roles %}
853 - {get_attr: [{{role.name}}ServiceChainRoleData, value]}
854 - {get_attr: [{{role.name}}MergedConfigSettings, value]}
857 ServerOsCollectConfigData:
858 type: OS::Heat::Value
862 {% for role in roles %}
863 {{role.name}}: {get_attr: [{{role.name}}, attributes, os_collect_config]}
866 DeployedServerEnvironment:
867 type: OS::TripleO::DeployedServerEnvironment
870 {% for role in roles %}
871 {{role.name}}DeployedServerCount: {get_param: {{role.name}}Count}
875 - {get_attr: [VipMap, net_ip_map]}
876 - redis: {get_attr: [RedisVirtualIP, ip_address]}
877 DeployedServerPortMap:
880 {% for role in roles %}
881 - {get_attr: [{{role.name}}, deployed_server_port_map]}
883 DeployedServerDeploymentSwiftDataMap:
886 {% for role in roles %}
887 - {get_attr: [{{role.name}}, deployed_server_deployment_swift_data_map]}
894 - {get_attr: [ServerOsCollectConfigData, value, {{primary_role_name}}, '0', request, metadata_url]}
900 description: Asserts that the keystone endpoints have been provisioned.
903 description: URL for the Overcloud Keystone service
904 value: {get_attr: [EndpointMapData, value, KeystonePublic, uri]}
906 description: Keystone Admin VIP endpoint
907 # Note that these nested get_attr functions require a dependency
908 # relationship between VipMap and ServiceNetMap, since we can't determine
909 # which attributes of VipMap are used until after ServiceNetMap's attribute
910 # values are available. If this is ever reworked to not use nested
911 # get_attr, that dependency can be removed.
912 value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, KeystoneAdminApiNetwork]}]}
915 Mapping of the resources with the needed info for their endpoints.
916 This includes the protocol used, the IP, port and also a full
917 representation of the URI.
918 value: {get_attr: [EndpointMapData, value]}
921 The content that should be appended to your /etc/hosts if you want to get
922 hostname-based access to the deployed nodes (useful for testing without
927 - - {get_attr: [hostsConfig, hosts_entries]}
928 - - {get_attr: [VipHosts, value]}
930 description: The services enabled on each role
932 {% for role in roles %}
933 {{role.name}}: {get_attr: [{{role.name}}ServiceNames, value]}
936 description: The configuration data associated with each role
938 {% for role in roles %}
941 - {get_attr: [{{role.name}}ServiceChainRoleData, value]}
942 - {get_attr: [{{role.name}}MergedConfigSettings, value]}
945 description: The configuration workflows associated with each role
946 value: {get_attr: [AllNodesDeploySteps, RoleConfig]}
948 description: Mapping of each network to a list of IPs for each role
950 {% for role in roles %}
951 {{role.name}}: {get_attr: [{{role.name}}IpListMap, net_ip_map]}
954 description: Mapping of each network to a list of hostnames for each role
956 {% for role in roles %}
957 {{role.name}}: {get_attr: [{{role.name}}NetworkHostnameMap, value]}
959 ServerOsCollectConfigData:
960 description: The os-collect-config configuration associated with each server resource
961 value: {get_attr: [ServerOsCollectConfigData, value]}
963 description: Mapping of each network to VIP addresses. Also includes the Redis VIP.
966 - {get_attr: [VipMap, net_ip_map]}
967 - redis: {get_attr: [RedisVirtualIP, ip_address]}
969 description: Mapping of each role to a list of nova server IDs and the bootstrap ID
970 value: {get_attr: [ServerIdMap, value]}
971 DeployedServerEnvironment:
973 Environment data that can be used as input into the services stack when
975 value: {get_attr: [DeployedServerEnvironment, deployed_server_environment]}