chore: apply all changes

This commit is contained in:
Hermes Agent service account
2026-09-01 12:28:16 -05:00
parent e9924a2524
commit 266b6c7be1
7 changed files with 157 additions and 17 deletions

View File

@@ -0,0 +1,22 @@
---
# Playbook: day3_deploy_qwen38_ctx131k.yml
# Purpose: Deploy Qwen3.8-27B-Q4_K_M ctx-size 65536 -> 131072 to astro-orbiter
# via llama-swap config re-render + restart.
#
# The git change to defaults/main.yml (line 235: ctx_size: 131072) is already staged.
# This playbook renders /etc/llama-swap/config.yaml from the updated defaults
# and restarts llama-swap to load the new ctx-size.
#
# Run:
# cd /home/hermes/git/homelab/ansible
# ansible-playbook -i inventory.yml playbooks/day3_deploy_qwen38_ctx131k.yml
#
- name: Deploy Qwen3.8 ctx-size 131072 to astro-orbiter
hosts: astro-orbiter
become: true
vars:
llm_swapmode_enabled: true
roles:
- role: llm-inference-multimodel
tags: [swapmode_config, swapmode_systemd, swapmode_verify]

View File

@@ -22,6 +22,7 @@ common_packages:
- net-tools - net-tools
- dnsutils - dnsutils
- lvm2 - lvm2
- cloud-guest-utils
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# LVM root volume expansion # LVM root volume expansion

View File

@@ -44,6 +44,15 @@ ExecStart={{ vllm_venv_path }}/bin/python -m vllm.entrypoints.openai.api_server
{% if item.enforce_eager is defined and item.enforce_eager %} {% if item.enforce_eager is defined and item.enforce_eager %}
--enforce-eager \ --enforce-eager \
{% endif %} {% endif %}
{% if item.enable_auto_tool_choice is defined and item.enable_auto_tool_choice %}
--enable-auto-tool-choice \
{% endif %}
{% if item.tool_call_parser is defined %}
--tool-call-parser {{ item.tool_call_parser }} \
{% endif %}
{% if item.reasoning_parser is defined %}
--reasoning-parser {{ item.reasoning_parser }} \
{% endif %}
{% if item.quantization is defined and item.quantization != 'none' %} {% if item.quantization is defined and item.quantization != 'none' %}
--quantization {{ item.quantization }} \ --quantization {{ item.quantization }} \
{% endif %} {% endif %}

View File

@@ -1,7 +1,8 @@
# expand-root-lv role # expand-root-lv role
Idempotent role that extends the root LVM logical volume to fill its Idempotent role that grows the root partition (via `growpart`), extends the
volume group and grows the underlying filesystem (ext4 or xfs). root LVM logical volume to fill its volume group, and grows the underlying
filesystem (ext4 or xfs).
## Where this runs in the lifecycle ## Where this runs in the lifecycle
@@ -24,6 +25,22 @@ size — a longstanding installer default that surprises every operator
who hasn't been bitten by it before. ~90% of mk-labs VMs need this who hasn't been bitten by it before. ~90% of mk-labs VMs need this
fix-up before they're fully useful. fix-up before they're fully useful.
After a Proxmox disk grow (increasing the VM disk size), the partition
table, physical volume, logical volume, and filesystem all need to be
extended in sequence. This role automates the full chain.
## Workflow
1. **growpart** — resizes the underlying partition to claim the newly
provisioned disk space. Idempotent: no-op when the partition already
fills the disk.
2. **pvresize** — tells the kernel/LVM about the new partition size so
the VG sees the additional free PEs.
3. **lvextend** — extends the LV to claim all free PE in the VG
(`+100%FREE`). No-op when there's nothing to grow.
4. **fs grow**`resize2fs` (ext4) or `xfs_growfs` (xfs), dispatched by
detected filesystem type.
## Idempotency ## Idempotency
- If `vg_free_count == 0`, the `lvextend` step is skipped and the - If `vg_free_count == 0`, the `lvextend` step is skipped and the
@@ -49,22 +66,30 @@ expand_root_lv_skip: true
The day0 playbook checks this flag and skips the role cleanly. The day0 playbook checks this flag and skips the role cleanly.
To skip only the partition growstep while keeping LV/FS expansion
(e.g. when the partition already covers the whole disk but the LV was
provisioned small by the template), set:
```yaml
expand_root_lv_pv_partition: undefined
```
## Defaults ## Defaults
| Variable | Default | Purpose | | Variable | Default | Purpose |
|-------------------------------|---------------|-----------------------------------------------------| |-------------------------------|---------------|-----------------------------------------------------|
| `expand_root_lv_vg_name` | `ubuntu-vg` | LVM volume group name (Ubuntu installer default). | | `expand_root_lv_vg_name` | `ubuntu-vg` | LVM volume group name (Ubuntu installer default). |
| `expand_root_lv_lv_name` | `ubuntu-lv` | LVM logical volume name (Ubuntu installer default). | | `expand_root_lv_lv_name` | `ubuntu-lv` | LVM logical volume name (Ubuntu installer default). |
| `expand_root_lv_pv_partition` | `/dev/sda3` | Partition backing the PV; grown via growpart. |
| `expand_root_lv_mountpoint` | `/` | Mountpoint of the filesystem to grow. | | `expand_root_lv_mountpoint` | `/` | Mountpoint of the filesystem to grow. |
Override the VG/LV names in `host_vars/<host>.yml` for hosts that use a Override the VG/LV/PV names in `host_vars/<host>.yml` for hosts that use a
different LVM layout. different layout.
## Limitations ## Limitations
- Does not extend the underlying partition. If the operator grows the - The `growpart` step requires the `cloud-guest-utils` package. The role
Proxmox disk and the partition itself needs to grow before lvextend installs it automatically on Debian/Ubuntu hosts when
can claim the new space, run `growpart /dev/sda 3` (or equivalent) `expand_root_lv_pv_partition` is defined.
first. A future enhancement could automate this via `cloud-utils`' - Only supports ext4 and xfs filesystems. Other filesystem types (btrfs,
`growpart` package, but it's out of scope for the initial template etc.) are left as a future enhancement.
fix-up case where the partition already covers the whole disk.

View File

@@ -20,6 +20,12 @@
expand_root_lv_vg_name: ubuntu-vg expand_root_lv_vg_name: ubuntu-vg
expand_root_lv_lv_name: ubuntu-lv expand_root_lv_lv_name: ubuntu-lv
# The partition that backs the physical volume. After a Proxmox disk grow,
# growpart must resize this partition before pvresize/lvextend can claim
# the new space. This is the full device path (e.g. /dev/sda3).
# If undefined, the growpart/pvresize steps are skipped.
expand_root_lv_pv_partition: /dev/sda3
# Mount point we expect to be backed by the target LV. Used purely for # Mount point we expect to be backed by the target LV. Used purely for
# the resize2fs / xfs_growfs decision — the role inspects this path's # the resize2fs / xfs_growfs decision — the role inspects this path's
# filesystem type and dispatches to the correct grow command. # filesystem type and dispatches to the correct grow command.

View File

@@ -2,44 +2,108 @@
# ============================================================================ # ============================================================================
# expand-root-lv / main # expand-root-lv / main
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# 1. Confirm the target VG exists (skip role cleanly on non-LVM hosts). # 0. Ensure growpart is available (cloud-guest-utils provides the growpart binary)
# 2. Read free physical-extent count for the VG. # 1. Grow the partition (growpart) if a PV partition device is defined
# 3. Extend the LV to +100%FREE only when free_pe > 0. # 2. Resize the physical volume (pvresize) to pick up the new partition size
# 4. Grow the filesystem on the mountpoint (ext4 -> resize2fs, xfs -> xfs_growfs). # 3. Confirm the target VG exists (skip role cleanly on non-LVM hosts).
# 4. Read free physical-extent count for the VG.
# 5. Extend the LV to +100%FREE only when free_pe > 0.
# 6. Grow the filesystem on the mountpoint (ext4 -> resize2fs, xfs -> xfs_growfs).
# Each step is idempotent and skips when there's nothing to do. # Each step is idempotent and skips when there's nothing to do.
# ============================================================================ # ============================================================================
# ---------------------------------------------------------------------------
# Step 0: Ensure growpart is available
# ---------------------------------------------------------------------------
- name: Ensure cloud-guest-utils (growpart) is installed
ansible.builtin.package:
name: cloud-guest-utils
state: present
when: expand_root_lv_pv_partition is defined
tags: [growpart, always]
# ---------------------------------------------------------------------------
# Step 1: Grow the partition that backs the PV
# ---------------------------------------------------------------------------
# growpart expects: growpart <device> <partition_number>
# e.g. growpart /dev/sda 3 — NOT growpart /dev/sda3
# We split expand_root_lv_pv_partition (e.g. /dev/sda3) into device and part_no.
- name: Derive device and partition number from PV partition path
ansible.builtin.set_fact:
expand_root_lv_pv_device: "{{ expand_root_lv_pv_partition | regex_replace('p?(\\d+)$', '') }}"
expand_root_lv_pv_part_no: "{{ expand_root_lv_pv_partition | regex_replace('.*p?(\\d+)$', '\\1') }}"
when: expand_root_lv_pv_partition is defined
tags: [growpart, always]
- name: Grow partition to fill disk (growpart)
ansible.builtin.command:
cmd: "growpart {{ expand_root_lv_pv_device }} {{ expand_root_lv_pv_part_no }}"
register: growpart_result
when: expand_root_lv_pv_partition is defined
changed_when: growpart_result.rc == 0 and "NO CHANGE" not in growpart_result.stdout
tags: [growpart, always]
# ---------------------------------------------------------------------------
# Step 2: Resize the physical volume to claim the new partition space
# ---------------------------------------------------------------------------
- name: Resize physical volume (pvresize)
ansible.builtin.command:
cmd: "pvresize {{ expand_root_lv_pv_partition }}"
register: pvresize_result
when: expand_root_lv_pv_partition is defined
changed_when: pvresize_result.rc == 0
tags: [pvresize, always]
# ---------------------------------------------------------------------------
# Step 3: Confirm the target VG exists (skip role cleanly on non-LVM hosts).
# ---------------------------------------------------------------------------
- name: Gather LVM facts - name: Gather LVM facts
ansible.builtin.command: ansible.builtin.command:
cmd: "vgs --noheadings --nosuffix --units b -o vg_name,vg_free_count {{ expand_root_lv_vg_name }}" cmd: "vgs --noheadings --nosuffix --units b -o vg_name,vg_free_count {{ expand_root_lv_vg_name }}"
register: vg_info register: vg_info
changed_when: false changed_when: false
failed_when: false failed_when: false
tags: [lvm, always]
- name: Skip role when target VG is absent - name: Skip role when target VG is absent
ansible.builtin.meta: end_play ansible.builtin.meta: end_play
when: vg_info.rc != 0 when: vg_info.rc != 0
tags: [lvm, always]
# ---------------------------------------------------------------------------
# Step 4: Parse free PE count for the VG
# ---------------------------------------------------------------------------
- name: Parse free PE count - name: Parse free PE count
ansible.builtin.set_fact: ansible.builtin.set_fact:
expand_root_lv_free_pe: "{{ (vg_info.stdout.split() | last | int) if vg_info.stdout | length > 0 else 0 }}" expand_root_lv_free_pe: "{{ (vg_info.stdout.split() | last | int) if vg_info.stdout | length > 0 else 0 }}"
tags: [lvm, always]
# ---------------------------------------------------------------------------
# Step 5: Extend the LV to +100%FREE only when free_pe > 0
# ---------------------------------------------------------------------------
- name: Extend LV to fill VG (only if free PE > 0) - name: Extend LV to fill VG (only if free PE > 0)
ansible.builtin.command: ansible.builtin.command:
cmd: "lvextend -l +100%FREE /dev/{{ expand_root_lv_vg_name }}/{{ expand_root_lv_lv_name }}" cmd: "lvextend -l +100%FREE /dev/{{ expand_root_lv_vg_name }}/{{ expand_root_lv_lv_name }}"
register: lvextend_result register: lvextend_result
when: expand_root_lv_free_pe | int > 0 when: expand_root_lv_free_pe | int > 0
changed_when: lvextend_result.rc == 0 changed_when: lvextend_result.rc == 0
tags: [lvm, always]
# ---------------------------------------------------------------------------
# Step 6: Detect filesystem type at mountpoint and grow
# ---------------------------------------------------------------------------
- name: Detect filesystem type at mountpoint - name: Detect filesystem type at mountpoint
ansible.builtin.command: ansible.builtin.command:
cmd: "findmnt {{ expand_root_lv_mountpoint }} -no FSTYPE" cmd: "findmnt {{ expand_root_lv_mountpoint }} -no FSTYPE"
register: fstype_result register: fstype_result
changed_when: false changed_when: false
tags: [filesystem, always]
- name: Set filesystem type fact - name: Set filesystem type fact
ansible.builtin.set_fact: ansible.builtin.set_fact:
expand_root_lv_fstype: "{{ fstype_result.stdout | trim }}" expand_root_lv_fstype: "{{ fstype_result.stdout | trim }}"
tags: [filesystem, always]
- name: Grow ext4 filesystem - name: Grow ext4 filesystem
ansible.builtin.command: ansible.builtin.command:
@@ -47,8 +111,12 @@
register: resize_result register: resize_result
when: when:
- expand_root_lv_fstype == "ext4" - expand_root_lv_fstype == "ext4"
- lvextend_result.changed | default(false) - (growpart_result is defined and growpart_result.changed) or
(pvresize_result is defined and pvresize_result.changed) or
(lvextend_result is defined and lvextend_result.changed) or
(growpart_result is not defined)
changed_when: resize_result.rc == 0 changed_when: resize_result.rc == 0
tags: [filesystem, always]
- name: Grow xfs filesystem - name: Grow xfs filesystem
ansible.builtin.command: ansible.builtin.command:
@@ -56,15 +124,24 @@
register: xfs_result register: xfs_result
when: when:
- expand_root_lv_fstype == "xfs" - expand_root_lv_fstype == "xfs"
- lvextend_result.changed | default(false) - (growpart_result is defined and growpart_result.changed) or
(pvresize_result is defined and pvresize_result.changed) or
(lvextend_result is defined and lvextend_result.changed) or
(growpart_result is not defined)
changed_when: xfs_result.rc == 0 changed_when: xfs_result.rc == 0
tags: [filesystem, always]
# ---------------------------------------------------------------------------
# Step 7: Report current root size
# ---------------------------------------------------------------------------
- name: Report current root size - name: Report current root size
ansible.builtin.command: ansible.builtin.command:
cmd: "df -h {{ expand_root_lv_mountpoint }}" cmd: "df -h {{ expand_root_lv_mountpoint }}"
register: df_result register: df_result
changed_when: false changed_when: false
tags: [always]
- name: Show post-resize disk usage - name: Show post-resize disk usage
ansible.builtin.debug: ansible.builtin.debug:
msg: "{{ df_result.stdout_lines }}" msg: "{{ df_result.stdout_lines }}"
tags: [always]

View File

@@ -232,7 +232,7 @@ llm_swapmode_models:
gguf_path: "{{ llm_models_dir }}/Qwen3.8-27B-Q4_K_M.gguf" gguf_path: "{{ llm_models_dir }}/Qwen3.8-27B-Q4_K_M.gguf"
port: 8105 port: 8105
n_gpu_layers: -1 # -1 = auto-detect / all layers to GPU n_gpu_layers: -1 # -1 = auto-detect / all layers to GPU
ctx_size: 65536 ctx_size: 131072 # t_ca3ff615: 65536 -> 131072 (VRAM pre-validated ~20.3GB < 24GB, t_441470b9)
batch_size: 4096 batch_size: 4096
ubatch_size: 4096 ubatch_size: 4096
parallel: 1 parallel: 1