Skip to content

Commit d5a3502

Browse files
committed
Add caas openhpc image-build roles and playbook
* Add a role to execute the Packer build process from ansible-slurm-appliance using the caas inventory variables. * Add an opt-in role that deploys any networking infrastructure required for the Packer build process.
1 parent 86f74d5 commit d5a3502

File tree

13 files changed

+382
-0
lines changed

13 files changed

+382
-0
lines changed

image-build.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
- name: Build image
3+
hosts: openstack
4+
tasks:
5+
- name: Manage image build infra
6+
include_role:
7+
name: image_build_infra
8+
when:
9+
- image_build_manage_infra is defined
10+
- image_build_manage_infra
11+
12+
- block:
13+
- name: Build fat image
14+
include_role:
15+
name: image_build
16+
17+
- name: Set cluster_image fact
18+
set_fact:
19+
cluster_image: "{{ image_build_data.artifact_id }}"
20+
21+
- name: Print cluster_image UUID
22+
debug:
23+
msg: "{{ cluster_image }}"
24+
when: cluster_state is not defined or (cluster_state is defined and cluster_state != "absent")

image-build/hosts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[openstack]
2+
localhost ansible_connection=local ansible_python_interpreter="{{ ansible_playbook_python }}"

roles/cluster_infra/tasks/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
# Only run when block_device_prefix isn't set as an extravar
7676
when:
7777
- block_device_prefix is not defined
78+
- cluster_image is defined
7879

7980
- name: Template Terraform files into project directory
8081
template:
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
# Attach a floating IP to the Packer build instance
3+
image_build_attach_floating_ip: false
4+
5+
# Use a volume for the root disk of the Packer build instance
6+
image_build_use_blockstorage_volume: false
7+
8+
# Packer image format (only used when image_build_use_blockstorage_volume: true
9+
image_build_image_disk_format: "qcow2"
10+
11+
# Metadata items to set on the Packer image
12+
image_build_metadata: {}
13+
14+
# The directory that contains the openstack.pkr.hcl to build the Slurm image
15+
image_build_packer_root_path: "{{ playbook_dir }}/vendor/stackhpc/ansible-slurm-appliance/packer"
16+
17+
# Vars to apply to the builder group
18+
image_build_builder_group_vars:
19+
update_log_path: /tmp/update_log
20+
appliances_repository_root: "{{ playbook_dir }}/vendor/stackhpc/ansible-slurm-appliance"
21+
22+
# ansible_ssh_common_args for Packer build
23+
image_build_ansible_ssh_common_args: >-
24+
{% if image_build_ssh_bastion_host is defined %}
25+
'-o ProxyCommand="ssh -W %h:%p -q
26+
{% if image_build_ssh_bastion_private_key_file is defined %}
27+
-i {{ image_build_ssh_bastion_private_key_file }}
28+
{% endif %}
29+
-l {{ image_build_ssh_bastion_username }}
30+
{{ image_build_ssh_bastion_host }}"'
31+
{% else %}
32+
""
33+
{% endif %}

roles/image_build/tasks/main.yml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
---
2+
3+
- name: Run prechecks
4+
include_tasks: prechecks.yml
5+
6+
- name: Create temporary file for pkrvars.hcl
7+
ansible.builtin.tempfile:
8+
state: file
9+
suffix: .pkrvars.hcl
10+
register: pkrvars_hcl_file
11+
12+
- name: Make Packer vars file
13+
template:
14+
src: builder.pkrvars.hcl.j2
15+
dest: "{{ pkrvars_hcl_file.path }}"
16+
17+
- name: Create temporary image-build inventory directory
18+
ansible.builtin.tempfile:
19+
state: directory
20+
prefix: image-build.
21+
register: image_build_inventory
22+
23+
- name: Symlink "everything" layout to image-build inventory
24+
file:
25+
state: link
26+
src: "{{ playbook_dir }}/vendor/stackhpc/ansible-slurm-appliance/environments/common/layouts/everything"
27+
dest: "{{ image_build_inventory.path }}/groups"
28+
29+
- name: Symlink CAAS group_vars to image-build inventory
30+
file:
31+
state: link
32+
src: "{{ playbook_dir }}/group_vars"
33+
dest: "{{ image_build_inventory.path }}/group_vars"
34+
35+
- name: Add builder vars to image-build inventory hosts file
36+
copy:
37+
dest: "{{ image_build_inventory.path }}/hosts"
38+
content: |
39+
[builder:vars]
40+
{% if image_build_ssh_bastion_host is defined %}
41+
ansible_ssh_common_args={{ image_build_ansible_ssh_common_args }}
42+
{% endif %}
43+
{% for k,v in image_build_builder_group_vars.items() -%}
44+
{{ k }}={{ v }}
45+
{% endfor -%}
46+
47+
- name: Create temporary file for ansible.cfg
48+
ansible.builtin.tempfile:
49+
state: file
50+
suffix: ansible.cfg
51+
register: ansible_cfg_file
52+
53+
- name: Template image-build ansible.cfg
54+
template:
55+
src: ansible.cfg.j2
56+
dest: "{{ ansible_cfg_file.path }}"
57+
58+
- name: Packer init
59+
command:
60+
cmd: |
61+
packer init .
62+
chdir: "{{ image_build_packer_root_path }}"
63+
64+
- name: Build image with packer
65+
command:
66+
cmd: |
67+
packer build -only openstack.openhpc -var-file={{ pkrvars_hcl_file.path }} openstack.pkr.hcl
68+
chdir: "{{ image_build_packer_root_path }}"
69+
environment:
70+
ANSIBLE_CONFIG: "{{ ansible_cfg_file.path }}"
71+
PACKER_LOG: "1"
72+
PACKER_LOG_PATH: "{{ lookup('ansible.builtin.env', 'PACKER_LOG_PATH', default='/tmp/packer-build.log') }}"
73+
74+
- name: Parse packer-manifest.json
75+
set_fact:
76+
packer_manifest: "{{ lookup('file', '/tmp/builder.manifest.json') | from_json }}"
77+
78+
- name: Extract image-build data
79+
set_fact:
80+
image_build_data: "{{ packer_manifest.builds | selectattr('packer_run_uuid', 'eq', packer_manifest.last_run_uuid) | first }}"
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
3+
- name: Check required vars are defined
4+
assert:
5+
that:
6+
- "{{ item }} is defined"
7+
fail_msg: "{{ item }} is not defined"
8+
loop:
9+
- image_build_network_id
10+
- image_build_floating_ip_network
11+
- image_build_source_image_id
12+
- image_build_security_group_id
13+
14+
- name: Ensure builder access mode
15+
fail:
16+
msg: >-
17+
Set either image_build_ssh_bastion_host or
18+
image_build_attach_floating_ip to access the image
19+
build instance via a bastion or directly
20+
when:
21+
- image_build_ssh_bastion_host is defined
22+
- image_build_attach_floating_ip is defined and image_build_attach_floating_ip
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[defaults]
2+
any_errors_fatal = True
3+
gathering = smart
4+
host_key_checking = False
5+
remote_tmp = /tmp
6+
roles_path = {{ playbook_dir }}/vendor/stackhpc/ansible-slurm-appliance/ansible/roles
7+
inventory = {{ playbook_dir }}/vendor/stackhpc/ansible-slurm-appliance/environments/common/inventory,{{ image_build_inventory.path }}
8+
9+
[ssh_connection]
10+
ssh_args = -o ControlMaster=auto -o ControlPersist=240s -o PreferredAuthentications=publickey -o UserKnownHostsFile=/dev/null
11+
pipelining = True
12+
# This is important because we are using one of the hosts in the play as a jump host
13+
# This ensures that if the proxy connection is interrupted, rendering the other hosts
14+
# unreachable, the connection is retried instead of failing the entire play
15+
retries = 10
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
repo_root = "{{ playbook_dir }}/vendor/stackhpc/ansible-slurm-appliance"
2+
environment_root = "{{ playbook_dir }}/image_build"
3+
networks = ["{{ image_build_network_id }}"]
4+
{% if image_build_ssh_bastion_host is defined %}
5+
ssh_bastion_host = "{{ image_build_ssh_bastion_host }}"
6+
{% endif %}
7+
{% if image_build_ssh_bastion_username is defined %}
8+
ssh_bastion_username = "{{ image_build_ssh_bastion_username }}"
9+
{% endif %}
10+
{% if image_build_ssh_bastion_private_key_file is defined %}
11+
ssh_bastion_private_key_file = "{{ image_build_ssh_bastion_private_key_file }}"
12+
{% endif %}
13+
{% if image_build_attach_floating_ip %}
14+
floating_ip_network = "{{ image_build_floating_ip_network }}"
15+
{% endif %}
16+
security_groups = ["{{ image_build_security_group_id }}"]
17+
fatimage_source_image = "{{ image_build_source_image_id }}"
18+
{% if image_build_ssh_keypair_name is defined %}
19+
ssh_keypair_name = "{{ image_build_ssh_keypair_name }}"
20+
{% endif %}
21+
{% if image_build_ssh_private_key_file is defined %}
22+
ssh_private_key_file = "{{ image_build_ssh_private_key_file }}"
23+
{% endif %}
24+
flavor = "{{ image_build_flavor_name }}"
25+
metadata = {
26+
{% for k,v in image_build_metadata.items() %}
27+
"{{ k }}" = "{{ v }}"
28+
{% endfor %}
29+
}
30+
use_blockstorage_volume = {{ image_build_use_blockstorage_volume | string | lower }}
31+
{% if image_build_use_blockstorage_volume %}
32+
volume_size = {{ image_build_volume_size }}
33+
image_disk_format = "{{ image_build_image_disk_format }}"
34+
{% endif %}
35+
manifest_output_path = "/tmp/builder.manifest.json"
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
3+
image_build_terraform_project_path: "{{ playbook_dir }}/terraform-caas-image-build"
4+
image_build_cluster_id: "caas-image-build"
5+
6+
# Regex to capture existing cloud image names to use as the
7+
# OpenHPC Slurm base-image
8+
image_build_existing_image_regex: "^Rocky-8-GenericCloud-Base-8.8-.*"
9+
# Attributes to sort the list of existing base images returned by
10+
# image_build_existing_image_regex. See
11+
# https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/data-sources/images_image_ids_v2#sort
12+
image_build_existing_image_sort_attributes: "name,updated_at"
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
- name: Get path to the image-buid Terraform templates directory
3+
set_fact:
4+
image_build_terraform_template_dir: "{{ role_path }}/templates"
5+
6+
- name: Run cluster_infra role with image-build terraform template
7+
include_role:
8+
name: cluster_infra
9+
public: true
10+
vars:
11+
cluster_id: "{{ image_build_cluster_id }}"
12+
cluster_name: "{{ image_build_cluster_id }}"
13+
cluster_terraform_template_dir: "{{ image_build_terraform_template_dir }}"
14+
terraform_project_path: "{{ image_build_terraform_project_path }}"
15+
16+
- name: Set image build infrastructure facts
17+
set_fact:
18+
image_build_network_id: "{{ terraform_provision.outputs.network_id.value }}"
19+
image_build_floating_ip_network: "{{ terraform_provision.outputs.floating_ip_network_id.value }}"
20+
image_build_source_image_id: "{{ terraform_provision.outputs.source_image_name.value.ids | first }}"
21+
image_build_security_group_id: "{{ terraform_provision.outputs.security_group_id.value }}"
22+
when: cluster_state is not defined or (cluster_state is defined and cluster_state != "absent")
23+

0 commit comments

Comments
 (0)