1 heat_template_version: 2016-10-14
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.
176 HeatAuthEncryptionKey:
177 type: OS::Heat::RandomString
180 type: OS::Heat::RandomString
185 type: OS::Heat::RandomString
190 type: OS::TripleO::ServiceNetMap
193 type: OS::TripleO::EndpointMap
196 external: {get_param: CloudName}
197 internal_api: {get_param: CloudNameInternal}
198 storage: {get_param: CloudNameStorage}
199 storage_mgmt: {get_param: CloudNameStorageManagement}
200 ctlplane: {get_param: CloudNameCtlplane}
201 NetIpMap: {get_attr: [VipMap, net_ip_map]}
202 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
204 # Jinja loop for Role in roles_data.yaml
205 {% for role in roles %}
206 # Resources generated for {{role.name}} Role
207 {{role.name}}ServiceChain:
208 type: OS::TripleO::Services
211 get_param: {{role.name}}Services
212 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
213 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
214 DefaultPasswords: {get_attr: [DefaultPasswords, passwords]}
216 {{role.name}}HostsDeployment:
217 type: OS::Heat::StructuredDeployments
219 name: {{role.name}}HostsDeployment
220 config: {get_attr: [hostsConfig, config_id]}
221 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
223 {{role.name}}AllNodesDeployment:
224 type: OS::Heat::StructuredDeployments
226 {% for role_inner in roles %}
227 - {{role_inner.name}}HostsDeployment
230 name: {{role.name}}AllNodesDeployment
231 config: {get_attr: [allNodesConfig, config_id]}
232 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
234 # Note we have to use yaql to look up the first hostname/ip in the
235 # list because heat path based attributes operate on the attribute
236 # inside the ResourceGroup, not the exposed list ref discussion in
237 # https://bugs.launchpad.net/heat/+bug/1640488
238 # The coalesce is needed because $.data is None during heat validation
241 expression: coalesce($.data, []).first(null)
242 data: {get_attr: [{{role.name}}, hostname]}
245 expression: coalesce($.data, []).first(null)
246 data: {get_attr: [{{role.name}}, ip_address]}
248 {{role.name}}AllNodesValidationDeployment:
249 type: OS::Heat::StructuredDeployments
250 depends_on: {{role.name}}AllNodesDeployment
252 name: {{role.name}}AllNodesValidationDeployment
253 config: {get_resource: AllNodesValidationConfig}
254 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
256 {{role.name}}IpListMap:
257 type: OS::TripleO::Network::Ports::NetIpListMap
259 ControlPlaneIpList: {get_attr: [{{role.name}}, ip_address]}
260 ExternalIpList: {get_attr: [{{role.name}}, external_ip_address]}
261 InternalApiIpList: {get_attr: [{{role.name}}, internal_api_ip_address]}
262 StorageIpList: {get_attr: [{{role.name}}, storage_ip_address]}
263 StorageMgmtIpList: {get_attr: [{{role.name}}, storage_mgmt_ip_address]}
264 TenantIpList: {get_attr: [{{role.name}}, tenant_ip_address]}
265 ManagementIpList: {get_attr: [{{role.name}}, management_ip_address]}
266 EnabledServices: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
267 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
268 ServiceHostnameList: {get_attr: [{{role.name}}, hostname]}
270 # Note (shardy) this somewhat complex yaql may be replaced
271 # with a map_deep_merge function in ocata. It merges the
272 # list of maps, but appends to colliding lists so we can
273 # create a map of lists for all nodes for each network
275 expression: dict($.data.where($ != null).flatten().selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
277 - {get_attr: [{{role.name}}, hostname_map]}
280 type: OS::Heat::ResourceGroup
283 count: {get_param: {{role.name}}Count}
284 removal_policies: {get_param: {{role.name}}RemovalPolicies}
286 type: OS::TripleO::{{role.name}}
288 CloudDomain: {get_param: CloudDomain}
289 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
290 EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
293 template: {get_param: {{role.name}}HostnameFormat}
295 '%stackname%': {get_param: 'OS::stack_name'}
297 {% if role.name != 'Compute' %}
298 {{role.name}}SchedulerHints: {get_param: {{role.name}}SchedulerHints}
300 NovaComputeSchedulerHints: {get_param: NovaComputeSchedulerHints}
302 ServiceConfigSettings:
304 - get_attr: [{{role.name}}ServiceChain, role_data, config_settings]
306 - get_attr: [{{r.name}}ServiceChain, role_data, global_config_settings]
308 # This next step combines two yaql passes:
309 # - The inner one does a deep merge on the service_config_settings for all roles
310 # - The outer one filters the map based on the services enabled for the role
311 # then merges the result into one map.
313 expression: let(root => $) -> $.data.map.items().where($[0] in $root.data.services).select($[1]).reduce($1.mergeWith($2), {})
317 expression: $.data.where($ != null).reduce($1.mergeWith($2), {})
320 - get_attr: [{{r.name}}ServiceChain, role_data, service_config_settings]
322 services: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
323 ServiceNames: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
324 MonitoringSubscriptions: {get_attr: [{{role.name}}ServiceChain, role_data, monitoring_subscriptions]}
328 type: OS::TripleO::Hosts::SoftwareConfig
331 {% for role in roles %}
334 - {get_attr: [{{role.name}}, hosts_entry]}
338 type: OS::TripleO::AllNodes::SoftwareConfig
340 cloud_name_external: {get_param: CloudName}
341 cloud_name_internal_api: {get_param: CloudNameInternal}
342 cloud_name_storage: {get_param: CloudNameStorage}
343 cloud_name_storage_mgmt: {get_param: CloudNameStorageManagement}
344 cloud_name_ctlplane: {get_param: CloudNameCtlplane}
348 {% for role in roles %}
349 - {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
354 $.data.groups.flatten()
357 {% for role in roles %}
358 - {get_attr: [{{role.name}}ServiceChain, role_data, logging_groups]}
363 $.data.sources.flatten()
366 {% for role in roles %}
367 - {get_attr: [{{role.name}}ServiceChain, role_data, logging_sources]}
369 controller_ips: {get_attr: [Controller, ip_address]}
370 controller_names: {get_attr: [Controller, hostname]}
372 # Note (shardy) this somewhat complex yaql may be replaced
373 # with a map_deep_merge function in ocata. It merges the
374 # list of maps, but appends to colliding lists when a service
375 # is deployed on more than one role
377 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
380 {% for role in roles %}
381 - {get_attr: [{{role.name}}IpListMap, service_ips]}
385 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
388 {% for role in roles %}
389 - {get_attr: [{{role.name}}IpListMap, service_hostnames]}
391 short_service_node_names:
393 expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
396 {% for role in roles %}
397 - {get_attr: [{{role.name}}IpListMap, short_service_hostnames]}
399 # FIXME(shardy): These require further work to move into service_ips
400 memcache_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, MemcachedNetwork]}]}
401 NetVipMap: {get_attr: [VipMap, net_ip_map]}
402 RedisVirtualIP: {get_attr: [RedisVirtualIP, ip_address]}
403 ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
404 DeployIdentifier: {get_param: DeployIdentifier}
405 UpdateIdentifier: {get_param: UpdateIdentifier}
408 type: OS::Heat::RandomString
413 type: OS::Heat::RandomString
416 salt: {get_param: RabbitCookieSalt}
419 type: OS::TripleO::DefaultPasswords
421 DefaultMysqlRootPassword: {get_attr: [MysqlRootPassword, value]}
422 DefaultRabbitCookie: {get_attr: [RabbitCookie, value]}
423 DefaultHeatAuthEncryptionKey: {get_attr: [HeatAuthEncryptionKey, value]}
424 DefaultPcsdPassword: {get_attr: [PcsdPassword, value]}
425 DefaultHorizonSecret: {get_attr: [HorizonSecret, value]}
427 # creates the network architecture
429 type: OS::TripleO::Network
432 type: OS::Neutron::Port
435 name: control_virtual_ip
436 network: {get_param: NeutronControlPlaneID}
437 fixed_ips: {get_param: ControlFixedIPs}
438 replacement_policy: AUTO
442 type: OS::TripleO::Network::Ports::RedisVipPort
444 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
445 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
446 PortName: redis_virtual_ip
447 NetworkName: {get_attr: [ServiceNetMap, service_net_map, RedisNetwork]}
449 FixedIPs: {get_param: RedisVirtualFixedIPs}
451 # The public VIP is on the External net, falls back to ctlplane
454 type: OS::TripleO::Network::Ports::ExternalVipPort
456 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
457 ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
458 PortName: public_virtual_ip
459 FixedIPs: {get_param: PublicVirtualFixedIPs}
461 InternalApiVirtualIP:
463 type: OS::TripleO::Network::Ports::InternalApiVipPort
465 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
466 PortName: internal_api_virtual_ip
467 FixedIPs: {get_param: InternalApiVirtualFixedIPs}
471 type: OS::TripleO::Network::Ports::StorageVipPort
473 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
474 PortName: storage_virtual_ip
475 FixedIPs: {get_param: StorageVirtualFixedIPs}
477 StorageMgmtVirtualIP:
479 type: OS::TripleO::Network::Ports::StorageMgmtVipPort
481 ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
482 PortName: storage_management_virtual_ip
483 FixedIPs: {get_param: StorageMgmtVirtualFixedIPs}
486 type: OS::TripleO::Network::Ports::NetVipMap
488 ControlPlaneIp: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
489 ExternalIp: {get_attr: [PublicVirtualIP, ip_address]}
490 ExternalIpUri: {get_attr: [PublicVirtualIP, ip_address_uri]}
491 InternalApiIp: {get_attr: [InternalApiVirtualIP, ip_address]}
492 InternalApiIpUri: {get_attr: [InternalApiVirtualIP, ip_address_uri]}
493 StorageIp: {get_attr: [StorageVirtualIP, ip_address]}
494 StorageIpUri: {get_attr: [StorageVirtualIP, ip_address_uri]}
495 StorageMgmtIp: {get_attr: [StorageMgmtVirtualIP, ip_address]}
496 StorageMgmtIpUri: {get_attr: [StorageMgmtVirtualIP, ip_address_uri]}
497 # No tenant or management VIP required
499 # All Nodes Validations
500 AllNodesValidationConfig:
501 type: OS::TripleO::AllNodes::Validation
506 - - {get_attr: [Controller, resource.0.external_ip_address]}
507 - {get_attr: [Controller, resource.0.internal_api_ip_address]}
508 - {get_attr: [Controller, resource.0.storage_ip_address]}
509 - {get_attr: [Controller, resource.0.storage_mgmt_ip_address]}
510 - {get_attr: [Controller, resource.0.tenant_ip_address]}
511 - {get_attr: [Controller, resource.0.management_ip_address]}
514 type: OS::TripleO::Tasks::UpdateWorkflow
516 {% for role in roles %}
517 - {{role.name}}AllNodesDeployment
521 {% for role in roles %}
522 {{role.name}}: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
525 deploy_identifier: {get_param: DeployIdentifier}
526 update_identifier: {get_param: UpdateIdentifier}
528 # Optional ExtraConfig for all nodes - all roles are passed in here, but
529 # the nested template may configure each role differently (or not at all)
531 type: OS::TripleO::AllNodesExtraConfig
534 {% for role in roles %}
535 - {{role.name}}AllNodesValidationDeployment
538 {% for role in roles %}
539 servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
542 # Post deployment steps for all roles
544 type: OS::TripleO::PostDeploySteps
546 {% for role in roles %}
547 - {{role.name}}AllNodesDeployment
551 {% for role in roles %}
552 {{role.name}}: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
555 {% for role in roles %}
556 {{role.name}}: {get_attr: [{{role.name}}ServiceChain, role_data]}
561 description: Asserts that the keystone endpoints have been provisioned.
564 description: URL for the Overcloud Keystone service
565 value: {get_attr: [EndpointMap, endpoint_map, KeystonePublic, uri]}
567 description: Keystone Admin VIP endpoint
568 value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, KeystoneAdminApiNetwork]}]}
571 Mapping of the resources with the needed info for their endpoints.
572 This includes the protocol used, the IP, port and also a full
573 representation of the URI.
574 value: {get_attr: [EndpointMap, endpoint_map]}
577 The content that should be appended to your /etc/hosts if you want to get
578 hostname-based access to the deployed nodes (useful for testing without
583 - - {get_attr: [hostsConfig, hosts_entries]}
588 IP: {get_attr: [VipMap, net_ip_map, external]}
589 HOST: {get_param: CloudName}
593 IP: {get_attr: [VipMap, net_ip_map, ctlplane]}
594 HOST: {get_param: CloudNameCtlplane}
598 IP: {get_attr: [VipMap, net_ip_map, internal_api]}
599 HOST: {get_param: CloudNameInternal}
603 IP: {get_attr: [VipMap, net_ip_map, storage]}
604 HOST: {get_param: CloudNameStorage}
608 IP: {get_attr: [VipMap, net_ip_map, storage_mgmt]}
609 HOST: {get_param: CloudNameStorageManagement}
611 description: The services enabled on each role
613 {% for role in roles %}
614 {{role.name}}: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}