Add Ansible integration for device management and deployment automation

- Added ansible/ directory with playbooks for:
  * deploy.yml: Update applications on devices from git
  * commands.yml: Execute arbitrary commands on devices
  * system_update.yml: OS updates and health checks
  * inventory.ini: Device and group configuration
  * README.md: Comprehensive Ansible guide
  * requirements.txt: Installation instructions

- Added ansible_integration.py: Python module wrapping Ansible operations
- Added utils_ansible.py: Updated utilities using Ansible instead of HTTP commands

Key benefits:
- Idempotent operations with error recovery
- Comprehensive logging and backup
- Multi-device orchestration
- Better reliability and control
- Replaces unreliable direct HTTP command execution
This commit is contained in:
Developer
2025-12-18 13:59:48 +02:00
parent 376240fb06
commit cb52e67afa
8 changed files with 1807 additions and 0 deletions

201
ansible/deploy.yml Normal file
View File

@@ -0,0 +1,201 @@
---
# deploy.yml - Deploy updates to Prezenta Work devices
# Handles pulling latest code and restarting services
- name: Deploy Prezenta Work Updates
hosts: prezenta_devices
gather_facts: yes
serial: 1 # Deploy one device at a time to avoid service interruption
vars:
app_directory: "/srv/prezenta_work"
git_branch: "dev"
restart_service: true
backup_before_deploy: true
tasks:
- name: Display deployment information
debug:
msg: "Deploying to {{ inventory_hostname }} ({{ ansible_host }})"
# Pre-deployment checks
- name: Check if app directory exists
stat:
path: "{{ app_directory }}"
register: app_dir_stat
- name: Fail if app directory doesn't exist
fail:
msg: "Application directory {{ app_directory }} not found on {{ inventory_hostname }}"
when: not app_dir_stat.stat.exists
# Backup current code
- name: Create backup directory
file:
path: "{{ app_directory }}/backups"
state: directory
mode: '0755'
when: backup_before_deploy
- name: Backup current code
shell: |
cd {{ app_directory }}
tar -czf backups/backup_{{ ansible_date_time.iso8601_basic_short }}.tar.gz \
--exclude=.git \
--exclude=__pycache__ \
--exclude=data \
--exclude=Files \
.
register: backup_result
when: backup_before_deploy
- name: Display backup created
debug:
msg: "Backup created: {{ backup_result.stdout_lines }}"
when: backup_before_deploy and backup_result is not skipped
# Pull latest code
- name: Fetch latest from repository
shell: |
cd {{ app_directory }}
git fetch origin
register: git_fetch
changed_when: "'Fetching' in git_fetch.stdout or 'Receiving' in git_fetch.stdout"
- name: Checkout dev branch
shell: |
cd {{ app_directory }}
git checkout {{ git_branch }}
register: git_checkout
- name: Pull latest changes
shell: |
cd {{ app_directory }}
git pull origin {{ git_branch }}
register: git_pull
changed_when: "'Already up to date' not in git_pull.stdout"
- name: Display git pull result
debug:
msg: "{{ git_pull.stdout }}"
# Verify deployment
- name: Check Python syntax
shell: |
python3 -m py_compile {{ app_directory }}/app.py
register: syntax_check
changed_when: false
failed_when: syntax_check.rc != 0
- name: Verify all modules compile
shell: |
cd {{ app_directory }}
python3 -m py_compile *.py
register: module_check
changed_when: false
- name: Verify configuration
shell: |
cd {{ app_directory }}
python3 -c "import config_settings; print('✓ Configuration OK')"
register: config_check
changed_when: false
- name: Display verification results
debug:
msg: "{{ config_check.stdout }}"
# Restart application
- name: Restart Prezenta application
block:
- name: Stop Prezenta service
systemd:
name: prezenta
state: stopped
daemon_reload: yes
become: yes
when: restart_service
- name: Wait for service to stop
pause:
seconds: 2
- name: Start Prezenta service
systemd:
name: prezenta
state: started
enabled: yes
become: yes
when: restart_service
- name: Verify service is running
systemd:
name: prezenta
state: started
become: yes
register: service_status
until: service_status.status.ActiveState == "active"
retries: 3
delay: 5
rescue:
- name: Service restart failed, attempting manual restart
debug:
msg: "Attempting to restart application manually on {{ inventory_hostname }}"
- name: Kill existing processes
shell: |
pkill -f "python3.*app.py" || true
become: yes
- name: Wait before restart
pause:
seconds: 3
- name: Start application in background
shell: |
cd {{ app_directory }}
nohup python3 app.py > data/startup.log 2>&1 &
become: yes
become_user: pi
# Post-deployment verification
- name: Wait for application to start
pause:
seconds: 5
- name: Check application status via HTTP
uri:
url: "http://{{ ansible_host }}:80/status"
method: GET
status_code: [200, 404]
timeout: 10
register: app_status
retries: 3
delay: 2
until: app_status.status in [200, 404]
- name: Display application status
debug:
msg: "Application on {{ inventory_hostname }} is running"
when: app_status.status in [200, 404]
# Log deployment
- name: Record deployment in log
lineinfile:
path: "{{ app_directory }}/data/deploy.log"
line: "[{{ ansible_date_time.iso8601 }}] Deployed {{ git_branch }} from {{ ansible_user }}@monitoring_server"
create: yes
state: present
- name: Log deployment summary
debug:
msg: |
Deployment completed for {{ inventory_hostname }}
Branch: {{ git_branch }}
Status: SUCCESS
Last git commit: {{ git_pull.stdout_lines[-1] if git_pull.stdout_lines else 'Unknown' }}
post_tasks:
- name: Send deployment notification
debug:
msg: "Deployment notification: {{ inventory_hostname }} updated to {{ git_branch }}"