60-agent-installation.yml 13 KB

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