Compare commits

..

10 Commits

5 changed files with 114 additions and 15 deletions
-1
View File
@@ -1,3 +1,2 @@
keys/
specs/
*.retry
+47
View File
@@ -0,0 +1,47 @@
# fleet
Идемпотентный провижнинг парка приёмников пеленгации (Raspberry Pi + HackRF).
Один прогон приводит новую или старую малинку в рабочее состояние: обновление
системы, зависимости сборки, общий deploy-ключ до Gitea, клон и сборка
`hackrf-scanner`.
Гоняется дома, пока узлы в сети с интернетом. После переноса в изолированную
сеть (коммутатор, статические IP) на карте уже есть всё; правки кода дальше
идут `rsync` + сборка на месте. Статические IP playbook не трогает.
## Требования
- на управляющей машине: `ansible` (Arch: `pacman -S ansible`), доступ по ssh
к узлам под `pi` по ключу;
- на узлах: Raspberry Pi OS (Debian 13), `pi` с sudo без пароля, интернет.
## Первый запуск
scripts/gen-key.sh # пара keys/gitea_deploy (в .gitignore)
# добавить keys/gitea_deploy.pub как deploy key (read-only)
# в Gitea: IU9/hackrf-scanner
ansible-playbook playbook.yml # весь парк
## Теги
base apt upgrade, зависимости, pi в plugdev
hostname имя узла из инвентаря
key deploy-ключ, ssh config, known_hosts
repo clone/pull ветки scanner_branch (stash локальных правок)
build cmake configure + build
ansible-playbook playbook.yml -l node106 --tags repo,build
## Инвентарь
`inventory/hosts.yml`: адреса узлов в домашней сети (транзитные), а также
справочно -- статический IP для поля, серийник HackRF и координаты x, y (м).
Ветка репозитория -- переменная `scanner_branch`.
## Приёмка
1. Прогон без `failed`.
2. Второй прогон подряд -- `changed=0` на всех узлах.
3. На узле: `hackrf_info` видит устройство, `~/hackrf-scanner/build/` собран,
`git rev-parse --abbrev-ref HEAD` = `scanner_branch`, `hostname` = имя узла.
4. `ssh -T git@monitor.yss.su` с узла отвечает Gitea.
+8 -3
View File
@@ -4,15 +4,18 @@ all:
scanner_branch: feature/scanner-v2
gitea_host: monitor.yss.su
gitea_port: 2222
server_ip: 11.0.0.100
hosts:
node102:
ansible_host: 192.168.1.45
sdr_id: 1
static_ip: 11.0.0.102
sdr_serial: a32868dc35944247
x: -0.68
y: -1.28
node104:
ansible_host: 192.168.1.50
sdr_id: 2
static_ip: 11.0.0.104
sdr_serial: 42a068dc377ab507
note: PortaPack
@@ -20,13 +23,15 @@ all:
y: 0.45
node105:
ansible_host: 192.168.1.87
sdr_id: 3
static_ip: 11.0.0.105
sdr_serial: a32868dc33894f47
x: 2.60
y: 0.00
x: 3.77
y: -0.74
node106:
ansible_host: 192.168.1.42
sdr_id: 4
static_ip: 11.0.0.106
sdr_serial: ""
sdr_serial: a32868dc346d2847
x: 0.00
y: 0.50
+50 -11
View File
@@ -2,27 +2,53 @@
hosts: all
tasks:
- name: apt update и full-upgrade
- name: Обновить кэш apt (не считается изменением)
become: true
ansible.builtin.apt:
update_cache: true
cache_valid_time: 3600
changed_when: false
tags: [base]
- name: apt full-upgrade
become: true
ansible.builtin.apt:
upgrade: full
tags: [base]
- name: Зависимости сборки и утилиты HackRF
become: true
ansible.builtin.apt:
name: [cmake, g++, pkg-config, git, rsync, libhackrf-dev, libusb-1.0-0-dev, libfftw3-dev, hackrf]
name: [cmake, g++, pkg-config, git, rsync, libhackrf-dev, libusb-1.0-0-dev, libfftw3-dev, hackrf, fish]
state: present
tags: [base]
- name: pi в группе plugdev (udev HackRF)
- name: pi в группе plugdev, login-shell fish
become: true
ansible.builtin.user:
name: pi
groups: plugdev
append: true
shell: /usr/bin/fish
tags: [base]
- name: Права udev на уже подключённый HackRF (устройство старше правил)
become: true
ansible.builtin.shell: |
bad=0
for d in /sys/bus/usb/devices/*; do
[ -f "$d/idVendor" ] || continue
case "$(cat "$d/idVendor"):$(cat "$d/idProduct")" in 1d50:6089|1d50:604b) ;; *) continue;; esac
node=/dev/bus/usb/$(printf %03d "$(cat "$d/busnum")")/$(printf %03d "$(cat "$d/devnum")")
[ "$(stat -c %G "$node")" = plugdev ] || bad=1
done
if [ "$bad" = 1 ]; then
udevadm control --reload-rules && udevadm trigger --subsystem-match=usb && echo FIXED
else
echo OK
fi
register: usb
changed_when: "'FIXED' in usb.stdout"
tags: [base]
- name: Имя узла
@@ -80,29 +106,41 @@
User git
IdentityFile ~/.ssh/gitea_deploy
IdentitiesOnly yes
StrictHostKeyChecking accept-new
tags: [key]
- name: Gitea в known_hosts
ansible.builtin.known_hosts:
name: "[{{ gitea_host }}]:{{ gitea_port }}"
key: "{{ lookup('pipe', 'ssh-keyscan -p ' ~ gitea_port ~ ' -t ed25519 ' ~ gitea_host ~ ' 2>/dev/null') }}"
path: ~/.ssh/known_hosts
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
failed_when: false
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: dirty.rc == 0 and dirty.stdout != ""
when: repo_dir.stat.exists and dirty.stdout != ""
tags: [repo]
- name: Репозиторий hackrf-scanner
@@ -111,6 +149,7 @@
dest: ~/hackrf-scanner
version: "{{ scanner_branch }}"
update: true
force: true
register: repo
tags: [repo]
Executable
+9
View File
@@ -0,0 +1,9 @@
#!/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 "$@"