Files
kevinveenbirkenbachandClaude Opus 5 21218e11e0 fix(lmstudio): bound the daemon readiness probe with the curl filter
The readiness wait called a bare curl, which test_curl_via_filter rejects: a peer that accepts the connection and never answers keeps curl hanging, and the task's own retries never fire. The probe now renders through the curl filter with a 10 second cap per attempt. It passes retries=0, so the task's 60 x 5 s loop stays the only retry layer instead of nesting curl's --retry inside every attempt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 18:46:25 +02:00

53 lines
2.8 KiB
YAML

---
- name: "🔍 Resolve the container before preloading on '{{ lmstudio_node }}'"
ansible.builtin.include_tasks: utils/cid.yml
- name: "⏳ Wait until the LM Studio daemon has finished starting on '{{ lmstudio_node }}'"
ansible.builtin.shell: > # nocheck: container-exec-resolver runtime-resolved CID, delegated to the hosting node
container exec {{ LMSTUDIO_LOCAL_CID | quote }} {{ 10 | curl(retries=0) }} -fS -o /dev/null http://127.0.0.1:{{ LMSTUDIO_PORT }}/lmstudio-greeting
register: lmstudio_daemon_ready
changed_when: false
retries: 60
delay: 5
until: lmstudio_daemon_ready.rc == 0
delegate_to: "{{ lmstudio_node }}"
- name: "🗄️ Measure the space the model store offers on '{{ lmstudio_node }}'"
ansible.builtin.shell: > # nocheck: container-exec-resolver runtime-resolved CID, delegated to the hosting node
container exec {{ LMSTUDIO_LOCAL_CID | quote }} df -P -B1 {{ LMSTUDIO_MODELS_TARGET | quote }}
register: lmstudio_store_space
changed_when: false
retries: 30
delay: 2
until: lmstudio_store_space.rc == 0
delegate_to: "{{ lmstudio_node }}"
when: not (LMSTUDIO_PRESEED_ENABLED | bool)
- name: "🛑 Refuse to preload models the store on '{{ lmstudio_node }}' cannot hold"
vars:
_free: "{{ lmstudio_store_space.stdout_lines[1].split()[3] | int }}"
_required: "{{ LMSTUDIO_PRELOAD_LARGEST_BYTES | int }}"
ansible.builtin.fail:
msg: >-
The model store on {{ lmstudio_node }} has
{{ (_free | int / 1024 / 1024 / 1024) | round(1) }} GiB free, less than the
{{ (_required | int / 1024 / 1024 / 1024) | round(1) }} GiB the largest
declared model needs. Shrink AI_LOCAL_MODELS in group_vars/all/16_ai.yml or
give the node more disk.
when:
- not (LMSTUDIO_PRESEED_ENABLED | bool)
- _free | int < _required | int
- name: "⬇️ Preload the LM Studio models on '{{ lmstudio_node }}'"
block:
- name: "⬇️ Preload the LM Studio models (first pass)"
ansible.builtin.include_tasks: utils/preload/pull.yml
rescue:
- name: "🐝 Re-raise the preload failure unchanged in swarm" # nocheck: rescue-recovery a timed-out transfer leaves the daemon reporting 0.00% for every further pull, and restarting the container it owns is the only lever the role has, though CI job 105558224377 shows a restart returning rc 0 without clearing it; the generic capture cannot even try, so swarm re-raises here instead, because under any_errors_fatal a rescued host keeps running while every other host is already marked failed, and compose ends the block by preloading again so an unrecovered failure still re-raises
ansible.builtin.fail:
msg: "{{ ansible_failed_result.msg | default('LM Studio preload failed') }}"
when: DEPLOYMENT_MODE == 'swarm'
- name: "♻️ Recover the wedged transfer and preload again"
ansible.builtin.include_tasks: utils/preload/recover.yml