Merge "Pin scenario001-multinode-containers to earlier ceph docker container" into...
[apex-tripleo-heat-templates.git] / common / deploy-steps.j2
1 # certain initialization steps (run in a container) will occur
2 # on the role marked as primary controller or the first role listed
3 {%- if enabled_roles is not defined -%}
4   # On upgrade certain roles can be disabled for operator driven upgrades
5   # See major_upgrade_steps.j2.yaml and post-upgrade.j2.yaml
6   {%- set enabled_roles = roles -%}
7   {%- set is_upgrade = false -%}
8 {%- else %}
9   {%- set is_upgrade = true -%}
10 {%- endif -%}
11 {%- set primary_role = [enabled_roles[0]] -%}
12 {%- for role in enabled_roles -%}
13   {%- if 'primary' in role.tags and 'controller' in role.tags -%}
14     {%- set _ = primary_role.pop() -%}
15     {%- set _ = primary_role.append(role) -%}
16   {%- endif -%}
17 {%- endfor -%}
18 {%- set primary_role_name = primary_role[0].name -%}
19 # primary role is: {{primary_role_name}}
20 {% set deploy_steps_max = 6 -%}
21 {% set update_steps_max = 6 -%}
22 {% set upgrade_steps_max = 6 -%}
23
24 heat_template_version: pike
25
26 description: >
27   Post-deploy configuration steps via puppet for all roles,
28   as defined in ../roles_data.yaml
29
30 parameters:
31   servers:
32     type: json
33     description: Mapping of Role name e.g Controller to a list of servers
34   stack_name:
35     type: string
36     description: Name of the topmost stack
37   role_data:
38     type: json
39     description: Mapping of Role name e.g Controller to the per-role data
40   DeployIdentifier:
41     default: ''
42     type: string
43     description: >
44       Setting this to a unique value will re-run any deployment tasks which
45       perform configuration on a Heat stack-update.
46   EndpointMap:
47     default: {}
48     description: Mapping of service endpoint -> protocol. Typically set
49                  via parameter_defaults in the resource registry.
50     type: json
51   DockerPuppetDebug:
52     type: string
53     default: ''
54     description: Set to True to enable debug logging with docker-puppet.py
55   DockerPuppetProcessCount:
56     type: number
57     default: 3
58     description: Number of concurrent processes to use when running docker-puppet to generate config files.
59   ctlplane_service_ips:
60     type: json
61
62 conditions:
63 {% for step in range(1, deploy_steps_max) %}
64   WorkflowTasks_Step{{step}}_Enabled:
65     or:
66     {%- for role in enabled_roles %}
67       - not:
68           equals:
69             - get_param: [role_data, {{role.name}}, workflow_tasks, step{{step}}]
70             - ''
71       - False
72     {%- endfor %}
73 {% endfor %}
74
75 resources:
76
77   RoleConfig:
78     type: OS::Heat::SoftwareConfig
79     properties:
80       group: ansible
81       options:
82         modulepath: /usr/share/ansible-modules
83       inputs:
84         - name: step
85         - name: role_name
86         - name: update_identifier
87         - name: bootstrap_server_id
88         - name: docker_puppet_debug
89         - name: docker_puppet_process_count
90       config:
91         str_replace:
92           template: |
93             - hosts: localhost
94               connection: local
95               tasks:
96               _TASKS
97           params:
98             _TASKS: {get_file: deploy-steps-tasks.yaml}
99
100 {%- for step in range(1, deploy_steps_max) %}
101 # BEGIN workflow_tasks handling
102   WorkflowTasks_Step{{step}}:
103     type: OS::Mistral::Workflow
104     condition: WorkflowTasks_Step{{step}}_Enabled
105     depends_on:
106     {%- if step == 1 %}
107     {%- for dep in enabled_roles %}
108       - {{dep.name}}PreConfig
109       - {{dep.name}}ArtifactsDeploy
110     {%- endfor %}
111     {%- else %}
112     {%- for dep in enabled_roles %}
113       - {{dep.name}}Deployment_Step{{step -1}}
114     {%- endfor %}
115     {%- endif %}
116     properties:
117       name: {list_join: [".", ["tripleo", {get_param: stack_name}, "workflow_tasks", "step{{step}}"]]}
118       type: direct
119       tasks:
120         yaql:
121           expression: $.data.where($ != '').select($.get('step{{step}}')).where($ != null).flatten()
122           data:
123           {%- for role in enabled_roles %}
124             - get_param: [role_data, {{role.name}}, workflow_tasks]
125           {%- endfor %}
126
127   WorkflowTasks_Step{{step}}_Execution:
128     type: OS::Mistral::ExternalResource
129     condition: WorkflowTasks_Step{{step}}_Enabled
130     depends_on: WorkflowTasks_Step{{step}}
131     properties:
132       actions:
133         CREATE:
134           workflow: { get_resource: WorkflowTasks_Step{{step}} }
135           params:
136             env:
137               service_ips: { get_param: ctlplane_service_ips }
138               role_merged_configs:
139                 {%- for r in roles %}
140                 {{r.name}}: {get_param: [role_data, {{r.name}}, merged_config_settings]}
141                 {%- endfor %}
142             evaluate_env: false
143         UPDATE:
144           workflow: { get_resource: WorkflowTasks_Step{{step}} }
145           params:
146             env:
147               service_ips: { get_param: ctlplane_service_ips }
148               role_merged_configs:
149                 {%- for r in roles %}
150                 {{r.name}}: {get_param: [role_data, {{r.name}}, merged_config_settings]}
151                 {%- endfor %}
152             evaluate_env: false
153       always_update: true
154 # END workflow_tasks handling
155 {% endfor %}
156
157 # Artifacts config and HostPrepConfig is done on all roles, not only
158 # enabled_roles, because on upgrade we need to write the json files
159 # for the operator driven upgrade scripts (the ansible steps consume them)
160 {% for role in roles %}
161   # Prepare host tasks for {{role.name}}
162   {{role.name}}ArtifactsConfig:
163     type: ../puppet/deploy-artifacts.yaml
164
165   {{role.name}}ArtifactsDeploy:
166     type: OS::Heat::StructuredDeploymentGroup
167     properties:
168       servers:  {get_param: [servers, {{role.name}}]}
169       config: {get_resource: {{role.name}}ArtifactsConfig}
170
171   {{role.name}}HostPrepConfig:
172     type: OS::Heat::SoftwareConfig
173     properties:
174       group: ansible
175       options:
176         modulepath: /usr/share/ansible-modules
177       config:
178         str_replace:
179           template: _PLAYBOOK
180           params:
181             _PLAYBOOK:
182               - hosts: localhost
183                 connection: local
184                 vars:
185                   puppet_config: {get_param: [role_data, {{role.name}}, puppet_config]}
186                   docker_puppet_script: {get_file: ../docker/docker-puppet.py}
187                   docker_puppet_tasks: {get_param: [role_data, {{role.name}}, docker_puppet_tasks]}
188                   docker_startup_configs: {get_param: [role_data, {{role.name}}, docker_config]}
189                   kolla_config: {get_param: [role_data, {{role.name}}, kolla_config]}
190                   bootstrap_server_id: {get_param: [servers, {{primary_role_name}}, '0']}
191                   puppet_step_config: {get_param: [role_data, {{role.name}}, step_config]}
192                 tasks:
193                   # Join host_prep_tasks with the other per-host configuration
194                   list_concat:
195 {%- if is_upgrade|default(false) and role.disable_upgrade_deployment|default(false) %}
196                     - []
197 {%- else %}
198                     - {get_param: [role_data, {{role.name}}, host_prep_tasks]}
199 {%- endif %}
200                     -
201 {%- raw %}
202                       # Write the manifest for baremetal puppet configuration
203                       - name: Create /var/lib/tripleo-config directory
204                         file: path=/var/lib/tripleo-config state=directory
205                       - name: Write the puppet step_config manifest
206                         copy: content="{{puppet_step_config}}" dest=/var/lib/tripleo-config/puppet_step_config.pp force=yes mode=0600
207                       # this creates a JSON config file for our docker-puppet.py script
208                       - name: Create /var/lib/docker-puppet
209                         file: path=/var/lib/docker-puppet state=directory
210                       - name: Write docker-puppet-tasks json files
211                         copy: content="{{puppet_config | to_json}}" dest=/var/lib/docker-puppet/docker-puppet.json force=yes mode=0600
212                       # FIXME: can we move docker-puppet somewhere so it's installed via a package?
213                       - name: Write docker-puppet.py
214                         copy: content="{{docker_puppet_script}}" dest=/var/lib/docker-puppet/docker-puppet.py force=yes mode=0600
215                       # Here we are dumping all the docker container startup configuration data
216                       # so that we can have access to how they are started outside of heat
217                       # and docker-cmd.  This lets us create command line tools to test containers.
218                       # FIXME do we need the docker-container-startup-configs.json or is the new per-step
219                       # data consumed by paunch enough?
220                       - name: Write docker-container-startup-configs
221                         copy: content="{{docker_startup_configs | to_json}}" dest=/var/lib/docker-container-startup-configs.json force=yes mode=0600
222                       - name: Write per-step docker-container-startup-configs
223                         copy: content="{{item.value|to_json}}" dest="/var/lib/tripleo-config/docker-container-startup-config-{{item.key}}.json" force=yes mode=0600
224                         with_dict: "{{docker_startup_configs}}"
225                       - name: Create /var/lib/kolla/config_files directory
226                         file: path=/var/lib/kolla/config_files state=directory
227                       - name: Write kolla config json files
228                         copy: content="{{item.value|to_json}}" dest="{{item.key}}" force=yes mode=0600
229                         with_dict: "{{kolla_config}}"
230                       ########################################################
231                       # Bootstrap tasks, only performed on bootstrap_server_id
232                       ########################################################
233                       - name: Clean /var/lib/docker-puppet/docker-puppet-tasks*.json files
234                         file:
235                           path: "{{item}}"
236                           state: absent
237                         with_fileglob:
238                           - /var/lib/docker-puppet/docker-puppet-tasks*.json
239                         when: deploy_server_id == bootstrap_server_id
240                       - name: Write docker-puppet-tasks json files
241                         copy: content="{{item.value|to_json}}" dest=/var/lib/docker-puppet/docker-puppet-tasks{{item.key.replace("step_", "")}}.json force=yes mode=0600
242                         with_dict: "{{docker_puppet_tasks}}"
243                         when: deploy_server_id == bootstrap_server_id
244 {%- endraw %}
245
246   {{role.name}}HostPrepDeployment:
247     type: OS::Heat::SoftwareDeploymentGroup
248     properties:
249       servers: {get_param: [servers, {{role.name}}]}
250       config: {get_resource: {{role.name}}HostPrepConfig}
251 {% endfor %}
252
253   # BEGIN CONFIG STEPS, only on enabled_roles
254 {%- for role in enabled_roles %}
255   {{role.name}}PreConfig:
256     type: OS::TripleO::Tasks::{{role.name}}PreConfig
257     depends_on: {{role.name}}HostPrepDeployment
258     properties:
259       servers: {get_param: [servers, {{role.name}}]}
260       input_values:
261         update_identifier: {get_param: DeployIdentifier}
262
263   # Deployment steps for {{role.name}}
264   # A single config is re-applied with an incrementing step number
265   {% for step in range(1, deploy_steps_max) %}
266   {{role.name}}Deployment_Step{{step}}:
267     type: OS::TripleO::DeploymentSteps
268     depends_on:
269       - WorkflowTasks_Step{{step}}_Execution
270     # TODO(gfidente): the following if/else condition
271     # replicates what is already defined for the
272     # WorkflowTasks_StepX resource and can be remove
273     # if https://bugs.launchpad.net/heat/+bug/1700569
274     # is fixed.
275     {%- if step == 1 %}
276     {%- for dep in enabled_roles %}
277       - {{dep.name}}PreConfig
278       - {{dep.name}}ArtifactsDeploy
279     {%- endfor %}
280     {%- else %}
281     {%- for dep in enabled_roles %}
282       - {{dep.name}}Deployment_Step{{step -1}}
283     {%- endfor %}
284     {%- endif %}
285     properties:
286       name: {{role.name}}Deployment_Step{{step}}
287       servers: {get_param: [servers, {{role.name}}]}
288       config: {get_resource: RoleConfig}
289       input_values:
290         step: {{step}}
291         role_name: {{role.name}}
292         update_identifier: {get_param: DeployIdentifier}
293         bootstrap_server_id: {get_param: [servers, {{primary_role_name}}, '0']}
294         docker_puppet_debug: {get_param: DockerPuppetDebug}
295         docker_puppet_process_count: {get_param: DockerPuppetProcessCount}
296   {% endfor %}
297   # END CONFIG STEPS
298
299   # Note, this should be the last step to execute configuration changes.
300   # Ensure that all {{role.name}}ExtraConfigPost steps are executed
301   # after all the previous deployment steps.
302   {{role.name}}ExtraConfigPost:
303     depends_on:
304   {%- for dep in enabled_roles %}
305       - {{dep.name}}Deployment_Step5
306   {%- endfor %}
307     type: OS::TripleO::NodeExtraConfigPost
308     properties:
309         servers: {get_param: [servers, {{role.name}}]}
310
311   # The {{role.name}}PostConfig steps are in charge of
312   # quiescing all services, i.e. in the Controller case,
313   # we should run a full service reload.
314   {{role.name}}PostConfig:
315     type: OS::TripleO::Tasks::{{role.name}}PostConfig
316     depends_on:
317   {%- for dep in enabled_roles %}
318       - {{dep.name}}ExtraConfigPost
319   {%- endfor %}
320     properties:
321       servers:  {get_param: servers}
322       input_values:
323         update_identifier: {get_param: DeployIdentifier}
324
325
326 {% endfor %}
327
328 outputs:
329   RoleConfig:
330     description: Mapping of config data for all roles
331     value:
332       deploy_steps_tasks: {get_file: deploy-steps-tasks.yaml}
333       deploy_steps_playbook: |
334         - hosts: overcloud
335           tasks:
336 {%- for role in roles %}
337             - include: {{role.name}}/host_prep_tasks.yaml
338               when: role_name == '{{role.name}}'
339 {%- endfor %}
340             - include: deploy_steps_tasks.yaml
341               with_sequence: start=0 end={{deploy_steps_max-1}}
342               loop_control:
343                 loop_var: step
344       update_steps_tasks: |
345 {%- for role in roles %}
346             - include: {{role.name}}/update_tasks.yaml
347               when: role_name == '{{role.name}}'
348 {%- endfor %}
349       update_steps_playbook: |
350         - hosts: overcloud
351           serial: 1
352           tasks:
353             - include: update_steps_tasks.yaml
354               with_sequence: start=0 end={{update_steps_max-1}}
355               loop_control:
356                 loop_var: step
357             - include: deploy_steps_tasks.yaml
358               with_sequence: start=0 end={{deploy_steps_max-1}}
359               loop_control:
360                 loop_var: step
361       upgrade_steps_tasks: |
362 {%- for role in roles %}
363             - include: {{role.name}}/upgrade_tasks.yaml
364               when: role_name == '{{role.name}}'
365 {%- endfor %}
366       upgrade_steps_playbook: |
367         - hosts: overcloud
368           tasks:
369             - include: upgrade_steps_tasks.yaml
370               with_sequence: start=0 end={{upgrade_steps_max-1}}
371               loop_control:
372                 loop_var: step