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)
|
||||
Reference in New Issue
Block a user