385 lines
15 KiB
YAML
385 lines
15 KiB
YAML
---
|
|
- name: Deploy WiFi debug (single device, linear)
|
|
hosts: all
|
|
gather_facts: no
|
|
|
|
vars:
|
|
remote_syslog_ip: "102.38.125.161"
|
|
|
|
ssh_user: "{{ ansible_user | default('root') }}"
|
|
ssh_pass: "{{ ansible_password | default(ansible_ssh_pass) }}"
|
|
|
|
# RabbitMQ (from env with defaults)
|
|
rmq_host: "{{ lookup('env','RMQ_HOST') | default('10.210.12.2', true) }}"
|
|
rmq_port: "{{ lookup('env','RMQ_PORT') | default('15672', true) }}"
|
|
rmq_user: "{{ lookup('env','RMQ_USER') | default('admin', true) }}"
|
|
rmq_pass: "{{ lookup('env','RMQ_PASS') | default('change_me', true) }}"
|
|
rmq_vhost: "{{ lookup('env','RMQ_VHOST') | default('app', true) }}"
|
|
rmq_exchange: "{{ lookup('env','RMQ_EXCHANGE') | default('amq.default', true) }}"
|
|
queue2_name: "{{ lookup('env','QUEUE2') | default('queue2', true) }}"
|
|
|
|
tasks:
|
|
|
|
- block:
|
|
|
|
# --- SSH reachability check ---
|
|
- name: Check SSH connectivity (raw ping)
|
|
raw: "echo ping"
|
|
register: ping_result
|
|
ignore_errors: true
|
|
|
|
- block:
|
|
|
|
############ step 1
|
|
|
|
- name: Check if crontab launch is already present in sysstart.lua
|
|
raw: |
|
|
grep -F 'crontabs -f -l 8' /usr/share/config/sysstart.lua >/dev/null 2>&1 && echo PRESENT || echo ABSENT
|
|
register: sysstart_cron_check
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Announce presence and skip edits
|
|
when: (sysstart_cron_check.stdout | trim) == 'PRESENT'
|
|
debug:
|
|
msg: "crontab is present in sysstart.lua; skipping download/edit/upload."
|
|
|
|
- name: Fetch sysstart.lua via scp (password auth)
|
|
when: (sysstart_cron_check.stdout | trim) != 'PRESENT'
|
|
delegate_to: localhost
|
|
command: >
|
|
sshpass -p {{ ssh_pass | quote }}
|
|
scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
|
|
{{ ssh_user }}@{{ ansible_host }}:/usr/share/config/sysstart.lua
|
|
/tmp/{{ inventory_hostname }}_sysstart.lua
|
|
register: scp_get
|
|
retries: 3
|
|
delay: 2
|
|
until: scp_get.rc == 0
|
|
|
|
- name: Edit the file locally
|
|
when: (sysstart_cron_check.stdout | trim) != 'PRESENT'
|
|
delegate_to: localhost
|
|
lineinfile:
|
|
path: "/tmp/{{ inventory_hostname }}_sysstart.lua"
|
|
line: 'launchd.set_process("crontab", "crond -c /etc/crontabs -f -l 8")'
|
|
insertbefore: '^tasks\.start\(ctx,\s*"finished"\)'
|
|
|
|
- name: Push the file back (write to -2)
|
|
when: (sysstart_cron_check.stdout | trim) != 'PRESENT'
|
|
delegate_to: localhost
|
|
command: >
|
|
sshpass -p {{ ssh_pass | quote }}
|
|
scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
|
|
/tmp/{{ inventory_hostname }}_sysstart.lua
|
|
{{ ssh_user }}@{{ ansible_host }}:/usr/share/config/sysstart.lua
|
|
register: scp_put
|
|
retries: 3
|
|
delay: 2
|
|
until: scp_put.rc == 0
|
|
|
|
############ step 2
|
|
|
|
- name: Compute MD5 of local wifidebug.sh
|
|
delegate_to: localhost
|
|
command: md5sum files/wifidebug.sh
|
|
register: md5_local_wdbg
|
|
changed_when: false
|
|
|
|
- name: Compute MD5 of remote /root/wifidebug.sh
|
|
raw: "md5sum /root/wifidebug.sh || busybox md5sum /root/wifidebug.sh"
|
|
register: md5_remote_wdbg
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Decide if wifidebug.sh needs upload
|
|
set_fact:
|
|
upload_wdbg: >-
|
|
{{ (md5_remote_wdbg.rc != 0)
|
|
or ((md5_local_wdbg.stdout.split()[0])
|
|
!= (md5_remote_wdbg.stdout.split()[0] if (md5_remote_wdbg.stdout is defined) else '')) }}
|
|
|
|
- name: Upload wifidebug.sh via scp (overwrite if changed)
|
|
when: upload_wdbg | bool
|
|
delegate_to: localhost
|
|
command: >
|
|
sshpass -p {{ ssh_pass | quote }}
|
|
scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
|
|
files/wifidebug.sh
|
|
{{ ssh_user }}@{{ ansible_host }}:/root/wifidebug.sh
|
|
register: scp_wifidebug
|
|
retries: 3
|
|
delay: 2
|
|
until: scp_wifidebug.rc == 0
|
|
|
|
- name: Ensure /root/wifidebug.sh is executable and owned by root
|
|
raw: |
|
|
chown root:root /root/wifidebug.sh && chmod 0755 /root/wifidebug.sh
|
|
|
|
############ step 3
|
|
|
|
- name: Ensure /etc/crontabs/root exists (touch with perms)
|
|
raw: |
|
|
if [ ! -f /etc/crontabs/root ]; then
|
|
touch /etc/crontabs/root
|
|
fi
|
|
chown root:root /etc/crontabs/root
|
|
chmod 0644 /etc/crontabs/root
|
|
|
|
- name: Check if cron line already present
|
|
raw: |
|
|
grep -Fxq '*/1 * * * * /root/wifidebug.sh' /etc/crontabs/root
|
|
register: cron_grep
|
|
failed_when: false
|
|
changed_when: false
|
|
|
|
- name: Upload snippet crond-root to /tmp (only if missing)
|
|
when: cron_grep.rc != 0
|
|
delegate_to: localhost
|
|
command: >
|
|
sshpass -p {{ ssh_pass | quote }}
|
|
scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
|
|
files/crond-root
|
|
{{ ssh_user }}@{{ ansible_host }}:/tmp/crond-root.snippet
|
|
|
|
- name: Append snippet to /etc/crontabs/root (only if missing)
|
|
when: cron_grep.rc != 0
|
|
raw: |
|
|
cat /tmp/crond-root.snippet >> /etc/crontabs/root && rm -f /tmp/crond-root.snippet
|
|
register: cron_append
|
|
changed_when: true
|
|
|
|
############ step 4
|
|
|
|
- name: Skip config.json edit if remote_syslog already matches
|
|
raw: |
|
|
EN_OK=$(cat /tmp/config.json | grep -A9 -m1 'remote_syslog' | grep 'enabled' | grep true | wc -l || echo 0)
|
|
SRV_OK=$(cat /tmp/config.json | grep -A9 -m1 'remote_syslog' | grep 'server' | grep '{{ remote_syslog_ip }}' | wc -l || echo 0)
|
|
if [ "$EN_OK" -eq 1 ] && [ "$SRV_OK" -eq 1 ]; then
|
|
echo "SKIP"
|
|
else
|
|
echo "EDIT"
|
|
fi
|
|
register: remote_syslog_check
|
|
changed_when: false
|
|
|
|
- name: Set do_edit flag from skip check
|
|
set_fact:
|
|
do_edit: "{{ (remote_syslog_check.stdout | default('EDIT')) | trim != 'SKIP' }}"
|
|
|
|
- name: Fetch /tmp/config.json to controller
|
|
when: do_edit
|
|
delegate_to: localhost
|
|
command: >
|
|
sshpass -p {{ ssh_pass | quote }}
|
|
scp -q -o StrictHostKeyChecking=no
|
|
{{ ssh_user }}@{{ ansible_host }}:/tmp/config.json
|
|
/tmp/{{ inventory_hostname }}_config.json
|
|
|
|
- name: Strict in-place style-preserving edit (services.remote_syslog only)
|
|
when: do_edit
|
|
delegate_to: localhost
|
|
shell: |
|
|
awk '
|
|
BEGIN { in_services=0; in_rs=0; depth=0; done_enabled=0; done_server=0 }
|
|
{
|
|
line = $0
|
|
if (!in_services && $0 ~ /"services"[[:space:]]*:/) { in_services=1 }
|
|
if (in_services && !in_rs && $0 ~ /"remote_syslog"[[:space:]]*:/) { in_rs=1; depth=0 }
|
|
if (in_rs) {
|
|
if (!done_enabled && line ~ /^[[:space:]]*"enabled"[[:space:]]*:[[:space:]]*false([[:space:]]*,?[[:space:]]*)$/) {
|
|
line = gensub(/^([[:space:]]*"enabled"[[:space:]]*:[[:space:]]*)false([[:space:]]*,?[[:space:]]*)$/, "\\1true\\2", 1, line)
|
|
done_enabled=1
|
|
}
|
|
if (!done_server && line ~ /^[[:space:]]*"server"[[:space:]]*:[[:space:]]*""([[:space:]]*,?[[:space:]]*)$/) {
|
|
line = gensub(/^([[:space:]]*"server"[[:space:]]*:[[:space:]]*)""([[:space:]]*,?[[:space:]]*)$/, "\\1\"102.38.125.161\"\\2", 1, line)
|
|
done_server=1
|
|
}
|
|
}
|
|
print line
|
|
if (in_rs) {
|
|
opens = gsub(/{/, "{", $0)
|
|
closes = gsub(/}/, "}", $0)
|
|
depth += (opens - closes)
|
|
if (depth <= 0 && $0 ~ /}/) { in_rs=0 }
|
|
}
|
|
}
|
|
' "/tmp/{{ inventory_hostname }}_config.json" \
|
|
> "/tmp/{{ inventory_hostname }}_config.json.new"
|
|
args:
|
|
executable: /bin/bash
|
|
|
|
- name: Push edited config.json.new to remote temp
|
|
when: do_edit
|
|
delegate_to: localhost
|
|
shell: |
|
|
sshpass -p {{ ssh_pass | quote }} scp -q -o StrictHostKeyChecking=no \
|
|
"/tmp/{{ inventory_hostname }}_config.json.new" \
|
|
{{ ssh_user }}@{{ ansible_host }}:/tmp/config.json.new
|
|
args:
|
|
executable: /bin/bash
|
|
|
|
- name: Compute MD5 of local .new
|
|
when: do_edit
|
|
delegate_to: localhost
|
|
command: md5sum "/tmp/{{ inventory_hostname }}_config.json.new"
|
|
register: md5_local
|
|
changed_when: false
|
|
|
|
- name: Compute MD5 of remote .new (no Python)
|
|
when: do_edit
|
|
raw: "md5sum /tmp/config.json.new || busybox md5sum /tmp/config.json.new"
|
|
register: md5_remote
|
|
changed_when: false
|
|
|
|
- name: Fail if MD5 mismatch
|
|
when:
|
|
- do_edit
|
|
- (md5_local.stdout.split()[0]) != (md5_remote.stdout.split()[0] if (md5_remote.stdout is defined) else 'BAD')
|
|
fail:
|
|
msg: "MD5 mismatch between controller and remote copy — aborting replace."
|
|
|
|
- name: Commit new config.json (overwrite original)
|
|
when: do_edit
|
|
raw: |
|
|
cp -a /tmp/config.json /tmp/config.json.bak.$(date +%Y%m%d%H%M%S)
|
|
mv /tmp/config.json.new /tmp/config.json
|
|
|
|
- name: Apply config to runtime (sysconf -w)
|
|
when: do_edit
|
|
raw: |
|
|
sysconf -w || /usr/sbin/sysconf -w
|
|
register: sysconf_result
|
|
changed_when: true
|
|
failed_when: sysconf_result.rc not in [0]
|
|
|
|
- name: Trigger full restart (system-stop; system-start) in background
|
|
when: do_edit
|
|
raw: |
|
|
sleep 1; /usr/sbin/system-stop; /usr/sbin/system-start
|
|
ignore_errors: true
|
|
changed_when: true
|
|
|
|
- name: Short grace delay before waiting
|
|
when: do_edit
|
|
delegate_to: localhost
|
|
pause:
|
|
seconds: 3
|
|
|
|
- name: Try to observe SSH port stopping (best effort)
|
|
when: do_edit
|
|
delegate_to: localhost
|
|
wait_for:
|
|
host: "{{ ansible_host }}"
|
|
port: 22
|
|
state: stopped
|
|
timeout: 30
|
|
sleep: 2
|
|
ignore_errors: true
|
|
|
|
- name: Wait for SSH port to be accepting connections
|
|
when: do_edit
|
|
delegate_to: localhost
|
|
wait_for:
|
|
host: "{{ ansible_host }}"
|
|
port: 22
|
|
state: started
|
|
timeout: 300
|
|
sleep: 2
|
|
|
|
- name: Reset Ansible SSH connection
|
|
when: do_edit
|
|
meta: reset_connection
|
|
|
|
- name: Verify command execution after restart (no python)
|
|
when: do_edit
|
|
raw: "echo rebooted_ok"
|
|
register: post_restart_probe
|
|
retries: 120
|
|
delay: 2
|
|
until: post_restart_probe is succeeded
|
|
changed_when: false
|
|
|
|
- name: Set result status (success deployed or no change)
|
|
set_fact:
|
|
result_status: "{{ 'SUCCESS_DEPLOYED' if (upload_wdbg | bool) else 'SUCCESS_NO_CHANGE' }}"
|
|
|
|
when: ping_result is succeeded
|
|
|
|
- name: Set status fact (no ssh)
|
|
when: ping_result is failed
|
|
set_fact:
|
|
result_status: "NO_SSH"
|
|
|
|
rescue:
|
|
- name: Mark result as failed
|
|
set_fact:
|
|
result_status: "FAILED during {{ ansible_failed_task.name }}"
|
|
|
|
always:
|
|
|
|
- name: Compute inscope device
|
|
set_fact:
|
|
inscope_device_name: "{{ ansible_hostname | default(inventory_hostname) }}"
|
|
|
|
- name: Build journal_add payload
|
|
set_fact:
|
|
journal_payload_obj:
|
|
inscope_device: "{{ inscope_device_name }}"
|
|
task_name: "journal_add"
|
|
task_result: "{{ result_status }}"
|
|
|
|
- name: Publish journal_add to queue2
|
|
uri:
|
|
url: "http://{{ rmq_host }}:{{ rmq_port }}/api/exchanges/{{ rmq_vhost | urlencode }}/{{ rmq_exchange | urlencode }}/publish"
|
|
method: POST
|
|
user: "{{ rmq_user }}"
|
|
password: "{{ rmq_pass }}"
|
|
force_basic_auth: true
|
|
status_code: 200
|
|
headers:
|
|
content-type: "application/json"
|
|
body_format: json
|
|
body:
|
|
properties:
|
|
content_type: "application/json"
|
|
routing_key: "{{ queue2_name }}"
|
|
payload: "{{ journal_payload_obj | to_json }}"
|
|
payload_encoding: "string"
|
|
delegate_to: localhost
|
|
|
|
- name: Build deploy_wifidebug success payload
|
|
when: result_status == 'SUCCESS_DEPLOYED'
|
|
set_fact:
|
|
success_payload_obj:
|
|
inscope_device: "{{ inscope_device_name }}"
|
|
task_name: "deploy_wifidebug"
|
|
task_result: "success"
|
|
|
|
- name: Publish deploy_wifidebug success to queue2
|
|
when: result_status == 'SUCCESS_DEPLOYED'
|
|
uri:
|
|
url: "http://{{ rmq_host }}:{{ rmq_port }}/api/exchanges/{{ rmq_vhost | urlencode }}/{{ rmq_exchange | urlencode }}/publish"
|
|
method: POST
|
|
user: "{{ rmq_user }}"
|
|
password: "{{ rmq_pass }}"
|
|
force_basic_auth: true
|
|
status_code: 200
|
|
headers:
|
|
content-type: "application/json"
|
|
body_format: json
|
|
body:
|
|
properties:
|
|
content_type: "application/json"
|
|
routing_key: "{{ queue2_name }}"
|
|
payload: "{{ success_payload_obj | to_json }}"
|
|
payload_encoding: "string"
|
|
delegate_to: localhost
|
|
|
|
- name: Summary
|
|
debug:
|
|
msg:
|
|
- "result_status: {{ result_status }}"
|
|
- "we're good"
|
|
|