From c72bea1a5e1ab4e495ea046c12a462fc1e058d60 Mon Sep 17 00:00:00 2001 From: Arseny <20096ninja@gmail.com> Date: Thu, 24 Sep 2026 23:36:10 +0300 Subject: [PATCH] =?UTF-8?q?[ADD]=20=D0=BF=D0=BB=D0=B5=D0=B9=D0=B1=D1=83?= =?UTF-8?q?=D0=BA=D0=B8=20bootstrap,=20wifi-on,=20wifi-off,=20deploy,=20po?= =?UTF-8?q?weroff?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + bootstrap.yml | 13 +++++++++ deploy.yml | 58 ++++++++++++++++++++++++++++++++++++++++ poweroff.yml | 18 +++++++++++++ vars/wifi.yml.example | 4 +++ wifi-off.yml | 19 +++++++++++++ wifi-on.yml | 62 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 175 insertions(+) create mode 100644 bootstrap.yml create mode 100644 deploy.yml create mode 100644 poweroff.yml create mode 100644 vars/wifi.yml.example create mode 100644 wifi-off.yml create mode 100644 wifi-on.yml diff --git a/.gitignore b/.gitignore index 23e80b0..5a8222a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ keys/ +vars/wifi.yml *.retry diff --git a/bootstrap.yml b/bootstrap.yml new file mode 100644 index 0000000..cde1553 --- /dev/null +++ b/bootstrap.yml @@ -0,0 +1,13 @@ +# Голый узел: вход по паролю pi/raspberry, кладём ключ управляющей машины. +# После этого остальные плейбуки ходят по ключу. +# ansible-playbook bootstrap.yml -l node107 +- name: Ключ управляющей машины на узел + hosts: all + gather_facts: false + vars: + ansible_password: raspberry + tasks: + - name: Публичный ключ в authorized_keys пользователя pi + ansible.posix.authorized_key: + user: pi + key: "{{ lookup('file', control_pubkey) }}" diff --git a/deploy.yml b/deploy.yml new file mode 100644 index 0000000..71f5572 --- /dev/null +++ b/deploy.yml @@ -0,0 +1,58 @@ +# Исходники hackrf-scanner с управляющей машины (scanner_src) на узлы и сборка +# на месте. Интернет не нужен, зависимости ставит playbook.yml (тег base). +# Что уехало, видно в ~/hackrf-scanner/DEPLOYED (git describe). +- name: Код hackrf-scanner на узлы и сборка + hosts: all + gather_facts: false + vars: + scanner_dest: /home/pi/hackrf-scanner + tasks: + - name: Ревизия исходников на управляющей машине + delegate_to: localhost + run_once: true + ansible.builtin.command: git -C {{ scanner_src }} describe --always --dirty + register: rev + changed_when: false + + - name: Исходники на узле (без .git и build), лишние файлы удаляются + ansible.posix.synchronize: + src: "{{ scanner_src }}/" + dest: "{{ scanner_dest }}/" + delete: true + rsync_opts: + - "--exclude=.git" + - "--exclude=build*" + - "--exclude=.cache" + - "--exclude=__pycache__" + - "--exclude=DEPLOYED" + + - name: След клона прежнего провижнинга не нужен + ansible.builtin.file: + path: "{{ scanner_dest }}/.git" + state: absent + + - name: Метка ревизии + ansible.builtin.copy: + content: "{{ rev.stdout }}\n" + dest: "{{ scanner_dest }}/DEPLOYED" + mode: "0644" + + - name: Сборка + ansible.builtin.shell: | + cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo >/dev/null + cmake --build build -j"$(nproc)" + args: + chdir: "{{ scanner_dest }}" + register: build + changed_when: "'Building CXX' in build.stdout or 'Linking' in build.stdout" + + - name: Бинарники на месте + ansible.builtin.stat: + path: "{{ scanner_dest }}/build/{{ item }}" + register: bins + failed_when: not bins.stat.exists + loop: [peleng, scan] + + - name: Итог по узлу + ansible.builtin.debug: + msg: "[+] {{ inventory_hostname }}: {{ rev.stdout }} собран" diff --git a/poweroff.yml b/poweroff.yml new file mode 100644 index 0000000..cc70eb8 --- /dev/null +++ b/poweroff.yml @@ -0,0 +1,18 @@ +# Штатное выключение всех узлов перед снятием питания. +# Плейбук ждёт, пока ssh каждого узла перестанет отвечать. +- name: Выключение узлов + hosts: all + gather_facts: false + tasks: + - name: poweroff + become: true + community.general.shutdown: + delay: 0 + + - name: Узел ушёл из сети + delegate_to: localhost + ansible.builtin.wait_for: + host: "{{ ansible_host }}" + port: 22 + state: stopped + timeout: 90 diff --git a/vars/wifi.yml.example b/vars/wifi.yml.example new file mode 100644 index 0000000..f0f92be --- /dev/null +++ b/vars/wifi.yml.example @@ -0,0 +1,4 @@ +# Домашняя сеть для провижнинга (apt, обновления). Скопировать в vars/wifi.yml, +# он в .gitignore. Смена роутера - смена этих двух строк и прогон wifi-on.yml. +wifi_ssid: Keenetic-6852 +wifi_psk: пароль diff --git a/wifi-off.yml b/wifi-off.yml new file mode 100644 index 0000000..4f49bcf --- /dev/null +++ b/wifi-off.yml @@ -0,0 +1,19 @@ +# Перед работой Wi-Fi узлов выключается: адаптер сидит в 2,4 ГГц рядом +# с приёмником. Состояние радио NetworkManager помнит через перезагрузку, +# обратно включает только wifi-on.yml. +- name: Wi-Fi выключить + hosts: all + gather_facts: false + tasks: + - name: Радио Wi-Fi выключено + become: true + ansible.builtin.shell: | + if [ "$(nmcli radio wifi)" = disabled ]; then echo OK; else nmcli radio wifi off && echo CHANGED; fi + register: radio + changed_when: "'CHANGED' in radio.stdout" + + - name: wlan0 без адреса + ansible.builtin.command: ip -4 -o addr show wlan0 + register: wlan + changed_when: false + failed_when: wlan.stdout != "" diff --git a/wifi-on.yml b/wifi-on.yml new file mode 100644 index 0000000..dc54a8c --- /dev/null +++ b/wifi-on.yml @@ -0,0 +1,62 @@ +# Узлы подключаются к домашней сети (vars/wifi.yml) ради интернета для apt. +# Проводная сеть 11.0.0.0/24 без шлюза, поэтому маршрут по умолчанию +# и DNS приходят от Wi-Fi. В конце каждый узел обязан достучаться до интернета. +- name: Wi-Fi включить и подключить к домашней сети + hosts: all + gather_facts: false + vars_files: + - vars/wifi.yml + vars: + wifi_con: fleet-wifi + tasks: + - name: Радио Wi-Fi включено + become: true + ansible.builtin.shell: | + if [ "$(nmcli radio wifi)" = enabled ]; then echo OK; else nmcli radio wifi on && echo CHANGED; fi + register: radio + changed_when: "'CHANGED' in radio.stdout" + + - name: Профиль {{ wifi_con }} с актуальными SSID и паролем + become: true + community.general.nmcli: + conn_name: "{{ wifi_con }}" + ifname: wlan0 + type: wifi + ssid: "{{ wifi_ssid }}" + wifi_sec: + key-mgmt: wpa-psk + psk: "{{ wifi_psk }}" + autoconnect: true + state: present + register: profile + + - name: Переподключение после смены SSID или пароля + become: true + ansible.builtin.command: nmcli con down {{ wifi_con }} + when: profile.changed + failed_when: false + + - name: Подключение активно + become: true + ansible.builtin.shell: | + state=$(nmcli -t -f GENERAL.STATE con show {{ wifi_con }} | cut -d: -f2) + if [ "$state" = activated ]; then echo OK; else nmcli con up {{ wifi_con }} >/dev/null && echo CHANGED; fi + register: up + changed_when: "'CHANGED' in up.stdout" + + - name: Интернет доступен (DNS и HTTPS) + ansible.builtin.uri: + url: https://deb.debian.org/ + register: inet + retries: 6 + delay: 5 + until: inet.status == 200 + + - name: Адрес в домашней сети + ansible.builtin.command: nmcli -t -f IP4.ADDRESS con show {{ wifi_con }} + register: addr + changed_when: false + + - name: Итог по узлу + ansible.builtin.debug: + msg: "[+] {{ inventory_hostname }}: {{ addr.stdout | regex_replace('^IP4.ADDRESS\\[1\\]:', '') }}, интернет есть"