Refactor llama_server role for Windows support and EL-specific setup
- Added Windows-specific tasks for llama_server role, including installation of dependencies, setup of services using NSSM, and configuration of firewall rules. - Introduced a new task file for Windows Exporter setup. - Consolidated EL-specific setup tasks into a separate include file. - Updated inventory to include additional host for llama server. - Adjusted error handling in Prometheus service removal task to prevent failures.
This commit is contained in:
@@ -0,0 +1,382 @@
|
||||
---
|
||||
# Windows-specific setup for llama_server role
|
||||
|
||||
- name: Define Windows paths and versions
|
||||
ansible.builtin.set_fact:
|
||||
__llama_user: "{{ llama_server_windows_user }}"
|
||||
__nssm_exe: "{{ llama_server_windows_nssm_dir }}\\nssm.exe"
|
||||
__llama_release_asset_name: "{{ 'llama-' ~ llama_server_windows_version ~ '-bin-win-' ~ llama_server_windows_backend ~ (llama_server_windows_backend == 'cuda') | ternary('-' ~ llama_server_cuda_version, '') ~ '-x64.zip' }}"
|
||||
__llama_release_zip_url: "https://github.com/ggml-org/llama.cpp/releases/download/{{ llama_server_windows_version }}/{{ 'llama-' ~ llama_server_windows_version ~ '-bin-win-' ~ llama_server_windows_backend ~ (llama_server_windows_backend == 'cuda') | ternary('-' ~ llama_server_cuda_version, '') ~ '-x64.zip' }}"
|
||||
__llama_release_zip_path: "{{ (ansible_env.TEMP | default('C:\\Windows\\Temp')) }}\\{{ 'llama-' ~ llama_server_windows_version ~ '-bin-win-' ~ llama_server_windows_backend ~ (llama_server_windows_backend == 'cuda') | ternary('-' ~ llama_server_cuda_version, '') ~ '-x64.zip' }}"
|
||||
__llama_release_marker: "{{ llama_server_windows_install_dir }}\\.release-{{ 'llama-' ~ llama_server_windows_version ~ '-bin-win-' ~ llama_server_windows_backend ~ (llama_server_windows_backend == 'cuda') | ternary('-' ~ llama_server_cuda_version, '') ~ '-x64.zip' }}"
|
||||
__nssm_zip_path: "{{ (ansible_env.TEMP | default('C:\\Windows\\Temp')) }}\\nssm.zip"
|
||||
__llama_sync_script: "{{ llama_server_windows_working_dir }}\\.router\\llama_hf_sync_windows.py"
|
||||
__llama_models_json: "{{ llama_server_windows_working_dir }}\\.router\\desired-models.json"
|
||||
__llama_preset_global_json: "{{ llama_server_windows_working_dir }}\\.router\\preset-global.json"
|
||||
__llama_managed_dir: "{{ llama_server_windows_working_dir }}\\models\\managed"
|
||||
__llama_links_dir: "{{ llama_server_windows_working_dir }}\\models\\managed-links"
|
||||
__llama_router_dir: "{{ llama_server_windows_working_dir }}\\.router"
|
||||
__llama_manifest: "{{ llama_server_windows_working_dir }}\\.router\\manifest.json"
|
||||
__llama_preset_file: "{{ llama_server_windows_working_dir }}\\.router\\models.ini"
|
||||
__llama_venv_path: "{{ llama_server_windows_working_dir }}\\.router\\.venv"
|
||||
__llama_venv_python: "{{ llama_server_windows_working_dir }}\\.router\\.venv\\Scripts\\python.exe"
|
||||
|
||||
- name: Validate llama_server_models schema
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- llama_server_models is iterable
|
||||
fail_msg: "llama_server_models must be a list"
|
||||
|
||||
- name: Create llama server installation directories
|
||||
ansible.windows.win_file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
loop:
|
||||
- "{{ llama_server_windows_install_dir }}"
|
||||
- "{{ llama_server_windows_working_dir }}"
|
||||
- "{{ llama_server_windows_working_dir }}\\models\\managed"
|
||||
- "{{ llama_server_windows_working_dir }}\\models\\managed-links"
|
||||
- "{{ llama_server_windows_working_dir }}\\.router"
|
||||
|
||||
- name: Check if Python is available
|
||||
ansible.windows.win_stat:
|
||||
path: "{{ llama_server_windows_python_path }}"
|
||||
register: __llama_python_check
|
||||
|
||||
- name: Download Python installer
|
||||
ansible.windows.win_get_url:
|
||||
url: "https://www.python.org/ftp/python/{{ llama_server_windows_python_version }}/python-{{ llama_server_windows_python_version }}-amd64.exe"
|
||||
dest: "{{ (ansible_env.TEMP | default('C:\\Windows\\Temp')) }}\\python-{{ llama_server_windows_python_version }}-amd64.exe"
|
||||
force: false
|
||||
when: not __llama_python_check.stat.exists
|
||||
|
||||
- name: Install Python if not available
|
||||
ansible.windows.win_package:
|
||||
path: "{{ (ansible_env.TEMP | default('C:\\Windows\\Temp')) }}\\python-{{ llama_server_windows_python_version }}-amd64.exe"
|
||||
arguments: /quiet InstallAllUsers=1 PrependPath=0 Include_test=0
|
||||
state: present
|
||||
when: not __llama_python_check.stat.exists
|
||||
|
||||
- name: Check Microsoft VC++ runtime availability
|
||||
ansible.windows.win_stat:
|
||||
path: "C:\\Windows\\System32\\vcruntime140.dll"
|
||||
register: __llama_vcredist_check
|
||||
|
||||
- name: Download Microsoft VC++ redistributable
|
||||
ansible.windows.win_get_url:
|
||||
url: "{{ llama_server_windows_vcredist_url }}"
|
||||
dest: "{{ (ansible_env.TEMP | default('C:\\Windows\\Temp')) }}\\vc_redist.x64.exe"
|
||||
force: false
|
||||
when: not __llama_vcredist_check.stat.exists
|
||||
|
||||
- name: Install Microsoft VC++ redistributable
|
||||
ansible.windows.win_package:
|
||||
path: "{{ (ansible_env.TEMP | default('C:\\Windows\\Temp')) }}\\vc_redist.x64.exe"
|
||||
arguments: /install /quiet /norestart
|
||||
state: present
|
||||
when: not __llama_vcredist_check.stat.exists
|
||||
|
||||
- name: Download llama.cpp Windows binary
|
||||
ansible.windows.win_get_url:
|
||||
url: "{{ __llama_release_zip_url }}"
|
||||
dest: "{{ __llama_release_zip_path }}"
|
||||
force: false
|
||||
|
||||
- name: Check deployed llama.cpp release marker
|
||||
ansible.windows.win_stat:
|
||||
path: "{{ __llama_release_marker }}"
|
||||
register: __llama_release_marker_stat
|
||||
|
||||
- name: Remove stale llama-server binary before release upgrade
|
||||
ansible.windows.win_file:
|
||||
path: "{{ llama_server_windows_install_dir }}\\{{ llama_server_windows_bin_name }}"
|
||||
state: absent
|
||||
when: not __llama_release_marker_stat.stat.exists
|
||||
|
||||
- name: Extract llama.cpp binary
|
||||
community.windows.win_unzip:
|
||||
src: "{{ __llama_release_zip_path }}"
|
||||
dest: "{{ llama_server_windows_install_dir }}"
|
||||
delete_archive: false
|
||||
when: not __llama_release_marker_stat.stat.exists
|
||||
|
||||
- name: Mark deployed llama.cpp release
|
||||
ansible.windows.win_copy:
|
||||
content: "{{ __llama_release_asset_name }}"
|
||||
dest: "{{ __llama_release_marker }}"
|
||||
when: not __llama_release_marker_stat.stat.exists
|
||||
|
||||
- name: Verify llama-server binary is present
|
||||
ansible.windows.win_stat:
|
||||
path: "{{ llama_server_windows_install_dir }}\\{{ llama_server_windows_bin_name }}"
|
||||
register: __llama_bin_stat
|
||||
|
||||
- name: Fail if llama-server binary is missing
|
||||
ansible.builtin.fail:
|
||||
msg: >-
|
||||
llama-server binary not found at {{ llama_server_windows_install_dir }}\{{ llama_server_windows_bin_name }}.
|
||||
Check download/unzip and llama_server_windows_backend settings.
|
||||
when: not __llama_bin_stat.stat.exists
|
||||
|
||||
- name: Check if NSSM is installed
|
||||
ansible.windows.win_stat:
|
||||
path: "{{ llama_server_windows_nssm_dir }}\\nssm-{{ llama_server_windows_nssm_version }}\\win64\\nssm.exe"
|
||||
register: __nssm_stat
|
||||
|
||||
- name: Download NSSM if not installed
|
||||
ansible.windows.win_get_url:
|
||||
url: "{{ llama_server_windows_nssm_url }}"
|
||||
dest: "{{ __nssm_zip_path }}"
|
||||
force: false
|
||||
when: not __nssm_stat.stat.exists
|
||||
|
||||
- name: Extract NSSM if not installed
|
||||
community.windows.win_unzip:
|
||||
src: "{{ __nssm_zip_path }}"
|
||||
dest: "{{ llama_server_windows_nssm_dir }}"
|
||||
delete_archive: false
|
||||
creates: "{{ llama_server_windows_nssm_dir }}\\nssm-{{ llama_server_windows_nssm_version }}\\win64\\nssm.exe"
|
||||
when: not __nssm_stat.stat.exists
|
||||
|
||||
- name: Copy NSSM executable
|
||||
ansible.windows.win_copy:
|
||||
src: "{{ llama_server_windows_nssm_dir }}\\nssm-{{ llama_server_windows_nssm_version }}\\win64\\nssm.exe"
|
||||
dest: "{{ __nssm_exe }}"
|
||||
remote_src: true
|
||||
|
||||
- name: Copy Windows-compatible Hugging Face sync script
|
||||
ansible.windows.win_copy:
|
||||
src: scripts/llama_hf_sync_windows.py
|
||||
dest: "{{ __llama_sync_script }}"
|
||||
mode: "0750"
|
||||
|
||||
- name: Write desired llama server model manifest input
|
||||
ansible.windows.win_copy:
|
||||
content: "{{ llama_server_models | to_nice_json }}"
|
||||
dest: "{{ __llama_models_json }}"
|
||||
|
||||
- name: Write global llama server preset options
|
||||
ansible.windows.win_copy:
|
||||
content: "{{ llama_server_preset_global | to_nice_json }}"
|
||||
dest: "{{ __llama_preset_global_json }}"
|
||||
|
||||
- name: Check llama sync virtualenv
|
||||
ansible.windows.win_stat:
|
||||
path: "{{ __llama_venv_python }}"
|
||||
register: __llama_venv_python_check
|
||||
|
||||
- name: Create llama sync virtualenv
|
||||
ansible.windows.win_command:
|
||||
argv:
|
||||
- "{{ llama_server_windows_python_path }}"
|
||||
- -m
|
||||
- venv
|
||||
- "{{ __llama_venv_path }}"
|
||||
changed_when: false
|
||||
when: not __llama_venv_python_check.stat.exists
|
||||
|
||||
- name: Upgrade pip tooling in llama sync virtualenv
|
||||
ansible.windows.win_command:
|
||||
argv:
|
||||
- "{{ __llama_venv_python }}"
|
||||
- -m
|
||||
- pip
|
||||
- install
|
||||
- --upgrade
|
||||
- pip
|
||||
- setuptools
|
||||
- packaging
|
||||
changed_when: false
|
||||
|
||||
- name: Install Hugging Face dependency in llama sync virtualenv
|
||||
ansible.windows.win_command:
|
||||
argv:
|
||||
- "{{ __llama_venv_python }}"
|
||||
- -m
|
||||
- pip
|
||||
- install
|
||||
- "huggingface_hub>=0.32.0"
|
||||
changed_when: false
|
||||
|
||||
- name: Run llama server model sync from Hugging Face
|
||||
ansible.windows.win_command:
|
||||
cmd: >-
|
||||
"{{ __llama_venv_python }}" "{{ __llama_sync_script }}"
|
||||
--models-file "{{ __llama_models_json }}"
|
||||
--managed-dir "{{ __llama_managed_dir }}"
|
||||
--links-dir "{{ __llama_links_dir }}"
|
||||
--manifest-file "{{ __llama_manifest }}"
|
||||
--preset-file "{{ __llama_preset_file }}"
|
||||
--preset-global-file "{{ __llama_preset_global_json }}"
|
||||
--container-links-dir "{{ __llama_links_dir | replace('\\', '/') }}"
|
||||
{% if llama_server_models_prune_enabled | default(true) %}--prune{% endif %}
|
||||
{% if llama_server_models_dry_run | default(false) %}--dry-run{% endif %}
|
||||
register: __llama_sync_output__
|
||||
changed_when: false
|
||||
environment:
|
||||
HF_TOKEN: "{{ lookup('env', 'HF_TOKEN') | default('', true) }}"
|
||||
|
||||
- name: Parse llama server sync output
|
||||
ansible.builtin.set_fact:
|
||||
__llama_sync_result__: "{{ __llama_sync_output__.stdout | from_json }}"
|
||||
|
||||
- name: Stat llama router preset file (when not in dry-run mode)
|
||||
ansible.windows.win_stat:
|
||||
path: "{{ __llama_preset_file }}"
|
||||
register: __llama_preset_stat__
|
||||
when: not (llama_server_models_dry_run | default(false))
|
||||
|
||||
- name: Ensure router preset file exists when not in dry-run mode
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- __llama_preset_stat__.stat.exists
|
||||
fail_msg: "llama router preset file was not created"
|
||||
when: not (llama_server_models_dry_run | default(false))
|
||||
|
||||
- name: Remove existing llama-server service if present
|
||||
ansible.windows.win_service:
|
||||
name: llama-server
|
||||
state: absent
|
||||
failed_when: false
|
||||
|
||||
- name: Install llama-server service via NSSM
|
||||
ansible.windows.win_command:
|
||||
argv: >-
|
||||
{{
|
||||
[
|
||||
__nssm_exe,
|
||||
'install',
|
||||
'llama-server',
|
||||
(llama_server_windows_install_dir ~ '\\' ~ llama_server_windows_bin_name),
|
||||
'--port',
|
||||
(llama_server_port | default(11434) | string),
|
||||
'--host',
|
||||
(llama_server_host | default('127.0.0.1') | string),
|
||||
'--metrics',
|
||||
'--models-preset',
|
||||
(__llama_preset_file | string),
|
||||
'--models-max',
|
||||
(llama_server_models_max | string)
|
||||
]
|
||||
+ (llama_server_argv_extra | default([]))
|
||||
}}
|
||||
args:
|
||||
chdir: "{{ llama_server_windows_install_dir }}"
|
||||
register: __llama_nssm_install
|
||||
changed_when: __llama_nssm_install.rc == 0
|
||||
|
||||
- name: Set llama-server AppDirectory via NSSM
|
||||
ansible.windows.win_command:
|
||||
argv:
|
||||
- "{{ __nssm_exe }}"
|
||||
- set
|
||||
- llama-server
|
||||
- AppDirectory
|
||||
- "{{ llama_server_windows_install_dir }}"
|
||||
|
||||
- name: Configure llama-server stdout log via NSSM
|
||||
ansible.windows.win_command:
|
||||
argv:
|
||||
- "{{ __nssm_exe }}"
|
||||
- set
|
||||
- llama-server
|
||||
- AppStdout
|
||||
- "{{ llama_server_windows_install_dir }}\\llama-server.out.log"
|
||||
|
||||
- name: Configure llama-server stderr log via NSSM
|
||||
ansible.windows.win_command:
|
||||
argv:
|
||||
- "{{ __nssm_exe }}"
|
||||
- set
|
||||
- llama-server
|
||||
- AppStderr
|
||||
- "{{ llama_server_windows_install_dir }}\\llama-server.err.log"
|
||||
|
||||
- name: Set llama-server Start mode to AUTO via NSSM
|
||||
ansible.windows.win_command:
|
||||
argv:
|
||||
- "{{ __nssm_exe }}"
|
||||
- set
|
||||
- llama-server
|
||||
- Start
|
||||
- SERVICE_AUTO_START
|
||||
|
||||
- name: Ensure llama-server service is running
|
||||
ansible.windows.win_service:
|
||||
name: llama-server
|
||||
start_mode: auto
|
||||
state: restarted
|
||||
when: not ansible_check_mode | default(false)
|
||||
|
||||
- name: Wait for llama-server to listen on port
|
||||
ansible.windows.win_wait_for:
|
||||
port: "{{ llama_server_port | default(11434) }}"
|
||||
delay: 5
|
||||
timeout: 60
|
||||
when: not ansible_check_mode | default(false)
|
||||
|
||||
- name: Query llama router model list
|
||||
ansible.windows.win_uri:
|
||||
url: "http://127.0.0.1:{{ llama_server_port | default(11434) }}/models?reload=1"
|
||||
method: GET
|
||||
status_code: 200
|
||||
return_content: true
|
||||
register: __llama_router_models__
|
||||
changed_when: false
|
||||
when:
|
||||
- llama_server_models_sync_enabled | default(true)
|
||||
- not (llama_server_models_dry_run | default(false))
|
||||
|
||||
- name: Parse llama router model list payload
|
||||
ansible.builtin.set_fact:
|
||||
__llama_router_models_payload__: "{{ __llama_router_models__.content | from_json }}"
|
||||
when:
|
||||
- llama_server_models_sync_enabled | default(true)
|
||||
- not (llama_server_models_dry_run | default(false))
|
||||
|
||||
- name: Validate expected model aliases are available in router
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- item.name in (__llama_router_models_payload__.data | map(attribute='id') | list)
|
||||
fail_msg: "Model name '{{ item.name }}' not present in llama router /models output"
|
||||
loop: "{{ __llama_sync_result__.models | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
when:
|
||||
- llama_server_models_sync_enabled | default(true)
|
||||
- not (llama_server_models_dry_run | default(false))
|
||||
|
||||
- name: Set firewall remote IPs when string provided
|
||||
ansible.builtin.set_fact:
|
||||
llama_server_windows_remoteip: "{{ llama_server_windows_sources }}"
|
||||
when:
|
||||
- llama_server_windows_sources is defined
|
||||
- llama_server_windows_sources is string
|
||||
|
||||
- name: Set firewall remote IPs when list provided
|
||||
ansible.builtin.set_fact:
|
||||
llama_server_windows_remoteip: "{{ llama_server_windows_sources | join(',') }}"
|
||||
when:
|
||||
- llama_server_windows_sources is defined
|
||||
- not (llama_server_windows_sources is string)
|
||||
|
||||
- name: Allow incoming traffic to llama-server port through Windows Firewall
|
||||
community.windows.win_firewall_rule:
|
||||
name: Llama Server "{{ llama_server_port | default(11434) }}"
|
||||
localport: "{{ llama_server_port | default(11434) }}"
|
||||
protocol: tcp
|
||||
direction: in
|
||||
action: allow
|
||||
enabled: true
|
||||
# Provide one or more IPs/CIDRs in llama_server_windows_sources (e.g. ['203.0.113.10'])
|
||||
remoteip: "{{ llama_server_windows_remoteip | default(omit) }}"
|
||||
state: present
|
||||
|
||||
# --- Windows Exporter tasks ---
|
||||
|
||||
- name: Run Windows Exporter setup
|
||||
when: llama_server_windows_exporter_enabled | default(true) | bool
|
||||
ansible.builtin.include_tasks:
|
||||
file: llama_exporter.yml
|
||||
tags:
|
||||
- roles::llama_server::llama_exporter
|
||||
Reference in New Issue
Block a user