1 .. Licensed under a Creative Commons Attribution 4.0 International License.
2 .. http://creativecommons.org/licenses/by/4.0
3 .. Copyright 2017 AT&T Intellectual Property. All rights reserved.
5 .. _ONAP Heat Heat Template Constructs:
7 ONAP Heat Heat Template Constructs
8 --------------------------------------
10 .. _Nested Heat Templates:
15 ONAP supports nested Heat templates per the OpenStack specifications.
16 Nested templates may be suitable for larger VNFs that contain many
17 repeated instances of the same VM type(s). A common usage pattern is to
18 create a nested template for each {vm-type} along with its supporting
19 resources. The VNF module may then reference these component templates
20 either statically by repeated definition or dynamically by using the
21 resource OS::Heat::ResourceGroup.
23 Nested Heat Template Requirements
24 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 ONAP supports nested Heat Orchestration Templates.
28 As stated in Requirements :need:`R-36582`, :need:`R-56721`, and
29 :need:`R-30395`, a Base Module, Incremental Module, and Cinder Volume
30 Module may use nested heat.
38 A VNF's Heat Orchestration Template **MAY**
39 reference the nested heat statically by repeated definition.
47 A VNF's Heat Orchestration Template **MAY**
48 reference the nested heat dynamically using the resource
49 ``OS::Heat::ResourceGroup``.
51 A VNF's Heat Orchestration Template must
52 reference a Nested YAML file by name.
53 The use of ``resource_registry`` in the VNF's Heat Orchestration Templates
54 Environment File must not be used (as stated in R-67231).
56 As stated in requirement R-99646, a VNF's YAML files
57 (i.e, Heat Orchestration Template files and Nested files) **MUST**
58 have a unique name in the scope of the VNF.
65 A VNF's Heat Orchestration Template **MUST** have no more than two
68 Two levels of nesting is defined as follows: A base module, incremental
69 module, or cinder volume module references a nested heat file either
70 statically or by using the resource ``OS::Heat::ResourceGroup``.
71 The referenced YAML heat file is the first level of nested heat.
72 If first level nested YAML file references a nested heat file, that file is
73 the second level of nested heat.
80 A VNF's Heat Orchestration Template's first level Nested YAML file
81 **MUST NOT** contain more than one ``OS::Nova::Server`` resource.
82 A VNF's Heat Orchestration Template's second level Nested YAML file
83 **MUST NOT** contain an ``OS::Nova::Server`` resource.
90 If a VNF's Heat Orchestration Template's resource invokes a nested
91 YAML file, either statically or dynamically, the names of the parameters
92 passed into the nested YAML file **MUST NOT** change.
95 This requirement was introduced with Generic Resource API (GR-API).
96 GR-API creates the new VNFC Object.
97 SDN-C matches the ``{vm-type}`` in the ``OS::Nova::Server`` resource in the
98 nested YAML file to the corresponding nfc_naming_code.
99 If the ``{vm-type}`` name changes when the parameter names are passed into
100 the nested YAML file, SDN-C will not be able to match the
101 ``{vm-type}`` to the nfc_naming_code, breaking the assignment logic
102 and ONAP assigns a default value (i.e., "DEFAULT").
103 Instantiation will succeed with the incorrect VNFC Object
104 (i.e, contains the DEFAULT value). However, the default VNFC object will
105 cause issues for other ONAP applications/features.
113 All parameters defined in a VNFs Nested YAML file
114 **MUST** be passed in as properties of the resource calling
115 the nested yaml file.
122 A VNF's Nested YAML file **MAY** be invoked more than once by
123 a VNF's Heat Orchestration Template.
130 A VNF's Nested YAML file **MAY** be invoked by more than one of
131 a VNF's Heat Orchestration Templates (when the VNF is composed of two
132 or more Heat Orchestration Templates).
135 stated in requirement R-00011, a VNF's Heat Orchestration Template's
136 Nested YAML file's parameter's **SHOULD NOT** have a parameter
140 If a VNF's Heat Orchestration Template's nested YAML file is required to
141 expose a resource property to the invoking Heat OrchestrationTemplate,
142 an ``outputs:`` statement must be used in the nested YAML file.
143 The invoking template references the property by using the intrinsic
144 function ``get_attr`` that targets the resource invoking the nested YAML
145 file and references the parameter defined in the ``outputs`` section.
149 Nested Heat Template Example: Static
150 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
160 dns_image_name: { get_param: dns_image_name }
161 dns_flavor_name: { get_param: dns_flavor_name }
162 availability_zone_0: { get_param: availability_zone_0 }
163 DNS_shared_sec_grp_id: { get_param: DNS_shared_sec_grp_id }
164 oam_protected_net_id: { get_param: oam_protected_net_id }
165 dns_oam_ip_0: { get_param: dns_oam_ip_0 }
166 dns_name_0: { get_param: dns_name_0 }
167 vnf_name: { get_param: vnf_name }
168 vnf_id: { get_param: vnf_id }
169 vf_module_id: {get_param: vf_module_id}
176 dns_0_oam_protected_port_0:
177 type: OS::Neutron::Port
181 template: VNF_NAME_dns_oam_port
183 VNF_NAME: {get_param: vnf_name}
184 network: { get_param: oam_protected_net_id }
185 fixed_ips: [{ "ip_address": { get_param: dns_oam_ip_0 }}]
186 security_groups: [{ get_param: DNS_shared_sec_grp_id }]
188 type: OS::Nova::Server
190 name: { get_param: dns_names }
191 image: { get_param: dns_image_name }
192 flavor: { get_param: dns_flavor_name }
193 availability_zone: { get_param: availability_zone_0 }
195 - port: { get_resource: ns_0_oam_protected_port_0 }
197 vnf_id: { get_param: vnf_id }
198 vf_module_id: { get_param: vf_module_id }
199 vnf_name {get_param: vnf_name }
201 Use of Heat ResourceGroup
202 ~~~~~~~~~~~~~~~~~~~~~~~~~
204 The OS::Heat::ResourceGroup is a useful Heat element for creating
205 multiple instances of a given resource or collection of resources.
206 Typically, it is used with a nested Heat template to create, for
207 example, a set of identical OS::Nova::Server resources plus their
208 related OS::Neutron::Port resources via a single resource in a master
211 OS::Heat::ResourceGroup may be used to simplify the structure of a Heat
212 template that creates multiple instances of the same VM type.
214 However, there are important caveats to be aware of:
216 OS::Heat::ResourceGroup does not deal with structured parameters
217 (comma-delimited-list and json) as one might typically expect. In
218 particular, when using a list-based parameter, where each list element
219 corresponds to one instance of the ResourceGroup, it is not possible to
220 use the intrinsic "loop variable" %index% in the OS::Heat::ResourceGroup
223 For instance, the following is **not** valid Heat for
224 OS::Heat::ResourceGroup:
228 type: OS::Heat::ResourceGroup
232 type: my_nested_vm_template.yaml
234 name: {get_param: [vm_name_list, "%index%"]}
236 Although this appears to use the nth entry of the vm_name_list list for
237 the nth element of the OS::Heat::ResourceGroup, it will in fact result
238 in a Heat exception. When parameters are provided as a list (one for
239 each element of a OS::Heat::ResourceGroup), you must pass the complete
240 parameter to the nested template along with the current index as
243 Below is an example of an **acceptable** Heat Syntax for a
248 type: OS::Heat::ResourceGroup
252 type: my_nested_vm_template.yaml
254 names: {get_param: vm_name_list}
257 You can then reference within the nested template as:
259 { get_param: [names, {get_param: index} ] }
261 OS::Heat::ResourceGroup Property count
262 ++++++++++++++++++++++++++++++++++++++
269 :validation_mode: static
272 A VNF's Heat Orchestration Template's ``OS::Heat::ResourceGroup``
273 property ``count`` **MUST** be enumerated in the VNF's
274 Heat Orchestration Template's Environment File and **MUST** be
277 This is required for ONAP to build the TOSCA model for the VNF.
281 type: OS::Heat::ResourceGroup
283 count: { get_param: count }
286 type: my_nested_vm_template.yaml
288 names: {get_param: vm_name_list}
291 Availability Zone and ResourceGroups
292 ++++++++++++++++++++++++++++++++++++
294 The resource OS::Heat::ResourceGroup and the property availability_zone
295 has been an "issue" with a few VNFs since ONAP only supports
296 availability_zone as a string parameter and not as a
297 comma_delimited_list. This makes it difficult to use a
298 OS::Heat::ResourceGroup to create Virtual Machines in more than one
301 There are numerous solutions to this issue. Below are two suggested
304 **Option 1:** create a CDL in the OS::Heat::ResourceGroup. In the
305 resource type: OS::Heat::ResourceGroup, create a comma_delimited_list
306 availability_zones by using the intrinsic function list_join.
311 type: OS::Heat::ResourceGroup
313 count: { get_param: node_count }
319 availability_zones: { list_join: [',', [ { get_param: availability_zone_0 }, { get_param: availability_zone_1 } ] ] }
327 type: comma_delimited_list
332 type: OS::Nova::Server
334 name: { get_param: [ dns_names, get_param: index ] }
335 image: { get_param: dns_image_name }
336 flavor: { get_param: dns_flavor_name }
337 availability_zone: { get_param: [ availability_zones, get_param: index ] }
339 **Option 2:** Create a CDL by passing the availability zone parameter
340 into a nested heat template. An example is provided below.
346 availability_zone_list:
347 type: az_list_generate.yaml
349 availability_zone_0: { get_param: availability_zone_0 }
350 availability_zone_1: { get_param: availability_zone_1 }
352 create_virtual_machines:
353 type: OS::Heat::ResourceGroup
355 count: { get_param: count }
361 availability_zone_0 : { get_attr: [availability_zone_list, general_zones ] }
364 az_list_generate.yaml
371 description: availability zone 0
375 description: availability zone 1
381 { get_param: availability_zone_0 },
382 { get_param: availability_zone_1 },
383 { get_param: availability_zone_0 },
384 { get_param: availability_zone_1 },
385 { get_param: availability_zone_0 },
386 { get_param: availability_zone_1 }
390 Nested Heat Template Example: OS::Heat::ResourceGroup
391 +++++++++++++++++++++++++++++++++++++++++++++++++++++
393 In this example, ocgapp_volume.yml creates volumes using a
394 OS::Heat::ResourceGroup that uses nested heat by calling
395 ocgapp_nested_volume.yml. ocgapp_volume.yml has an outputs: parameter
396 ocgapp_volume_ids which is declared a input parameter of type: json in
400 This is an example of requirement :need:`R-07443`, where
401 a VNF's Heat Orchestration Templates' Cinder Volume Module Output
402 Parameter's name and type **MUST** match the input parameter name and type
403 in the corresponding Base Module or Incremental Module unless the Output
404 Parameter is of the type ``comma_delimited_list``, then the corresponding
405 input parameter **MUST** be declared as type ``json``.
411 heat_template_version: 2014-10-16
413 description: Template for the volumes
419 description: OCG VNF Name
420 ocgapp_volume_size_0:
422 label: Cinder volume 1 size
423 description: the size of the Cinder volume
425 - range: { min: 100, max: 400 }
426 ocgapp_volume_type_0:
428 label: app vm 1 volume type
429 description: the name of the target volume backend for the first OCG APP
433 description: number of volumes needed
436 ocgapp_volume_resource_group:
437 type: OS::Heat::ResourceGroup
439 count: {get_param: volume_count}
442 type: ocgapp_nested_volume.yml
445 size: {get_param: ocgapp_volume_size_0}
446 volume_type: {get_param: ocgapp_volume_type_0}
447 vnf_name: {get_param: vnf_name}
451 description: ocgapp volume ids
452 value: {get_attr: [ocgapp_volume_resource_group, ocgapp_volume_id_0]}
454 ocgapp_nested_volume.yml
458 heat_template_version: 2014-10-16
460 description: nested heat
466 description: number of volumes to spin up
470 description: size of the cinder volumes
474 description: type of cinder volumes
478 description: vnf name
482 type: OS::Cinder::Volume
484 size: {get_param: size}
485 volume_type: {get_param: volume_type}
488 template: VF_NAME_STACK_NAME_INDEX
490 VF_NAME: { get_param: vnf_name }
491 STACK_NAME: { get_param: 'OS::stack_name' }
492 INDEX: {get_param: index}
496 description: the ocgapp volume uuid
497 value: {get_resource: ocgapp_volume_0}
499 Below is a screen shot of parameter ocgapp_volume_ids from the OpenStack
500 Horizon GUI showing the output.
502 .. image:: ../../heat_picture3.png
507 The heat template below is a partial heat template,
513 heat_template_version: 2014-10-16
516 description: OCG Apps template
521 description: Unique IDs for volumes
525 type: OS::Nova::Server
529 type: OS::Nova::Server
532 ocgapp_volume_attachment_0:
533 type: OS::Cinder::VolumeAttachment
535 volume_id: {get_param: [ocgapp_volume_ids, 0]}
536 instance_uuid: {get_resource: ocgapp_server_0}
537 ocgapp_volume_attachment_1:
538 type: OS::Cinder::VolumeAttachment
540 volume_id: {get_param: [ocgapp_volume_ids, 1]}
541 instance_uuid: {get_resource: ocgapp_server_1}
546 Heat templates *must not* reference any HTTP-based resource
547 definitions, any HTTP-based nested configurations, or any HTTP-based
550 - During orchestration, ONAP *must not* retrieve any such resources
551 from external/untrusted/unknown sources.
553 - VNF images must not contain external references in user-data or other
554 configuration/operational scripts that are specified via Heat or
555 encoded into the VNF image itself.
557 *Note: HTTP-based references are acceptable if the HTTP-based reference
558 is accessing information utilizing the VM private/internal network.*
560 Note that Namespaces in XML (defined at
561 http://www.w3.org/TR/2009/REC-xml-names-20091208/) are allowed if the
562 Heat Orchestration Template is describing and storing software
563 configuration information. An XML namespace is identified by a URI
564 reference. A Uniform Resource Identifier (URI) is a string of characters
565 which identifies an Internet Resource. The most common URI is the
566 Uniform Resource Locator (URL) which identifies an Internet domain
567 address. Another, not so common type of URI is the Universal Resource
568 Name (URN). The namespace URI is not used by XML the parser to look up
569 information. The purpose of using an URI is to give the namespace a
572 Heat Files Support (get_file)
573 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
575 A VNF's Heat Orchestration Template may contain the inclusion of text files
576 containing scripts or configuration files. The ``get_file`` intrinsic
577 function returns the content of a file into a Heat Orchestration Template.
579 The support for the ``get_file`` intrinsic function in ONAP is subject to the
580 following limitations:
586 :validation_mode: static
589 If a VNF's Heat Orchestration Template uses the intrinsic function
590 ``get_file``, the ``get_file`` target **MUST** be referenced in
591 the Heat Orchestration Template by file name.
593 The ``get_file`` target files are on-boarded to SDC in the same zip file
594 that contains the VNF's complete Heat Orchestration Template.
595 See requirement R-511776.
601 :validation_mode: static
604 A VNF's Heat Orchestration Template intrinsic function
605 ``get_file`` **MUST NOT** utilize URL-based file retrieval.
614 A VNF's Heat Orchestration Templates intrinsic function
615 ``get_file`` <content key> **MAY** be used:
617 * more than once in a VNF's Heat Orchestration Template
618 * in two or more of a VNF's Heat Orchestration Templates
619 * in a VNF's Heat Orchestration Templates nested YAML file
624 When Nova Servers are created via Heat templates, they may be passed a
625 "keypair" which provides an ssh key to the 'root' login on the newly
626 created VM. This is often done so that an initial root key/password does
627 not need to be hard-coded into the image.
629 Key pairs are unusual in OpenStack, because they are the one resource
630 that is owned by an OpenStack User as opposed to being owned by an
631 OpenStack Tenant. As a result, they are usable only by the User that
632 created the keypair. This causes a problem when a Heat template attempts
633 to reference a keypair by name, because it assumes that the keypair was
634 previously created by a specific ONAP user ID.
636 When a keypair is assigned to a server, the SSH public-key is
637 provisioned on the VMs at instantiation time. They keypair itself is not
638 referenced further by the VM (i.e. if the keypair is updated with a new
639 public key, it would only apply to subsequent VMs created with that
642 Due to this behavior, the recommended usage of keypairs is in a more
643 generic manner which does not require the pre-requisite creation of a
644 keypair. The Heat should be structured in such a way as to:
646 - Pass a public key as a parameter value instead of a keypair name
648 - Create a new keypair within the VNF Heat templates (in the base module)
649 based on an existing public key for use within that VNF
651 By following this approach, the end result is the same as pre-creating
652 the keypair using the public key – i.e., that public key will be
653 provisioned in the new VM. However, this recommended approach also makes
654 sure that a known public key is supplied (instead of having OpenStack
655 generate a public/private pair to be saved and tracked outside of ONAP).
656 It also removes any access/ownership issues over the created keypair.
658 The public keys may be enumerated as a VNF Orchestration Constant in the
659 environment file (since it is public, it is not a secret key), or passed
660 at run-time as instance-specific parameters. ONAP will never
661 automatically assign a public/private key pair.
663 *Example (create keypair with an existing ssh public-key for {vm-type}
664 of lb (for load balancer)):*
676 type: OS::Nova::Keypair
680 template: VNF_NAME_key_pair
682 VNF_NAME: { get_param: vnf_name }
683 public_key: {get_param: lb_ssh_public_key}
684 save_private_key: false
689 OpenStack allows a tenant to create Security groups and define rules
690 within the security groups.
692 Security groups, with their rules, may either be created in the Heat
693 Orchestration Template or they can be pre-created in OpenStack and
694 referenced within the Heat template via parameter(s). There can be a
695 different approach for security groups assigned to ports on internal
696 (intra-VNF) networks or external networks (inter-VNF). Furthermore,
697 there can be a common security group across all VMs for a specific
698 network or it can vary by VM (i.e., {vm-type}) and network type (i.e.,
701 Anti-Affinity and Affinity Rules
702 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
704 Anti-affinity or affinity rules are supported using normal OpenStack
705 OS::Nova::ServerGroup resources. Separate ServerGroups are typically
706 created for each VM type to prevent them from residing on the same host,
707 but they can be applied to multiple VM types to extend the
708 affinity/anti-affinity across related VM types as well.
712 In this example, the {network-role} has been defined as oam to represent
713 an oam network and the {vm-type} have been defined as lb for load
714 balancer and db for database.
720 type: OS::Nova::ServerGroup
725 $vnf_name: {get_param: vnf_name}
726 template: $vnf_name-server_group1
730 type: OS::Nova::ServerGroup
735 $vnf_name: {get_param: vnf_name}
736 template: $vnf_name-server_group2
740 type: OS::Nova::Server
744 group: {get_resource: db_server_group}
746 type: OS::Nova::Server
750 group: {get_resource: db_server_group}
752 type: OS::Nova::Server
756 group: {get_resource: lb_server_group}
758 Resource Data Synchronization
759 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
761 For cases where synchronization is required in the orchestration of Heat
762 resources, two approaches are recommended:
764 - Standard Heat depends_on property for resources
766 - Assures that one resource completes before the dependent resource
769 - Definition of completeness to OpenStack may not be sufficient
770 (e.g., a VM is considered complete by OpenStack when it is ready
771 to be booted, not when the application is up and running).
773 - Use of Heat Notifications
775 - Create OS::Heat::WaitCondition and OS::Heat::WaitConditionHandle
778 - Pre-requisite resources issue *wc_notify* commands in user_data.
780 - Dependent resource define depends_on in the
781 OS::Heat::WaitCondition resource.
783 *Example: "depends_on" case*
785 In this example, the {network-role} has been defined as oam to represent
786 an oam network and the {vm-type} has been defined as oam to represent an
793 type: OS::Nova::Server
795 name: {get_param: [oam_names, 0]}
796 image: {get_param: oam_image_name}
797 flavor: {get_param: oam_flavor_name}
798 availability_zone: {get_param: availability_zone_0}
800 - port: {get_resource: oam01_port_0}
801 - port: {get_resource: oam01_port_1}
803 scheduler_hints: {group: {get_resource: oam_servergroup}}
804 user_data_format: RAW
806 type: OS::Neutron::Port
808 network: {get_resource: oam_net_name}
809 fixed_ips: [{"ip_address": {get_param: [oam_oam_net_ips, 1]}}]
810 security_groups: [{get_resource: oam_security_group}]
812 type: OS::Neutron::Port
814 network: {get_param: oam_net_name}
815 fixed_ips: [{"ip_address": {get_param: [oam_oam_net_ips, 2]}}]
816 security_groups: [{get_resource: oam_security_group}]
817 oam_volume_attachment_0:
818 type: OS::Cinder::VolumeAttachment
819 depends_on: oam_server_01
821 volume_id: {get_param: oam_vol_1}
823 instance_uuid: {get_resource: oam_server_01}