All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chuck Lever <cel@kernel.org>
To: <kdevops@lists.linux.dev>
Cc: Chuck Lever <chuck.lever@oracle.com>
Subject: [PATCH v2 08/12] guestfs: Convert scripts/bringup_guestfs.sh to Ansible
Date: Fri, 30 May 2025 13:52:25 -0400	[thread overview]
Message-ID: <20250530175229.489925-9-cel@kernel.org> (raw)
In-Reply-To: <20250530175229.489925-1-cel@kernel.org>

From: Chuck Lever <chuck.lever@oracle.com>

The bringup_guestfs.sh is converted to Ansible to enable the
virt-builder part of bring to run in parallel. This also gives us
a fighting chance to integrate terraform and guestfs ssh key
management in the future.

In addition to those benefits, the new Ansible code takes a stab at
being more idempotent than the shell script was. Idempotency is
achieved by checking that each guest is defined, and then defining
it if not; then using community.libvirt.virt to boot the guest,
which does nothing if the guest is already running.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 playbooks/guestfs.yml                         |   2 +-
 playbooks/roles/guestfs/defaults/main.yml     |   1 +
 .../guestfs/tasks/bringup/extra-disks.yml     |  16 +++
 .../roles/guestfs/tasks/bringup/largeio.yml   |  11 ++
 .../roles/guestfs/tasks/bringup/main.yml      | 132 ++++++++++++++++++
 playbooks/roles/guestfs/tasks/main.yml        |  29 ++++
 scripts/guestfs.Makefile                      |   1 -
 7 files changed, 190 insertions(+), 2 deletions(-)
 create mode 100644 playbooks/roles/guestfs/tasks/bringup/extra-disks.yml
 create mode 100644 playbooks/roles/guestfs/tasks/bringup/largeio.yml
 create mode 100644 playbooks/roles/guestfs/tasks/bringup/main.yml

diff --git a/playbooks/guestfs.yml b/playbooks/guestfs.yml
index 8bb496e0f05a..784775cdb818 100644
--- a/playbooks/guestfs.yml
+++ b/playbooks/guestfs.yml
@@ -1,6 +1,6 @@
 ---
 - name: Provision target nodes with libvirt/guestfs
-  gather_facts: false
+  gather_facts: true
   connection: local
   hosts: all
   roles:
diff --git a/playbooks/roles/guestfs/defaults/main.yml b/playbooks/roles/guestfs/defaults/main.yml
index e250a40fd27a..eec137bd730a 100644
--- a/playbooks/roles/guestfs/defaults/main.yml
+++ b/playbooks/roles/guestfs/defaults/main.yml
@@ -2,3 +2,4 @@
 distro_debian_based: false
 
 libvirt_uri_system: false
+libvirt_enable_largeio: false
diff --git a/playbooks/roles/guestfs/tasks/bringup/extra-disks.yml b/playbooks/roles/guestfs/tasks/bringup/extra-disks.yml
new file mode 100644
index 000000000000..438b65ed5d3d
--- /dev/null
+++ b/playbooks/roles/guestfs/tasks/bringup/extra-disks.yml
@@ -0,0 +1,16 @@
+---
+- name: Create the new drive image
+  ansible.builtin.command:
+    argv:
+      - "qemu-img"
+      - "create"
+      - "-f"
+      - "{{ libvirt_extra_drive_format }}"
+      - "{{ path }}"
+      - "100G"
+
+- name: Update the permission settings of the drive image file
+  ansible.builtin.file:
+    path: "{{ path }}"
+    group: "{{ libvirt_qemu_group }}"
+    mode: "g+rw,o-rw"
diff --git a/playbooks/roles/guestfs/tasks/bringup/largeio.yml b/playbooks/roles/guestfs/tasks/bringup/largeio.yml
new file mode 100644
index 000000000000..4246677d18d8
--- /dev/null
+++ b/playbooks/roles/guestfs/tasks/bringup/largeio.yml
@@ -0,0 +1,11 @@
+---
+- name: Compute the total number of devices to build
+  ansible.builtin.set_fact:
+    total_devices: "{{ libvirt_largeio_pow_limit * libvirt_largeio_drives_per_space }}"
+
+- name: Create largeio block devices
+  ansible.builtin.include_tasks:
+    file: "{{ role_path }}/tasks/extra_disks.yml"
+  vars:
+    path: "{{ storagedir }}/{{ inventory_hostname }}/extra{{ item }}.{{ libvirt_extra_drive_format }}"
+  loop: "{{ range(0, total_devices) | list }}"
diff --git a/playbooks/roles/guestfs/tasks/bringup/main.yml b/playbooks/roles/guestfs/tasks/bringup/main.yml
new file mode 100644
index 000000000000..007dabddb2b4
--- /dev/null
+++ b/playbooks/roles/guestfs/tasks/bringup/main.yml
@@ -0,0 +1,132 @@
+---
+- name: List defined libvirt guests
+  run_once: true
+  community.libvirt.virt:
+    command: list_vms
+    uri: "{{ libvirt_uri }}"
+  register: defined_vms
+
+- name: Provision each target node
+  when:
+    - 'inventory_hostname not in defined_vms.list_vms'
+  block:
+    - name: Set the pathname of the ssh directory for each target node
+      ansible.builtin.set_fact:
+        ssh_key_dir: "{{ guestfs_path }}/{{ inventory_hostname }}/ssh"
+
+    - name: Set the pathname of the ssh key for each target node
+      ansible.builtin.set_fact:
+        ssh_key: "{{ ssh_key_dir }}/id_ed25519"
+
+    - name: Generate ssh keys for each target node
+      block:
+        - name: Create the ssh key directory on the control host
+          ansible.builtin.file:
+            path: "{{ ssh_key_dir }}"
+            state: directory
+            mode: "u=rwx"
+
+        - name: Generate fresh keys for each target node
+          ansible.builtin.command:
+            cmd: 'ssh-keygen -q -t ed25519 -f {{ ssh_key }} -N ""'
+
+    - name: Set the pathname of the root disk image for each target node
+      ansible.builtin.set_fact:
+        root_image: "{{ storagedir }}/{{ inventory_hostname }}/root.raw"
+
+    - name: Create the storage pool directory for each target node
+      ansible.builtin.file:
+        path: "{{ storagedir }}/{{ inventory_hostname }}"
+        state: directory
+
+    - name: Duplicate the root disk image for each target node
+      ansible.builtin.command:
+        cmd: "cp --reflink=auto {{ base_image }} {{ root_image }}"
+
+    - name: Get the timezone of the control host
+      ansible.builtin.command:
+        cmd: "timedatectl show -p Timezone --value"
+      register: host_timezone
+
+    - name: Build the root image for each target node (as root)
+      become: true
+      become_method: ansible.builtin.sudo
+      ansible.builtin.command:
+        argv:
+          - "virt-sysprep"
+          - "-a"
+          - "{{ root_image }}"
+          - "--hostname"
+          - "{{ inventory_hostname }}"
+          - "--ssh-inject"
+          - "kdevops:file:{{ ssh_key }}.pub"
+          - "--timezone"
+          - "{{ host_timezone.stdout }}"
+      when:
+        - libvirt_uri_system|bool
+
+    - name: Build the root image for each target node (non-root)
+      ansible.builtin.command:
+        argv:
+          - "virt-sysprep"
+          - "-a"
+          - "{{ root_image }}"
+          - "--hostname"
+          - "{{ inventory_hostname }}"
+          - "--ssh-inject"
+          - "kdevops:file:{{ ssh_key }}.pub"
+          - "--timezone"
+          - "{{ host_timezone.stdout }}"
+      when:
+        - not libvirt_uri_system|bool
+
+    - name: Create largeio devices
+      ansible.builtin.include_tasks:
+        file: "{{ role_path }}/tasks/bringup/largeio.yml"
+      when:
+        - libvirt_enable_largeio|bool
+
+    - name: Create extra disks
+      vars:
+        path: "{{ storagedir }}/{{ inventory_hostname }}/extra{{ item }}.{{ libvirt_extra_drive_format }}"
+      ansible.builtin.include_tasks:
+        file: "{{ role_path }}/tasks/bringup/extra-disks.yml"
+      loop: "{{ range(0, 4) | list }}"
+      when:
+        - not libvirt_enable_largeio|bool
+
+    - name: Define each target node
+      vars:
+        xml_file: "{{ guestfs_path }}/{{ inventory_hostname }}/{{ inventory_hostname }}.xml"
+      community.libvirt.virt:
+        command: define
+        name: "{{ inventory_hostname }}"
+        xml: "{{ lookup('file', xml_file) }}"
+        uri: "{{ libvirt_uri }}"
+
+    - name: Find PCIe passthrough devices
+      ansible.builtin.find:
+        paths: "{{ guestfs_path }}/{{ inventory_hostname }}"
+        file_type: file
+        patterns: "pcie_passthrough_*.xml"
+      register: passthrough_devices
+
+    - name: Attach PCIe passthrough devices to each target node
+      ansible.builtin.command:
+        argv:
+          - "virsh"
+          - "attach-device"
+          - "{{ inventory_hostname }}"
+          - "{{ item }}"
+          - "--config"
+      loop: "{{ passthrough_devices.files }}"
+      loop_control:
+        label: "Doing PCI-E passthrough for device {{ item }}"
+      when:
+        - passthrough_devices.matched > 0
+
+- name: Boot each target node
+  community.libvirt.virt:
+    name: "{{ inventory_hostname }}"
+    uri: "{{ libvirt_uri }}"
+    state: running
diff --git a/playbooks/roles/guestfs/tasks/main.yml b/playbooks/roles/guestfs/tasks/main.yml
index 6981d3c1a70b..8201c8a4dcb2 100644
--- a/playbooks/roles/guestfs/tasks/main.yml
+++ b/playbooks/roles/guestfs/tasks/main.yml
@@ -21,6 +21,35 @@
   ansible.builtin.import_tasks:
     file: "{{role_path }}/tasks/bringup/network.yml"
 
+- name: Set the pathname of storage pool directory
+  tags:
+    - bringup
+  ansible.builtin.set_fact:
+    storagedir: "{{ kdevops_storage_pool_path }}/guestfs"
+
+- name: Set the pathname of the OS base image
+  tags:
+    - bringup
+  ansible.builtin.set_fact:
+    base_image: "{{ storagedir }}/base_images/{{ virtbuilder_os_version }}.raw"
+
+- name: Ensure the base OS image exists
+  delegate_to: localhost
+  run_once: true
+  tags:
+    - bringup
+  ansible.builtin.import_role:
+    name: base_image
+  vars:
+    base_image_os_version: "{{ virtbuilder_os_version }}"
+    base_image_pathname: "{{ base_image }}"
+
+- name: Bring up each target node
+  tags:
+    - bringup
+  ansible.builtin.import_tasks:
+    file: "{{role_path }}/tasks/bringup/main.yml"
+
 - name: Shut down and destroy each target node
   tags:
     - destroy
diff --git a/scripts/guestfs.Makefile b/scripts/guestfs.Makefile
index f2900a684960..0f0a8b858dba 100644
--- a/scripts/guestfs.Makefile
+++ b/scripts/guestfs.Makefile
@@ -79,7 +79,6 @@ bringup_guestfs: $(GUESTFS_BRINGUP_DEPS)
 		-i hosts playbooks/guestfs.yml \
 		--extra-vars=@./extra_vars.yaml \
 		--tags bringup
-	$(Q)$(TOPDIR)/scripts/bringup_guestfs.sh
 	$(Q)ansible-playbook $(ANSIBLE_VERBOSE) --connection=local \
 		--inventory localhost, \
 		playbooks/bringup_guestfs.yml \
-- 
2.49.0


  parent reply	other threads:[~2025-05-30 17:52 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-30 17:52 [PATCH v2 00/12] Convert bringup_guestfs to a single Ansible role Chuck Lever
2025-05-30 17:52 ` [PATCH v2 01/12] guestfs: Replace scripts/destroy_guestfs.sh with an Ansible playbook Chuck Lever
2025-05-30 17:52 ` [PATCH v2 02/12] Move the guestfs install-deps to the guestfs playbook Chuck Lever
2025-05-30 17:52 ` [PATCH v2 03/12] guestfs: Do not use the config-check tag Chuck Lever
2025-05-30 17:52 ` [PATCH v2 04/12] guestfs: Add a "bringup" tag to the guestfs role Chuck Lever
2025-05-30 17:52 ` [PATCH v2 05/12] guestfs: Copy "network" tag steps to " Chuck Lever
2025-05-30 17:52 ` [PATCH v2 06/12] guestfs: Move the QEMU_GROUP check Chuck Lever
2025-05-30 17:52 ` [PATCH v2 07/12] Add a base-image role Chuck Lever
2025-05-30 17:52 ` Chuck Lever [this message]
2025-05-30 17:52 ` [PATCH v2 09/12] guestfs: Move console-related steps to guestfs role Chuck Lever
2025-05-30 17:52 ` [PATCH v2 10/12] bringup_guestfs: Remove the role Chuck Lever
2025-05-30 17:52 ` [PATCH v2 11/12] scripts: Remove the bringup_guestfs.sh script Chuck Lever
2025-05-30 17:52 ` [PATCH v2 12/12] scripts: Remove the destroy_guestfs.sh script Chuck Lever
2025-06-03 19:29 ` [PATCH v2 00/12] Convert bringup_guestfs to a single Ansible role Luis Chamberlain
2025-06-04 14:29   ` Chuck Lever
2025-06-04 17:02     ` Luis Chamberlain

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250530175229.489925-9-cel@kernel.org \
    --to=cel@kernel.org \
    --cc=chuck.lever@oracle.com \
    --cc=kdevops@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.