Heat engine settings required for Undercloud
[apex-tripleo-heat-templates.git] / overcloud.j2.yaml
1 heat_template_version: ocata
2
3 description: >
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.
8
9
10 # TODO(shadower): we should probably use the parameter groups to put
11 # some order in here.
12 parameters:
13
14   # Common parameters (not specific to a role)
15   CloudName:
16     default: overcloud.localdomain
17     description: The DNS name of this cloud. E.g. ci-overcloud.tripleo.org
18     type: string
19   CloudNameInternal:
20     default: overcloud.internalapi.localdomain
21     description: >
22       The DNS name of this cloud's internal API endpoint. E.g.
23       'ci-overcloud.internalapi.tripleo.org'.
24     type: string
25   CloudNameStorage:
26     default: overcloud.storage.localdomain
27     description: >
28       The DNS name of this cloud's storage endpoint. E.g.
29       'ci-overcloud.storage.tripleo.org'.
30     type: string
31   CloudNameStorageManagement:
32     default: overcloud.storagemgmt.localdomain
33     description: >
34       The DNS name of this cloud's storage management endpoint. E.g.
35       'ci-overcloud.storagemgmt.tripleo.org'.
36     type: string
37   CloudNameCtlplane:
38     default: overcloud.ctlplane.localdomain
39     description: >
40       The DNS name of this cloud's storage management endpoint. E.g.
41       'ci-overcloud.management.tripleo.org'.
42     type: string
43   ControlFixedIPs:
44     default: []
45     description: Should be used for arbitrary ips.
46     type: json
47   InternalApiVirtualFixedIPs:
48     default: []
49     description: >
50         Control the IP allocation for the InternalApiVirtualInterface port. E.g.
51         [{'ip_address':'1.2.3.4'}]
52     type: json
53   NeutronControlPlaneID:
54     default: 'ctlplane'
55     type: string
56     description: Neutron ID or name for ctlplane network.
57   NeutronPublicInterface:
58     default: nic1
59     description: What interface to bridge onto br-ex for network nodes.
60     type: string
61   PublicVirtualFixedIPs:
62     default: []
63     description: >
64         Control the IP allocation for the PublicVirtualInterface port. E.g.
65         [{'ip_address':'1.2.3.4'}]
66     type: json
67   RabbitCookieSalt:
68     type: string
69     default: unset
70     description: Salt for the rabbit cookie, change this to force the randomly generated rabbit cookie to change.
71   StorageVirtualFixedIPs:
72     default: []
73     description: >
74         Control the IP allocation for the StorageVirtualInterface port. E.g.
75         [{'ip_address':'1.2.3.4'}]
76     type: json
77   StorageMgmtVirtualFixedIPs:
78     default: []
79     description: >
80         Control the IP allocation for the StorageMgmgVirtualInterface port. E.g.
81         [{'ip_address':'1.2.3.4'}]
82     type: json
83   RedisVirtualFixedIPs:
84     default: []
85     description: >
86         Control the IP allocation for the virtual IP used by Redis. E.g.
87         [{'ip_address':'1.2.3.4'}]
88     type: json
89   CloudDomain:
90     default: 'localdomain'
91     type: string
92     description: >
93       The DNS domain used for the hosts. This should match the dhcp_domain
94       configured in the Undercloud neutron. Defaults to localdomain.
95   ServerMetadata:
96     default: {}
97     description: >
98       Extra properties or metadata passed to Nova for the created nodes in
99       the overcloud. It's accessible via the Nova metadata API.
100     type: json
101
102 # Compute-specific params
103 # FIXME(shardy) handle these deprecated names as they don't match compute.yaml
104   HypervisorNeutronPhysicalBridge:
105     default: 'br-ex'
106     description: >
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.
110     type: string
111   HypervisorNeutronPublicInterface:
112     default: nic1
113     description: What interface to add to the HypervisorNeutronPhysicalBridge.
114     type: string
115
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
124
125   {{role.name}}Count:
126     description: Number of {{role.name}} nodes to deploy
127     type: number
128     default: {{role.CountDefault|default(0)}}
129
130   {{role.name}}HostnameFormat:
131     type: string
132     description: >
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}}"
138   {% else %}
139     default: "%stackname%-{{role.name.lower()}}-%index%"
140   {% endif %}
141
142   {{role.name}}RemovalPolicies:
143     default: []
144     type: json
145     description: >
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']}]
149
150 {% if role.name != 'Compute' %}
151   {{role.name}}SchedulerHints:
152 {% else %}
153   NovaComputeSchedulerHints:
154 {% endif %}
155     type: json
156     description: Optional scheduler hints to pass to nova
157     default: {}
158 {% endfor %}
159
160   # Identifiers to trigger tasks on nodes
161   UpdateIdentifier:
162     default: ''
163     type: string
164     description: >
165       Setting to a previously unused value during stack-update will trigger
166       package update on all nodes
167   DeployIdentifier:
168     default: ''
169     type: string
170     description: >
171       Setting this to a unique value will re-run any deployment tasks which
172       perform configuration on a Heat stack-update.
173   AddVipsToEtcHosts:
174     default: True
175     type: boolean
176     description: >
177       Set to true to append per network Vips to /etc/hosts on each node.
178
179 conditions:
180   add_vips_to_etc_hosts: {equals : [{get_param: AddVipsToEtcHosts}, True]}
181
182 resources:
183
184   VipHosts:
185     type: OS::Heat::Value
186     properties:
187       type: string
188       value:
189         list_join:
190         - "\n"
191         - - str_replace:
192               template: IP  HOST
193               params:
194                 IP: {get_attr: [VipMap, net_ip_map, external]}
195                 HOST: {get_param: CloudName}
196           - str_replace:
197               template: IP  HOST
198               params:
199                 IP: {get_attr: [VipMap, net_ip_map, ctlplane]}
200                 HOST: {get_param: CloudNameCtlplane}
201           - str_replace:
202               template: IP  HOST
203               params:
204                 IP: {get_attr: [VipMap, net_ip_map, internal_api]}
205                 HOST: {get_param: CloudNameInternal}
206           - str_replace:
207               template: IP  HOST
208               params:
209                 IP: {get_attr: [VipMap, net_ip_map, storage]}
210                 HOST: {get_param: CloudNameStorage}
211           - str_replace:
212               template: IP  HOST
213               params:
214                 IP: {get_attr: [VipMap, net_ip_map, storage_mgmt]}
215                 HOST: {get_param: CloudNameStorageManagement}
216
217   HeatAuthEncryptionKey:
218     type: OS::Heat::RandomString
219
220   PcsdPassword:
221     type: OS::Heat::RandomString
222     properties:
223       length: 16
224
225   HorizonSecret:
226     type: OS::Heat::RandomString
227     properties:
228       length: 10
229
230   ServiceNetMap:
231     type: OS::TripleO::ServiceNetMap
232
233   EndpointMap:
234     type: OS::TripleO::EndpointMap
235     properties:
236       CloudEndpoints:
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]}
244
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
250     properties:
251       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]}
256
257   {{role.name}}HostsDeployment:
258     type: OS::Heat::StructuredDeployments
259     properties:
260       name: {{role.name}}HostsDeployment
261       config: {get_attr: [hostsConfig, config_id]}
262       servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
263
264   {{role.name}}AllNodesDeployment:
265     type: OS::Heat::StructuredDeployments
266     depends_on:
267 {% for role_inner in roles %}
268       - {{role_inner.name}}HostsDeployment
269 {% endfor %}
270     properties:
271       name: {{role.name}}AllNodesDeployment
272       config: {get_attr: [allNodesConfig, config_id]}
273       servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
274       input_values:
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
280         bootstrap_nodeid:
281           yaql:
282             expression: coalesce($.data, []).first(null)
283             data: {get_attr: [{{role.name}}, hostname]}
284         bootstrap_nodeid_ip:
285           yaql:
286             expression: coalesce($.data, []).first(null)
287             data: {get_attr: [{{role.name}}, ip_address]}
288
289   {{role.name}}AllNodesValidationDeployment:
290     type: OS::Heat::StructuredDeployments
291     depends_on: {{role.name}}AllNodesDeployment
292     properties:
293       name: {{role.name}}AllNodesValidationDeployment
294       config: {get_resource: AllNodesValidationConfig}
295       servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
296
297   {{role.name}}IpListMap:
298     type: OS::TripleO::Network::Ports::NetIpListMap
299     properties:
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]}
310       NetworkHostnameMap:
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
315         yaql:
316           expression: dict($.data.where($ != null).flatten().selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
317           data:
318             - {get_attr: [{{role.name}}, hostname_map]}
319
320   {{role.name}}:
321     type: OS::Heat::ResourceGroup
322     depends_on: Networks
323     properties:
324       count: {get_param: {{role.name}}Count}
325       removal_policies: {get_param: {{role.name}}RemovalPolicies}
326       resource_def:
327         type: OS::TripleO::{{role.name}}
328         properties:
329           CloudDomain: {get_param: CloudDomain}
330           ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
331           EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
332           Hostname:
333             str_replace:
334               template: {get_param: {{role.name}}HostnameFormat}
335               params:
336                 '%stackname%': {get_param: 'OS::stack_name'}
337           NodeIndex: '%index%'
338   {% if role.name != 'Compute' %}
339           {{role.name}}SchedulerHints: {get_param: {{role.name}}SchedulerHints}
340   {% else %}
341           NovaComputeSchedulerHints: {get_param: NovaComputeSchedulerHints}
342   {% endif %}
343           ServiceConfigSettings:
344             map_merge:
345               -  get_attr: [{{role.name}}ServiceChain, role_data, config_settings]
346           {% for r in roles %}
347               - get_attr: [{{r.name}}ServiceChain, role_data, global_config_settings]
348           {% endfor %}
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.
353               - yaql:
354                   expression: let(root => $) -> $.data.map.items().where($[0] in coalesce($root.data.services, [])).select($[1]).reduce($1.mergeWith($2), {})
355                   data:
356                     map:
357                       yaql:
358                         expression: $.data.where($ != null).reduce($1.mergeWith($2), {})
359                         data:
360                         {% for r in roles %}
361                           - get_attr: [{{r.name}}ServiceChain, role_data, service_config_settings]
362                         {% endfor %}
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]}
367 {% endfor %}
368
369   hostsConfig:
370     type: OS::TripleO::Hosts::SoftwareConfig
371     properties:
372       hosts:
373         list_join:
374         - "\n"
375         - - if:
376             - add_vips_to_etc_hosts
377             - {get_attr: [VipHosts, value]}
378             - ''
379         -
380 {% for role in roles %}
381           - list_join:
382             - "\n"
383             - {get_attr: [{{role.name}}, hosts_entry]}
384 {% endfor %}
385
386   allNodesConfig:
387     type: OS::TripleO::AllNodes::SoftwareConfig
388     properties:
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}
394       enabled_services:
395         list_join:
396           - ','
397 {% for role in roles %}
398           - {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
399 {% endfor %}
400       logging_groups:
401         yaql:
402           expression: >
403             $.data.groups.flatten()
404           data:
405             groups:
406 {% for role in roles %}
407               - {get_attr: [{{role.name}}ServiceChain, role_data, logging_groups]}
408 {% endfor %}
409       logging_sources:
410         yaql:
411           expression: >
412             $.data.sources.flatten()
413           data:
414             sources:
415 {% for role in roles %}
416               - {get_attr: [{{role.name}}ServiceChain, role_data, logging_sources]}
417 {% endfor %}
418       controller_ips: {get_attr: [Controller, ip_address]}
419       controller_names: {get_attr: [Controller, hostname]}
420       service_ips:
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
425         yaql:
426           expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
427           data:
428             l:
429 {% for role in roles %}
430               - {get_attr: [{{role.name}}IpListMap, service_ips]}
431 {% endfor %}
432       service_node_names:
433         yaql:
434           expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
435           data:
436             l:
437 {% for role in roles %}
438               - {get_attr: [{{role.name}}IpListMap, service_hostnames]}
439 {% endfor %}
440       short_service_node_names:
441         yaql:
442           expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
443           data:
444             l:
445 {% for role in roles %}
446               - {get_attr: [{{role.name}}IpListMap, short_service_hostnames]}
447 {% endfor %}
448       short_service_bootstrap_node:
449         yaql:
450           expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten().first()]))
451           data:
452             l:
453 {% for role in roles %}
454               - {get_attr: [{{role.name}}IpListMap, short_service_bootstrap_hostnames]}
455 {% endfor %}
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}
463
464   MysqlRootPassword:
465     type: OS::Heat::RandomString
466     properties:
467       length: 10
468
469   RabbitCookie:
470     type: OS::Heat::RandomString
471     properties:
472       length: 20
473       salt: {get_param: RabbitCookieSalt}
474
475   DefaultPasswords:
476     type: OS::TripleO::DefaultPasswords
477     properties:
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]}
483
484   # creates the network architecture
485   Networks:
486     type: OS::TripleO::Network
487
488   ControlVirtualIP:
489     type: OS::TripleO::Network::Ports::ControlPlaneVipPort
490     depends_on: Networks
491     properties:
492       name: control_virtual_ip
493       network: {get_param: NeutronControlPlaneID}
494       fixed_ips: {get_param: ControlFixedIPs}
495       replacement_policy: AUTO
496
497   RedisVirtualIP:
498     depends_on: Networks
499     type: OS::TripleO::Network::Ports::RedisVipPort
500     properties:
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]}
505       ServiceName: redis
506       FixedIPs: {get_param: RedisVirtualFixedIPs}
507
508   # The public VIP is on the External net, falls back to ctlplane
509   PublicVirtualIP:
510     depends_on: Networks
511     type: OS::TripleO::Network::Ports::ExternalVipPort
512     properties:
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}
517
518   InternalApiVirtualIP:
519     depends_on: Networks
520     type: OS::TripleO::Network::Ports::InternalApiVipPort
521     properties:
522       ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
523       PortName: internal_api_virtual_ip
524       FixedIPs: {get_param: InternalApiVirtualFixedIPs}
525
526   StorageVirtualIP:
527     depends_on: Networks
528     type: OS::TripleO::Network::Ports::StorageVipPort
529     properties:
530       ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
531       PortName: storage_virtual_ip
532       FixedIPs: {get_param: StorageVirtualFixedIPs}
533
534   StorageMgmtVirtualIP:
535     depends_on: Networks
536     type: OS::TripleO::Network::Ports::StorageMgmtVipPort
537     properties:
538       ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
539       PortName: storage_management_virtual_ip
540       FixedIPs: {get_param: StorageMgmtVirtualFixedIPs}
541
542   VipMap:
543     type: OS::TripleO::Network::Ports::NetVipMap
544     properties:
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
555
556   # All Nodes Validations
557   AllNodesValidationConfig:
558     type: OS::TripleO::AllNodes::Validation
559     properties:
560       PingTestIps:
561         list_join:
562         - ' '
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]}
569
570   UpdateWorkflow:
571     type: OS::TripleO::Tasks::UpdateWorkflow
572     depends_on:
573 {% for role in roles %}
574       - {{role.name}}AllNodesDeployment
575 {% endfor %}
576     properties:
577       servers:
578 {% for role in roles %}
579         {{role.name}}: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
580 {% endfor %}
581       input_values:
582         deploy_identifier: {get_param: DeployIdentifier}
583         update_identifier: {get_param: UpdateIdentifier}
584
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)
587   AllNodesExtraConfig:
588     type: OS::TripleO::AllNodesExtraConfig
589     depends_on:
590       - UpdateWorkflow
591 {% for role in roles %}
592       - {{role.name}}AllNodesValidationDeployment
593 {% endfor %}
594     properties:
595 {% for role in roles %}
596       servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
597 {% endfor %}
598
599   # Upgrade steps for all roles
600   AllNodesUpgradeSteps:
601     type: OS::TripleO::UpgradeSteps
602     depends_on:
603 {% for role in roles %}
604       - {{role.name}}AllNodesDeployment
605 {% endfor %}
606     properties:
607       servers:
608 {% for role in roles %}
609         {{role.name}}: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
610 {% endfor %}
611       role_data:
612 {% for role in roles %}
613         {{role.name}}: {get_attr: [{{role.name}}ServiceChain, role_data]}
614 {% endfor %}
615
616   # Post deployment steps for all roles
617   AllNodesDeploySteps:
618     type: OS::TripleO::PostDeploySteps
619     depends_on: AllNodesUpgradeSteps
620     properties:
621       servers:
622 {% for role in roles %}
623         {{role.name}}: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
624 {% endfor %}
625       role_data:
626 {% for role in roles %}
627         {{role.name}}: {get_attr: [{{role.name}}ServiceChain, role_data]}
628 {% endfor %}
629
630 outputs:
631   ManagedEndpoints:
632     description: Asserts that the keystone endpoints have been provisioned.
633     value: true
634   KeystoneURL:
635     description: URL for the Overcloud Keystone service
636     value: {get_attr: [EndpointMap, endpoint_map, KeystonePublic, uri]}
637   KeystoneAdminVip:
638     description: Keystone Admin VIP endpoint
639     value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, KeystoneAdminApiNetwork]}]}
640   EndpointMap:
641     description: |
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]}
646   HostsEntry:
647     description: |
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
650       setting up a DNS).
651     value:
652       list_join:
653       - "\n"
654       - - {get_attr: [hostsConfig, hosts_entries]}
655       - - {get_attr: [VipHosts, value]}
656   EnabledServices:
657     description: The services enabled on each role
658     value:
659 {% for role in roles %}
660       {{role.name}}: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
661 {% endfor %}
662   RoleData:
663     description: The configuration data associated with each role
664     value:
665 {% for role in roles %}
666       {{role.name}}: {get_attr: [{{role.name}}ServiceChain, role_data]}
667 {% endfor %}