1 {% set primary_role_name = roles[0].name -%}
2 heat_template_version: ocata
5 Deploy an OpenStack environment, consisting of several node types (roles),
6 Controller, Compute, BlockStorage, SwiftStorage and CephStorage. The Storage
7 roles enable independent scaling of the storage components, but the minimal
8 deployment is one Controller and one Compute node.
11 # TODO(shadower): we should probably use the parameter groups to put
15 # Common parameters (not specific to a role)
17 default: overcloud.localdomain
18 description: The DNS name of this cloud. E.g. ci-overcloud.tripleo.org
21 default: overcloud.internalapi.localdomain
23 The DNS name of this cloud's internal API endpoint. E.g.
24 'ci-overcloud.internalapi.tripleo.org'.
27 default: overcloud.storage.localdomain
29 The DNS name of this cloud's storage endpoint. E.g.
30 'ci-overcloud.storage.tripleo.org'.
32 CloudNameStorageManagement:
33 default: overcloud.storagemgmt.localdomain
35 The DNS name of this cloud's storage management endpoint. E.g.
36 'ci-overcloud.storagemgmt.tripleo.org'.
39 default: overcloud.ctlplane.localdomain
41 The DNS name of this cloud's storage management endpoint. E.g.
42 'ci-overcloud.management.tripleo.org'.
46 description: Should be used for arbitrary ips.
48 InternalApiVirtualFixedIPs:
51 Control the IP allocation for the InternalApiVirtualInterface port. E.g.
52 [{'ip_address':'1.2.3.4'}]
54 NeutronControlPlaneID:
57 description: Neutron ID or name for ctlplane network.
58 NeutronPublicInterface:
60 description: What interface to bridge onto br-ex for network nodes.
62 PublicVirtualFixedIPs:
65 Control the IP allocation for the PublicVirtualInterface port. E.g.
66 [{'ip_address':'1.2.3.4'}]
71 description: Salt for the rabbit cookie, change this to force the randomly generated rabbit cookie to change.
72 StorageVirtualFixedIPs:
75 Control the IP allocation for the StorageVirtualInterface port. E.g.
76 [{'ip_address':'1.2.3.4'}]
78 StorageMgmtVirtualFixedIPs:
81 Control the IP allocation for the StorageMgmgVirtualInterface port. E.g.
82 [{'ip_address':'1.2.3.4'}]
87 Control the IP allocation for the virtual IP used by Redis. E.g.
88 [{'ip_address':'1.2.3.4'}]
91 default: 'localdomain'
94 The DNS domain used for the hosts. This should match the dhcp_domain
95 configured in the Undercloud neutron. Defaults to localdomain.
99 Extra properties or metadata passed to Nova for the created nodes in
100 the overcloud. It's accessible via the Nova metadata API.
103 # Compute-specific params
104 # FIXME(shardy) handle these deprecated names as they don't match compute.yaml
105 HypervisorNeutronPhysicalBridge:
108 An OVS bridge to create on each hypervisor. This defaults to br-ex the
109 same as the control plane nodes, as we have a uniform configuration of
110 the openvswitch agent. Typically should not need to be changed.
112 HypervisorNeutronPublicInterface:
114 description: What interface to add to the HypervisorNeutronPhysicalBridge.
117 # Jinja loop for Role in role_data.yaml
118 {% for role in roles %}
119 # Parameters generated for {{role.name}} Role
120 {{role.name}}Services:
121 description: A list of service resources (configured in the Heat
122 resource_registry) which represent nested stacks
123 for each service that should get installed on the {{role.name}} role.
124 type: comma_delimited_list
127 description: Number of {{role.name}} nodes to deploy
129 default: {{role.CountDefault|default(0)}}
131 {{role.name}}HostnameFormat:
134 Format for {{role.name}} node hostnames
135 Note %index% is translated into the index of the node, e.g 0/1/2 etc
136 and %stackname% is replaced with the stack name e.g overcloud
137 {% if role.HostnameFormatDefault %}
138 default: "{{role.HostnameFormatDefault}}"
140 default: "%stackname%-{{role.name.lower()}}-%index%"
143 {{role.name}}RemovalPolicies:
147 List of resources to be removed from {{role.name}} ResourceGroup when
148 doing an update which requires removal of specific resources.
149 Example format ComputeRemovalPolicies: [{'resource_list': ['0']}]
151 {% if role.name != 'Compute' %}
152 {{role.name}}SchedulerHints:
154 NovaComputeSchedulerHints:
157 description: Optional scheduler hints to pass to nova
161 # Identifiers to trigger tasks on nodes
166 Setting to a previously unused value during stack-update will trigger
167 package update on all nodes
172 Setting this to a unique value will re-run any deployment tasks which
173 perform configuration on a Heat stack-update.
178 Set to true to append per network Vips to /etc/hosts on each node.
181 add_vips_to_etc_hosts: {equals : [{get_param: AddVipsToEtcHosts}, True]}
186 type: OS::Heat::Value
195 IP: {get_attr: [VipMap, net_ip_map, external]}
196 HOST: {get_param: CloudName}
200 IP: {get_attr: [VipMap, net_ip_map, ctlplane]}
201 HOST: {get_param: CloudNameCtlplane}
205 IP: {get_attr: [VipMap, net_ip_map, internal_api]}
206 HOST: {get_param: CloudNameInternal}
210 IP: {get_attr: [VipMap, net_ip_map, storage]}
211 HOST: {get_param: CloudNameStorage}
215 IP: {get_attr: [VipMap, net_ip_map, storage_mgmt]}
216 HOST: {get_param: CloudNameStorageManagement}
218 HeatAuthEncryptionKey:
219 type: OS::Heat::RandomString
222 type: OS::Heat::RandomString
227 type: OS::Heat::RandomString
232 type: OS::TripleO::ServiceNetMap
235 type: OS::TripleO::EndpointMap
238 external: {get_param: CloudName}
239 internal_api: {get_param: CloudNameInternal}
240 storage: {get_param: CloudNameStorage}
241 storage_mgmt: {get_param: CloudNameStorageManagement}
242 ctlplane: {get_param: CloudNameCtlplane}
243 NetIpMap: {get_attr: [VipMap, net_ip_map]}
244 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
246 # Jinja loop for Role in roles_data.yaml
247 {% for role in roles %}
248 # Resources generated for {{role.name}} Role
249 {{role.name}}ServiceChain:
250 type: OS::TripleO::Services
253 get_param: {{role.name}}Services
254 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
255 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
256 DefaultPasswords: {get_attr: [DefaultPasswords, passwords]}
258 {{role.name}}HostsDeployment:
259 type: OS::Heat::StructuredDeployments
261 name: {{role.name}}HostsDeployment
262 config: {get_attr: [hostsConfig, config_id]}
263 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
265 {{role.name}}AllNodesDeployment:
266 type: OS::Heat::StructuredDeployments
268 {% for role_inner in roles %}
269 - {{role_inner.name}}HostsDeployment
272 name: {{role.name}}AllNodesDeployment
273 config: {get_attr: [allNodesConfig, config_id]}
274 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
276 # Note we have to use yaql to look up the first hostname/ip in the
277 # list because heat path based attributes operate on the attribute
278 # inside the ResourceGroup, not the exposed list ref discussion in
279 # https://bugs.launchpad.net/heat/+bug/1640488
280 # The coalesce is needed because $.data is None during heat validation
283 expression: coalesce($.data, []).first(null)
284 data: {get_attr: [{{role.name}}, hostname]}
287 expression: coalesce($.data, []).first(null)
288 data: {get_attr: [{{role.name}}, ip_address]}
290 {{role.name}}AllNodesValidationDeployment:
291 type: OS::Heat::StructuredDeployments
292 depends_on: {{role.name}}AllNodesDeployment
294 name: {{role.name}}AllNodesValidationDeployment
295 config: {get_resource: AllNodesValidationConfig}
296 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
298 {{role.name}}IpListMap:
299 type: OS::TripleO::Network::Ports::NetIpListMap
301 ControlPlaneIpList: {get_attr: [{{role.name}}, ip_address]}
302 ExternalIpList: {get_attr: [{{role.name}}, external_ip_address]}
303 InternalApiIpList: {get_attr: [{{role.name}}, internal_api_ip_address]}
304 StorageIpList: {get_attr: [{{role.name}}, storage_ip_address]}
305 StorageMgmtIpList: {get_attr: [{{role.name}}, storage_mgmt_ip_address]}
306 TenantIpList: {get_attr: [{{role.name}}, tenant_ip_address]}
307 ManagementIpList: {get_attr: [{{role.name}}, management_ip_address]}
308 EnabledServices: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
309 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
310 ServiceHostnameList: {get_attr: [{{role.name}}, hostname]}
312 # Note (shardy) this somewhat complex yaql may be replaced
313 # with a map_deep_merge function in ocata. It merges the
314 # list of maps, but appends to colliding lists so we can
315 # create a map of lists for all nodes for each network
317 expression: dict($.data.where($ != null).flatten().selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
319 - {get_attr: [{{role.name}}, hostname_map]}
322 type: OS::Heat::ResourceGroup
325 count: {get_param: {{role.name}}Count}
326 removal_policies: {get_param: {{role.name}}RemovalPolicies}
328 type: OS::TripleO::{{role.name}}
330 CloudDomain: {get_param: CloudDomain}
331 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
332 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
335 template: {get_param: {{role.name}}HostnameFormat}
337 '%stackname%': {get_param: 'OS::stack_name'}
339 {% if role.name != 'Compute' %}
340 {{role.name}}SchedulerHints: {get_param: {{role.name}}SchedulerHints}
342 NovaComputeSchedulerHints: {get_param: NovaComputeSchedulerHints}
344 ServiceConfigSettings:
346 - get_attr: [{{role.name}}ServiceChain, role_data, config_settings]
348 - get_attr: [{{r.name}}ServiceChain, role_data, global_config_settings]
350 # This next step combines two yaql passes:
351 # - The inner one does a deep merge on the service_config_settings for all roles
352 # - The outer one filters the map based on the services enabled for the role
353 # then merges the result into one map.
355 expression: let(root => $) -> $.data.map.items().where($[0] in coalesce($root.data.services, [])).select($[1]).reduce($1.mergeWith($2), {})
359 expression: $.data.where($ != null).reduce($1.mergeWith($2), {})
362 - get_attr: [{{r.name}}ServiceChain, role_data, service_config_settings]
364 services: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
365 ServiceNames: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
366 MonitoringSubscriptions: {get_attr: [{{role.name}}ServiceChain, role_data, monitoring_subscriptions]}
367 ServiceMetadataSettings: {get_attr: [{{role.name}}ServiceChain, role_data, service_metadata_settings]}
371 type: OS::TripleO::Hosts::SoftwareConfig
377 - add_vips_to_etc_hosts
378 - {get_attr: [VipHosts, value]}
381 {% for role in roles %}
384 - {get_attr: [{{role.name}}, hosts_entry]}
388 type: OS::TripleO::AllNodes::SoftwareConfig
390 cloud_name_external: {get_param: CloudName}
391 cloud_name_internal_api: {get_param: CloudNameInternal}
392 cloud_name_storage: {get_param: CloudNameStorage}
393 cloud_name_storage_mgmt: {get_param: CloudNameStorageManagement}
394 cloud_name_ctlplane: {get_param: CloudNameCtlplane}
398 {% for role in roles %}
399 - {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
404 $.data.groups.flatten()
407 {% for role in roles %}
408 - {get_attr: [{{role.name}}ServiceChain, role_data, logging_groups]}
413 $.data.sources.flatten()
416 {% for role in roles %}
417 - {get_attr: [{{role.name}}ServiceChain, role_data, logging_sources]}
419 controller_ips: {get_attr: [{{primary_role_name}}, ip_address]}
420 controller_names: {get_attr: [{{primary_role_name}}, hostname]}
422 # Note (shardy) this somewhat complex yaql may be replaced
423 # with a map_deep_merge function in ocata. It merges the
424 # list of maps, but appends to colliding lists when a service
425 # is deployed on more than one role
427 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
430 {% for role in roles %}
431 - {get_attr: [{{role.name}}IpListMap, service_ips]}
435 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
438 {% for role in roles %}
439 - {get_attr: [{{role.name}}IpListMap, service_hostnames]}
441 short_service_node_names:
443 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
446 {% for role in roles %}
447 - {get_attr: [{{role.name}}IpListMap, short_service_hostnames]}
449 short_service_bootstrap_node:
451 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten().first()]))
454 {% for role in roles %}
455 - {get_attr: [{{role.name}}IpListMap, short_service_bootstrap_hostnames]}
457 # FIXME(shardy): These require further work to move into service_ips
458 memcache_node_ips: {get_attr: [{{primary_role_name}}IpListMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, MemcachedNetwork]}]}
459 NetVipMap: {get_attr: [VipMap, net_ip_map]}
460 RedisVirtualIP: {get_attr: [RedisVirtualIP, ip_address]}
461 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
462 DeployIdentifier: {get_param: DeployIdentifier}
463 UpdateIdentifier: {get_param: UpdateIdentifier}
466 type: OS::Heat::RandomString
471 type: OS::Heat::RandomString
474 salt: {get_param: RabbitCookieSalt}
477 type: OS::TripleO::DefaultPasswords
479 DefaultMysqlRootPassword: {get_attr: [MysqlRootPassword, value]}
480 DefaultRabbitCookie: {get_attr: [RabbitCookie, value]}
481 DefaultHeatAuthEncryptionKey: {get_attr: [HeatAuthEncryptionKey, value]}
482 DefaultPcsdPassword: {get_attr: [PcsdPassword, value]}
483 DefaultHorizonSecret: {get_attr: [HorizonSecret, value]}
485 # creates the network architecture
487 type: OS::TripleO::Network
490 type: OS::TripleO::Network::Ports::ControlPlaneVipPort
493 name: control_virtual_ip
494 network: {get_param: NeutronControlPlaneID}
495 fixed_ips: {get_param: ControlFixedIPs}
496 replacement_policy: AUTO
500 type: OS::TripleO::Network::Ports::RedisVipPort
502 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
503 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
504 PortName: redis_virtual_ip
505 NetworkName: {get_attr: [ServiceNetMap, service_net_map, RedisNetwork]}
507 FixedIPs: {get_param: RedisVirtualFixedIPs}
509 # The public VIP is on the External net, falls back to ctlplane
512 type: OS::TripleO::Network::Ports::ExternalVipPort
514 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
515 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
516 PortName: public_virtual_ip
517 FixedIPs: {get_param: PublicVirtualFixedIPs}
519 InternalApiVirtualIP:
521 type: OS::TripleO::Network::Ports::InternalApiVipPort
523 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
524 PortName: internal_api_virtual_ip
525 FixedIPs: {get_param: InternalApiVirtualFixedIPs}
529 type: OS::TripleO::Network::Ports::StorageVipPort
531 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
532 PortName: storage_virtual_ip
533 FixedIPs: {get_param: StorageVirtualFixedIPs}
535 StorageMgmtVirtualIP:
537 type: OS::TripleO::Network::Ports::StorageMgmtVipPort
539 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
540 PortName: storage_management_virtual_ip
541 FixedIPs: {get_param: StorageMgmtVirtualFixedIPs}
544 type: OS::TripleO::Network::Ports::NetVipMap
546 ControlPlaneIp: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
547 ExternalIp: {get_attr: [PublicVirtualIP, ip_address]}
548 ExternalIpUri: {get_attr: [PublicVirtualIP, ip_address_uri]}
549 InternalApiIp: {get_attr: [InternalApiVirtualIP, ip_address]}
550 InternalApiIpUri: {get_attr: [InternalApiVirtualIP, ip_address_uri]}
551 StorageIp: {get_attr: [StorageVirtualIP, ip_address]}
552 StorageIpUri: {get_attr: [StorageVirtualIP, ip_address_uri]}
553 StorageMgmtIp: {get_attr: [StorageMgmtVirtualIP, ip_address]}
554 StorageMgmtIpUri: {get_attr: [StorageMgmtVirtualIP, ip_address_uri]}
555 # No tenant or management VIP required
557 # All Nodes Validations
558 AllNodesValidationConfig:
559 type: OS::TripleO::AllNodes::Validation
564 - - {get_attr: [{{primary_role_name}}, resource.0.external_ip_address]}
565 - {get_attr: [{{primary_role_name}}, resource.0.internal_api_ip_address]}
566 - {get_attr: [{{primary_role_name}}, resource.0.storage_ip_address]}
567 - {get_attr: [{{primary_role_name}}, resource.0.storage_mgmt_ip_address]}
568 - {get_attr: [{{primary_role_name}}, resource.0.tenant_ip_address]}
569 - {get_attr: [{{primary_role_name}}, resource.0.management_ip_address]}
572 type: OS::TripleO::Tasks::UpdateWorkflow
574 {% for role in roles %}
575 - {{role.name}}AllNodesDeployment
579 {% for role in roles %}
580 {{role.name}}: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
583 deploy_identifier: {get_param: DeployIdentifier}
584 update_identifier: {get_param: UpdateIdentifier}
586 # Optional ExtraConfig for all nodes - all roles are passed in here, but
587 # the nested template may configure each role differently (or not at all)
589 type: OS::TripleO::AllNodesExtraConfig
592 {% for role in roles %}
593 - {{role.name}}AllNodesValidationDeployment
597 {% for role in roles %}
598 {{role.name}}: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
601 # Post deployment steps for all roles
603 type: OS::TripleO::PostDeploySteps
605 {% for role in roles %}
606 - {{role.name}}AllNodesDeployment
610 {% for role in roles %}
611 {{role.name}}: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
613 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
615 {% for role in roles %}
616 {{role.name}}: {get_attr: [{{role.name}}ServiceChain, role_data]}
621 description: Asserts that the keystone endpoints have been provisioned.
624 description: URL for the Overcloud Keystone service
625 value: {get_attr: [EndpointMap, endpoint_map, KeystonePublic, uri]}
627 description: Keystone Admin VIP endpoint
628 value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, KeystoneAdminApiNetwork]}]}
631 Mapping of the resources with the needed info for their endpoints.
632 This includes the protocol used, the IP, port and also a full
633 representation of the URI.
634 value: {get_attr: [EndpointMap, endpoint_map]}
637 The content that should be appended to your /etc/hosts if you want to get
638 hostname-based access to the deployed nodes (useful for testing without
643 - - {get_attr: [hostsConfig, hosts_entries]}
644 - - {get_attr: [VipHosts, value]}
646 description: The services enabled on each role
648 {% for role in roles %}
649 {{role.name}}: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
652 description: The configuration data associated with each role
654 {% for role in roles %}
655 {{role.name}}: {get_attr: [{{role.name}}ServiceChain, role_data]}