[CICDANSIBLE] Add availability_zone Heat stack parameter
[oom/offline-installer.git] / tools / cicdansible / heat / installer.yaml
1 #This is the environment heat template, compatible with openstack ocata.
2 heat_template_version: 2017-02-24
3 description: "Heat template for deploying onap env"
4 parameters:
5   auth_key:
6     label: "Auth public key"
7     description: "The public key used to authenticate to instances"
8     type: string
9   node_flavor_name:
10     label: "name of node flavor"
11     description: "The name of the flavor used to create kubernetes nodes"
12     type: string
13     constraints:
14       - custom_constraint: nova.flavor
15         description: "need to specify a valid flavor"
16   infra_flavor_name:
17     label: "name of infra flavor"
18     description: "flavor used to create infra instance"
19     type: string
20     constraints:
21       - custom_constraint: nova.flavor
22         description: "need to specify a valid flavor"
23   installer_flavor_name:
24     label: "name of installer flavor"
25     description: "flavor used to create installer instance"
26     type: string
27     constraints:
28       - custom_constraint: nova.flavor
29         description: "need to specify a valid flavor"
30   image_name:
31     label: "image name"
32     description: "name of the image from which to create all instances, should be rhel/centos 7.9 image"
33     type: string
34     constraints:
35       - custom_constraint: glance.image
36         description: "must specify a valid image name"
37   availability_zone:
38     label: "availability zone"
39     description: "availability zone to use for scheduling instances"
40     type: string
41   subnet_cidr:
42     label: "private subnet cidr"
43     description: "Cidr of a private subnet instances will be connected to"
44     type: string
45     constraints:
46       - custom_constraint: net_cidr
47   subnet_range_start:
48     label: "subnet dhcp allocation range start"
49     description: "Start of range of dhcp allocatable ips on private subnet"
50     type: string
51     constraints:
52       - custom_constraint: ip_addr
53   subnet_range_end:
54     label: "end of subnet dhcp allocation range"
55     description: "End of private subnet's dhcp allocation range"
56     type: string
57     constraints:
58       - custom_constraint: ip_addr
59   router_addr:
60     label: "ip address of router"
61     description: "IP address of the router allowing access to other networks incl. company network"
62     type: string
63     constraints:
64       - custom_constraint: ip_addr
65   dns_nameservers:
66     label: "dns resolvers"
67     description: "List of dns resolvers"
68     type: comma_delimited_list
69   public_network_name:
70     label: "name of the public network"
71     description: "Name of the public, internet facing network, also allowing access to company internal hosts"
72     type: string
73     constraints:
74       - custom_constraint: neutron.network
75         description: "Must specify a valid network name or id"
76   external_subnet_cidr:
77     label: "external subnet cidr"
78     description: "The CIDR of the external subnet, that should be accessible from instances, even when internet access is cut. Putting 0.0.0.0/0 here means access to internet."
79     type: string
80     constraints:
81       - custom_constraint: net_cidr
82   installer_ip:
83     label: "floating ip of the installer"
84     description: "a pre-allocated floating ip that will be associated with the installer instance"
85     type: string
86   infra_ip:
87     label: "floating ip of the infra"
88     description: "a pre-allocated floating ip that will be associated with the infrastructure instance"
89     type: string
90   node_ip:
91     label: "floating ip of the first node"
92     description: "a pre-allocated floating ip that will be associated with the first kubernetes node and allow accessing onap"
93     type: string
94   num_nodes:
95     label: "num nodes"
96     description: "the number of kubernetes nodes to create, min 1"
97     type: number
98     constraints:
99       - range: { min: 1 }
100         description: "must be a positive number"
101   use_volume_for_nfs:
102     type: boolean
103     label: "use volume for nfs storage"
104     description: "Indicates whether a cinder volume should be used for nfs storage or not. If not checked, the nfs would be stored in the root disk"
105   demo_network:
106     label: "demo net id"
107     type: string
108     description: "specifies id of network used for demo usecases"
109     default: ""
110   docker_storage_size:
111     label: "nodes' docker storage size"
112     type: number
113     description: "Size of the volume for the docker storage on nodes"
114 conditions:
115   #Condition for nfs volume usage.
116   use_volume_for_nfs: { get_param: use_volume_for_nfs }
117 resources:
118   # Security group used to secure access to instances.
119   secgroup:
120     type: OS::Neutron::SecurityGroup
121     properties:
122       rules:
123         # Egress rule allowing access to external_subnet_cidr.
124         - direction: egress
125           ethertype: IPv4
126           remote_ip_prefix: { get_param: external_subnet_cidr }
127         # Ingress rule, allowing also inbound access by external network.
128         - direction: ingress
129           ethertype: IPv4
130           remote_ip_prefix: { get_param: external_subnet_cidr }
131         # Allow outbound communication with the internal subnet.
132         - direction: egress
133           ethertype: IPv4
134           remote_ip_prefix: { get_param: subnet_cidr }
135         # Allow inbound communication from internal network.
136         - direction: ingress
137           ethertype: IPv4
138           remote_ip_prefix: { get_param: subnet_cidr }
139         # Allow outbound access to 169.254.0.0/16, mainly for metadata. We do not need inbound.
140         - direction: egress
141           ethertype: IPv4
142           remote_ip_prefix: 169.254.0.0/16
143   #A network that our test environment will be connected to.
144   privnet:
145     type: OS::Neutron::Net
146   #Subnet that instances will live in.
147   privsubnet:
148     type: OS::Neutron::Subnet
149     properties:
150       network: { get_resource: privnet }
151       cidr: { get_param: subnet_cidr }
152       allocation_pools:
153         - { start: { get_param: subnet_range_start }, end: { get_param: subnet_range_end } }
154       gateway_ip: { get_param: router_addr }
155       dns_nameservers: { get_param: dns_nameservers }
156       ip_version: 4
157   #A port connected to the private network, taken by router.
158   routerport:
159     type: OS::Neutron::Port
160     properties:
161       network: { get_resource: privnet }
162       fixed_ips:
163         - { subnet: { get_resource: privsubnet }, ip_address: { get_param: router_addr } }
164       security_groups: [{ get_resource: secgroup }]
165   #This is a router, routing between us and the internet.
166   #It has an external gateway to public network.
167   router:
168     type: OS::Neutron::Router
169     properties:
170       external_gateway_info:
171         network: { get_param: public_network_name }
172   #This is a router interface connecting it to our private subnet's router port.
173   routercon:
174     type: OS::Neutron::RouterInterface
175     properties:
176       router: { get_resource: router }
177       port: { get_resource: routerport }
178
179   #Key used to authenticate to instances as root.
180   key:
181     type: OS::Nova::KeyPair
182     properties:
183       name: { get_param: "OS::stack_name" }
184       public_key: { get_param: auth_key }
185   #Handle to signal about starting up of instances.
186   instance_wait_handle:
187     type: OS::Heat::WaitConditionHandle
188   #Monitor waiting for all instances to start.
189   instance_wait:
190     type: OS::Heat::WaitCondition
191     properties:
192       handle: { get_resource: instance_wait_handle }
193       timeout: 1200
194       count:
195         yaql:
196           data: { num_nodes: { get_param: num_nodes } }
197           #This is number of all nodes + 2 (infra instance and installer)
198           expression: "$.data.num_nodes + 2"
199   #Affinity Policy - nodes spread onto as many physical machines as possible (aka. .anti-affinity.).
200   anti_affinity_group:
201    type: OS::Nova::ServerGroup
202    properties:
203      name: k8s nodes on separate computes
204      policies:
205       - anti-affinity
206   #Resource group to deploy n nodes using node template for each, each node numbered starting from 0.
207   nodes:
208     type: OS::Heat::ResourceGroup
209     properties:
210       count: { get_param: num_nodes }
211       resource_def:
212         type: node.yaml
213         properties:
214           nodenum: "%index%"
215           key_name: { get_resource: key }
216           image_name: { get_param: image_name }
217           network: { get_resource: privnet }
218           subnet: { get_resource: privsubnet }
219           flavor_name: { get_param: node_flavor_name }
220           availability_zone: { get_param: availability_zone }
221           notify_command: { get_attr: ["instance_wait_handle", "curl_cli"] }
222           security_group: { get_resource: secgroup }
223           demo_network: { get_param: demo_network }
224           docker_storage_size: { get_param: docker_storage_size }
225           scheduler_hints:
226             group: { get_resource: anti_affinity_group }
227     depends_on: [routercon, instance_wait_handle]
228   #Nfs storage volume for first node.
229   nfs_storage:
230     type: OS::Cinder::Volume
231     condition: use_volume_for_nfs
232     properties:
233       name: nfs_storage
234       size: 50
235   #Attachment of volume to first node.
236   nfs_storage_attachment:
237     type: OS::Cinder::VolumeAttachment
238     condition: use_volume_for_nfs
239     properties:
240       instance_uuid: { get_attr: [nodes, "resource.0"] }
241       volume_id: { get_resource: nfs_storage }
242   #Floating ip association for node (first only).
243   node_fip_assoc:
244     type: OS::Neutron::FloatingIPAssociation
245     properties:
246       floatingip_id: { get_param: node_ip }
247       port_id: { get_attr: ["nodes", "resource.0.port_id"] }
248   #Openstack volume used for storing resources.
249   resources_storage:
250     type: "OS::Cinder::Volume"
251     properties:
252       name: "resources_storage"
253       size: 120
254   #Instance representing infrastructure instance, created using subtemplate.
255   infra:
256     type: "instance.yaml"
257     properties:
258       instance_name: infra
259       network: { get_resource: privnet }
260       subnet: { get_resource: privsubnet }
261       key_name: { get_resource: key }
262       flavor_name: { get_param: infra_flavor_name }
263       availability_zone: { get_param: availability_zone }
264       image_name: { get_param: image_name }
265       notify_command: { get_attr: ["instance_wait_handle", "curl_cli"] }
266       security_group: { get_resource: secgroup }
267       scheduler_hints: {}
268       demo_network: { get_param: demo_network }
269     depends_on: [instance_wait_handle]
270   #Volume attachment for infra node.
271   resources_storage_attachment:
272     type: OS::Cinder::VolumeAttachment
273     properties:
274       volume_id: { get_resource: resources_storage }
275       instance_uuid: { get_resource: infra }
276   #Floating ip association for infra.
277   infra_fip_assoc:
278     type: OS::Neutron::FloatingIPAssociation
279     properties:
280       floatingip_id: { get_param: infra_ip }
281       port_id: { get_attr: ["infra", "port_id"] }
282   #Small installer vm having access to other instances, used to install onap.
283   installer:
284     type: "instance.yaml"
285     properties:
286       instance_name: installer
287       image_name: { get_param: image_name }
288       flavor_name: { get_param: installer_flavor_name }
289       availability_zone: { get_param: availability_zone }
290       key_name: { get_resource: key }
291       network: { get_resource: privnet }
292       subnet: { get_resource: privsubnet }
293       notify_command: { get_attr: ["instance_wait_handle", "curl_cli"] }
294       security_group: { get_resource: secgroup }
295       scheduler_hints: {}
296     depends_on: instance_wait_handle
297   #Floating ip for installer.
298   installer_fip_assoc:
299     type: OS::Neutron::FloatingIPAssociation
300     properties:
301       floatingip_id: { get_param: installer_ip }
302       port_id: { get_attr: [installer, port_id] }
303   #Map of node volumes, taken from volumes output param.
304   node_volumes:
305     type: OS::Heat::Value
306     properties:
307       type: json
308       #We need yaql transformation to be done on the volume map.
309       value:
310         yaql:
311           data:
312             #This is a map of node number to value of "volumes" attribute, that contains
313             #a list of volumes written as pairs [volumeid, mountpoint].
314             volumes: { get_attr: [nodes, attributes, volumes] }
315           #We need yaql expressions to transform node numbers to node names in the form "node0" and similar.
316           #However we don't need anything more complicated.
317           expression: "$.data.volumes?.items()?.toDict('node'+str($[0]), $[1])"
318   #List of infra specific volumes (not a map as above).
319   infra_volumes:
320     type: OS::Heat::Value
321     properties:
322       value:
323         - [{ get_resource: resources_storage }, "/opt/onap"]
324   #Contains node0 specific volume list.
325   node0_volumes:
326     type: OS::Heat::Value
327     properties:
328       #Note that it returns an empty list if nfs volume is disabled.
329       value:
330         if:
331           - use_volume_for_nfs
332           - - [{ get_resource: nfs_storage }, "/dockerdata-nfs"]
333           - []
334 #Output values
335 outputs:
336   network_name:
337     value: {get_attr: [privnet, name] }
338     description: "Name of private network"
339   network_id:
340     value: { get_resource: privnet }
341     description: "ID of private network"
342   subnet_id:
343     value: { get_resource: privsubnet }
344     description: "ID of private subnet"
345   installer_ip:
346     value: { get_attr: [installer, ip] }
347     description: "Internal ip of installer instance"
348   infra_ip:
349     value: { get_attr: [infra, ip] }
350     description: "Internal ip of infra instance"
351   node_ips:
352     value: { get_attr: [nodes, ip] }
353     description: "Serialized json list of node internal ips starting at node0"
354   volumes:
355     description: "map of volumes per each instance"
356     value:
357       #Can do deep merging only with yaql.
358       yaql:
359         data:
360           node_volumes: { get_attr: [node_volumes, value]}
361           infra_volumes: { infra: { get_attr: [infra_volumes, value] }}
362           node0_volumes: {node0: { get_attr: [node0_volumes, value] }}
363         expression: "$.data.node_volumes?.mergeWith($.data.infra_volumes)?.mergeWith($.data.node0_volumes)"