Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 401ef2c101 | |||
| bd4443d5f1 | |||
| 5417445fb5 | |||
| 37dd184978 | |||
| 0fe490c95e | |||
| c72bea1a5e | |||
| ee291f7a26 |
@@ -1,2 +1,3 @@
|
|||||||
keys/
|
keys/
|
||||||
|
vars/wifi.yml
|
||||||
*.retry
|
*.retry
|
||||||
|
|||||||
@@ -1,47 +1,85 @@
|
|||||||
# fleet
|
# fleet
|
||||||
|
|
||||||
Идемпотентный провижнинг парка приёмников пеленгации (Raspberry Pi + HackRF).
|
Плейбуки ansible, которые приводят любую малинку парка (Raspberry Pi +
|
||||||
Один прогон приводит новую или старую малинку в рабочее состояние: обновление
|
HackRF) в рабочее состояние и управляют ею дальше: домашний Wi-Fi ради
|
||||||
системы, зависимости сборки, общий deploy-ключ до Gitea, клон и сборка
|
интернета, пакеты, код `hackrf-scanner` со сборкой на месте, паспорт узла,
|
||||||
`hackrf-scanner`.
|
запуск и остановка сканера, перезагрузка и выключение.
|
||||||
|
Управление идёт по проводной сети 11.0.0.0/24 (`ansible_host` в инвентаре),
|
||||||
Гоняется дома, пока узлы в сети с интернетом. После переноса в изолированную
|
Wi-Fi нужен только на время установки пакетов и перед работой выключается,
|
||||||
сеть (коммутатор, статические IP) на карте уже есть всё; правки кода дальше
|
потому что адаптер сидит в 2,4 ГГц рядом с приёмником.
|
||||||
идут `rsync` + сборка на месте. Статические IP playbook не трогает.
|
|
||||||
|
|
||||||
## Требования
|
## Требования
|
||||||
|
|
||||||
- на управляющей машине: `ansible` (Arch: `pacman -S ansible`), доступ по ssh
|
- управляющая машина: `ansible` с коллекциями `community.general` и
|
||||||
к узлам под `pi` по ключу;
|
`ansible.posix`, `rsync`, `sshpass` (только для `bootstrap.yml`),
|
||||||
- на узлах: Raspberry Pi OS (Debian 13), `pi` с sudo без пароля, интернет.
|
рядом лежит каталог `../hackrf-scanner` (переменная `scanner_src`);
|
||||||
|
- узлы: Raspberry Pi OS Lite (Debian 13, NetworkManager), пользователь `pi`
|
||||||
|
с sudo без пароля, статический адрес 11.0.0.x на eth0; на полном образе
|
||||||
|
с рабочим столом первый `full-upgrade` по Wi-Fi идёт больше часа;
|
||||||
|
- `vars/wifi.yml` (в `.gitignore`) по образцу `vars/wifi.yml.example`.
|
||||||
|
|
||||||
## Первый запуск
|
## Новый узел
|
||||||
|
|
||||||
scripts/gen-key.sh # пара keys/gitea_deploy (в .gitignore)
|
```bash
|
||||||
# добавить keys/gitea_deploy.pub как deploy key (read-only)
|
nmap -sn 11.0.0.0/24 # какие узлы в сети
|
||||||
# в Gitea: IU9/hackrf-scanner
|
ansible-playbook bootstrap.yml -l node107 # ключ по паролю pi/raspberry
|
||||||
ansible-playbook playbook.yml # весь парк
|
ansible-playbook wifi-on.yml # Wi-Fi и проверка интернета
|
||||||
|
ansible-playbook playbook.yml # пакеты, права, имя
|
||||||
|
ansible-playbook wifi-off.yml # Wi-Fi выключен до следующего раза
|
||||||
|
ansible-playbook deploy.yml # код с этой машины, сборка на узле
|
||||||
|
ansible-playbook env.yml # паспорт ~/node.env из инвентаря
|
||||||
|
```
|
||||||
|
|
||||||
## Теги
|
## Работа
|
||||||
|
|
||||||
base apt upgrade, зависимости, pi в plugdev
|
```bash
|
||||||
hostname имя узла из инвентаря
|
# 1. расстановка: x, y узлов и server_ip в inventory/hosts.yml
|
||||||
key deploy-ключ, ssh config, known_hosts
|
ansible-playbook env.yml --diff # 2. паспорта на узлы
|
||||||
repo clone/pull ветки scanner_branch (stash локальных правок)
|
ansible-playbook scanner-start.yml # 3. peleng на всех узлах
|
||||||
build cmake configure + build
|
ansible-playbook scanner-start.yml -e scanner_args="--freq 2437 --lna 8"
|
||||||
|
ansible-playbook scanner-stop.yml # HackRF свободен (scan, калибровка)
|
||||||
|
```
|
||||||
|
|
||||||
ansible-playbook playbook.yml -l node106 --tags repo,build
|
`scanner-start.yml` на каждом узле зовёт `node.py start <профиль> <флаги>`:
|
||||||
|
останавливает прежний peleng и любой процесс, держащий HackRF, переинициализирует
|
||||||
|
USB и запускает peleng в фоне с логом `/tmp/peleng.log`. Профиль и флаги по
|
||||||
|
умолчанию - `scanner_profile` и `scanner_args` в инвентаре. peleng читает паспорт
|
||||||
|
только при старте, поэтому после `env.yml` нужен повторный `scanner-start.yml`.
|
||||||
|
|
||||||
|
Новый узел сначала вписывается в `inventory/hosts.yml`. Смена роутера: правка
|
||||||
|
`vars/wifi.yml` и `wifi-on.yml`, профиль на узлах обновится.
|
||||||
|
|
||||||
|
## Плейбуки
|
||||||
|
|
||||||
|
| Плейбук | Что делает |
|
||||||
|
|---|---|
|
||||||
|
| `bootstrap.yml` | ключ управляющей машины в `authorized_keys`, вход по паролю |
|
||||||
|
| `wifi-on.yml` | радио включено, профиль `fleet-wifi` с кредами из `vars/wifi.yml`, подключение, проверка DNS и HTTPS |
|
||||||
|
| `playbook.yml` | теги `base` (apt, зависимости, plugdev, udev для HackRF, fish), `hostname`, `key` (deploy-ключ Gitea) |
|
||||||
|
| `wifi-off.yml` | радио выключено, NetworkManager помнит это через перезагрузку |
|
||||||
|
| `deploy.yml` | `rsync` исходников без `.git` и `build`, ревизия в `~/hackrf-scanner/DEPLOYED`, `cmake` сборка, проверка бинарников |
|
||||||
|
| `env.yml` | `~/node.env` (`SDR_ID`, `X`, `Y`, `SERVER`) из инвентаря, перезаписывается целиком |
|
||||||
|
| `scanner-start.yml` | `node.py start`: освободить HackRF, переинициализировать USB, peleng в фоне, `status` |
|
||||||
|
| `scanner-stop.yml` | `node.py stop`: peleng и любой процесс с HackRF остановлены, проверка `status` |
|
||||||
|
| `reboot.yml` | перезагрузка с ожиданием возврата, печатает ядро |
|
||||||
|
| `poweroff.yml` | штатное выключение и ожидание, пока узел пропадёт из сети |
|
||||||
|
|
||||||
|
Ограничение по узлам и тегам как обычно: `-l node106`, `--tags base`.
|
||||||
|
|
||||||
## Инвентарь
|
## Инвентарь
|
||||||
|
|
||||||
`inventory/hosts.yml`: адреса узлов в домашней сети (транзитные), а также
|
`inventory/hosts.yml`: адрес узла в проводной сети, `sdr_id`, серийник HackRF,
|
||||||
справочно -- статический IP для поля, серийник HackRF и координаты x, y (м).
|
координаты x, y в метрах. Общие переменные: `server_ip` (куда узлы шлют замеры),
|
||||||
Ветка репозитория -- переменная `scanner_branch`.
|
`scanner_dir` (каталог сканера на узле), `scanner_profile` и `scanner_args`
|
||||||
|
(запуск по умолчанию). Инвентарь главный: `env.yml` перезаписывает паспорт узла,
|
||||||
|
правки руками на узле до следующего прогона.
|
||||||
|
|
||||||
## Приёмка
|
## Приёмка
|
||||||
|
|
||||||
1. Прогон без `failed`.
|
1. Все плейбуки без `failed`, второй прогон подряд `changed=0`.
|
||||||
2. Второй прогон подряд -- `changed=0` на всех узлах.
|
2. После `wifi-on.yml` каждый узел печатает адрес в домашней сети и
|
||||||
3. На узле: `hackrf_info` видит устройство, `~/hackrf-scanner/build/` собран,
|
"интернет есть", после `wifi-off.yml` у `wlan0` нет адреса.
|
||||||
`git rev-parse --abbrev-ref HEAD` = `scanner_branch`, `hostname` = имя узла.
|
3. На узле `~/hackrf-scanner/build/peleng` и `scan` собраны, `DEPLOYED`
|
||||||
4. `ssh -T git@monitor.yss.su` с узла отвечает Gitea.
|
совпадает с `git describe` на управляющей машине, `hostname` = имя узла.
|
||||||
|
4. После `scanner-start.yml` каждый узел печатает "peleng запущен" и строку
|
||||||
|
замера, после `scanner-stop.yml` статус "не запущен".
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ inventory = inventory/hosts.yml
|
|||||||
remote_user = pi
|
remote_user = pi
|
||||||
host_key_checking = False
|
host_key_checking = False
|
||||||
interpreter_python = auto_silent
|
interpreter_python = auto_silent
|
||||||
|
# Все узлы парка одновременно: старт сканера ждёт USB и первый замер ~15 с на узел
|
||||||
|
forks = 16
|
||||||
|
|
||||||
[ssh_connection]
|
[ssh_connection]
|
||||||
pipelining = True
|
pipelining = True
|
||||||
|
|||||||
@@ -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) }}"
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
# Исходники hackrf-scanner с управляющей машины (scanner_src) на узлы и сборка
|
||||||
|
# на месте. Интернет не нужен, зависимости ставит playbook.yml (тег base).
|
||||||
|
# Что уехало, видно в ~/hackrf-scanner/DEPLOYED (git describe).
|
||||||
|
- name: Код hackrf-scanner на узлы и сборка
|
||||||
|
hosts: all
|
||||||
|
gather_facts: false
|
||||||
|
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_dir }}/"
|
||||||
|
delete: true
|
||||||
|
rsync_opts:
|
||||||
|
- "--exclude=.git"
|
||||||
|
- "--exclude=build*"
|
||||||
|
- "--exclude=.cache"
|
||||||
|
- "--exclude=__pycache__"
|
||||||
|
- "--exclude=DEPLOYED"
|
||||||
|
|
||||||
|
- name: След клона прежнего провижнинга не нужен
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ scanner_dir }}/.git"
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Метка ревизии
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: "{{ rev.stdout }}\n"
|
||||||
|
dest: "{{ scanner_dir }}/DEPLOYED"
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Сборка
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo >/dev/null
|
||||||
|
cmake --build build -j"$(nproc)"
|
||||||
|
args:
|
||||||
|
chdir: "{{ scanner_dir }}"
|
||||||
|
register: build
|
||||||
|
changed_when: "'Building CXX' in build.stdout or 'Linking' in build.stdout"
|
||||||
|
|
||||||
|
- name: Бинарники на месте
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ scanner_dir }}/build/{{ item }}"
|
||||||
|
register: bins
|
||||||
|
failed_when: not bins.stat.exists
|
||||||
|
loop: [peleng, scan]
|
||||||
|
|
||||||
|
- name: Итог по узлу
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "[+] {{ inventory_hostname }}: {{ rev.stdout }} собран"
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Паспорт узла ~/node.env из инвентаря: SDR_ID, X, Y, SERVER. Инвентарь главный,
|
||||||
|
# файл на узле перезаписывается целиком. peleng читает паспорт только при
|
||||||
|
# старте, поэтому после смены расстановки нужен scanner-start.yml.
|
||||||
|
# ansible-playbook env.yml --diff
|
||||||
|
- name: Паспорт узла из инвентаря
|
||||||
|
hosts: all
|
||||||
|
gather_facts: false
|
||||||
|
tasks:
|
||||||
|
- name: ~/node.env
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: ~/node.env
|
||||||
|
mode: "0644"
|
||||||
|
content: |
|
||||||
|
SDR_ID={{ sdr_id }}
|
||||||
|
X={{ x }}
|
||||||
|
Y={{ y }}
|
||||||
|
SERVER={{ server_ip }}
|
||||||
|
register: env
|
||||||
|
|
||||||
|
- name: Итог по узлу
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "[{{ '+' if env.changed else 'i' }}] {{ inventory_hostname }}: SDR_ID={{ sdr_id }} X={{ x }} Y={{ y }} SERVER={{ server_ip }}{{ ' (обновлён)' if env.changed else '' }}"
|
||||||
+37
-18
@@ -1,37 +1,56 @@
|
|||||||
|
# Координаты x, y в метрах, замер 27.09.2026 (комната).
|
||||||
all:
|
all:
|
||||||
vars:
|
vars:
|
||||||
scanner_repo: ssh://git@monitor.yss.su:2222/IU9/hackrf-scanner.git
|
scanner_src: "{{ playbook_dir }}/../hackrf-scanner"
|
||||||
scanner_branch: feature/scanner-v2
|
control_pubkey: ~/.ssh/id_ed25519.pub
|
||||||
gitea_host: monitor.yss.su
|
gitea_host: monitor.yss.su
|
||||||
gitea_port: 2222
|
gitea_port: 2222
|
||||||
server_ip: 11.0.0.100
|
server_ip: 11.0.0.100
|
||||||
|
scanner_dir: /home/pi/hackrf-scanner
|
||||||
|
# Запуск по умолчанию для scanner-start.yml; поверх: -e scanner_args="--freq 2437 --lna 8"
|
||||||
|
scanner_profile: dji24
|
||||||
|
scanner_args: ""
|
||||||
hosts:
|
hosts:
|
||||||
node102:
|
node102:
|
||||||
ansible_host: 192.168.1.45
|
ansible_host: 11.0.0.102
|
||||||
sdr_id: 1
|
sdr_id: 1
|
||||||
static_ip: 11.0.0.102
|
|
||||||
sdr_serial: a32868dc35944247
|
sdr_serial: a32868dc35944247
|
||||||
x: -0.68
|
x: 0.34
|
||||||
y: -1.28
|
y: 0.47
|
||||||
|
node103:
|
||||||
|
ansible_host: 11.0.0.103
|
||||||
|
sdr_id: 6
|
||||||
|
sdr_serial: d63861dc2d9b4353
|
||||||
|
x: 0.77
|
||||||
|
y: 0.60
|
||||||
node104:
|
node104:
|
||||||
ansible_host: 192.168.1.50
|
ansible_host: 11.0.0.104
|
||||||
sdr_id: 2
|
sdr_id: 2
|
||||||
static_ip: 11.0.0.104
|
|
||||||
sdr_serial: 42a068dc377ab507
|
sdr_serial: 42a068dc377ab507
|
||||||
note: PortaPack
|
note: PortaPack
|
||||||
x: 2.28
|
x: 2.28
|
||||||
y: 0.45
|
y: 0.45
|
||||||
node105:
|
node105:
|
||||||
ansible_host: 192.168.1.87
|
ansible_host: 11.0.0.105
|
||||||
sdr_id: 3
|
sdr_id: 3
|
||||||
static_ip: 11.0.0.105
|
|
||||||
sdr_serial: a32868dc33894f47
|
sdr_serial: a32868dc33894f47
|
||||||
x: 3.77
|
|
||||||
y: -0.74
|
|
||||||
node106:
|
|
||||||
ansible_host: 192.168.1.42
|
|
||||||
sdr_id: 4
|
|
||||||
static_ip: 11.0.0.106
|
|
||||||
sdr_serial: a32868dc346d2847
|
|
||||||
x: 0.00
|
x: 0.00
|
||||||
y: 0.50
|
y: -1.02
|
||||||
|
node106:
|
||||||
|
ansible_host: 11.0.0.106
|
||||||
|
sdr_id: 4
|
||||||
|
sdr_serial: a32868dc346d2847
|
||||||
|
x: 3.77
|
||||||
|
y: -0.78
|
||||||
|
node107:
|
||||||
|
ansible_host: 11.0.0.107
|
||||||
|
sdr_id: 5
|
||||||
|
sdr_serial: b25062dc2242970b
|
||||||
|
x: 3.77
|
||||||
|
y: 0.00
|
||||||
|
node108:
|
||||||
|
ansible_host: 11.0.0.108
|
||||||
|
sdr_id: 7
|
||||||
|
sdr_serial: a32868dc33324c47
|
||||||
|
x: -0.74
|
||||||
|
y: 0.47
|
||||||
|
|||||||
+5
-57
@@ -1,3 +1,5 @@
|
|||||||
|
# Базовый провижнинг: пакеты, права на HackRF, имя узла, deploy-ключ.
|
||||||
|
# Нужен интернет на узлах (wifi-on.yml). Код на узлы кладёт deploy.yml.
|
||||||
- name: Провижнинг приёмников пеленгации
|
- name: Провижнинг приёмников пеленгации
|
||||||
hosts: all
|
hosts: all
|
||||||
tasks:
|
tasks:
|
||||||
@@ -16,10 +18,10 @@
|
|||||||
upgrade: full
|
upgrade: full
|
||||||
tags: [base]
|
tags: [base]
|
||||||
|
|
||||||
- name: Зависимости сборки и утилиты HackRF
|
- name: Зависимости сборки, утилиты HackRF, python для node.py
|
||||||
become: true
|
become: true
|
||||||
ansible.builtin.apt:
|
ansible.builtin.apt:
|
||||||
name: [cmake, g++, pkg-config, git, rsync, libhackrf-dev, libusb-1.0-0-dev, libfftw3-dev, hackrf, fish]
|
name: [cmake, g++, pkg-config, git, rsync, libhackrf-dev, libusb-1.0-0-dev, libfftw3-dev, hackrf, python3, fish]
|
||||||
state: present
|
state: present
|
||||||
tags: [base]
|
tags: [base]
|
||||||
|
|
||||||
@@ -76,7 +78,7 @@
|
|||||||
- name: Ключа нет
|
- name: Ключа нет
|
||||||
run_once: true
|
run_once: true
|
||||||
ansible.builtin.fail:
|
ansible.builtin.fail:
|
||||||
msg: "[!] нет keys/gitea_deploy -- запустите scripts/gen-key.sh"
|
msg: "[!] нет keys/gitea_deploy, запустите scripts/gen-key.sh"
|
||||||
when: not deploy_key.stat.exists
|
when: not deploy_key.stat.exists
|
||||||
tags: [key]
|
tags: [key]
|
||||||
|
|
||||||
@@ -108,57 +110,3 @@
|
|||||||
IdentitiesOnly yes
|
IdentitiesOnly yes
|
||||||
StrictHostKeyChecking accept-new
|
StrictHostKeyChecking accept-new
|
||||||
tags: [key]
|
tags: [key]
|
||||||
|
|
||||||
- name: ~/node.env для обёртки node.sh (только засев, полевые правки не трогаем)
|
|
||||||
ansible.builtin.copy:
|
|
||||||
dest: ~/node.env
|
|
||||||
mode: "0644"
|
|
||||||
force: false
|
|
||||||
content: |
|
|
||||||
SDR_ID={{ sdr_id }}
|
|
||||||
X={{ x }}
|
|
||||||
Y={{ y }}
|
|
||||||
SERVER={{ server_ip }}
|
|
||||||
tags: [env]
|
|
||||||
|
|
||||||
- name: Репозиторий уже клонирован?
|
|
||||||
ansible.builtin.stat:
|
|
||||||
path: ~/hackrf-scanner/.git
|
|
||||||
register: repo_dir
|
|
||||||
tags: [repo]
|
|
||||||
|
|
||||||
- name: Локальные правки в репо (rsync-разработка)?
|
|
||||||
ansible.builtin.command: git status --porcelain
|
|
||||||
args:
|
|
||||||
chdir: ~/hackrf-scanner
|
|
||||||
register: dirty
|
|
||||||
changed_when: false
|
|
||||||
when: repo_dir.stat.exists
|
|
||||||
tags: [repo]
|
|
||||||
|
|
||||||
- name: Stash локальных правок перед обновлением
|
|
||||||
ansible.builtin.command: git stash push -m fleet-provision
|
|
||||||
args:
|
|
||||||
chdir: ~/hackrf-scanner
|
|
||||||
when: repo_dir.stat.exists and dirty.stdout != ""
|
|
||||||
tags: [repo]
|
|
||||||
|
|
||||||
- name: Репозиторий hackrf-scanner
|
|
||||||
ansible.builtin.git:
|
|
||||||
repo: "{{ scanner_repo }}"
|
|
||||||
dest: ~/hackrf-scanner
|
|
||||||
version: "{{ scanner_branch }}"
|
|
||||||
update: true
|
|
||||||
force: true
|
|
||||||
register: repo
|
|
||||||
tags: [repo]
|
|
||||||
|
|
||||||
- name: Сборка
|
|
||||||
ansible.builtin.shell: |
|
|
||||||
cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo >/dev/null
|
|
||||||
cmake --build build -j4
|
|
||||||
args:
|
|
||||||
chdir: ~/hackrf-scanner
|
|
||||||
register: build
|
|
||||||
changed_when: "'Building CXX' in build.stdout or 'Linking' in build.stdout"
|
|
||||||
tags: [build]
|
|
||||||
|
|||||||
@@ -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
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
# Перезагрузка узлов с ожиданием возврата по ssh (например, после обновления
|
||||||
|
# ядра). В конце каждый узел печатает ядро, на котором поднялся.
|
||||||
|
- name: Перезагрузка узлов
|
||||||
|
hosts: all
|
||||||
|
gather_facts: false
|
||||||
|
tasks:
|
||||||
|
- name: reboot и ожидание возврата
|
||||||
|
become: true
|
||||||
|
ansible.builtin.reboot:
|
||||||
|
reboot_timeout: 300
|
||||||
|
|
||||||
|
- name: Ядро после перезагрузки
|
||||||
|
ansible.builtin.command: uname -r
|
||||||
|
register: kernel
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Итог по узлу
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "[+] {{ inventory_hostname }}: поднялся, ядро {{ kernel.stdout }}"
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# run.sh [аргументы ansible-playbook] примеры:
|
|
||||||
# ./run.sh весь парк, все теги
|
|
||||||
# ./run.sh --tags base -l node106
|
|
||||||
# ./run.sh --check --diff сухой прогон
|
|
||||||
set -e
|
|
||||||
cd "$(dirname "$0")"
|
|
||||||
[ -f keys/gitea_deploy ] || { echo "[!] нет keys/gitea_deploy -- запустите scripts/gen-key.sh"; exit 1; }
|
|
||||||
exec ansible-playbook playbook.yml "$@"
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Запуск peleng на всех узлах одной командой node.py start: остановить прежний
|
||||||
|
# peleng и любой процесс, держащий HackRF, переинициализировать USB, запустить
|
||||||
|
# в фоне (лог /tmp/peleng.log). Профиль и флаги из инвентаря или поверх:
|
||||||
|
# ansible-playbook scanner-start.yml -e scanner_args="--freq 2437 --lna 8"
|
||||||
|
- name: Запуск сканера на узлах
|
||||||
|
hosts: all
|
||||||
|
gather_facts: false
|
||||||
|
tasks:
|
||||||
|
- name: node.py start {{ scanner_profile }} {{ scanner_args }}
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv: "{{ ['python3', scanner_dir + '/scripts/node.py', 'start', scanner_profile] + scanner_args.split() }}"
|
||||||
|
register: start
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: node.py status
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv: ["python3", "{{ scanner_dir }}/scripts/node.py", "status"]
|
||||||
|
register: status
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Итог по узлу
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ start.stdout_lines + status.stdout_lines }}"
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Остановка peleng на всех узлах: node.py stop останавливает свой peleng и любой
|
||||||
|
# процесс, держащий HackRF. После этого HackRF свободен для scan или калибровки.
|
||||||
|
- name: Остановка сканера на узлах
|
||||||
|
hosts: all
|
||||||
|
gather_facts: false
|
||||||
|
tasks:
|
||||||
|
- name: node.py stop
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv: ["python3", "{{ scanner_dir }}/scripts/node.py", "stop"]
|
||||||
|
register: stop
|
||||||
|
changed_when: stop.stdout | length > 0
|
||||||
|
|
||||||
|
- name: node.py status
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv: ["python3", "{{ scanner_dir }}/scripts/node.py", "status"]
|
||||||
|
register: status
|
||||||
|
changed_when: false
|
||||||
|
failed_when: "'работает' in status.stdout"
|
||||||
|
|
||||||
|
- name: Итог по узлу
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ stop.stdout_lines + status.stdout_lines }}"
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Домашняя сеть для провижнинга (apt, обновления). Скопировать в vars/wifi.yml,
|
||||||
|
# он в .gitignore. Смена роутера - смена этих двух строк и прогон wifi-on.yml.
|
||||||
|
wifi_ssid: Keenetic-6852
|
||||||
|
wifi_psk: пароль
|
||||||
@@ -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 != ""
|
||||||
+62
@@ -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\\]:', '') }}, интернет есть"
|
||||||
Reference in New Issue
Block a user