summaryrefslogtreecommitdiffstats
path: root/tools/cicdansible/heat/installer.yaml
blob: 8fff3a74a28a1152c005214d2e5e17a890619db2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
#This is the environment heat template, compatible with openstack ocata.
heat_template_version: 2017-02-24
description: "Heat template for deploying onap env"
parameters:
  auth_key:
    label: "Auth public key"
    description: "The public key used to authenticate to instances"
    type: string
  node_flavor_name:
    label: "name of node flavor"
    description: "The name of the flavor used to create kubernetes nodes"
    type: string
    constraints:
      - custom_constraint: nova.flavor
        description: "need to specify a valid flavor"
  infra_flavor_name:
    label: "name of infra flavor"
    description: "flavor used to create infra instance"
    type: string
    constraints:
      - custom_constraint: nova.flavor
        description: "need to specify a valid flavor"
  installer_flavor_name:
    label: "name of installer flavor"
    description: "flavor used to create installer instance"
    type: string
    constraints:
      - custom_constraint: nova.flavor
        description: "need to specify a valid flavor"
  image_name:
    label: "image name"
    description: "name of the image from which to create all instances, should be rhel 7.6 or centos image"
    type: string
    constraints:
      - custom_constraint: glance.image
        description: "must specify a valid image name"
  subnet_cidr:
    label: "private subnet cidr"
    description: "Cidr of a private subnet instances will be connected to"
    type: string
    constraints:
      - custom_constraint: net_cidr
  subnet_range_start:
    label: "subnet dhcp allocation range start"
    description: "Start of range of dhcp allocatable ips on private subnet"
    type: string
    constraints:
      - custom_constraint: ip_addr
  subnet_range_end:
    label: "end of subnet dhcp allocation range"
    description: "End of private subnet's dhcp allocation range"
    type: string
    constraints:
      - custom_constraint: ip_addr
  router_addr:
    label: "ip address of router"
    description: "IP address of the router allowing access to other networks incl. company network"
    type: string
    constraints:
      - custom_constraint: ip_addr
  public_network_name:
    label: "name of the public network"
    description: "Name of the public, internet facing network, also allowing access to company internal hosts"
    type: string
    constraints:
      - custom_constraint: neutron.network
        description: "Must specify a valid network name or id"
  external_subnet_cidr:
    label: "external subnet cidr"
    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."
    type: string
    constraints:
      - custom_constraint: net_cidr
  installer_ip:
    label: "floating ip of the installer"
    description: "a pre-allocated floating ip that will be associated with the installer instance"
    type: string
  infra_ip:
    label: "floating ip of the infra"
    description: "a pre-allocated floating ip that will be associated with the infrastructure instance"
    type: string
  node_ip:
    label: "floating ip of the first node"
    description: "a pre-allocated floating ip that will be associated with the first kubernetes node and allow accessing onap"
    type: string
  num_nodes:
    label: "num nodes"
    description: "the number of kubernetes nodes to create, min 1"
    type: number
    constraints:
      - range: { min: 1 }
        description: "must be a positive number"
resources:
  # Security group used to secure access to instances.
  secgroup:
    type: OS::Neutron::SecurityGroup
    properties:
      rules:
        # Egress rule allowing access to external_subnet_cidr.
        - direction: egress
          ethertype: IPv4
          remote_ip_prefix: { get_param: external_subnet_cidr }
        # Ingress rule, allowing also inbound access by external network.
        - direction: ingress
          ethertype: IPv4
          remote_ip_prefix: { get_param: external_subnet_cidr }
        # Allow outbound communication with the internal subnet.
        - direction: egress
          ethertype: IPv4
          remote_ip_prefix: { get_param: subnet_cidr }
        # Allow inbound communication from internal network.
        - direction: ingress
          ethertype: IPv4
          remote_ip_prefix: { get_param: subnet_cidr }
        # Allow outbound access to 169.254.0.0/16, mainly for metadata. We do not need inbound.
        - direction: egress
          ethertype: IPv4
          remote_ip_prefix: 169.254.0.0/16
  #A network that our test environment will be connected to.
  privnet:
    type: OS::Neutron::Net
  #Subnet that instances will live in.
  privsubnet:
    type: OS::Neutron::Subnet
    properties:
      network: { get_resource: privnet }
      cidr: { get_param: subnet_cidr }
      allocation_pools:
        - { start: { get_param: subnet_range_start }, end: { get_param: subnet_range_end } }
      gateway_ip: { get_param: router_addr }
      ip_version: 4
  #A port connected to the private network, taken by router.
  routerport:
    type: OS::Neutron::Port
    properties:
      network: { get_resource: privnet }
      fixed_ips:
        - { subnet: { get_resource: privsubnet }, ip_address: { get_param: router_addr } }
      security_groups: [{ get_resource: secgroup }]
  #This is a router, routing between us and the internet.
  #It has an external gateway to public network.
  router:
    type: OS::Neutron::Router
    properties:
      external_gateway_info:
        network: { get_param: public_network_name }
  #This is a router interface connecting it to our private subnet's router port.
  routercon:
    type: OS::Neutron::RouterInterface
    properties:
      router: { get_resource: router }
      port: { get_resource: routerport }

  #Key used to authenticate to instances as root.
  key:
    type: OS::Nova::KeyPair
    properties:
      name: { get_param: "OS::stack_name" }
      public_key: { get_param: auth_key }
  #Handle to signal about starting up of instances.
  instance_wait_handle:
    type: OS::Heat::WaitConditionHandle
  #Monitor waiting for all instances to start.
  instance_wait:
    type: OS::Heat::WaitCondition
    properties:
      handle: { get_resource: instance_wait_handle }
      timeout: 1200
      count:
        yaql:
          data: { num_nodes: { get_param: num_nodes } }
          #This is number of all nodes + 2 (infra instance and installer)
          expression: "$.data.num_nodes + 2"
  #Resource group to deploy n nodes using node template for each, each node numbered starting from 0.
  nodes:
    type: OS::Heat::ResourceGroup
    properties:
      count: { get_param: num_nodes }
      resource_def:
        type: node.yaml
        properties:
          nodenum: "%index%"
          key_name: { get_resource: key }
          image_name: { get_param: image_name }
          network: { get_resource: privnet }
          subnet: { get_resource: privsubnet }
          flavor_name: { get_param: node_flavor_name }
          notify_command: { get_attr: ["instance_wait_handle", "curl_cli"] }
          security_group: { get_resource: secgroup }
    depends_on: [routercon, instance_wait_handle]
  #Nfs storage volume for first node.
  nfs_storage:
    type: OS::Cinder::Volume
    properties:
      name: nfs_storage
      size: 50
  #Attachment of volume to first node.
  nfs_storage_attachment:
    type: OS::Cinder::VolumeAttachment
    properties:
      instance_uuid: { get_attr: [nodes, "resource.0"] }
      volume_id: { get_resource: nfs_storage }
  #Floating ip association for node (first only).
  node_fip_assoc:
    type: OS::Neutron::FloatingIPAssociation
    properties:
      floatingip_id: { get_param: node_ip }
      port_id: { get_attr: ["nodes", "resource.0.port_id"] }
  #Openstack volume used for storing resources.
  resources_storage:
    type: "OS::Cinder::Volume"
    properties:
      name: "resources_storage"
      size: 120
  #Instance representing infrastructure instance, created using subtemplate.
  infra:
    type: "instance.yaml"
    properties:
      instance_name: infra
      network: { get_resource: privnet }
      subnet: { get_resource: privsubnet }
      key_name: { get_resource: key }
      flavor_name: { get_param: infra_flavor_name }
      image_name: { get_param: image_name }
      notify_command: { get_attr: ["instance_wait_handle", "curl_cli"] }
      security_group: { get_resource: secgroup }
    depends_on: [instance_wait_handle]
  #Volume attachment for infra node.
  resources_storage_attachment:
    type: OS::Cinder::VolumeAttachment
    properties:
      volume_id: { get_resource: resources_storage }
      instance_uuid: { get_resource: infra }
  #Floating ip association for infra.
  infra_fip_assoc:
    type: OS::Neutron::FloatingIPAssociation
    properties:
      floatingip_id: { get_param: infra_ip }
      port_id: { get_attr: ["infra", "port_id"] }
  #Small installer vm having access to other instances, used to install onap.
  installer:
    type: "instance.yaml"
    properties:
      instance_name: installer
      image_name: { get_param: image_name }
      flavor_name: { get_param: installer_flavor_name }
      key_name: { get_resource: key }
      network: { get_resource: privnet }
      subnet: { get_resource: privsubnet }
      notify_command: { get_attr: ["instance_wait_handle", "curl_cli"] }
      security_group: { get_resource: secgroup }
    depends_on: instance_wait_handle
  #Floating ip for installer.
  installer_fip_assoc:
    type: OS::Neutron::FloatingIPAssociation
    properties:
      floatingip_id: { get_param: installer_ip }
      port_id: { get_attr: [installer, port_id] }
#Output values
outputs:
  installer_ip:
    value: { get_attr: [installer, ip] }
    description: "Internal ip of installer instance"
  infra_ip:
    value: { get_attr: [infra, ip] }
    description: "Internal ip of infra instance"
  node_ips:
    value: { get_attr: [nodes, ip] }
    description: "Serialized json list of node internal ips starting at node0"
  volumes:
    description: "map of volumes per each instance"
    value:
      yaql:
        data:
          resources_volid: { get_resource: resources_storage }
          nfs_volid: { get_resource: nfs_storage }
          docker_volids: { get_attr: [nodes, docker_storage_id] }
        #This is going to create a map, where keys are instance names, and values are lists of
        #pairs of volume ids and their mount points.
        #This is done by merging few generated maps together, base map is taken by
        #enumerating over docker storage volumes and transforming them into a map like
        #{"node0"=>["volid","/var/lib/docker"],...], node1=>...}
        expression: 'dict($.data.docker_volids.enumerate().select(["node"+str($[0]), [[$[1], "/var/lib/docker"]]])).mergeWith({"infra" => [[$.data.resources_volid, "/opt/onap"]], "node0" => [[$.data.nfs_volid, "/dockerdata-nfs"]]})'