1 heat_template_version: ocata
4 Deploy an OpenStack environment, consisting of several node types (roles),
5 Controller, Compute, BlockStorage, SwiftStorage and CephStorage. The Storage
6 roles enable independent scaling of the storage components, but the minimal
7 deployment is one Controller and one Compute node.
10 # TODO(shadower): we should probably use the parameter groups to put
14 # Common parameters (not specific to a role)
16 default: overcloud.localdomain
17 description: The DNS name of this cloud. E.g. ci-overcloud.tripleo.org
20 default: overcloud.internalapi.localdomain
22 The DNS name of this cloud's internal API endpoint. E.g.
23 'ci-overcloud.internalapi.tripleo.org'.
26 default: overcloud.storage.localdomain
28 The DNS name of this cloud's storage endpoint. E.g.
29 'ci-overcloud.storage.tripleo.org'.
31 CloudNameStorageManagement:
32 default: overcloud.storagemgmt.localdomain
34 The DNS name of this cloud's storage management endpoint. E.g.
35 'ci-overcloud.storagemgmt.tripleo.org'.
38 default: overcloud.ctlplane.localdomain
40 The DNS name of this cloud's storage management endpoint. E.g.
41 'ci-overcloud.management.tripleo.org'.
45 description: Should be used for arbitrary ips.
47 InternalApiVirtualFixedIPs:
50 Control the IP allocation for the InternalApiVirtualInterface port. E.g.
51 [{'ip_address':'1.2.3.4'}]
53 NeutronControlPlaneID:
56 description: Neutron ID or name for ctlplane network.
57 NeutronPublicInterface:
59 description: What interface to bridge onto br-ex for network nodes.
61 PublicVirtualFixedIPs:
64 Control the IP allocation for the PublicVirtualInterface port. E.g.
65 [{'ip_address':'1.2.3.4'}]
70 description: Salt for the rabbit cookie, change this to force the randomly generated rabbit cookie to change.
71 StorageVirtualFixedIPs:
74 Control the IP allocation for the StorageVirtualInterface port. E.g.
75 [{'ip_address':'1.2.3.4'}]
77 StorageMgmtVirtualFixedIPs:
80 Control the IP allocation for the StorageMgmgVirtualInterface port. E.g.
81 [{'ip_address':'1.2.3.4'}]
86 Control the IP allocation for the virtual IP used by Redis. E.g.
87 [{'ip_address':'1.2.3.4'}]
90 default: 'localdomain'
93 The DNS domain used for the hosts. This should match the dhcp_domain
94 configured in the Undercloud neutron. Defaults to localdomain.
98 Extra properties or metadata passed to Nova for the created nodes in
99 the overcloud. It's accessible via the Nova metadata API.
102 # Compute-specific params
103 # FIXME(shardy) handle these deprecated names as they don't match compute.yaml
104 HypervisorNeutronPhysicalBridge:
107 An OVS bridge to create on each hypervisor. This defaults to br-ex the
108 same as the control plane nodes, as we have a uniform configuration of
109 the openvswitch agent. Typically should not need to be changed.
111 HypervisorNeutronPublicInterface:
113 description: What interface to add to the HypervisorNeutronPhysicalBridge.
116 # Jinja loop for Role in role_data.yaml
117 {% for role in roles %}
118 # Parameters generated for {{role.name}} Role
119 {{role.name}}Services:
120 description: A list of service resources (configured in the Heat
121 resource_registry) which represent nested stacks
122 for each service that should get installed on the {{role.name}} role.
123 type: comma_delimited_list
126 description: Number of {{role.name}} nodes to deploy
128 default: {{role.CountDefault|default(0)}}
130 {{role.name}}HostnameFormat:
133 Format for {{role.name}} node hostnames
134 Note %index% is translated into the index of the node, e.g 0/1/2 etc
135 and %stackname% is replaced with the stack name e.g overcloud
136 {% if role.HostnameFormatDefault %}
137 default: "{{role.HostnameFormatDefault}}"
139 default: "%stackname%-{{role.name.lower()}}-%index%"
142 {{role.name}}RemovalPolicies:
146 List of resources to be removed from {{role.name}} ResourceGroup when
147 doing an update which requires removal of specific resources.
148 Example format ComputeRemovalPolicies: [{'resource_list': ['0']}]
150 {% if role.name != 'Compute' %}
151 {{role.name}}SchedulerHints:
153 NovaComputeSchedulerHints:
156 description: Optional scheduler hints to pass to nova
160 # Identifiers to trigger tasks on nodes
165 Setting to a previously unused value during stack-update will trigger
166 package update on all nodes
171 Setting this to a unique value will re-run any deployment tasks which
172 perform configuration on a Heat stack-update.
177 Set to true to append per network Vips to /etc/hosts on each node.
180 add_vips_to_etc_hosts: {equals : [{get_param: AddVipsToEtcHosts}, True]}
185 type: OS::Heat::Value
194 IP: {get_attr: [VipMap, net_ip_map, external]}
195 HOST: {get_param: CloudName}
199 IP: {get_attr: [VipMap, net_ip_map, ctlplane]}
200 HOST: {get_param: CloudNameCtlplane}
204 IP: {get_attr: [VipMap, net_ip_map, internal_api]}
205 HOST: {get_param: CloudNameInternal}
209 IP: {get_attr: [VipMap, net_ip_map, storage]}
210 HOST: {get_param: CloudNameStorage}
214 IP: {get_attr: [VipMap, net_ip_map, storage_mgmt]}
215 HOST: {get_param: CloudNameStorageManagement}
217 HeatAuthEncryptionKey:
218 type: OS::Heat::RandomString
221 type: OS::Heat::RandomString
226 type: OS::Heat::RandomString
231 type: OS::TripleO::ServiceNetMap
234 type: OS::TripleO::EndpointMap
237 external: {get_param: CloudName}
238 internal_api: {get_param: CloudNameInternal}
239 storage: {get_param: CloudNameStorage}
240 storage_mgmt: {get_param: CloudNameStorageManagement}
241 ctlplane: {get_param: CloudNameCtlplane}
242 NetIpMap: {get_attr: [VipMap, net_ip_map]}
243 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
245 # Jinja loop for Role in roles_data.yaml
246 {% for role in roles %}
247 # Resources generated for {{role.name}} Role
248 {{role.name}}ServiceChain:
249 type: OS::TripleO::Services
252 get_param: {{role.name}}Services
253 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
254 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
255 DefaultPasswords: {get_attr: [DefaultPasswords, passwords]}
257 {{role.name}}HostsDeployment:
258 type: OS::Heat::StructuredDeployments
260 name: {{role.name}}HostsDeployment
261 config: {get_attr: [hostsConfig, config_id]}
262 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
264 {{role.name}}AllNodesDeployment:
265 type: OS::Heat::StructuredDeployments
267 {% for role_inner in roles %}
268 - {{role_inner.name}}HostsDeployment
271 name: {{role.name}}AllNodesDeployment
272 config: {get_attr: [allNodesConfig, config_id]}
273 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
275 # Note we have to use yaql to look up the first hostname/ip in the
276 # list because heat path based attributes operate on the attribute
277 # inside the ResourceGroup, not the exposed list ref discussion in
278 # https://bugs.launchpad.net/heat/+bug/1640488
279 # The coalesce is needed because $.data is None during heat validation
282 expression: coalesce($.data, []).first(null)
283 data: {get_attr: [{{role.name}}, hostname]}
286 expression: coalesce($.data, []).first(null)
287 data: {get_attr: [{{role.name}}, ip_address]}
289 {{role.name}}AllNodesValidationDeployment:
290 type: OS::Heat::StructuredDeployments
291 depends_on: {{role.name}}AllNodesDeployment
293 name: {{role.name}}AllNodesValidationDeployment
294 config: {get_resource: AllNodesValidationConfig}
295 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
297 {{role.name}}IpListMap:
298 type: OS::TripleO::Network::Ports::NetIpListMap
300 ControlPlaneIpList: {get_attr: [{{role.name}}, ip_address]}
301 ExternalIpList: {get_attr: [{{role.name}}, external_ip_address]}
302 InternalApiIpList: {get_attr: [{{role.name}}, internal_api_ip_address]}
303 StorageIpList: {get_attr: [{{role.name}}, storage_ip_address]}
304 StorageMgmtIpList: {get_attr: [{{role.name}}, storage_mgmt_ip_address]}
305 TenantIpList: {get_attr: [{{role.name}}, tenant_ip_address]}
306 ManagementIpList: {get_attr: [{{role.name}}, management_ip_address]}
307 EnabledServices: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
308 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
309 ServiceHostnameList: {get_attr: [{{role.name}}, hostname]}
311 # Note (shardy) this somewhat complex yaql may be replaced
312 # with a map_deep_merge function in ocata. It merges the
313 # list of maps, but appends to colliding lists so we can
314 # create a map of lists for all nodes for each network
316 expression: dict($.data.where($ != null).flatten().selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
318 - {get_attr: [{{role.name}}, hostname_map]}
321 type: OS::Heat::ResourceGroup
324 count: {get_param: {{role.name}}Count}
325 removal_policies: {get_param: {{role.name}}RemovalPolicies}
327 type: OS::TripleO::{{role.name}}
329 CloudDomain: {get_param: CloudDomain}
330 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
331 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
334 template: {get_param: {{role.name}}HostnameFormat}
336 '%stackname%': {get_param: 'OS::stack_name'}
338 {% if role.name != 'Compute' %}
339 {{role.name}}SchedulerHints: {get_param: {{role.name}}SchedulerHints}
341 NovaComputeSchedulerHints: {get_param: NovaComputeSchedulerHints}
343 ServiceConfigSettings:
345 - get_attr: [{{role.name}}ServiceChain, role_data, config_settings]
347 - get_attr: [{{r.name}}ServiceChain, role_data, global_config_settings]
349 # This next step combines two yaql passes:
350 # - The inner one does a deep merge on the service_config_settings for all roles
351 # - The outer one filters the map based on the services enabled for the role
352 # then merges the result into one map.
354 expression: let(root => $) -> $.data.map.items().where($[0] in coalesce($root.data.services, [])).select($[1]).reduce($1.mergeWith($2), {})
358 expression: $.data.where($ != null).reduce($1.mergeWith($2), {})
361 - get_attr: [{{r.name}}ServiceChain, role_data, service_config_settings]
363 services: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
364 ServiceNames: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
365 MonitoringSubscriptions: {get_attr: [{{role.name}}ServiceChain, role_data, monitoring_subscriptions]}
366 ServiceMetadataSettings: {get_attr: [{{role.name}}ServiceChain, role_data, service_metadata_settings]}
370 type: OS::TripleO::Hosts::SoftwareConfig
376 - add_vips_to_etc_hosts
377 - {get_attr: [VipHosts, value]}
380 {% for role in roles %}
383 - {get_attr: [{{role.name}}, hosts_entry]}
387 type: OS::TripleO::AllNodes::SoftwareConfig
389 cloud_name_external: {get_param: CloudName}
390 cloud_name_internal_api: {get_param: CloudNameInternal}
391 cloud_name_storage: {get_param: CloudNameStorage}
392 cloud_name_storage_mgmt: {get_param: CloudNameStorageManagement}
393 cloud_name_ctlplane: {get_param: CloudNameCtlplane}
397 {% for role in roles %}
398 - {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
403 $.data.groups.flatten()
406 {% for role in roles %}
407 - {get_attr: [{{role.name}}ServiceChain, role_data, logging_groups]}
412 $.data.sources.flatten()
415 {% for role in roles %}
416 - {get_attr: [{{role.name}}ServiceChain, role_data, logging_sources]}
418 controller_ips: {get_attr: [Controller, ip_address]}
419 controller_names: {get_attr: [Controller, hostname]}
421 # Note (shardy) this somewhat complex yaql may be replaced
422 # with a map_deep_merge function in ocata. It merges the
423 # list of maps, but appends to colliding lists when a service
424 # is deployed on more than one role
426 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
429 {% for role in roles %}
430 - {get_attr: [{{role.name}}IpListMap, service_ips]}
434 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
437 {% for role in roles %}
438 - {get_attr: [{{role.name}}IpListMap, service_hostnames]}
440 short_service_node_names:
442 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
445 {% for role in roles %}
446 - {get_attr: [{{role.name}}IpListMap, short_service_hostnames]}
448 short_service_bootstrap_node:
450 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten().first()]))
453 {% for role in roles %}
454 - {get_attr: [{{role.name}}IpListMap, short_service_bootstrap_hostnames]}
456 # FIXME(shardy): These require further work to move into service_ips
457 memcache_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, MemcachedNetwork]}]}
458 NetVipMap: {get_attr: [VipMap, net_ip_map]}
459 RedisVirtualIP: {get_attr: [RedisVirtualIP, ip_address]}
460 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
461 DeployIdentifier: {get_param: DeployIdentifier}
462 UpdateIdentifier: {get_param: UpdateIdentifier}
465 type: OS::Heat::RandomString
470 type: OS::Heat::RandomString
473 salt: {get_param: RabbitCookieSalt}
476 type: OS::TripleO::DefaultPasswords
478 DefaultMysqlRootPassword: {get_attr: [MysqlRootPassword, value]}
479 DefaultRabbitCookie: {get_attr: [RabbitCookie, value]}
480 DefaultHeatAuthEncryptionKey: {get_attr: [HeatAuthEncryptionKey, value]}
481 DefaultPcsdPassword: {get_attr: [PcsdPassword, value]}
482 DefaultHorizonSecret: {get_attr: [HorizonSecret, value]}
484 # creates the network architecture
486 type: OS::TripleO::Network
489 type: OS::TripleO::Network::Ports::ControlPlaneVipPort
492 name: control_virtual_ip
493 network: {get_param: NeutronControlPlaneID}
494 fixed_ips: {get_param: ControlFixedIPs}
495 replacement_policy: AUTO
499 type: OS::TripleO::Network::Ports::RedisVipPort
501 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
502 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
503 PortName: redis_virtual_ip
504 NetworkName: {get_attr: [ServiceNetMap, service_net_map, RedisNetwork]}
506 FixedIPs: {get_param: RedisVirtualFixedIPs}
508 # The public VIP is on the External net, falls back to ctlplane
511 type: OS::TripleO::Network::Ports::ExternalVipPort
513 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
514 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
515 PortName: public_virtual_ip
516 FixedIPs: {get_param: PublicVirtualFixedIPs}
518 InternalApiVirtualIP:
520 type: OS::TripleO::Network::Ports::InternalApiVipPort
522 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
523 PortName: internal_api_virtual_ip
524 FixedIPs: {get_param: InternalApiVirtualFixedIPs}
528 type: OS::TripleO::Network::Ports::StorageVipPort
530 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
531 PortName: storage_virtual_ip
532 FixedIPs: {get_param: StorageVirtualFixedIPs}
534 StorageMgmtVirtualIP:
536 type: OS::TripleO::Network::Ports::StorageMgmtVipPort
538 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
539 PortName: storage_management_virtual_ip
540 FixedIPs: {get_param: StorageMgmtVirtualFixedIPs}
543 type: OS::TripleO::Network::Ports::NetVipMap
545 ControlPlaneIp: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
546 ExternalIp: {get_attr: [PublicVirtualIP, ip_address]}
547 ExternalIpUri: {get_attr: [PublicVirtualIP, ip_address_uri]}
548 InternalApiIp: {get_attr: [InternalApiVirtualIP, ip_address]}
549 InternalApiIpUri: {get_attr: [InternalApiVirtualIP, ip_address_uri]}
550 StorageIp: {get_attr: [StorageVirtualIP, ip_address]}
551 StorageIpUri: {get_attr: [StorageVirtualIP, ip_address_uri]}
552 StorageMgmtIp: {get_attr: [StorageMgmtVirtualIP, ip_address]}
553 StorageMgmtIpUri: {get_attr: [StorageMgmtVirtualIP, ip_address_uri]}
554 # No tenant or management VIP required
556 # All Nodes Validations
557 AllNodesValidationConfig:
558 type: OS::TripleO::AllNodes::Validation
563 - - {get_attr: [Controller, resource.0.external_ip_address]}
564 - {get_attr: [Controller, resource.0.internal_api_ip_address]}
565 - {get_attr: [Controller, resource.0.storage_ip_address]}
566 - {get_attr: [Controller, resource.0.storage_mgmt_ip_address]}
567 - {get_attr: [Controller, resource.0.tenant_ip_address]}
568 - {get_attr: [Controller, resource.0.management_ip_address]}
571 type: OS::TripleO::Tasks::UpdateWorkflow
573 {% for role in roles %}
574 - {{role.name}}AllNodesDeployment
578 {% for role in roles %}
579 {{role.name}}: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
582 deploy_identifier: {get_param: DeployIdentifier}
583 update_identifier: {get_param: UpdateIdentifier}
585 # Optional ExtraConfig for all nodes - all roles are passed in here, but
586 # the nested template may configure each role differently (or not at all)
588 type: OS::TripleO::AllNodesExtraConfig
591 {% for role in roles %}
592 - {{role.name}}AllNodesValidationDeployment
595 {% for role in roles %}
596 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
599 # Upgrade steps for all roles
600 AllNodesUpgradeSteps:
601 type: OS::TripleO::UpgradeSteps
603 {% for role in roles %}
604 - {{role.name}}AllNodesDeployment
608 {% for role in roles %}
609 {{role.name}}: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
612 {% for role in roles %}
613 {{role.name}}: {get_attr: [{{role.name}}ServiceChain, role_data]}
616 # Post deployment steps for all roles
618 type: OS::TripleO::PostDeploySteps
619 depends_on: AllNodesUpgradeSteps
622 {% for role in roles %}
623 {{role.name}}: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
626 {% for role in roles %}
627 {{role.name}}: {get_attr: [{{role.name}}ServiceChain, role_data]}
632 description: Asserts that the keystone endpoints have been provisioned.
635 description: URL for the Overcloud Keystone service
636 value: {get_attr: [EndpointMap, endpoint_map, KeystonePublic, uri]}
638 description: Keystone Admin VIP endpoint
639 value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, KeystoneAdminApiNetwork]}]}
642 Mapping of the resources with the needed info for their endpoints.
643 This includes the protocol used, the IP, port and also a full
644 representation of the URI.
645 value: {get_attr: [EndpointMap, endpoint_map]}
648 The content that should be appended to your /etc/hosts if you want to get
649 hostname-based access to the deployed nodes (useful for testing without
654 - - {get_attr: [hostsConfig, hosts_entries]}
655 - - {get_attr: [VipHosts, value]}
657 description: The services enabled on each role
659 {% for role in roles %}
660 {{role.name}}: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
663 description: The configuration data associated with each role
665 {% for role in roles %}
666 {{role.name}}: {get_attr: [{{role.name}}ServiceChain, role_data]}