mirror of
https://github.com/dredx/prole.git
synced 2026-09-23 10:13:58 +00:00
- ansible.sh: export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES (fixes macOS fork safety abort when pywinrm loads ObjC frameworks before fork()) - hosts.ini: add winrm scheme=http port=5985, transport=ntlm for Windows hosts; remove hardcoded ansible_user (now per-host) - group_vars/workstations_windows/vars.yml: created; WinRM connection vars (ansible_user/password resolved per-host) - host_vars/morgoth.prole.org.yml: ansible_user=chrisfu + vault ref - host_vars/fairyland.prole.org.yml: ansible_user=minecraft + vault ref - windows_ollama_models.yml: fix PowerShell ollama show check — wrap in try/catch so ErrorActionPreference=Stop does not abort on model-not-found Result: mxbai-embed-large-2k (num_ctx=2048) created on both hosts. Idempotent — re-running only recreates if Modelfile hash changes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
173 lines
5.7 KiB
YAML
173 lines
5.7 KiB
YAML
---
|
|
# windows_ollama_models.yml — Manage local Ollama model variants on Windows GPU hosts.
|
|
#
|
|
# This is the small, Ansible-like control surface for the two Windows NVIDIA
|
|
# machines that run Ollama for Prole embedding workloads.
|
|
#
|
|
# Usage:
|
|
# cd infrastructure
|
|
# ansible-playbook playbooks/windows_ollama_models.yml --ask-pass
|
|
#
|
|
# Single host:
|
|
# ansible-playbook playbooks/windows_ollama_models.yml --limit morgoth.prole.org --ask-pass
|
|
#
|
|
# Dry-run intent only:
|
|
# ansible-playbook playbooks/windows_ollama_models.yml --check --diff --ask-pass
|
|
#
|
|
# Inventory target:
|
|
# [workstations_windows]
|
|
# morgoth.prole.org
|
|
# fairyland.prole.org
|
|
#
|
|
# What this deploys:
|
|
# ollama create mxbai-embed-large-2k FROM mxbai-embed-large PARAMETER num_ctx 2048
|
|
#
|
|
# The desired Modelfile is written to C:\ProgramData\Prole\Ollama\Models and a
|
|
# SHA-256 marker is recorded after successful creation. Re-running the playbook
|
|
# is safe: it recreates the model only when the target model is missing or the
|
|
# managed Modelfile content changes.
|
|
|
|
- name: Configure Prole Ollama models on Windows GPU hosts
|
|
hosts: workstations_windows
|
|
gather_facts: false
|
|
become: false
|
|
|
|
vars:
|
|
ansible_become: false
|
|
ansible_become_method: runas
|
|
prole_ollama_models_dir: 'C:\ProgramData\Prole\Ollama\Models'
|
|
prole_ollama_models:
|
|
- name: mxbai-embed-large-2k
|
|
base: mxbai-embed-large
|
|
parameters:
|
|
num_ctx: 2048
|
|
|
|
# Override per-host if WinRM cannot see ollama.exe in PATH.
|
|
# Common installs include:
|
|
# C:\Program Files\Ollama\ollama.exe
|
|
# C:\Users\<user>\AppData\Local\Programs\Ollama\ollama.exe
|
|
ollama_windows_exe: ''
|
|
|
|
tasks:
|
|
- name: Resolve ollama.exe path
|
|
ansible.windows.win_shell: |
|
|
$ErrorActionPreference = 'Stop'
|
|
$candidates = @()
|
|
|
|
if ('{{ ollama_windows_exe }}') {
|
|
$candidates += '{{ ollama_windows_exe }}'
|
|
}
|
|
|
|
$cmd = Get-Command ollama.exe -ErrorAction SilentlyContinue
|
|
if ($cmd) {
|
|
$candidates += $cmd.Source
|
|
}
|
|
|
|
$candidates += @(
|
|
'C:\Program Files\Ollama\ollama.exe',
|
|
'C:\Users\{{ ansible_user }}\AppData\Local\Programs\Ollama\ollama.exe'
|
|
)
|
|
|
|
foreach ($candidate in $candidates | Select-Object -Unique) {
|
|
if ($candidate -and (Test-Path -LiteralPath $candidate)) {
|
|
Write-Output $candidate
|
|
exit 0
|
|
}
|
|
}
|
|
|
|
throw 'ollama.exe was not found. Set ollama_windows_exe for this host or install Ollama first.'
|
|
args:
|
|
executable: powershell.exe
|
|
register: ollama_exe_result
|
|
changed_when: false
|
|
|
|
- name: Set resolved Ollama executable fact
|
|
ansible.builtin.set_fact:
|
|
ollama_resolved_exe: "{{ ollama_exe_result.stdout_lines[0] }}"
|
|
|
|
- name: Ensure Prole Ollama model state directory exists
|
|
ansible.windows.win_file:
|
|
path: "{{ prole_ollama_models_dir }}"
|
|
state: directory
|
|
|
|
- name: Show planned Ollama model configuration in check mode
|
|
ansible.builtin.debug:
|
|
msg: >-
|
|
Would ensure {{ item.name }} exists from {{ item.base }} with num_ctx={{ item.parameters.num_ctx }}
|
|
using {{ ollama_resolved_exe }}.
|
|
loop: "{{ prole_ollama_models }}"
|
|
when: ansible_check_mode
|
|
|
|
- name: Create or update managed Ollama model variants
|
|
ansible.windows.win_shell: |
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$ollama = '{{ ollama_resolved_exe }}'
|
|
$modelName = '{{ item.name }}'
|
|
$baseModel = '{{ item.base }}'
|
|
$modelDir = '{{ prole_ollama_models_dir }}'
|
|
$modelfilePath = Join-Path $modelDir "$modelName.Modelfile"
|
|
$markerPath = Join-Path $modelDir "$modelName.Modelfile.sha256"
|
|
|
|
$modelfile = @"
|
|
FROM {{ item.base }}
|
|
PARAMETER num_ctx {{ item.parameters.num_ctx }}
|
|
"@.TrimStart()
|
|
|
|
Set-Content -LiteralPath $modelfilePath -Value $modelfile -Encoding ascii -NoNewline
|
|
$desiredHash = (Get-FileHash -Algorithm SHA256 -LiteralPath $modelfilePath).Hash
|
|
$recordedHash = if (Test-Path -LiteralPath $markerPath) {
|
|
(Get-Content -LiteralPath $markerPath -Raw).Trim()
|
|
} else {
|
|
''
|
|
}
|
|
|
|
# Check model existence without letting $ErrorActionPreference = Stop
|
|
# treat a non-zero exit code as a terminating error.
|
|
$modelExists = $false
|
|
try {
|
|
$null = & $ollama show $modelName 2>&1
|
|
$modelExists = ($LASTEXITCODE -eq 0)
|
|
} catch {
|
|
$modelExists = $false
|
|
}
|
|
|
|
if ($modelExists -and ($recordedHash -eq $desiredHash)) {
|
|
Write-Output "unchanged: $modelName already matches managed Modelfile"
|
|
exit 0
|
|
}
|
|
|
|
& $ollama pull $baseModel
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "ollama pull failed for $baseModel"
|
|
}
|
|
|
|
& $ollama create $modelName -f $modelfilePath
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "ollama create failed for $modelName"
|
|
}
|
|
|
|
Set-Content -LiteralPath $markerPath -Value $desiredHash -Encoding ascii -NoNewline
|
|
Write-Output "changed: created or updated $modelName from $baseModel"
|
|
args:
|
|
executable: powershell.exe
|
|
loop: "{{ prole_ollama_models }}"
|
|
register: ollama_model_results
|
|
changed_when: "'changed:' in ollama_model_results.stdout"
|
|
when: not ansible_check_mode
|
|
|
|
- name: Verify managed Ollama model variants
|
|
ansible.windows.win_shell: |
|
|
$ErrorActionPreference = 'Stop'
|
|
& '{{ ollama_resolved_exe }}' list
|
|
args:
|
|
executable: powershell.exe
|
|
register: ollama_list_result
|
|
changed_when: false
|
|
when: not ansible_check_mode
|
|
|
|
- name: Show Ollama model list
|
|
ansible.builtin.debug:
|
|
var: ollama_list_result.stdout_lines
|
|
when: not ansible_check_mode
|