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:
388
ansible/README.md
Normal file
388
ansible/README.md
Normal file
@@ -0,0 +1,388 @@
|
||||
# Ansible Integration for Server_Monitorizare
|
||||
|
||||
This directory contains Ansible playbooks and configuration for managing Prezenta Work devices remotely.
|
||||
|
||||
## Overview
|
||||
|
||||
The Ansible integration replaces direct HTTP command execution with a more robust, scalable solution:
|
||||
|
||||
### **Before (HTTP-based)**
|
||||
```
|
||||
Server → HTTP Request → Device (/execute_command endpoint)
|
||||
Problems:
|
||||
- No idempotency
|
||||
- Hard to track what happened
|
||||
- No built-in error recovery
|
||||
- Limited command execution control
|
||||
```
|
||||
|
||||
### **After (Ansible-based)**
|
||||
```
|
||||
Server → Ansible Playbook → Device (SSH)
|
||||
Benefits:
|
||||
- Idempotent operations
|
||||
- Comprehensive logging
|
||||
- Built-in error handling & retry logic
|
||||
- Structured playbooks
|
||||
- Multi-device orchestration
|
||||
- Backup and rollback capability
|
||||
```
|
||||
|
||||
## Files
|
||||
|
||||
### Configuration
|
||||
- **inventory.ini** - Defines all devices, groups, and variables
|
||||
|
||||
### Playbooks
|
||||
- **deploy.yml** - Deploy application updates (pull from git, restart service)
|
||||
- **commands.yml** - Execute arbitrary commands on devices
|
||||
- **system_update.yml** - System maintenance (OS updates, health checks)
|
||||
|
||||
### Python Integration
|
||||
- **ansible_integration.py** - Python module for Ansible automation
|
||||
- **utils_ansible.py** - Updated utilities using Ansible (replaces old utils.py)
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Install Ansible on Server
|
||||
|
||||
```bash
|
||||
# On Server_Monitorizare (Ubuntu/Debian)
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ansible
|
||||
|
||||
# Verify installation
|
||||
ansible --version
|
||||
```
|
||||
|
||||
### 2. Configure Inventory
|
||||
|
||||
Edit `inventory.ini` and add your devices:
|
||||
|
||||
```ini
|
||||
[prezenta_devices]
|
||||
device_1 ansible_host=192.168.1.20
|
||||
device_2 ansible_host=192.168.1.21
|
||||
device_3 ansible_host=192.168.1.22
|
||||
```
|
||||
|
||||
### 3. Setup SSH Keys (Optional but Recommended)
|
||||
|
||||
For password-less authentication:
|
||||
|
||||
```bash
|
||||
# Generate SSH keys if not present
|
||||
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N ""
|
||||
|
||||
# Copy public key to each device
|
||||
ssh-copy-id -i ~/.ssh/id_rsa.pub pi@192.168.1.20
|
||||
ssh-copy-id -i ~/.ssh/id_rsa.pub pi@192.168.1.21
|
||||
ssh-copy-id -i ~/.ssh/id_rsa.pub pi@192.168.1.22
|
||||
```
|
||||
|
||||
Update inventory.ini to use SSH key auth:
|
||||
```ini
|
||||
[all:vars]
|
||||
ansible_user=pi
|
||||
ansible_ssh_private_key_file=~/.ssh/id_rsa
|
||||
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
|
||||
```
|
||||
|
||||
### 4. Test Connectivity
|
||||
|
||||
```bash
|
||||
# Test all devices
|
||||
ansible all -i inventory.ini -m ping
|
||||
|
||||
# Test specific group
|
||||
ansible prezenta_devices -i inventory.ini -m ping
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### From Command Line
|
||||
|
||||
#### Deploy Updates
|
||||
```bash
|
||||
# Deploy dev branch to all devices
|
||||
ansible-playbook -i inventory.ini deploy.yml \
|
||||
-e git_branch=dev \
|
||||
-e backup_before_deploy=true \
|
||||
-e restart_service=true
|
||||
|
||||
# Deploy to specific device
|
||||
ansible-playbook -i inventory.ini deploy.yml \
|
||||
--limit device_1 \
|
||||
-e git_branch=dev
|
||||
```
|
||||
|
||||
#### Execute Commands
|
||||
```bash
|
||||
# Execute command on all devices
|
||||
ansible-playbook -i inventory.ini commands.yml \
|
||||
-e command="ps aux | grep prezenta"
|
||||
|
||||
# Execute on specific device
|
||||
ansible-playbook -i inventory.ini commands.yml \
|
||||
--limit device_1 \
|
||||
-e command="systemctl status prezenta"
|
||||
```
|
||||
|
||||
#### System Update
|
||||
```bash
|
||||
# Update Python packages and perform health check
|
||||
ansible-playbook -i inventory.ini system_update.yml \
|
||||
-e update_python_packages=true \
|
||||
-e perform_health_check=true
|
||||
|
||||
# Also update OS packages
|
||||
ansible-playbook -i inventory.ini system_update.yml \
|
||||
-e update_os_packages=true \
|
||||
-e update_python_packages=true \
|
||||
-e perform_health_check=true
|
||||
```
|
||||
|
||||
### From Python Code
|
||||
|
||||
```python
|
||||
from utils_ansible import (
|
||||
deploy_updates_to_device,
|
||||
deploy_updates_to_all_devices,
|
||||
execute_command_on_device,
|
||||
system_update_device,
|
||||
get_device_status,
|
||||
get_execution_logs
|
||||
)
|
||||
|
||||
# Deploy to specific device
|
||||
result = deploy_updates_to_device('device_1', git_branch='dev')
|
||||
print(result)
|
||||
|
||||
# Deploy to all devices
|
||||
result = deploy_updates_to_all_devices(git_branch='dev')
|
||||
print(result)
|
||||
|
||||
# Execute command
|
||||
result = execute_command_on_device('device_1', 'systemctl status prezenta')
|
||||
print(result)
|
||||
|
||||
# System update
|
||||
result = system_update_device('device_1', update_python=True, health_check=True)
|
||||
print(result)
|
||||
|
||||
# Get device status
|
||||
result = get_device_status('device_1')
|
||||
print(result)
|
||||
|
||||
# Get recent logs
|
||||
logs = get_execution_logs(limit=10)
|
||||
print(logs)
|
||||
```
|
||||
|
||||
### In Flask Routes
|
||||
|
||||
Update your Flask routes to use the new Ansible-based utilities:
|
||||
|
||||
```python
|
||||
from flask import request, jsonify
|
||||
from utils_ansible import (
|
||||
deploy_updates_to_device,
|
||||
execute_command_on_device,
|
||||
get_device_status
|
||||
)
|
||||
|
||||
@app.route('/api/deploy', methods=['POST'])
|
||||
def deploy_api():
|
||||
data = request.json
|
||||
device = data.get('device')
|
||||
branch = data.get('branch', 'dev')
|
||||
|
||||
result = deploy_updates_to_device(device, git_branch=branch)
|
||||
return jsonify(result)
|
||||
|
||||
@app.route('/api/command', methods=['POST'])
|
||||
def command_api():
|
||||
data = request.json
|
||||
device = data.get('device')
|
||||
command = data.get('command')
|
||||
|
||||
result = execute_command_on_device(device, command)
|
||||
return jsonify(result)
|
||||
|
||||
@app.route('/api/device/<device>/status', methods=['GET'])
|
||||
def device_status_api(device):
|
||||
result = get_device_status(device)
|
||||
return jsonify(result)
|
||||
```
|
||||
|
||||
## Playbook Details
|
||||
|
||||
### deploy.yml
|
||||
|
||||
**What it does:**
|
||||
1. Backs up current code (optional)
|
||||
2. Fetches latest from git repository
|
||||
3. Checks out specified branch
|
||||
4. Pulls latest changes
|
||||
5. Verifies syntax
|
||||
6. Restarts application service
|
||||
7. Verifies service is running
|
||||
8. Logs deployment
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
ansible-playbook deploy.yml -e git_branch=dev -e backup_before_deploy=true
|
||||
```
|
||||
|
||||
**Output Locations:**
|
||||
- Backups: `/srv/prezenta_work/backups/`
|
||||
- Logs: `./logs/deploy_YYYYMMDD_HHMMSS.log`
|
||||
|
||||
### commands.yml
|
||||
|
||||
**What it does:**
|
||||
1. Executes command with specified user
|
||||
2. Captures output and errors
|
||||
3. Logs command in device's command history
|
||||
4. Returns result
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
ansible-playbook commands.yml -e command="sudo systemctl restart prezenta"
|
||||
```
|
||||
|
||||
**Output Locations:**
|
||||
- Logs: `./logs/command_DEVICE_YYYYMMDD_HHMMSS.log`
|
||||
- Device log: `/srv/prezenta_work/data/command_history.log`
|
||||
|
||||
### system_update.yml
|
||||
|
||||
**What it does:**
|
||||
1. Gathers system facts
|
||||
2. Updates OS packages (optional)
|
||||
3. Updates Python packages
|
||||
4. Checks service status
|
||||
5. Performs health checks (disk, memory, CPU temp)
|
||||
6. Logs results
|
||||
7. Reboots if needed (optional)
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
ansible-playbook system_update.yml \
|
||||
-e update_os_packages=false \
|
||||
-e update_python_packages=true \
|
||||
-e perform_health_check=true
|
||||
```
|
||||
|
||||
**Output Locations:**
|
||||
- Logs: `./logs/system_update_YYYYMMDD_HHMMSS.log`
|
||||
- Device log: `/srv/prezenta_work/data/system_update.log`
|
||||
|
||||
## Execution Logs
|
||||
|
||||
Logs are stored in `ansible/logs/` directory:
|
||||
|
||||
```bash
|
||||
# View recent logs
|
||||
ls -lht ansible/logs/ | head -10
|
||||
|
||||
# Follow live deployment
|
||||
tail -f ansible/logs/deploy_*.log
|
||||
|
||||
# Search logs
|
||||
grep "error\|fail" ansible/logs/*.log
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### SSH Connection Issues
|
||||
|
||||
```bash
|
||||
# Test SSH manually
|
||||
ssh -i ~/.ssh/id_rsa pi@192.168.1.20
|
||||
|
||||
# Test with verbose output
|
||||
ansible device_1 -i inventory.ini -m ping -vvv
|
||||
```
|
||||
|
||||
### Ansible Module Errors
|
||||
|
||||
```bash
|
||||
# Run with increased verbosity
|
||||
ansible-playbook deploy.yml -vvv
|
||||
```
|
||||
|
||||
### Device Not Found in Inventory
|
||||
|
||||
```bash
|
||||
# List all hosts
|
||||
ansible all -i inventory.ini --list-hosts
|
||||
|
||||
# List specific group
|
||||
ansible prezenta_devices -i inventory.ini --list-hosts
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **SSH Keys**: Use SSH key authentication instead of passwords
|
||||
2. **Inventory**: Don't commit inventory.ini with passwords to git
|
||||
3. **Ansible Vault**: Use for sensitive data:
|
||||
```bash
|
||||
ansible-vault create secrets.yml
|
||||
ansible-playbook deploy.yml -e @secrets.yml --ask-vault-pass
|
||||
```
|
||||
|
||||
4. **Firewall**: Ensure SSH (port 22) is open on devices
|
||||
|
||||
## Performance Tips
|
||||
|
||||
1. **Parallel Execution**: Run playbooks on multiple devices
|
||||
```bash
|
||||
ansible-playbook deploy.yml --forks 5
|
||||
```
|
||||
|
||||
2. **Task Caching**: Avoid unnecessary updates
|
||||
```bash
|
||||
# Playbooks already use idempotent operations
|
||||
```
|
||||
|
||||
3. **Logging**: Monitor log files for issues
|
||||
```bash
|
||||
# Compress old logs
|
||||
gzip ansible/logs/deploy_*.log
|
||||
```
|
||||
|
||||
## Migration from HTTP Commands
|
||||
|
||||
**Old (HTTP-based):**
|
||||
```python
|
||||
def execute_command_on_device(device_ip, command):
|
||||
url = f"http://{device_ip}:80/execute_command"
|
||||
response = requests.post(url, json={"command": command})
|
||||
return response.json()
|
||||
```
|
||||
|
||||
**New (Ansible-based):**
|
||||
```python
|
||||
from utils_ansible import execute_command_on_device
|
||||
|
||||
result = execute_command_on_device('device_hostname', command)
|
||||
return result
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Install Ansible on Server_Monitorizare
|
||||
2. Configure inventory.ini with your devices
|
||||
3. Set up SSH key authentication
|
||||
4. Test connectivity with `ansible all -m ping`
|
||||
5. Create first deployment
|
||||
6. Update Flask routes to use new utils_ansible
|
||||
7. Monitor logs in `ansible/logs/`
|
||||
|
||||
## Documentation
|
||||
|
||||
For more information on Ansible:
|
||||
- [Ansible Documentation](https://docs.ansible.com/)
|
||||
- [Playbook Syntax](https://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.html)
|
||||
- [Modules Reference](https://docs.ansible.com/ansible/latest/modules/modules_by_category.html)
|
||||
51
ansible/commands.yml
Normal file
51
ansible/commands.yml
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
# commands.yml - Execute commands on Prezenta devices
|
||||
# Provides structured command execution with logging and error handling
|
||||
|
||||
- name: Execute Command on Prezenta Devices
|
||||
hosts: "{{ target_devices | default('prezenta_devices') }}"
|
||||
gather_facts: no
|
||||
|
||||
vars:
|
||||
command_to_run: "{{ command | default('pwd') }}"
|
||||
command_user: pi
|
||||
log_commands: true
|
||||
|
||||
tasks:
|
||||
- name: Display command execution info
|
||||
debug:
|
||||
msg: |
|
||||
Executing on: {{ inventory_hostname }} ({{ ansible_host }})
|
||||
Command: {{ command_to_run }}
|
||||
User: {{ command_user }}
|
||||
|
||||
- name: Execute command
|
||||
shell: "{{ command_to_run }}"
|
||||
register: command_result
|
||||
become: yes
|
||||
become_user: "{{ command_user }}"
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Display command output
|
||||
debug:
|
||||
msg: |
|
||||
Return Code: {{ command_result.rc }}
|
||||
STDOUT:
|
||||
{{ command_result.stdout }}
|
||||
STDERR:
|
||||
{{ command_result.stderr | default('None') }}
|
||||
|
||||
- name: Log command execution
|
||||
lineinfile:
|
||||
path: "{{ app_directory }}/data/command_history.log"
|
||||
line: "[{{ ansible_date_time.iso8601 }}] [{{ inventory_hostname }}] Command: {{ command_to_run }} | RC: {{ command_result.rc }}"
|
||||
create: yes
|
||||
state: present
|
||||
delegate_to: "{{ inventory_hostname }}"
|
||||
become: yes
|
||||
when: log_commands
|
||||
|
||||
- name: Fail if command failed
|
||||
fail:
|
||||
msg: "Command failed on {{ inventory_hostname }} with return code {{ command_result.rc }}"
|
||||
when: command_result.rc != 0 and fail_on_error | default(false)
|
||||
201
ansible/deploy.yml
Normal file
201
ansible/deploy.yml
Normal 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 }}"
|
||||
34
ansible/inventory.ini
Normal file
34
ansible/inventory.ini
Normal file
@@ -0,0 +1,34 @@
|
||||
# Ansible Inventory for Prezenta Work Devices
|
||||
# This inventory file manages all Raspberry Pi devices running prezenta_work
|
||||
|
||||
[all:vars]
|
||||
# Common variables for all devices
|
||||
ansible_user=pi
|
||||
ansible_password=Initial01!
|
||||
ansible_become=yes
|
||||
ansible_become_method=sudo
|
||||
ansible_become_password=Initial01!
|
||||
ansible_python_interpreter=/usr/bin/python3
|
||||
ansible_connection=ssh
|
||||
|
||||
[prezenta_devices]
|
||||
# Raspberry Pi devices running the prezenta_work application
|
||||
# Format: device_name ansible_host=192.168.1.x
|
||||
|
||||
device_1 ansible_host=192.168.1.20
|
||||
device_2 ansible_host=192.168.1.21
|
||||
device_3 ansible_host=192.168.1.22
|
||||
|
||||
[prezenta_devices:vars]
|
||||
# Variables specific to prezenta devices
|
||||
app_directory=/srv/prezenta_work
|
||||
app_user=pi
|
||||
app_service=prezenta
|
||||
|
||||
[monitoring_server]
|
||||
# Central monitoring server
|
||||
monitor ansible_host=192.168.1.103 ansible_user=root
|
||||
|
||||
[local]
|
||||
# Local development/test
|
||||
localhost ansible_connection=local ansible_become=no
|
||||
64
ansible/requirements.txt
Normal file
64
ansible/requirements.txt
Normal file
@@ -0,0 +1,64 @@
|
||||
# Requirements for Server_Monitorizare Ansible Integration
|
||||
|
||||
## System Requirements
|
||||
- Ubuntu/Debian Linux
|
||||
- Python 3.7+
|
||||
- SSH access to target devices
|
||||
|
||||
## Python Packages
|
||||
# Flask and server dependencies
|
||||
Flask==2.3.0
|
||||
Werkzeug==2.3.0
|
||||
requests==2.31.0
|
||||
|
||||
# Ansible automation
|
||||
ansible>=2.10.0,<3.0.0
|
||||
ansible-core>=2.12.0
|
||||
|
||||
# Additional utilities
|
||||
python-dotenv==1.0.0
|
||||
pyyaml==6.0
|
||||
|
||||
## Installation
|
||||
|
||||
### 1. Install System Dependencies
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y python3-pip python3-dev
|
||||
sudo apt-get install -y openssh-client openssh-server
|
||||
```
|
||||
|
||||
### 2. Install Python Packages
|
||||
```bash
|
||||
cd /srv/Server_Monitorizare
|
||||
pip3 install -r requirements.txt
|
||||
```
|
||||
|
||||
### 3. Install Ansible
|
||||
```bash
|
||||
pip3 install ansible>=2.10.0
|
||||
# or
|
||||
sudo apt-get install -y ansible
|
||||
```
|
||||
|
||||
### 4. Verify Installation
|
||||
```bash
|
||||
ansible --version
|
||||
ansible-playbook --version
|
||||
python3 -c "import ansible; print(ansible.__version__)"
|
||||
```
|
||||
|
||||
## Optional: For SSH Key Authentication
|
||||
```bash
|
||||
sudo apt-get install -y openssh-client
|
||||
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N ""
|
||||
```
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# Test Ansible installation
|
||||
ansible localhost -m debug -a msg="Ansible works!"
|
||||
|
||||
# Test against devices
|
||||
ansible all -i ansible/inventory.ini -m ping
|
||||
```
|
||||
163
ansible/system_update.yml
Normal file
163
ansible/system_update.yml
Normal file
@@ -0,0 +1,163 @@
|
||||
---
|
||||
# system_update.yml - System updates and maintenance
|
||||
# Updates OS packages, manages services, and performs health checks
|
||||
|
||||
- name: System Update and Maintenance
|
||||
hosts: "{{ target_devices | default('prezenta_devices') }}"
|
||||
serial: 1 # One device at a time to maintain availability
|
||||
gather_facts: yes
|
||||
|
||||
vars:
|
||||
update_os_packages: false
|
||||
update_python_packages: true
|
||||
perform_health_check: true
|
||||
reboot_after_update: false
|
||||
|
||||
tasks:
|
||||
# System Information
|
||||
- name: Gather system information
|
||||
debug:
|
||||
msg: |
|
||||
System: {{ ansible_system }}
|
||||
Distribution: {{ ansible_distribution }} {{ ansible_distribution_version }}
|
||||
Hostname: {{ ansible_hostname }}
|
||||
IP Address: {{ ansible_default_ipv4.address }}
|
||||
Uptime: {{ ansible_uptime_seconds }} seconds
|
||||
|
||||
# OS Package Updates
|
||||
- name: Update OS package lists
|
||||
apt:
|
||||
update_cache: yes
|
||||
cache_valid_time: 300
|
||||
become: yes
|
||||
when: update_os_packages
|
||||
|
||||
- name: Upgrade OS packages
|
||||
apt:
|
||||
upgrade: full
|
||||
autoremove: yes
|
||||
autoclean: yes
|
||||
become: yes
|
||||
register: apt_upgrade
|
||||
when: update_os_packages
|
||||
|
||||
- name: Display OS updates
|
||||
debug:
|
||||
msg: "OS packages updated"
|
||||
when: update_os_packages and apt_upgrade.changed
|
||||
|
||||
# Python Package Updates
|
||||
- name: Check for prezenta_work directory
|
||||
stat:
|
||||
path: "{{ app_directory }}"
|
||||
register: app_dir
|
||||
|
||||
- name: Update Python dependencies
|
||||
block:
|
||||
- name: Find requirements.txt
|
||||
stat:
|
||||
path: "{{ app_directory }}/requirements.txt"
|
||||
register: requirements_file
|
||||
|
||||
- name: Install Python requirements
|
||||
pip:
|
||||
requirements: "{{ app_directory }}/requirements.txt"
|
||||
state: latest
|
||||
become: yes
|
||||
when: requirements_file.stat.exists
|
||||
|
||||
- name: Install Flask if not present
|
||||
pip:
|
||||
name:
|
||||
- Flask
|
||||
- requests
|
||||
- RPi.GPIO
|
||||
state: latest
|
||||
become: yes
|
||||
register: pip_install
|
||||
|
||||
- name: Display Python updates
|
||||
debug:
|
||||
msg: "Python packages updated"
|
||||
when: pip_install.changed
|
||||
when: app_dir.stat.exists and update_python_packages
|
||||
|
||||
# Service Management
|
||||
- name: Check Prezenta service status
|
||||
systemd:
|
||||
name: prezenta
|
||||
enabled: yes
|
||||
become: yes
|
||||
register: prezenta_service
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Display service status
|
||||
debug:
|
||||
msg: |
|
||||
Service: {{ prezenta_service.status.ActiveState if prezenta_service.status is defined else 'Not found' }}
|
||||
Enabled: {{ prezenta_service.status.UnitFileState if prezenta_service.status is defined else 'Unknown' }}
|
||||
|
||||
# Health Checks
|
||||
- name: Check disk space
|
||||
shell: df -h / | tail -1 | awk '{print $5}'
|
||||
register: disk_usage
|
||||
changed_when: false
|
||||
when: perform_health_check
|
||||
|
||||
- name: Check memory usage
|
||||
shell: free -h | grep Mem | awk '{print $3 "/" $2}'
|
||||
register: mem_usage
|
||||
changed_when: false
|
||||
when: perform_health_check
|
||||
|
||||
- name: Check CPU temperature (Raspberry Pi)
|
||||
shell: vcgencmd measure_temp 2>/dev/null | grep -oP '\d+\.\d+' || echo "N/A"
|
||||
register: cpu_temp
|
||||
changed_when: false
|
||||
when: perform_health_check and ansible_system == 'Linux'
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Display health check results
|
||||
debug:
|
||||
msg: |
|
||||
Disk Usage: {{ disk_usage.stdout }}
|
||||
Memory Usage: {{ mem_usage.stdout }}
|
||||
CPU Temp: {{ cpu_temp.stdout if cpu_temp.stdout != 'N/A' else 'N/A' }}°C
|
||||
when: perform_health_check
|
||||
|
||||
- name: Warn if disk space critical
|
||||
debug:
|
||||
msg: "WARNING: Disk usage is {{ disk_usage.stdout }} - Consider cleanup"
|
||||
when:
|
||||
- perform_health_check
|
||||
- disk_usage.stdout | int >= 85
|
||||
|
||||
# Log update
|
||||
- name: Create system update log
|
||||
lineinfile:
|
||||
path: "{{ app_directory }}/data/system_update.log"
|
||||
line: "[{{ ansible_date_time.iso8601 }}] System maintenance completed - Disk: {{ disk_usage.stdout }} | Memory: {{ mem_usage.stdout }}"
|
||||
create: yes
|
||||
state: present
|
||||
become: yes
|
||||
when: perform_health_check and app_dir.stat.exists
|
||||
|
||||
# Reboot if required
|
||||
- name: Schedule reboot if needed
|
||||
debug:
|
||||
msg: "System reboot scheduled after updates"
|
||||
when: reboot_after_update and apt_upgrade.changed
|
||||
|
||||
- name: Reboot system
|
||||
reboot:
|
||||
msg: "Rebooting after system updates"
|
||||
pre_reboot_delay: 60
|
||||
become: yes
|
||||
when: reboot_after_update and apt_upgrade.changed
|
||||
|
||||
post_tasks:
|
||||
- name: Display maintenance summary
|
||||
debug:
|
||||
msg: |
|
||||
Maintenance completed for {{ inventory_hostname }}
|
||||
Date: {{ ansible_date_time.iso8601 }}
|
||||
Reference in New Issue
Block a user