test0823

Young-Kyoo Kim·2025년 8월 22일
0
# service_status_check_complete.yml
# 이 파일을 엔트리포인트 플레이북에서 include_tasks로 호출하세요
# 예: - include_tasks: service_status_check_complete.yml

# ========================================
# Phase 1: Individual Host Service Checks
# ========================================

- name: Check if auditd service unit file exists
  stat:
    path: /usr/lib/systemd/system/auditd.service
  register: auditd_unit_file
  
- name: Check auditd service status only if unit exists
  systemd:
    name: auditd
  register: auditd_status
  failed_when: false
  when: auditd_unit_file.stat.exists
  
- name: Check if mlocate-updatedb.timer exists
  stat:
    path: /usr/lib/systemd/system/mlocate-updatedb.timer
  register: mlocate_timer_file
  
- name: Check mlocate updatedb timer status
  systemd:
    name: mlocate-updatedb.timer
  register: mlocate_timer_status
  failed_when: false
  when: mlocate_timer_file.stat.exists
  
- name: Check if updatedb.timer exists (alternative)
  stat:
    path: /usr/lib/systemd/system/updatedb.timer
  register: updatedb_timer_file
  
- name: Check updatedb timer status
  systemd:
    name: updatedb.timer
  register: updatedb_timer_status
  failed_when: false
  when: updatedb_timer_file.stat.exists and not mlocate_timer_file.stat.exists
  
- name: Check if mlocate package is installed
  package_facts:
    manager: rpm
  
- name: Check locate database paths
  stat:
    path: "{{ item }}"
  register: locate_db_paths
  loop:
    - /var/lib/mlocate/mlocate.db
    - /var/lib/locate/locatedb
    - /var/lib/slocate/slocate.db

- name: Check if chronyd service exists (RHEL 10 default)
  stat:
    path: /usr/lib/systemd/system/chronyd.service
  register: chronyd_unit_file
  
- name: Check chronyd service status
  systemd:
    name: chronyd
  register: chronyd_status
  failed_when: false
  when: chronyd_unit_file.stat.exists
  
- name: Check if ntpd service exists (legacy)
  stat:
    path: /usr/lib/systemd/system/ntpd.service
  register: ntpd_unit_file
  
- name: Check ntpd service status
  systemd:
    name: ntpd
  register: ntpd_status
  failed_when: false
  when: ntpd_unit_file.stat.exists

- name: Check if systemd-timesyncd service exists (alternative)
  stat:
    path: /usr/lib/systemd/system/systemd-timesyncd.service
  register: timesyncd_unit_file
  
- name: Check systemd-timesyncd service status
  systemd:
    name: systemd-timesyncd
  register: timesyncd_status
  failed_when: false
  when: timesyncd_unit_file.stat.exists

- name: Get current time and timezone
  setup:
    filter: ansible_date_time
  register: current_time_info

- name: Check NTP synchronization status (timedatectl)
  command: timedatectl status
  register: timedatectl_output
  failed_when: false

- name: Check chrony sources (if chronyd is running)
  command: chronyc sources -v
  register: chrony_sources
  failed_when: false
  when: chronyd_unit_file.stat.exists and chronyd_status.status is defined and chronyd_status.status.ActiveState == 'active'

- name: Get NTP server sync status from chrony
  command: chronyc tracking
  register: chrony_tracking
  failed_when: false
  when: chronyd_unit_file.stat.exists and chronyd_status.status is defined and chronyd_status.status.ActiveState == 'active'
    
- name: Analyze service status
  set_fact:
    node_result:
      hostname: "{{ inventory_hostname }}"
      os_info: "{{ ansible_distribution }} {{ ansible_distribution_version }}"
      current_time: "{{ current_time_info.ansible_facts.ansible_date_time.iso8601 }}"
      timezone: "{{ current_time_info.ansible_facts.ansible_date_time.tz }}"
      auditd:
        service_exists: "{{ auditd_unit_file.stat.exists }}"
        status: "{{ auditd_status.status.ActiveState if (auditd_unit_file.stat.exists and auditd_status.status is defined) else 'N/A' }}"
        enabled: "{{ auditd_status.status.UnitFileState if (auditd_unit_file.stat.exists and auditd_status.status is defined) else 'N/A' }}"
        running: "{{ auditd_status.status.ActiveState == 'active' if (auditd_unit_file.stat.exists and auditd_status.status is defined) else false }}"
      mlocate:
        package_installed: "{{ 'mlocate' in ansible_facts.packages or 'plocate' in ansible_facts.packages }}"
        timer_exists: "{{ mlocate_timer_file.stat.exists or updatedb_timer_file.stat.exists }}"
        timer_service: "{{ 'mlocate-updatedb.timer' if mlocate_timer_file.stat.exists else ('updatedb.timer' if updatedb_timer_file.stat.exists else 'none') }}"
        timer_status: "{{ mlocate_timer_status.status.ActiveState if mlocate_timer_status.status is defined else (updatedb_timer_status.status.ActiveState if updatedb_timer_status.status is defined else 'N/A') }}"
        timer_running: "{{ (mlocate_timer_status.status.ActiveState == 'active') if mlocate_timer_status.status is defined else ((updatedb_timer_status.status.ActiveState == 'active') if updatedb_timer_status.status is defined else false) }}"
        db_exists: "{{ locate_db_paths.results | selectattr('stat.exists', 'equalto', true) | list | length > 0 }}"
        db_path: "{{ (locate_db_paths.results | selectattr('stat.exists', 'equalto', true) | first).item if locate_db_paths.results | selectattr('stat.exists', 'equalto', true) | list | length > 0 else 'none' }}"
        db_size_mb: "{{ ((locate_db_paths.results | selectattr('stat.exists', 'equalto', true) | first).stat.size / 1024 / 1024) | round(2) if locate_db_paths.results | selectattr('stat.exists', 'equalto', true) | list | length > 0 else 0 }}"
      ntp:
        chronyd_exists: "{{ chronyd_unit_file.stat.exists }}"
        chronyd_status: "{{ chronyd_status.status.ActiveState if chronyd_status.status is defined else 'N/A' }}"
        chronyd_enabled: "{{ chronyd_status.status.UnitFileState if chronyd_status.status is defined else 'N/A' }}"
        chronyd_running: "{{ chronyd_status.status.ActiveState == 'active' if chronyd_status.status is defined else false }}"
        ntpd_exists: "{{ ntpd_unit_file.stat.exists }}"
        ntpd_status: "{{ ntpd_status.status.ActiveState if ntpd_status.status is defined else 'N/A' }}"
        ntpd_running: "{{ ntpd_status.status.ActiveState == 'active' if ntpd_status.status is defined else false }}"
        timesyncd_exists: "{{ timesyncd_unit_file.stat.exists }}"
        timesyncd_status: "{{ timesyncd_status.status.ActiveState if timesyncd_status.status is defined else 'N/A' }}"
        timesyncd_running: "{{ timesyncd_status.status.ActiveState == 'active' if timesyncd_status.status is defined else false }}"
        ntp_synchronized: "{{ 'NTP synchronized: yes' in timedatectl_output.stdout if timedatectl_output.stdout is defined else false }}"
        active_service: "{{ 'chronyd' if (chronyd_unit_file.stat.exists and chronyd_status.status is defined and chronyd_status.status.ActiveState == 'active') else ('ntpd' if (ntpd_unit_file.stat.exists and ntpd_status.status is defined and ntpd_status.status.ActiveState == 'active') else ('systemd-timesyncd' if (timesyncd_unit_file.stat.exists and timesyncd_status.status is defined and timesyncd_status.status.ActiveState == 'active') else 'none')) }}"
        chrony_sources: "{{ chrony_sources.stdout if chrony_sources.stdout is defined else 'N/A' }}"
        chrony_tracking: "{{ chrony_tracking.stdout if chrony_tracking.stdout is defined else 'N/A' }}"
        
- name: Display clear service status
  debug:
    msg: |
      
      ================================================
      HOST: {{ inventory_hostname }} ({{ ansible_distribution }} {{ ansible_distribution_version }})
      ================================================
      🕐 CURRENT TIME: {{ node_result.current_time }} ({{ node_result.timezone }})
      
      🔍 AUDITD SERVICE ANALYSIS:
      {% if node_result.auditd.service_exists %}
      ✅ Service Definition: FOUND (/usr/lib/systemd/system/auditd.service)
      {% if node_result.auditd.running %}
      ✅ Current Status: ACTIVE AND RUNNING
      {% else %}
      ❌ Current Status: {{ node_result.auditd.status | upper }} (NOT RUNNING)
      {% endif %}
      📋 Boot Status: {{ node_result.auditd.enabled | upper }}
      {% else %}
      ❌ Service Definition: NOT FOUND
      ❌ auditd is NOT INSTALLED on this system
      {% endif %}
      
      📍 MLOCATE/LOCATE SERVICE ANALYSIS:
      {% if node_result.mlocate.package_installed %}
      ✅ Package: INSTALLED (mlocate or plocate found)
      {% else %}
      ❌ Package: NOT INSTALLED
      {% endif %}
      
      {% if node_result.mlocate.timer_exists %}
      ✅ Timer Service: FOUND ({{ node_result.mlocate.timer_service }})
      {% if node_result.mlocate.timer_running %}
      ✅ Timer Status: ACTIVE AND RUNNING
      {% else %}
      ❌ Timer Status: {{ node_result.mlocate.timer_status | upper }} (NOT RUNNING)
      {% endif %}
      {% else %}
      ❌ Timer Service: NOT FOUND
      {% endif %}
      
      {% if node_result.mlocate.db_exists %}
      ✅ Locate Database: FOUND
      📁 Path: {{ node_result.mlocate.db_path }}
      📏 Size: {{ node_result.mlocate.db_size_mb }}MB
      {% else %}
      ❌ Locate Database: NOT FOUND
      {% endif %}
      
      🕐 NTP/TIME SYNCHRONIZATION ANALYSIS:
      {% if node_result.ntp.active_service != 'none' %}
      ✅ Active Time Service: {{ node_result.ntp.active_service | upper }}
      {% if node_result.ntp.ntp_synchronized %}
      ✅ NTP Synchronization: SYNCHRONIZED
      {% else %}
      ⚠️  NTP Synchronization: NOT SYNCHRONIZED
      {% endif %}
      {% else %}
      ❌ No Active Time Service Found
      {% endif %}
      
      📊 Time Services Status:
      {% if node_result.ntp.chronyd_exists %}
      ├─ chronyd: {{ '✅ RUNNING' if node_result.ntp.chronyd_running else ('❌ ' + node_result.ntp.chronyd_status) }} ({{ node_result.ntp.chronyd_enabled }})
      {% endif %}
      {% if node_result.ntp.ntpd_exists %}
      ├─ ntpd: {{ '✅ RUNNING' if node_result.ntp.ntpd_running else ('❌ ' + node_result.ntp.ntpd_status) }}
      {% endif %}
      {% if node_result.ntp.timesyncd_exists %}
      └─ systemd-timesyncd: {{ '✅ RUNNING' if node_result.ntp.timesyncd_running else ('❌ ' + node_result.ntp.timesyncd_status) }}
      {% endif %}
      
      🎯 SUMMARY:
      {% if node_result.auditd.service_exists and node_result.auditd.running %}
      ✅ auditd: FULLY OPERATIONAL
      {% elif node_result.auditd.service_exists %}
      ⚠️  auditd: INSTALLED BUT NOT RUNNING
      {% else %}
      ❌ auditd: NOT INSTALLED
      {% endif %}
      
      {% if node_result.mlocate.package_installed and node_result.mlocate.timer_running and node_result.mlocate.db_exists %}
      ✅ mlocate: FULLY OPERATIONAL
      {% elif node_result.mlocate.package_installed %}
      ⚠️  mlocate: INSTALLED BUT NOT FULLY FUNCTIONAL
      {% else %}
      ❌ mlocate: NOT INSTALLED
      {% endif %}
      
      {% if node_result.ntp.active_service != 'none' and node_result.ntp.ntp_synchronized %}
      ✅ NTP: FULLY OPERATIONAL ({{ node_result.ntp.active_service }})
      {% elif node_result.ntp.active_service != 'none' %}
      ⚠️  NTP: SERVICE RUNNING BUT NOT SYNCHRONIZED ({{ node_result.ntp.active_service }})
      {% else %}
      ❌ NTP: NO TIME SERVICE RUNNING
      {% endif %}

- name: Save individual host result to temp file
  copy:
    content: "{{ node_result | to_nice_json }}"
    dest: "/tmp/service_results_{{ inventory_hostname }}.json"
  delegate_to: localhost

# ========================================
# Phase 2: Generate Summary Report (run_once)
# ========================================

- name: Find all result files
  find:
    paths: /tmp
    patterns: "service_results_*.json"
  register: result_files
  delegate_to: localhost
  run_once: true
  
- name: Read all result files
  slurp:
    src: "{{ item.path }}"
  register: file_contents
  loop: "{{ result_files.files }}"
  delegate_to: localhost
  run_once: true
  
- name: Combine all results
  set_fact:
    service_check_results: "{{ service_check_results | default([]) + [item.content | b64decode | from_json] }}"
  loop: "{{ file_contents.results }}"
  delegate_to: localhost
  run_once: true
  
- name: Clean up temporary files
  file:
    path: "{{ item.path }}"
    state: absent
  loop: "{{ result_files.files }}"
  delegate_to: localhost
  run_once: true
  
- name: Calculate statistics step by step
  set_fact:
    total_nodes: "{{ service_check_results | length }}"
  delegate_to: localhost
  run_once: true
    
- name: Calculate auditd statistics
  set_fact:
    auditd_installed_list: "{{ service_check_results | selectattr('auditd.service_exists', 'equalto', true) | list }}"
    auditd_running_list: "{{ service_check_results | selectattr('auditd.running', 'equalto', true) | list }}"
  delegate_to: localhost
  run_once: true
    
- name: Calculate mlocate statistics
  set_fact:
    mlocate_installed_list: "{{ service_check_results | selectattr('mlocate.package_installed', 'equalto', true) | list }}"
  delegate_to: localhost
  run_once: true
    
- name: Calculate mlocate functional nodes
  set_fact:
    mlocate_functional_list: "{{ mlocate_installed_list | selectattr('mlocate.timer_running', 'equalto', true) | selectattr('mlocate.db_exists', 'equalto', true) | list }}"
  delegate_to: localhost
  run_once: true

- name: Calculate NTP statistics
  set_fact:
    ntp_service_running_list: "{{ service_check_results | selectattr('ntp.active_service', 'ne', 'none') | list }}"
    ntp_synchronized_list: "{{ service_check_results | selectattr('ntp.ntp_synchronized', 'equalto', true) | list }}"
  delegate_to: localhost
  run_once: true

- name: Calculate time differences from first node
  set_fact:
    time_reference: "{{ service_check_results[0].current_time }}"
  delegate_to: localhost
  run_once: true

- name: Parse times and calculate differences
  set_fact:
    time_analysis: |
      {% set ref_time = time_reference | to_datetime('%Y-%m-%dT%H:%M:%S%z') %}
      {% for node in service_check_results %}
      {% set node_time = node.current_time | to_datetime('%Y-%m-%dT%H:%M:%S%z') %}
      {% set diff_seconds = ((node_time - ref_time).total_seconds()) %}
      {{ node.hostname }}:{{ diff_seconds | round(2) }},
      {% endfor %}
  delegate_to: localhost
  run_once: true
    
- name: Set final statistics
  set_fact:
    auditd_installed: "{{ auditd_installed_list | length }}"
    auditd_running: "{{ auditd_running_list | length }}"
    mlocate_installed: "{{ mlocate_installed_list | length }}"
    mlocate_functional: "{{ mlocate_functional_list | length }}"
    ntp_service_running: "{{ ntp_service_running_list | length }}"
    ntp_synchronized: "{{ ntp_synchronized_list | length }}"
  delegate_to: localhost
  run_once: true
    
- name: Get problem nodes
  set_fact:
    auditd_missing_nodes: "{{ service_check_results | selectattr('auditd.service_exists', 'equalto', false) | map(attribute='hostname') | list }}"
    mlocate_missing_nodes: "{{ service_check_results | selectattr('mlocate.package_installed', 'equalto', false) | map(attribute='hostname') | list }}"
    ntp_missing_nodes: "{{ service_check_results | selectattr('ntp.active_service', 'equalto', 'none') | map(attribute='hostname') | list }}"
    ntp_unsync_nodes: "{{ service_check_results | selectattr('ntp.ntp_synchronized', 'equalto', false) | map(attribute='hostname') | list }}"
  delegate_to: localhost
  run_once: true
    
- name: Display final summary
  debug:
    msg: |
      
      ================================================
      📊 OVERALL SUMMARY REPORT
      ================================================
      
      Total Nodes Analyzed: {{ total_nodes }}
      
      🔍 AUDITD SERVICE:
      ├─ Installed: {{ auditd_installed }}/{{ total_nodes }} nodes ({{ ((auditd_installed | int / total_nodes | int) * 100) | round(1) }}%)
      ├─ Running: {{ auditd_running }}/{{ total_nodes }} nodes ({{ ((auditd_running | int / total_nodes | int) * 100) | round(1) }}%)
      └─ Issues: {% if auditd_missing_nodes %}{{ auditd_missing_nodes | join(', ') }}{% else %}None{% endif %}
      
      📍 MLOCATE SERVICE:
      ├─ Installed: {{ mlocate_installed }}/{{ total_nodes }} nodes ({{ ((mlocate_installed | int / total_nodes | int) * 100) | round(1) }}%)
      ├─ Fully Functional: {{ mlocate_functional }}/{{ total_nodes }} nodes ({{ ((mlocate_functional | int / total_nodes | int) * 100) | round(1) }}%)
      └─ Issues: {% if mlocate_missing_nodes %}{{ mlocate_missing_nodes | join(', ') }}{% else %}None{% endif %}
      
      🕐 NTP/TIME SYNCHRONIZATION:
      ├─ Service Running: {{ ntp_service_running }}/{{ total_nodes }} nodes ({{ ((ntp_service_running | int / total_nodes | int) * 100) | round(1) }}%)
      ├─ NTP Synchronized: {{ ntp_synchronized }}/{{ total_nodes }} nodes ({{ ((ntp_synchronized | int / total_nodes | int) * 100) | round(1) }}%)
      ├─ No Time Service: {% if ntp_missing_nodes %}{{ ntp_missing_nodes | join(', ') }}{% else %}None{% endif %}
      └─ Not Synchronized: {% if ntp_unsync_nodes %}{{ ntp_unsync_nodes | join(', ') }}{% else %}None{% endif %}
      
      ⏰ TIME DIFFERENCES FROM REFERENCE ({{ service_check_results[0].hostname }}):
      {% for node in service_check_results %}
      {% if loop.index0 == 0 %}
      ├─ {{ node.hostname }}: 0.00s (Reference Node)
      {% else %}
      {% set ref_time = service_check_results[0].current_time | to_datetime('%Y-%m-%dT%H:%M:%SZ') %}
      {% set node_time = node.current_time | to_datetime('%Y-%m-%dT%H:%M:%SZ') %}
      {% set diff_seconds = (node_time - ref_time).total_seconds() %}
      {% if diff_seconds | abs > 30 %}
      ├─ {{ node.hostname }}: {{ diff_seconds | round(2) }}s ⚠️  SIGNIFICANT DRIFT
      {% elif diff_seconds | abs > 5 %}
      ├─ {{ node.hostname }}: {{ diff_seconds | round(2) }}s ⚠️  MINOR DRIFT  
      {% else %}
      ├─ {{ node.hostname }}: {{ diff_seconds | round(2) }}s ✅ OK
      {% endif %}
      {% endif %}
      {% endfor %}
  delegate_to: localhost
  run_once: true
      
- name: Display auditd issues if any
  debug:
    msg: |
      
      ⚠️  AUDITD ISSUES DETECTED:
      {% for node in service_check_results %}
      {% if not node.auditd.service_exists %}
      ❌ {{ node.hostname }}: auditd NOT INSTALLED
      {% elif not node.auditd.running %}
      ⚠️  {{ node.hostname }}: auditd installed but {{ node.auditd.status }}
      {% endif %}
      {% endfor %}
  when: auditd_running | int < total_nodes | int
  delegate_to: localhost
  run_once: true
  
- name: Display mlocate issues if any
  debug:
    msg: |
      
      ⚠️  MLOCATE ISSUES DETECTED:
      {% for node in service_check_results %}
      {% if node.mlocate.package_installed and not (node.mlocate.timer_running and node.mlocate.db_exists) %}
      ⚠️  {{ node.hostname }}: mlocate installed but timer={{ node.mlocate.timer_status }}, db={{ 'exists' if node.mlocate.db_exists else 'missing' }}
      {% endif %}
      {% endfor %}
- name: Display NTP/Time issues if any
  debug:
    msg: |
      
      ⚠️  NTP/TIME SYNCHRONIZATION ISSUES DETECTED:
      {% for node in service_check_results %}
      {% if node.ntp.active_service == 'none' %}
      ❌ {{ node.hostname }}: NO TIME SERVICE RUNNING
      {% elif not node.ntp.ntp_synchronized %}
      ⚠️  {{ node.hostname }}: {{ node.ntp.active_service }} running but NOT SYNCHRONIZED
      {% endif %}
      {% endfor %}
  when: ntp_service_running | int < total_nodes | int or ntp_synchronized | int < ntp_service_running | int
  delegate_to: localhost
  run_once: true: localhost
  run_once: true
      
- name: Generate clear status report
  copy:
    content: |
      Hostname,OS,Current_Time,Timezone,Time_Diff_Seconds,auditd_Installed,auditd_Running,auditd_Status,mlocate_Installed,mlocate_Timer_Running,mlocate_DB_Exists,NTP_Service_Running,NTP_Synchronized,NTP_Active_Service,chronyd_Status,ntpd_Status,timesyncd_Status,Overall_auditd,Overall_mlocate,Overall_NTP
      {% for node in service_check_results -%}
      {% if loop.index0 == 0 -%}
      {% set time_diff = 0.0 -%}
      {% else -%}
      {% set ref_time = service_check_results[0].current_time | to_datetime('%Y-%m-%dT%H:%M:%SZ') -%}
      {% set node_time = node.current_time | to_datetime('%Y-%m-%dT%H:%M:%SZ') -%}
      {% set time_diff = (node_time - ref_time).total_seconds() -%}
      {% endif -%}
      {{ node.hostname }},{{ node.os_info }},{{ node.current_time }},{{ node.timezone }},{{ time_diff | round(2) }},{{ node.auditd.service_exists }},{{ node.auditd.running }},{{ node.auditd.status }},{{ node.mlocate.package_installed }},{{ node.mlocate.timer_running }},{{ node.mlocate.db_exists }},{{ 'YES' if node.ntp.active_service != 'none' else 'NO' }},{{ node.ntp.ntp_synchronized }},{{ node.ntp.active_service }},{{ node.ntp.chronyd_status }},{{ node.ntp.ntpd_status }},{{ node.ntp.timesyncd_Status }},{{ 'OK' if node.auditd.running else ('INSTALLED' if node.auditd.service_exists else 'MISSING') }},{{ 'OK' if (node.mlocate.package_installed and node.mlocate.timer_running and node.mlocate.db_exists) else ('PARTIAL' if node.mlocate.package_installed else 'MISSING') }},{{ 'OK' if (node.ntp.active_service != 'none' and node.ntp.ntp_synchronized) else ('PARTIAL' if node.ntp.active_service != 'none' else 'MISSING') }}
      {% endfor %}
    dest: "./clear_service_status.csv"
  delegate_to: localhost
  run_once: true

- name: Generate time synchronization detailed report
  copy:
    content: |
      Hostname,Current_Time,Timezone,Time_Diff_From_Reference,Time_Status,NTP_Service,NTP_Synchronized,chronyd_Running,ntpd_Running,timesyncd_Running,Chrony_Sources,Chrony_Tracking
      {% for node in service_check_results -%}
      {% if loop.index0 == 0 -%}
      {% set time_diff = 0.0 -%}
      {% set time_status = "REFERENCE" -%}
      {% else -%}
      {% set ref_time = service_check_results[0].current_time | to_datetime('%Y-%m-%dT%H:%M:%SZ') -%}
      {% set node_time = node.current_time | to_datetime('%Y-%m-%dT%H:%M:%SZ') -%}
      {% set time_diff = (node_time - ref_time).total_seconds() -%}
      {% if time_diff | abs > 30 -%}
      {% set time_status = "SIGNIFICANT_DRIFT" -%}
      {% elif time_diff | abs > 5 -%}
      {% set time_status = "MINOR_DRIFT" -%}
      {% else -%}
      {% set time_status = "OK" -%}
      {% endif -%}
      {% endif -%}
      {{ node.hostname }},{{ node.current_time }},{{ node.timezone }},{{ time_diff | round(2) }},{{ time_status }},{{ node.ntp.active_service }},{{ node.ntp.ntp_synchronized }},{{ node.ntp.chronyd_running }},{{ node.ntp.ntpd_running }},{{ node.ntp.timesyncd_running }},"{{ node.ntp.chrony_sources | replace('\n', ' | ') | replace('"', '""') }}","{{ node.ntp.chrony_tracking | replace('\n', ' | ') | replace('"', '""') }}"
      {% endfor %}
    dest: "./time_sync_detailed_report.csv"
  delegate_to: localhost
  run_once: true
    
- name: Display action recommendations
  debug:
    msg: |
      
      ================================================
      🔧 RECOMMENDED ACTIONS
      ================================================
      
      {% if auditd_installed < total_nodes %}
      📥 Install auditd on missing nodes:
      sudo yum install audit (RHEL/CentOS)
      {% endif %}
      
      {% if auditd_running < auditd_installed %}
      🚀 Start auditd service on inactive nodes:
      sudo systemctl start auditd
      sudo systemctl enable auditd
      {% endif %}
      
      {% if mlocate_installed < total_nodes %}
      📥 Install mlocate on missing nodes:
      sudo yum install mlocate (RHEL/CentOS)
      {% endif %}
      
      {% if mlocate_functional < mlocate_installed %}
      🚀 Fix mlocate issues:
      sudo systemctl start mlocate-updatedb.timer
      sudo systemctl enable mlocate-updatedb.timer
      sudo updatedb  # Manual database update
      {% endif %}
      
      {% if ntp_service_running < total_nodes %}
      📥 Install and configure NTP service on missing nodes:
      # For RHEL 10 (recommended):
      sudo yum install chrony
      sudo systemctl start chronyd
      sudo systemctl enable chronyd
      
      # Alternative options:
      sudo yum install ntp  # Legacy ntpd
      sudo yum install systemd-timesyncd  # Minimal option
      {% endif %}
      
      {% if ntp_synchronized < ntp_service_running %}
      🚀 Fix NTP synchronization issues:
      # Check NTP configuration:
      sudo timedatectl status
      sudo chronyc sources -v  # For chronyd
      sudo chronyc tracking     # For chronyd
      
      # Force time synchronization:
      sudo chrony -q 'server pool.ntp.org iburst'
      sudo systemctl restart chronyd
      {% endif %}
      
      {% if ntp_unsync_nodes %}
      ⚠️  Time drift detected on nodes: {{ ntp_unsync_nodes | join(', ') }}
      Consider checking network connectivity to NTP servers and firewall settings.
      {% endif %}
      
      📄 Reports generated:
      - ./clear_service_status.csv (Complete service status)
      - ./time_sync_detailed_report.csv (Detailed time sync analysis)
  delegate_to: localhost
  run_once: true

0개의 댓글