312 lines
12 KiB
YAML
312 lines
12 KiB
YAML
---
|
|
# Disk Usage Report Playbook
|
|
# Monitor storage usage across all hosts and generate comprehensive reports
|
|
# Usage: ansible-playbook playbooks/disk_usage_report.yml
|
|
# Usage: ansible-playbook playbooks/disk_usage_report.yml -e "alert_threshold=80"
|
|
# Usage: ansible-playbook playbooks/disk_usage_report.yml -e "detailed_analysis=true"
|
|
|
|
- name: Generate Comprehensive Disk Usage Report
|
|
hosts: "{{ host_target | default('all') }}"
|
|
gather_facts: yes
|
|
vars:
|
|
alert_threshold: "{{ alert_threshold | default(85) }}"
|
|
warning_threshold: "{{ warning_threshold | default(75) }}"
|
|
detailed_analysis: "{{ detailed_analysis | default(false) }}"
|
|
report_dir: "/tmp/disk_reports"
|
|
include_docker_analysis: "{{ include_docker_analysis | default(true) }}"
|
|
top_directories_count: "{{ top_directories_count | default(10) }}"
|
|
|
|
tasks:
|
|
- name: Create report directory
|
|
file:
|
|
path: "{{ report_dir }}/{{ ansible_date_time.date }}"
|
|
state: directory
|
|
mode: '0755'
|
|
delegate_to: localhost
|
|
|
|
- name: Get basic disk usage
|
|
shell: df -h
|
|
register: disk_usage_basic
|
|
changed_when: false
|
|
|
|
- name: Get disk usage percentages
|
|
shell: df --output=source,pcent,avail,target | grep -v "Filesystem"
|
|
register: disk_usage_percent
|
|
changed_when: false
|
|
|
|
- name: Identify high usage filesystems
|
|
shell: |
|
|
df --output=source,pcent,target | awk 'NR>1 {gsub(/%/, "", $2); if ($2 >= {{ alert_threshold }}) print $0}'
|
|
register: high_usage_filesystems
|
|
changed_when: false
|
|
|
|
- name: Get inode usage
|
|
shell: df -i
|
|
register: inode_usage
|
|
changed_when: false
|
|
|
|
- name: Analyze Docker storage usage
|
|
shell: |
|
|
echo "=== DOCKER STORAGE ANALYSIS ==="
|
|
if command -v docker &> /dev/null; then
|
|
echo "Docker System Usage:"
|
|
docker system df 2>/dev/null || echo "Cannot access Docker"
|
|
echo ""
|
|
|
|
echo "Container Sizes:"
|
|
docker ps --format "table {{.Names}}\t{{.Size}}" 2>/dev/null || echo "Cannot access Docker containers"
|
|
echo ""
|
|
|
|
echo "Image Sizes:"
|
|
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" 2>/dev/null | head -20 || echo "Cannot access Docker images"
|
|
echo ""
|
|
|
|
echo "Volume Usage:"
|
|
docker volume ls -q | xargs -I {} sh -c 'echo "Volume: {}"; docker volume inspect {} --format "{{.Mountpoint}}" | xargs du -sh 2>/dev/null || echo "Cannot access volume"' 2>/dev/null || echo "Cannot access Docker volumes"
|
|
else
|
|
echo "Docker not available"
|
|
fi
|
|
register: docker_storage_analysis
|
|
when: include_docker_analysis | bool
|
|
changed_when: false
|
|
|
|
- name: Find largest directories
|
|
shell: |
|
|
echo "=== TOP {{ top_directories_count }} LARGEST DIRECTORIES ==="
|
|
|
|
# Find largest directories in common locations
|
|
for path in / /var /opt /home /volume1 /volume2; do
|
|
if [ -d "$path" ]; then
|
|
echo "=== $path ==="
|
|
du -h "$path"/* 2>/dev/null | sort -hr | head -{{ top_directories_count }} || echo "Cannot analyze $path"
|
|
echo ""
|
|
fi
|
|
done
|
|
register: largest_directories
|
|
when: detailed_analysis | bool
|
|
changed_when: false
|
|
|
|
- name: Analyze log file sizes
|
|
shell: |
|
|
echo "=== LOG FILE ANALYSIS ==="
|
|
|
|
# System logs
|
|
echo "System Logs:"
|
|
find /var/log -type f -name "*.log" -exec du -h {} \; 2>/dev/null | sort -hr | head -10 || echo "Cannot access system logs"
|
|
echo ""
|
|
|
|
# Docker logs
|
|
echo "Docker Container Logs:"
|
|
if [ -d "/var/lib/docker/containers" ]; then
|
|
find /var/lib/docker/containers -name "*-json.log" -exec du -h {} \; 2>/dev/null | sort -hr | head -10 || echo "Cannot access Docker logs"
|
|
fi
|
|
echo ""
|
|
|
|
# Application logs
|
|
echo "Application Logs:"
|
|
find /volume1 /opt -name "*.log" -type f -exec du -h {} \; 2>/dev/null | sort -hr | head -10 || echo "No application logs found"
|
|
register: log_analysis
|
|
when: detailed_analysis | bool
|
|
changed_when: false
|
|
|
|
- name: Check for large files
|
|
shell: |
|
|
echo "=== LARGE FILES (>1GB) ==="
|
|
find / -type f -size +1G -exec du -h {} \; 2>/dev/null | sort -hr | head -20 || echo "No large files found or permission denied"
|
|
register: large_files
|
|
when: detailed_analysis | bool
|
|
changed_when: false
|
|
|
|
- name: Analyze temporary files
|
|
shell: |
|
|
echo "=== TEMPORARY FILES ANALYSIS ==="
|
|
|
|
for temp_dir in /tmp /var/tmp /volume1/tmp; do
|
|
if [ -d "$temp_dir" ]; then
|
|
echo "=== $temp_dir ==="
|
|
du -sh "$temp_dir" 2>/dev/null || echo "Cannot access $temp_dir"
|
|
echo "File count: $(find "$temp_dir" -type f 2>/dev/null | wc -l)"
|
|
echo "Oldest file: $(find "$temp_dir" -type f -printf '%T+ %p\n' 2>/dev/null | sort | head -1 | cut -d' ' -f2- || echo 'None')"
|
|
echo ""
|
|
fi
|
|
done
|
|
register: temp_files_analysis
|
|
changed_when: false
|
|
|
|
- name: Generate disk usage alerts
|
|
set_fact:
|
|
disk_alerts: []
|
|
disk_warnings: []
|
|
|
|
- name: Process disk usage alerts
|
|
set_fact:
|
|
disk_alerts: "{{ disk_alerts + [item] }}"
|
|
loop: "{{ disk_usage_percent.stdout_lines }}"
|
|
when:
|
|
- item.split()[1] | regex_replace('%', '') | int >= alert_threshold | int
|
|
vars:
|
|
usage_percent: "{{ item.split()[1] | regex_replace('%', '') | int }}"
|
|
|
|
- name: Process disk usage warnings
|
|
set_fact:
|
|
disk_warnings: "{{ disk_warnings + [item] }}"
|
|
loop: "{{ disk_usage_percent.stdout_lines }}"
|
|
when:
|
|
- item.split()[1] | regex_replace('%', '') | int >= warning_threshold | int
|
|
- item.split()[1] | regex_replace('%', '') | int < alert_threshold | int
|
|
|
|
- name: Create comprehensive report
|
|
copy:
|
|
content: |
|
|
📊 DISK USAGE REPORT - {{ inventory_hostname }}
|
|
=============================================
|
|
|
|
📅 Generated: {{ ansible_date_time.iso8601 }}
|
|
🖥️ Host: {{ inventory_hostname }}
|
|
💿 OS: {{ ansible_distribution }} {{ ansible_distribution_version }}
|
|
⚠️ Alert Threshold: {{ alert_threshold }}%
|
|
⚡ Warning Threshold: {{ warning_threshold }}%
|
|
|
|
🚨 CRITICAL ALERTS (>={{ alert_threshold }}%):
|
|
{% if disk_alerts | length > 0 %}
|
|
{% for alert in disk_alerts %}
|
|
❌ {{ alert }}
|
|
{% endfor %}
|
|
{% else %}
|
|
✅ No critical disk usage alerts
|
|
{% endif %}
|
|
|
|
⚠️ WARNINGS (>={{ warning_threshold }}%):
|
|
{% if disk_warnings | length > 0 %}
|
|
{% for warning in disk_warnings %}
|
|
🟡 {{ warning }}
|
|
{% endfor %}
|
|
{% else %}
|
|
✅ No disk usage warnings
|
|
{% endif %}
|
|
|
|
💾 FILESYSTEM USAGE:
|
|
{{ disk_usage_basic.stdout }}
|
|
|
|
📁 INODE USAGE:
|
|
{{ inode_usage.stdout }}
|
|
|
|
🧹 TEMPORARY FILES:
|
|
{{ temp_files_analysis.stdout }}
|
|
|
|
{% if include_docker_analysis and docker_storage_analysis.stdout is defined %}
|
|
🐳 DOCKER STORAGE:
|
|
{{ docker_storage_analysis.stdout }}
|
|
{% endif %}
|
|
|
|
{% if detailed_analysis %}
|
|
{% if largest_directories.stdout is defined %}
|
|
📂 LARGEST DIRECTORIES:
|
|
{{ largest_directories.stdout }}
|
|
{% endif %}
|
|
|
|
{% if log_analysis.stdout is defined %}
|
|
📝 LOG FILES:
|
|
{{ log_analysis.stdout }}
|
|
{% endif %}
|
|
|
|
{% if large_files.stdout is defined %}
|
|
📦 LARGE FILES:
|
|
{{ large_files.stdout }}
|
|
{% endif %}
|
|
{% endif %}
|
|
|
|
💡 RECOMMENDATIONS:
|
|
{% if disk_alerts | length > 0 %}
|
|
- 🚨 IMMEDIATE ACTION REQUIRED: Clean up filesystems above {{ alert_threshold }}%
|
|
{% endif %}
|
|
{% if disk_warnings | length > 0 %}
|
|
- ⚠️ Monitor filesystems above {{ warning_threshold }}%
|
|
{% endif %}
|
|
- 🧹 Run cleanup playbook: ansible-playbook playbooks/cleanup_old_backups.yml
|
|
- 🐳 Prune Docker: ansible-playbook playbooks/prune_containers.yml
|
|
- 📝 Rotate logs: ansible-playbook playbooks/log_rotation.yml
|
|
- 🗑️ Clean temp files: find /tmp -type f -mtime +7 -delete
|
|
|
|
📊 SUMMARY:
|
|
- Total Filesystems: {{ disk_usage_percent.stdout_lines | length }}
|
|
- Critical Alerts: {{ disk_alerts | length }}
|
|
- Warnings: {{ disk_warnings | length }}
|
|
- Docker Analysis: {{ 'Included' if include_docker_analysis else 'Skipped' }}
|
|
- Detailed Analysis: {{ 'Included' if detailed_analysis else 'Skipped' }}
|
|
|
|
dest: "{{ report_dir }}/{{ ansible_date_time.date }}/{{ inventory_hostname }}_disk_report.txt"
|
|
delegate_to: localhost
|
|
|
|
- name: Create JSON report for automation
|
|
copy:
|
|
content: |
|
|
{
|
|
"timestamp": "{{ ansible_date_time.iso8601 }}",
|
|
"hostname": "{{ inventory_hostname }}",
|
|
"thresholds": {
|
|
"alert": {{ alert_threshold }},
|
|
"warning": {{ warning_threshold }}
|
|
},
|
|
"alerts": {{ disk_alerts | to_json }},
|
|
"warnings": {{ disk_warnings | to_json }},
|
|
"filesystems": {{ disk_usage_percent.stdout_lines | to_json }},
|
|
"summary": {
|
|
"total_filesystems": {{ disk_usage_percent.stdout_lines | length }},
|
|
"critical_count": {{ disk_alerts | length }},
|
|
"warning_count": {{ disk_warnings | length }},
|
|
"status": "{% if disk_alerts | length > 0 %}CRITICAL{% elif disk_warnings | length > 0 %}WARNING{% else %}OK{% endif %}"
|
|
}
|
|
}
|
|
dest: "{{ report_dir }}/{{ ansible_date_time.date }}/{{ inventory_hostname }}_disk_report.json"
|
|
delegate_to: localhost
|
|
|
|
- name: Display summary
|
|
debug:
|
|
msg: |
|
|
|
|
📊 DISK USAGE REPORT COMPLETE - {{ inventory_hostname }}
|
|
================================================
|
|
|
|
{% if disk_alerts | length > 0 %}
|
|
🚨 CRITICAL ALERTS: {{ disk_alerts | length }}
|
|
{% for alert in disk_alerts %}
|
|
❌ {{ alert }}
|
|
{% endfor %}
|
|
{% endif %}
|
|
|
|
{% if disk_warnings | length > 0 %}
|
|
⚠️ WARNINGS: {{ disk_warnings | length }}
|
|
{% for warning in disk_warnings %}
|
|
🟡 {{ warning }}
|
|
{% endfor %}
|
|
{% endif %}
|
|
|
|
{% if disk_alerts | length == 0 and disk_warnings | length == 0 %}
|
|
✅ All filesystems within normal usage levels
|
|
{% endif %}
|
|
|
|
📄 Reports saved to:
|
|
- {{ report_dir }}/{{ ansible_date_time.date }}/{{ inventory_hostname }}_disk_report.txt
|
|
- {{ report_dir }}/{{ ansible_date_time.date }}/{{ inventory_hostname }}_disk_report.json
|
|
|
|
🔍 Next Steps:
|
|
{% if disk_alerts | length > 0 %}
|
|
- Run cleanup: ansible-playbook playbooks/cleanup_old_backups.yml
|
|
- Prune Docker: ansible-playbook playbooks/prune_containers.yml
|
|
{% endif %}
|
|
- Schedule regular monitoring via cron
|
|
|
|
================================================
|
|
|
|
- name: Send alert if critical usage detected
|
|
debug:
|
|
msg: |
|
|
🚨 CRITICAL DISK USAGE ALERT 🚨
|
|
Host: {{ inventory_hostname }}
|
|
Critical filesystems: {{ disk_alerts | length }}
|
|
Immediate action required!
|
|
when:
|
|
- disk_alerts | length > 0
|
|
- send_alerts | default(false) | bool
|