55-coreos-installer.yml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. ---
  2. # Perform the tasks involved with installing SNO using coreos-installer.
  3. #
  4. # NOTE: If you want to skip the dangerous parts, use --skip-tags=destroy
  5. #
  6. - name: Prepare the files required for a SNO installation using coreos-installer.
  7. hosts: workstation.lab.example.com
  8. become: no
  9. gather_subset: min
  10. tasks:
  11. - name: Check the dependency status.
  12. ansible.builtin.stat:
  13. path: "{{ ansible_facts['user_dir'] }}/{{ item }}"
  14. get_attributes: no
  15. get_checksum: no
  16. get_mime: no
  17. register: dependencies
  18. loop:
  19. - install-pull-secret
  20. - .ssh/openshift.pub
  21. - ca/ca-cert.pem
  22. - mirror/working-dir/cluster-resources/idms-oc-mirror.yaml
  23. - Downloads/rhcos-418.94.202501221327-0-live.x86_64.iso
  24. - ansible.builtin.assert:
  25. that:
  26. - dependencies.results[0].stat.exists
  27. - dependencies.results[1].stat.exists
  28. - dependencies.results[2].stat.exists
  29. - dependencies.results[3].stat.exists
  30. - dependencies.results[4].stat.exists
  31. fail_msg: |
  32. ERROR: Either pull secret, SSH keypair, CA certificate, RHCOS ISO, or mirror artifacts are missing.
  33. Ensure all the relevant preceding tasks have been completed:
  34. - Quay prerequisites,
  35. - Quay deployment,
  36. - oc-mirror prerequisites,
  37. - oc-mirror execution,
  38. - OpenShift installation prerequisites
  39. Exiting.
  40. success_msg: "OK, dependencies exist."
  41. - name: Check whether someone fiddled with installation before.
  42. ansible.builtin.stat:
  43. path: "{{ ansible_facts['user_dir'] }}/sno-iso/.openshift_install.log"
  44. register: install_log
  45. - name: Warn if installation log was found.
  46. ansible.builtin.pause:
  47. prompt: |
  48. WARNING: Found .openshift_install.log in the cluster working directory. This usually
  49. means there were previous attempts of creating installation artifacts.
  50. If you want to recreate the cluster working directory from scratch, run this
  51. playbook with the variable "recreate_cluster_dir" set to any value like this:
  52. ansible-playbook -e recreate_cluster_dir=yes ./52-coreos-installer.yml
  53. Continuing in 5 seconds unless you interrupt execution.
  54. seconds: 5
  55. when:
  56. - install_log.stat.exists
  57. - recreate_cluster_dir is not defined
  58. - name: Load the dependencies as facts.
  59. ansible.builtin.set_fact:
  60. pull_secret: "{{ lookup('ansible.builtin.file', ansible_facts['user_dir'] + '/install-pull-secret') }}"
  61. public_key: "{{ lookup('ansible.builtin.file', ansible_facts['user_dir'] + '/.ssh/openshift.pub') }}"
  62. lab_ca_cert: "{{ lookup('ansible.builtin.file', ansible_facts['user_dir'] + '/ca/ca-cert.pem') }}"
  63. content_sources: "{{ lookup('ansible.builtin.file', ansible_facts['user_dir'] + '/mirror/working-dir/cluster-resources/idms-oc-mirror.yaml')
  64. | ansible.builtin.from_yaml_all }}"
  65. - name: Set the fact determining installation type (required for templating).
  66. ansible.builtin.set_fact:
  67. install_type: iso
  68. - name: Ensure install-config is there.
  69. ansible.builtin.template:
  70. src: templates/install-config-template.yaml.j2
  71. dest: "{{ ansible_facts['user_dir'] }}/install-config-sno-iso.yaml"
  72. mode: 0644
  73. owner: student
  74. group: student
  75. register: updated_install_config
  76. - name: Remove the installation directory if so required.
  77. ansible.builtin.file:
  78. path: "{{ ansible_facts['user_dir'] }}/sno-iso"
  79. state: absent
  80. when:
  81. - recreate_cluster_dir is defined
  82. - recreate_cluster_dir
  83. - name: Ensure the presence of installation directory.
  84. ansible.builtin.file:
  85. path: "{{ ansible_facts['user_dir'] }}/sno-iso"
  86. state: directory
  87. mode: 0755
  88. - name: Also, ensure that the right install-config.yaml file is in there.
  89. ansible.builtin.copy:
  90. src: "{{ ansible_facts['user_dir'] }}/install-config-sno-iso.yaml"
  91. remote_src: yes
  92. dest: "{{ ansible_facts['user_dir'] }}/sno-iso/install-config.yaml"
  93. mode: 0644
  94. register: published_install_config
  95. when:
  96. - (not install_log.stat.exists) or (recreate_cluster_dir is defined) or updated_install_config.changed
  97. - name: Create installation manifests if install config was published.
  98. ansible.builtin.command:
  99. cmd: openshift-install-fips create manifests
  100. chdir: "{{ ansible_facts['user_dir'] }}/sno-iso"
  101. when: published_install_config.changed
  102. - name: Render chrony customizations in home directory.
  103. ansible.builtin.template:
  104. src: templates/chrony-customization.bu.j2
  105. dest: "{{ ansible_facts['user_dir'] }}/chrony-{{ item }}.bu"
  106. mode: 0644
  107. owner: student
  108. group: student
  109. loop:
  110. - master
  111. - worker
  112. - name: Publish chrony customizations in manifests directory.
  113. ansible.builtin.command:
  114. cmd: butane ./chrony-{{ item }}.bu -o ./sno-iso/openshift/99_chrony_{{ item }}.yaml
  115. chdir: "{{ ansible_facts['user_dir'] }}"
  116. creates: sno-iso/openshift/99_chrony_{{ item }}.yaml
  117. loop:
  118. - master
  119. - worker
  120. when: published_install_config.changed
  121. - name: Everything should be set by now, so create SNO install config.
  122. ansible.builtin.command:
  123. cmd: openshift-install-fips create single-node-ignition-config
  124. chdir: "{{ ansible_facts['user_dir'] }}/sno-iso"
  125. when: published_install_config.changed
  126. register: recreated_sno_cfg
  127. - name: Ensure custom ISO is gone if anything was changed.
  128. ansible.builtin.file:
  129. path: "{{ ansible_facts['user_dir'] }}/sno-coreos-installer.iso"
  130. state: absent
  131. when:
  132. - recreated_sno_cfg is defined
  133. - recreated_sno_cfg.changed
  134. - name: Check if custom ISO is there.
  135. ansible.builtin.stat:
  136. path: "{{ ansible_facts['user_dir'] }}/sno-coreos-installer.iso"
  137. get_attributes: no
  138. get_checksum: no
  139. get_mime: no
  140. register: custom_iso
  141. - name: Embed install config in the ISO.
  142. ansible.builtin.command:
  143. cmd: coreos-installer iso ignition embed -fi ./sno-iso/bootstrap-in-place-for-live-iso.ign -o sno-coreos-installer.iso {{ ansible_facts['user_dir'] }}/Downloads/rhcos-418.94.202501221327-0-live.x86_64.iso
  144. chdir: "{{ ansible_facts['user_dir'] }}"
  145. when: not custom_iso.stat.exists
  146. - name: Ensure utility is configured in terms of DNS and DHCP.
  147. hosts: utility.lab.example.com
  148. gather_subset: min
  149. become: yes
  150. tasks:
  151. - name: Ensure the old master01 host config is gone (it is a single line).
  152. ansible.builtin.lineinfile:
  153. path: /etc/dhcp/dhcpd.conf
  154. regexp: '\s*host master01\.ocp4\.example\.com { .* }\s*$'
  155. state: absent
  156. notify:
  157. - restart dhcpd
  158. - name: Ensure the new master01 host config is present (it is a block).
  159. ansible.builtin.blockinfile:
  160. path: /etc/dhcp/dhcpd.conf
  161. marker: '# {mark} DHCP config for master01'
  162. marker_begin: "Start"
  163. marker_end: "End"
  164. block: |
  165. host master01.ocp4.example.com {
  166. hardware ethernet 52:54:00:00:32:0A;
  167. fixed-address 192.168.50.10;
  168. option host-name "master01";
  169. option domain-name "iso.ocp4.example.com";
  170. option routers 127.0.0.1;
  171. }
  172. insertbefore: "host master02"
  173. state: present
  174. notify:
  175. - restart dhcpd
  176. - name: Ensure forward DNS records are there.
  177. ansible.builtin.lineinfile:
  178. path: /var/named/ocp4.example.com.db
  179. regexp: "{{ item.regex }}"
  180. line: "{{ item.line }}"
  181. insertafter: "{{ item.after }}"
  182. loop:
  183. - regex: '^master01\.iso '
  184. line: "master01.iso IN A 192.168.50.10"
  185. after: '^master01 '
  186. - regex: '^api\.iso '
  187. line: "api.iso IN CNAME master01.iso"
  188. after: '^master01\.iso '
  189. - regex: '^api-int\.iso '
  190. line: "api-int.iso IN CNAME master01.iso"
  191. after: '^api\.iso '
  192. - regex: '^\*\.apps\.iso '
  193. line: "*.apps.iso IN A 192.168.50.10"
  194. after: '^api-int\.iso '
  195. register: dnsfw_fix
  196. notify:
  197. - reload dns
  198. - name: Increase the serial number of the forward zone if changed.
  199. block:
  200. - name: Load the zone file.
  201. ansible.builtin.slurp:
  202. src: /var/named/ocp4.example.com.db
  203. register: zonefile_fw
  204. - name: Read the serial number from the zone file and increase it by one.
  205. ansible.builtin.set_fact:
  206. new_fw_serial: "{{ (zonefile_fw.content | ansible.builtin.b64decode() | ansible.builtin.regex_search('^.*; serial', ignorecase=True, multiline=True) | ansible.builtin.regex_replace('; serial.*$', '') | trim | int) + 1 }}"
  207. - name: Insert the new serial number instead of the old one.
  208. ansible.builtin.lineinfile:
  209. path: /var/named/ocp4.example.com.db
  210. regexp: "; serial"
  211. line: " {{ new_fw_serial }} ; serial"
  212. when: dnsfw_fix.changed
  213. - name: Ensure reverse DNS record is there.
  214. ansible.builtin.lineinfile:
  215. path: /var/named/ocp4.example.com.reverse.db
  216. regexp: '^10\s+IN\s+PTR'
  217. line: "10 IN PTR master01.iso.ocp4.example.com."
  218. insertbefore: "master02"
  219. register: dnsre_fix
  220. notify:
  221. - reload dns
  222. - name: Increase the serial number of the reverse zone if changed.
  223. block:
  224. - name: Load the zone file.
  225. ansible.builtin.slurp:
  226. src: /var/named/ocp4.example.com.reverse.db
  227. register: zonefile_re
  228. - name: Read the serial number from the zone file and increase it by one.
  229. ansible.builtin.set_fact:
  230. new_re_serial: "{{ (zonefile_re.content | ansible.builtin.b64decode() | ansible.builtin.regex_search('^.*; serial', ignorecase=True, multiline=True) | ansible.builtin.regex_replace('; serial.*$', '') | trim | int) + 1 }}"
  231. - name: Insert the new serial number instead of the old one.
  232. ansible.builtin.lineinfile:
  233. path: /var/named/ocp4.example.com.reverse.db
  234. regexp: "; serial"
  235. line: " {{ new_re_serial }} ; serial"
  236. when: dnsre_fix.changed
  237. handlers:
  238. - name: restart dhcpd
  239. ansible.builtin.systemd_service:
  240. name: dhcpd
  241. state: restarted
  242. - name: reload dns
  243. ansible.builtin.systemd_service:
  244. name: named
  245. state: reloaded
  246. - name: Copy the ISO file to target machine and write it to /dev/sdb
  247. hosts: master01.ocp4.example.com
  248. gather_subset: min
  249. become: yes
  250. tasks:
  251. - name: Copy the ISO file to master01.
  252. ansible.builtin.copy:
  253. src: /home/student/sno-coreos-installer.iso
  254. dest: /root/sno-coreos-installer.iso
  255. mode: 0644
  256. register: copied_iso
  257. - name: Write the ISO to /dev/sdb if it was changed.
  258. ansible.builtin.command:
  259. cmd: dd if=/root/sno-coreos-installer.iso of=/dev/sdb conv=sync bs=4k
  260. when: copied_iso.changed
  261. register: wrote_iso
  262. tags:
  263. - destroy
  264. - name: Wipe the filesystem of /dev/sda if ISO was written to /dev/sdb.
  265. ansible.builtin.command:
  266. cmd: wipefs -af /dev/sda
  267. when: wrote_iso.changed
  268. register: wiped_fs
  269. tags:
  270. - destroy
  271. - name: Reboot the machine if filesystem was wiped.
  272. ansible.builtin.command:
  273. cmd: reboot
  274. ignore_errors: yes
  275. when: wiped_fs.changed
  276. tags:
  277. - destroy
  278. ...