From d53b2400c98e159ec603c36e5fe3707a201be937 Mon Sep 17 00:00:00 2001 From: spektr Date: Sat, 31 Oct 2026 15:44:55 +0100 Subject: [PATCH] =?UTF-8?q?LLM-Server:=20llm/ansible=20f=C3=BCr=20Check-Mo?= =?UTF-8?q?dus=20und=20ansible-core=202.21=20fit=20gemacht?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nach Live-Check-Modus gegen ghostnet-ki (ok=23, changed=4, failed=0): - Freiraumprüfung auf existierendes Elternelement (df schlägt im Check-Modus auf dem noch nicht angelegten Store fehl) - Rechte-Durchsetzung nur über vorhandene Artefakte (file-Modul im Check-Modus) - assert ohne loop (2.21 lehnt loop auf assert ab); statische Meldungen, Modell-Anwesenheit im Check-Modus nur informell - find file_type=any für Character-Devices (renderD*) - README: Aufruf mit --private-key nach Workstation-Konvention Preview prognostiziert korrekt: 2 Modellverzeichnisse, 2 SOURCE.yml, Netz-Quadlet, 2 Container-Quadlets; gepinntes ROCm-Image bereits im Store. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe --- llm-server/llm/ansible/README.md | 13 +++++++-- .../roles/inference_engine/tasks/main.yml | 29 +++++++++++++------ .../ansible/roles/model_store/tasks/main.yml | 10 ++++--- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/llm-server/llm/ansible/README.md b/llm-server/llm/ansible/README.md index b49908b..599e176 100644 --- a/llm-server/llm/ansible/README.md +++ b/llm-server/llm/ansible/README.md @@ -32,15 +32,22 @@ cd llm-server/llm/ansible ## Usage (Testing) +All commands use the operator deploy key +`~/.ssh/id_ed25519_ghostnet_ai_ansible_deploy` (see AGENTS.md; no ssh-agent +required): + ```bash # Preview only – no changes, no downloads, no service start: -../../../.venv/bin/ansible-playbook -i inventories/testing playbooks/ai.yml --check --diff +../../../.venv/bin/ansible-playbook -i inventories/testing playbooks/ai.yml \ + --check --diff --private-key ~/.ssh/id_ed25519_ghostnet_ai_ansible_deploy # Provision model weights only (tag models): -../../../.venv/bin/ansible-playbook -i inventories/testing playbooks/ai.yml --tags models +../../../.venv/bin/ansible-playbook -i inventories/testing playbooks/ai.yml \ + --tags models --private-key ~/.ssh/id_ed25519_ghostnet_ai_ansible_deploy # Render quadlets and start/verify the selected profile (tag service): -../../../.venv/bin/ansible-playbook -i inventories/testing playbooks/ai.yml --tags service +../../../.venv/bin/ansible-playbook -i inventories/testing playbooks/ai.yml \ + --tags service --private-key ~/.ssh/id_ed25519_ghostnet_ai_ansible_deploy ``` `inference_engine_active_profile` selects which rendered quadlet is started; diff --git a/llm-server/llm/ansible/roles/inference_engine/tasks/main.yml b/llm-server/llm/ansible/roles/inference_engine/tasks/main.yml index 43c8532..165cb00 100644 --- a/llm-server/llm/ansible/roles/inference_engine/tasks/main.yml +++ b/llm-server/llm/ansible/roles/inference_engine/tasks/main.yml @@ -48,12 +48,14 @@ - name: Verify the rootless runtime utilities are executable ansible.builtin.assert: that: - - item.stat.exists - - item.stat.executable - loop: "{{ inference_engine_tools.results }}" + - inference_engine_tools.results | selectattr('stat.exists') | list | length + == inference_engine_tools.results | length + - inference_engine_tools.results | selectattr('stat.executable', 'equalto', true) | list | length + == inference_engine_tools.results | length fail_msg: >- - {{ item.item }} is missing or not executable; run the host baseline - roles first (llm-server/host/ansible). + A required rootless runtime utility is missing or not executable + (runuser, podman, systemctl or the Podman system generator); run the + host baseline roles first (llm-server/host/ansible). tags: - service @@ -68,6 +70,9 @@ ansible.builtin.find: paths: /dev/dri patterns: renderD* + # Render nodes are character devices; the default file_type (file) would + # skip them. + file_type: any register: inference_engine_render_node_find tags: - service @@ -105,11 +110,17 @@ - name: Verify every profile model artifact is present ansible.builtin.assert: that: - - item.stat.exists - loop: "{{ inference_engine_models.results }}" + - inference_engine_models.results | selectattr('stat.exists', 'equalto', true) | list | length + == inference_engine_models.results | length fail_msg: >- - Model artifact for {{ item.item.key }} is missing under - {{ model_store_root }}; run the model_store role (--tags models) first. + Missing model artifacts under {{ model_store_root }}: + {{ inference_engine_models.results + | selectattr('stat.exists', 'equalto', false) + | map(attribute='item.key') | list | join(', ') }}; + run the model_store role (--tags models) first. + # Check mode deliberately downloads nothing, so the preview continues and + # only shows the pending quadlet changes; a real run enforces presence. + when: not ansible_check_mode tags: - service diff --git a/llm-server/llm/ansible/roles/model_store/tasks/main.yml b/llm-server/llm/ansible/roles/model_store/tasks/main.yml index f906682..de2185f 100644 --- a/llm-server/llm/ansible/roles/model_store/tasks/main.yml +++ b/llm-server/llm/ansible/roles/model_store/tasks/main.yml @@ -80,7 +80,9 @@ - /bin/df - -m - --output=avail - - "{{ model_store_root }}" + # dirname is used because the store root itself may not exist yet in + # check mode; it lives on the same filesystem as the store. + - "{{ model_store_root | dirname }}" changed_when: false check_mode: false register: model_store_free_space @@ -151,14 +153,14 @@ - name: Enforce model artifact ownership and permissions ansible.builtin.file: - path: "{{ model_store_root }}/{{ item.directory }}/{{ item.file }}" + path: "{{ model_store_root }}/{{ item.item.directory }}/{{ item.item.file }}" state: file owner: root group: root mode: "{{ model_store_file_mode }}" - loop: "{{ model_store_all_artifacts }}" + loop: "{{ model_store_present.results | selectattr('stat.exists', 'equalto', true) | list }}" loop_control: - label: "{{ item.profile }}" + label: "{{ item.item.profile }}" tags: - models - service