cb5ba958d475f97365156a4497564e5a329ae4db
[ta/infra-ansible.git] / roles / baremetal_provision / tasks / ironic_nodes_deploy.yml
1 ---
2
3 # Copyright 2019 Nokia
4
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 #     http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Block traffic during nodes power on/off so that possible old deployment
18 # clients cannot connect new deployment services (like mysql)  and ruin
19 # the installation.
20 - name: Block traffic on infra_internal
21   iptables:
22     state: present
23     action: insert
24     chain: INPUT
25     jump: REJECT
26     in_interface: "{{ networking['infra_internal']['interface'] }}"
27   when:
28     - installation_phase == "provisioning-started"
29
30 - name: Power off nodes
31   environment:
32     OS_AUTH_TOKEN: "fake-token"
33     IRONIC_URL: "{{ ironic_service_adminurl }}"
34   command: "/usr/bin/ironic node-set-power-state {{item.uuid}} off"
35   with_items: "{{ baremetal_ironic_nodes_ids }}"
36   when:
37     - not virtual_env
38     - installation_phase == "provisioning-started"
39   retries: 5
40   delay: 10
41   loop_control:
42     label: "{{ item.name }}"
43
44 - name: Power off nodes
45   command: "openstack --os-cloud default baremetal node power off {{item.uuid}}"
46   with_items: "{{ baremetal_ironic_nodes_ids }}"
47   when:
48     - not virtual_env
49     - installation_phase != "provisioning-started"
50   retries: 5
51   delay: 10
52   loop_control:
53     label: "{{ item.name }}"
54
55 - name: Ensure nodes are powered off
56   environment:
57     OS_AUTH_TOKEN: "fake-token"
58     IRONIC_URL: "{{ ironic_service_adminurl }}"
59   os_node_power_check:
60     auth:
61     auth_type: 'None'
62     ironic_url: "{{ ironic_service_adminurl }}"
63     nodes_details: "{{ baremetal_ironic_nodes_ids }}"
64     power_state: 'power off'
65   until: power_pending_list | length == 0
66   retries: 30
67   delay: 6
68   when:
69     - not virtual_env and baremetal_ironic_nodes_ids | length > 0
70     - installation_phase == "provisioning-started"
71   no_log: True
72
73 - name: Ensure nodes are powered off
74   os_node_power_check:
75     cloud: default
76     auth_type: password
77     ironic_url: "{{ ironic_service_adminurl }}"
78     nodes_details: "{{ baremetal_ironic_nodes_ids }}"
79     power_state: 'power off'
80     endpoint_type: internal
81   until: power_pending_list | length == 0
82   retries: 30
83   delay: 6
84   when:
85     - not virtual_env and baremetal_ironic_nodes_ids | length > 0
86     - installation_phase != "provisioning-started"
87   no_log: True
88
89 # Sleep to make sure power is off
90 - name: Sleep for 15 seconds
91   pause:
92     seconds: 15
93   when: not virtual_env and baremetal_ironic_nodes_ids | length > 0
94
95 - name: Create config-drive directories for all nodes
96   file:
97     path: "/var/lib/ironic/confdrive/{{item.name}}/openstack/latest/"
98     state: "directory"
99     owner: "ironic"
100     group: "ironic"
101   with_items: "{{ baremetal_ironic_nodes_ids }}"
102   loop_control:
103     label: "{{ item.name }}"
104
105 - name: Generate config-drive files
106   config_template:
107     src: "{{ item[1].src }}"
108     dest: "/var/lib/ironic/confdrive/{{item[0].name}}/openstack/latest/{{ item[1].dest }}"
109     owner: "ironic"
110     group: "ironic"
111     mode: "0644"
112     config_type: "{{ item[1].config_type }}"
113   with_nested: 
114     - "{{ baremetal_ironic_nodes_ids }}"
115     - "{{ config_drive_templates }}"
116   loop_control:
117     label: "{{ item[0].name }}"
118
119 - name: Stat config-drive files to check if they exists
120   stat:
121     path: "/var/lib/ironic/confdrive/{{ item.name }}.base64"
122   register: confdrive_stat
123   with_items: "{{ baremetal_ironic_nodes_ids }}"
124
125 - name: Prepare Config-drive ISO file
126   shell: |
127     # Generated ISO
128     genisoimage -o /var/lib/ironic/confdrive/{{ item.item.name }}.iso -ldots -allow-lowercase -allow-multidot -l -publisher 'ironicclient-configdrive 0.1' -quiet -J -r -V config-2 /var/lib/ironic/confdrive/{{ item.item.name }}
129     # Zip it!
130     gzip /var/lib/ironic/confdrive/{{ item.item.name }}.iso
131     # Encode it to base64
132     base64 -w 0 /var/lib/ironic/confdrive/{{ item.item.name }}.iso.gz > /var/lib/ironic/confdrive/{{ item.item.name }}.base64
133   when: not item.stat.exists
134   with_items: "{{confdrive_stat.results}}"
135
136 - name: Remove os_net_config temp files
137   file:
138     dest: "/tmp/{{item.name}}_config.yaml"
139     state: absent
140   with_items: "{{ baremetal_ironic_nodes }}"
141   loop_control:
142     label: "{{ item.name }}"
143
144 - name: Calculate md5sum of Golden image
145   stat:
146     path: "/opt/images/guest-image.img"
147     get_md5: yes
148   register: golden_img_md5sum
149   when: baremetal_ironic_nodes_ids | length > 0
150
151 - name: Enable traffic on infra_internal
152   iptables:
153     state: absent
154     chain: INPUT
155     jump: REJECT
156     in_interface: "{{ networking['infra_internal']['interface'] }}"
157   when:
158     - installation_phase == "provisioning-started"
159
160 - name: Configure Baremetal deployment
161   environment:
162     OS_AUTH_TOKEN: "fake-token"
163     IRONIC_URL: "{{ ironic_service_adminurl }}"
164   os_ironic_node:
165     auth:
166     auth_type: 'None'
167     ironic_url: "{{ ironic_service_adminurl }}"
168     uuid: "{{item.uuid}}"
169     deploy: False
170     state: present
171     power: absent
172     maintenance: False
173     instance_info:
174       root_gb: 10
175       image_source: "http://{{ansible_host}}:{{golden_image_http_port}}/guest-image.img"
176       image_checksum: "{{golden_img_md5sum.stat.md5}}"
177   with_items: "{{ baremetal_ironic_nodes_ids }}"
178   loop_control:
179     label: "{{ item.name }}"
180   when:
181     - installation_phase == "provisioning-started"
182
183 - name: Configure Baremetal deployment
184   os_ironic_node:
185     cloud: default
186     endpoint_type: internal
187     auth_type: password
188     uuid: "{{item.uuid}}"
189     deploy: False
190     state: present
191     power: absent
192     maintenance: False
193     instance_info:
194       root_gb: 10
195       image_source: "http://{{ansible_host}}:{{golden_image_http_port}}/guest-image.img"
196       image_checksum: "{{golden_img_md5sum.stat.md5}}"
197   with_items: "{{ baremetal_ironic_nodes_ids }}"
198   loop_control:
199     label: "{{ item.name }}"
200   when:
201     - installation_phase != "provisioning-started"
202
203 - name: Start Baremetal deployment
204   environment:
205     OS_AUTH_TOKEN: "fake-token"
206     IRONIC_URL: "{{ ironic_service_adminurl }}"
207   os_ironic_node:
208     auth:
209     auth_type: 'None'
210     ironic_url: "{{ ironic_service_adminurl }}"
211     deploy: True
212     power: present
213     config_drive: "{{lookup('file', '/var/lib/ironic/confdrive/{{ item.name }}.base64')}}"
214     uuid: "{{item.uuid}}"
215     instance_info:
216       root_gb: 10
217       image_source: "http://{{ansible_host}}:{{golden_image_http_port}}/guest-image.img"
218       image_checksum: "{{golden_img_md5sum.stat.md5}}"
219   with_items: "{{ baremetal_ironic_nodes_ids }}"
220   loop_control:
221     label: "{{ item.name }}"
222   when:
223     - installation_phase == "provisioning-started"
224
225 - name: Start Baremetal deployment
226   os_ironic_node:
227     cloud: default
228     endpoint_type: internal
229     auth_type: password
230     deploy: True
231     power: present
232     config_drive: "{{lookup('file', '/var/lib/ironic/confdrive/{{ item.name }}.base64')}}"
233     uuid: "{{item.uuid}}"
234     instance_info:
235       root_gb: 10
236       image_source: "http://{{ansible_host}}:{{golden_image_http_port}}/guest-image.img"
237       image_checksum: "{{golden_img_md5sum.stat.md5}}"
238   with_items: "{{ baremetal_ironic_nodes_ids }}"
239   loop_control:
240     label: "{{ item.name }}"
241   when:
242     - installation_phase != "provisioning-started"
243
244 - name: Verify node provisioning state. Waiting for 60mins max.
245   environment:
246     OS_AUTH_TOKEN: "fake-token"
247     IRONIC_URL: "{{ ironic_service_adminurl }}"
248   os_node_provision_check:
249     auth:
250     auth_type: 'None'
251     ironic_url: "{{ ironic_service_adminurl }}"
252     nodes_details: "{{baremetal_ironic_nodes_ids}}"
253   register: baremetal_ironic_node_provisionin_results
254   until: provision_pending_list | length == 0
255   retries: 360
256   delay: 10
257   when:
258     - installation_phase == "provisioning-started"
259
260 - name: Checking for any deployment failures
261   fail:
262     msg: "One or more nodes failed in deployment. {{baremetal_ironic_node_provisionin_results['ansible_facts']['provision_failed_list'] }}"
263   when:
264     - installation_phase == "provisioning-started"
265     - baremetal_ironic_node_provisionin_results['ansible_facts']['provision_failed_list'] | length > 0
266
267 - name: Verify node provisioning state. Waiting for 60mins max.
268   os_node_provision_check:
269     cloud: default
270     endpoint_type: internal
271     auth_type: password
272     nodes_details: "{{baremetal_ironic_nodes_ids}}"
273   register: baremetal_ironic_node_provisionin_results
274   until: provision_pending_list | length == 0
275   retries: 360
276   delay: 10
277   when:
278     - installation_phase != "provisioning-started"
279
280 - name: Checking for any deployment failures
281   fail:
282     msg: "One or more nodes failed in deployment. {{baremetal_ironic_node_provisionin_results['ansible_facts']['provision_failed_list'] }}"
283   when:
284     - installation_phase != "provisioning-started"
285     - baremetal_ironic_node_provisionin_results['ansible_facts']['provision_failed_list'] | length > 0
286
287 # JanneS: until looping is a fix for the problem in wait_for module; it does not catch socket error in recv if peer closes the connection.
288 - name: Verify remote node ssh ports active. Waiting for 60mins max.
289   wait_for:
290      host: "{{ item.node_ip[0] }}"
291      port: 22
292      search_regex: OpenSSH
293      sleep: 5
294      timeout: 3600
295   register: remote_success
296   until: remote_success | success
297   retries: 3
298   with_items: "{{net_conn_details}}"
299
300 - name: Wait for remote node ssh login. Waiting for 10mins max.
301   become: "{{ ansible_env.SUDO_USER }}"
302   local_action: shell ssh -oBatchMode=yes -4 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null {{ item.node_ip[0] }} "echo success"
303   register: user_enabled
304   with_items: "{{net_conn_details}}"
305   until: user_enabled.stdout.find("success") != -1
306   retries: 90
307   delay: 10
308
309 - name: Set Ironic maintenance mode to all nodes.
310   os_ironic_node:
311     cloud: default
312     endpoint_type: internal
313     auth_type: password
314     uuid: "{{item.name}}"
315     maintenance: True
316     deploy: False
317   with_items: "{{ baremetal_ironic_nodes }}"
318   loop_control:
319     label: "{{ item.name }}"
320   when:
321     - installation_phase != "provisioning-started"
322
323 - name: Set Ironic maintenance mode to all nodes.
324   environment:
325     OS_AUTH_TOKEN: "fake-token"
326     IRONIC_URL: "{{ ironic_service_adminurl }}"
327   os_ironic_node:
328     auth:
329     auth_type: 'None'
330     ironic_url: "{{ ironic_service_adminurl }}"
331     uuid: "{{item.name}}"
332     maintenance: True
333     deploy: False
334   with_items: "{{ baremetal_ironic_nodes }}"
335   loop_control:
336     label: "{{ item.name }}"
337   when:
338     - installation_phase == "provisioning-started"