Skip to content

Infrastructure: Ansible Rolling Update System for Dependency Patching (oVirt-style) #682

Closed

Description

@mrveiss

Objective

Implement an Ansible-based rolling update system for non-disruptive dependency patching across AutoBot's 5-VM infrastructure, inspired by oVirt's cluster upgrade patterns.

Background

Architecture Reference

oVirt-Style Patterns to Adopt

Based on research from oVirt Ansible modules and cluster upgrade issues:

  1. Maintenance Mode - Put host in maintenance before updates
  2. Rolling Updates - One VM at a time with health verification
  3. Service Migration - Drain connections before updating
  4. Health Verification - Confirm service health after each update
  5. Rollback Capability - Automatic rollback on failure

AutoBot VM Infrastructure

VM IP Services Update Order
VM3 (Database) 172.16.168.23 Redis Stack 1st (stateful, needs careful handling)
VM2 (Backend) 172.16.168.20 FastAPI 2nd (depends on Redis)
VM4 (AI/ML) 172.16.168.24 AI Stack, NPU 3rd (depends on Backend)
VM1 (Frontend) 172.16.168.21 Vue.js 4th (depends on Backend API)
VM5 (Browser) 172.16.168.25 Playwright 5th (isolated)

Proposed Playbook Structure

infrastructure/shared/scripts/ansible/
├── playbooks/
│   ├── patch-dependencies.yml        # Main orchestrator
│   ├── patch-python-deps.yml         # Python venv updates
│   ├── patch-system-packages.yml     # apt package updates
│   └── patch-node-deps.yml           # npm package updates
├── roles/
│   └── dependency_patching/
│       ├── tasks/
│       │   ├── main.yml
│       │   ├── pre-update.yml        # Backup, drain, maintenance mode
│       │   ├── update-venv.yml       # pip install --upgrade
│       │   ├── post-update.yml       # Health check, restore
│       │   └── rollback.yml          # Restore from backup
│       ├── vars/
│       │   └── main.yml              # Package versions, CVE mappings
│       ├── handlers/
│       │   └── main.yml              # Service restart handlers
│       └── templates/
│           └── requirements-update.txt.j2

Key Features

1. Pre-Update Phase

- name: Create venv backup
  archive:
    path: /opt/autobot/venv
    dest: /opt/autobot/backups/venv-{{ ansible_date_time.iso8601_basic }}.tar.gz

- name: Drain active connections
  uri:
    url: "http://localhost:{{ service_port }}/admin/drain"
    method: POST
  
- name: Wait for connections to close
  wait_for:
    port: "{{ service_port }}"
    state: drained
    timeout: 60

2. Rolling Update Strategy

- name: Update VMs in sequence
  hosts: "{{ item }}"
  serial: 1  # One VM at a time
  max_fail_percentage: 0  # Stop on any failure
  vars:
    update_order:
      - database
      - backend
      - ai_stack
      - frontend
      - browser

3. Health Verification

- name: Verify service health after update
  uri:
    url: "http://{{ ansible_host }}:{{ service_port }}/health"
    return_content: yes
  register: health_check
  until: health_check.status == 200
  retries: 10
  delay: 5

4. Automatic Rollback

- name: Rollback on failure
  block:
    - name: Update dependencies
      pip:
        requirements: /tmp/requirements-update.txt
        virtualenv: /opt/autobot/venv
  rescue:
    - name: Restore venv from backup
      unarchive:
        src: "{{ latest_backup }}"
        dest: /opt/autobot/
        remote_src: yes
    - name: Restart service
      systemd:
        name: "{{ service_name }}"
        state: restarted

CVE-Specific Updates (Issue #544)

Package updates to implement:

Usage

# Preview changes (dry run)
./deploy.sh --patch-dependencies --check

# Update all VMs with rolling updates
./deploy.sh --patch-dependencies

# Update specific VM group
ansible-playbook playbooks/patch-dependencies.yml --limit backend

# Emergency rollback
./deploy.sh --rollback-dependencies

Tasks

Phase 1: Core Infrastructure

  • Create dependency_patching role
  • Implement pre-update backup and drain logic
  • Implement venv update with pip
  • Add health verification handlers

Phase 2: Rolling Update Orchestration

  • Create patch-dependencies.yml main playbook
  • Implement serial execution with proper ordering
  • Add automatic rollback on failure
  • Integrate with existing health-check.yml

Phase 3: CLI Integration

  • Add --patch-dependencies to deploy.sh
  • Add --rollback-dependencies option
  • Add dry-run/check mode support

Phase 4: Testing & Documentation

  • Test rolling update on staging
  • Document usage in infrastructure/shared/scripts/ansible/README.md
  • Add to maintenance procedures

Acceptance Criteria

  • Can update Python dependencies on all VMs without service disruption
  • Automatic rollback on failure
  • Health checks pass before moving to next VM
  • CLI integration with deploy.sh
  • Works with existing Ansible infrastructure

Related

References

Labels

infrastructure, ansible, security, dependencies

Activity

  1. mrveiss commented on Dec 31, 2025

    @mrveiss
    OwnerAuthor

    Implementation Complete ✅

    The Ansible rolling update system has been implemented. Here's what was created:

    New Role: dependency_patching

    Location: ansible/roles/dependency_patching/

    Structure:

    roles/dependency_patching/
    ├── defaults/main.yml      # Default variables (backup settings, timeouts, package versions)
    ├── vars/main.yml          # Service definitions, update order, CVE references
    ├── tasks/
    │   ├── main.yml           # Main orchestrator
    │   ├── pre-update.yml     # Backup venv, drain connections, enter maintenance mode
    │   ├── update-venv.yml    # pip install security updates
    │   ├── post-update.yml    # Health check, restart service, cleanup old backups
    │   └── rollback.yml       # Restore from backup on failure
    ├── handlers/main.yml      # Service restart handlers
    └── templates/
        └── requirements-security-update.txt.j2  # Dynamic requirements file
    

    New Playbook: patch-dependencies.yml

    Location: ansible/playbooks/patch-dependencies.yml

    Features:

    • 5-phase rolling update (Database → Backend → AI Stack → NPU → Frontend)
    • Serial execution (one VM at a time)
    • max_fail_percentage: 0 (stops on any failure)
    • Automatic confirmation prompt
    • Post-completion summary with next steps

    Updated: deploy.sh

    New CLI options:

    • --patch-dependencies - Live rolling update
    • --patch-dependencies-check - Dry run (preview changes)
    • --rollback-dependencies - Restore from backup

    Key oVirt-Style Patterns Implemented:

    1. ✅ Maintenance Mode - Stop service before update
    2. ✅ Backup Before Update - tar.gz archive of venv
    3. ✅ Rolling Updates - One VM at a time with serial: 1
    4. ✅ Health Verification - HTTP health checks with retries
    5. ✅ Automatic Rollback - block/rescue pattern restores on failure
    6. ✅ Connection Draining - Optional drain endpoint support
    7. ✅ Backup Retention - Automatic cleanup of old backups

    CVE Updates Configured:

    python_security_updates:
      filelock: "3.20.1"
      keras: "3.12.0"
      langchain-core: "0.3.81"
      markdownify: "0.14.1"
      marshmallow: "3.26.2"
      pypdf: "6.4.0"
      starlette: "0.49.1"
      urllib3: "2.6.0"
      werkzeug: "3.1.4"
      requests: "2.32.4"

    Usage:

    # Preview changes (dry run)
    ./deploy.sh --patch-dependencies-check
    
    # Apply updates with rolling updates
    ./deploy.sh --patch-dependencies
    
    # Emergency rollback
    ./deploy.sh --rollback-dependencies

    Files Changed:

    • ansible/roles/dependency_patching/ (new role - 7 files)
    • ansible/playbooks/patch-dependencies.yml (new playbook)
    • ansible/deploy.sh (updated with 3 new options)

    Next Steps:

    1. Test on staging environment
    2. Apply to Security: Remediate 5 CVEs in Python Dependencies #544 CVE remediation
    3. Document in ansible/README.md
  2. mrveiss commented on Dec 31, 2025

    @mrveiss
    OwnerAuthor

    Commit Complete ✅

    All changes committed in b80ff577:

    • 16 files changed, 961 insertions(+), 14 deletions(-)

    Critical Issues Fixed (from Code Review)

    1. ✅ Rollback health check now fatal - Added explicit failure task after health check
    2. ✅ Backup existence validation - Added fail task if no backup available for rollback
    3. ✅ Fixed deploy.sh rollback target - Created dedicated rollback-dependencies.yml playbook that targets only Python hosts

    Commit Details

    feat(security): Ansible rolling update system for CVE remediation (#544, #682)
    
    - New role: dependency_patching/
    - New playbooks: patch-dependencies.yml, rollback-dependencies.yml  
    - Updated deploy.sh with --patch-dependencies options
    

    Ready for Testing

    The infrastructure is ready for testing. Use:

    # Preview changes (dry run)
    ./ansible/deploy.sh --patch-dependencies-check
    
    # Apply updates with rolling updates
    ./ansible/deploy.sh --patch-dependencies
  3. mrveiss commented on Dec 31, 2025

    @mrveiss
    OwnerAuthor

    Extending to System Package Updates

    Now implementing the system (apt) package update capability as described in the issue's playbook structure:

    • patch-system-packages.yml - apt package updates with rolling deployment
    • System update tasks in the dependency_patching role
    • Integration with deploy.sh via --patch-system option

    This complements the Python dependency patching already implemented.

  4. mrveiss commented on Dec 31, 2025

    @mrveiss
    OwnerAuthor

    System Package Updates Implementation Complete ✅

    Extended the rolling update infrastructure to support apt package updates.

    New Files Created:

    • ansible/playbooks/patch-system-packages.yml - 6-phase rolling update for apt
    • ansible/playbooks/rollback-system-packages.yml - Emergency service restoration
    • ansible/roles/dependency_patching/tasks/update-system.yml - apt upgrade with backup
    • ansible/roles/dependency_patching/tasks/rollback-system.yml - Service restoration

    CLI Options Added to deploy.sh:

    # Full system update
    ./deploy.sh --patch-system
    
    # Dry run preview
    ./deploy.sh --patch-system-check
    
    # Security updates only
    ./deploy.sh --patch-system-security
    
    # Update and reboot if required (kernel updates)
    ./deploy.sh --patch-system-reboot
    
    # Emergency rollback
    ./deploy.sh --rollback-system

    Features:

    • dpkg state backup before updates
    • apt cache update with 3x retry logic
    • Security-only update mode
    • Optional reboot for kernel updates
    • Automatic rollback on failure
    • Health verification after each host

    Code Review Fixes Applied:

    1. CRITICAL: Fixed shell injection in dpkg backup (uses ansible.builtin.copy instead of shell)
    2. CRITICAL: Added retry and failure handling for apt cache update
    3. CRITICAL: Fixed race condition in rollback service restart
    4. HIGH: Added browser group to service_definitions

    Commit:

    a765cf4e feat(security): Add system package (apt) rolling updates (#682)
    

    Updated Checklist:

    Phase 1: Core Infrastructure ✅

    • Create dependency_patching role
    • Implement pre-update backup and drain logic
    • Implement venv update with pip
    • Add health verification handlers

    Phase 2: Rolling Update Orchestration ✅

    • Create patch-dependencies.yml main playbook
    • Implement serial execution with proper ordering
    • Add automatic rollback on failure
    • Integrate with existing health-check.yml

    Phase 3: CLI Integration ✅

    • Add --patch-dependencies to deploy.sh
    • Add --rollback-dependencies option
    • Add dry-run/check mode support
    • Add --patch-system options (NEW)

    Phase 4: System Package Updates ✅ (NEW)

    • Create patch-system-packages.yml playbook
    • Implement apt upgrade with backup
    • Add security-only mode
    • Add reboot option for kernel updates

    The infrastructure is now complete for both Python dependency and system package patching.

  5. mrveiss commented on Jan 6, 2026

    @mrveiss
    OwnerAuthor

    Starting work on implementing the Ansible Rolling Update System for Dependency Patching.

    Phase 1: Core Infrastructure - Beginning implementation of dependency_patching role with:

    • Pre-update backup and drain logic
    • Virtual environment update with pip
    • Health verification handlers
    • Automatic rollback capability
  6. mrveiss commented on Jan 6, 2026

    @mrveiss
    OwnerAuthor

    Implementation Complete ✅

    Changes Made:

    1. Fixed host group name alignment across all files:

    • Updated ansible/roles/dependency_patching/vars/main.yml - Changed ai_stack → aiml, npu_workers → npu
    • Updated ansible/playbooks/patch-dependencies.yml - Fixed host group references
    • Updated ansible/playbooks/rollback-dependencies.yml - Fixed host group references
    • Updated ansible/playbooks/patch-system-packages.yml - Fixed host group references
    • Updated ansible/playbooks/rollback-system-packages.yml - Fixed host group references

    2. Fixed rollback order (from code review):

    • Changed rollback-dependencies.yml to use correct reverse order: npu → aiml → backend
    • Added documentation comment explaining the rollback order logic

    3. Improved rollback safety (from code review - HIGH priority):

    • Modified ansible/roles/dependency_patching/tasks/rollback.yml to use two-stage restore:
      1. Extract backup to temporary directory first
      2. Verify extracted venv structure is valid
      3. Only then remove failed venv and move restored one
      4. This prevents data loss if backup is corrupted

    Acceptance Criteria Verified:

    • ✅ dependency_patching role created with all required task files
    • ✅ Pre-update backup and drain logic implemented
    • ✅ Venv update with pip implemented
    • ✅ Health verification handlers implemented
    • ✅ patch-dependencies.yml main playbook created with serial execution
    • ✅ Automatic rollback on failure implemented
    • ✅ Integration with existing health-check.yml
    • ✅ --patch-dependencies added to deploy.sh
    • ✅ --rollback-dependencies option added
    • ✅ Dry-run/check mode support added
    • ✅ Works with existing Ansible infrastructure

    Code Review Summary:

    • 0 Critical, 3 High (2 are inventory passwords - existing issue, 1 fixed), 8 Medium, 10 Low issues identified
    • All host groups now aligned: backend, frontend, database, aiml, npu, browser
    • Rollback order corrected to be reverse of update order
    • Rollback safety improved with two-stage extraction

    CLI Usage:

    # Preview dependency updates (dry run)
    ./deploy.sh --patch-dependencies-check
    
    # Apply dependency updates with rolling updates
    ./deploy.sh --patch-dependencies
    
    # Emergency rollback
    ./deploy.sh --rollback-dependencies
    
    # System package updates
    ./deploy.sh --patch-system
    ./deploy.sh --patch-system-check
    ./deploy.sh --patch-system-security
    ./deploy.sh --rollback-system

    Files Modified:

    • ansible/roles/dependency_patching/vars/main.yml
    • ansible/roles/dependency_patching/tasks/rollback.yml
    • ansible/playbooks/patch-dependencies.yml
    • ansible/playbooks/rollback-dependencies.yml
    • ansible/playbooks/patch-system-packages.yml
    • ansible/playbooks/rollback-system-packages.yml

    Note:

    The code review identified plaintext passwords in inventory/production.yml as a HIGH security concern. This is an existing infrastructure issue that should be addressed separately by migrating to Ansible Vault or SSH key-only authentication.

  7. mrveiss commented on Jan 14, 2026

    @mrveiss
    OwnerAuthor

    Related: GUI Foundation Implemented in #695

    Issue #695 (Node Management UI) has been completed and provides the GUI infrastructure for this rolling update system:

    Now Available via GUI

    Per-Node Updates:

    • Check for updates on individual nodes via SSH (/api/infrastructure/nodes/{id}/check-updates)
    • Apply updates to individual nodes (/api/infrastructure/nodes/{id}/update)
    • Support for different update types: system, security, dependencies, all
    • Dry-run mode for previewing changes

    Dependency-Aware Ordering:

    • ROLE_DEPENDENCIES graph implemented in infrastructure_nodes.py
    • GET /api/infrastructure/nodes/update-order calculates proper update sequence
    • Batch updates respect role dependencies (Redis → AI Stack → Backend → Frontend)

    Batch Update Orchestration:

    • POST /api/infrastructure/nodes/update-batch runs updates across multiple nodes
    • Stage-based execution (parallel within stage, sequential across stages)
    • Stop-on-failure option for safety
    • Real-time progress via lifecycle events and WebSocket

    Lifecycle Event Tracking:

    • Full visibility into update progress
    • Events: UPDATE_STARTED, UPDATE_PROGRESS, UPDATE_COMPLETE, UPDATE_FAILED
    • WebSocket broadcasts for real-time UI updates

    What This Issue Still Covers

    The Ansible playbook integration and CLI (deploy.sh --patch-dependencies) aspects are still pending:

    • Create dependency_patching Ansible role
    • Implement pre-update backup and drain logic in playbooks
    • Add automatic rollback on failure via Ansible
    • CLI integration with deploy.sh

    The GUI-based update system in #695 provides an alternative to the CLI approach, allowing ops to run updates per-node or in batches directly from the Infrastructure Settings UI.

  8. mrveiss commented on Feb 10, 2026

    @mrveiss
    OwnerAuthor

    Implementation: Fleet Overview Update Workflow

    Starting work on the Fleet Overview integration for #682. The UI workflow will:

    1. FleetSummary: New 'Updates Available' stat card showing total nodes needing updates
    2. NodeCard: Update badge per node showing counts: system packages + AutoBot code
    3. Backend: New GET /api/updates/fleet-summary endpoint returning per-node update counts
    4. Types: Extended SLMNode with code_status and code_version fields

    Checklist

    • Backend: Add fleet update summary endpoint
    • Backend: Include code_status/code_version in node list responses
    • Frontend: Extend SLMNode type
    • Frontend: Add update badges to NodeCard
    • Frontend: Add 'Updates Available' to FleetSummary
    • Frontend: Fleet store update summary fetching
    • Frontend: Wire 'Updates' action to lifecycle panel
  9. mrveiss commented on Feb 10, 2026

    @mrveiss
    OwnerAuthor

    Fleet Update Summary - Implementation Complete

    What was implemented

    Backend (SLM):

    • GET /api/updates/fleet-summary endpoint — returns per-node update counts (system packages + code status)
    • NodeUpdateSummary and FleetUpdateSummaryResponse schemas
    • code_version / code_status added to NodeResponse schema
    • Helper _build_node_summaries() extracted per Extract Method pattern

    Frontend (SLM):

    • SLMNode type extended with code_status / code_version
    • NodeUpdateSummary and FleetUpdateSummary TypeScript interfaces
    • NodeCard: Amber update badge showing X pkgs + code when updates available
    • FleetSummary: 5th "Need Updates" stat card (amber theme)
    • Fleet store: fetchFleetUpdateSummary() action, nodesNeedingUpdates computed, getNodeUpdateSummary() getter
    • FleetOverview: Fetches summary on mount, 'updates' action opens lifecycle panel

    Code review findings addressed

    • Fixed total_system_updates double-counting global updates (was inflating by nodes × global_count)
    • Grouped 'updates' case with other lifecycle panel actions

    Files changed (8 files, +223/-9 lines)

    • autobot-slm-backend/api/updates.py
    • autobot-slm-backend/models/schemas.py
    • autobot-slm-frontend/src/types/slm.ts
    • autobot-slm-frontend/src/composables/useSlmApi.ts
    • autobot-slm-frontend/src/stores/fleet.ts
    • autobot-slm-frontend/src/components/fleet/NodeCard.vue
    • autobot-slm-frontend/src/components/fleet/FleetSummary.vue
    • autobot-slm-frontend/src/views/FleetOverview.vue

    Commits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions