A simple but powerful orchestrator, designed to be easy to use and API-first.
  • Go 95.1%
  • Shell 4.8%
Find a file
GnomeZworc 0c0b58820c
f-46: dhcpapi: add the control socket, its protocol and its client #46
Le contrat et le listener vont dans internal/api/dhcp (package dhcpapi), sur la
forme de internal/api/agent, et le client dans internal/client/dhcp. Chaînage
des imports : statefile <- dhcpd <- dhcpapi <- dhcpclient, sans cycle.

dhcpd parle net.IP et net.IPNet et garde ses structs disque privées ; dhcpapi
parle chaînes JSON et convertit à la frontière. Un même type portait jusqu'ici
le format du fil, la signature du Store et le format du .state — ce qui couplait
le fichier au protocole alors que le ticket le décrit comme un détail interne.

Le digest est calculé sur une forme canonique partagée par les deux côtés : MAC,
IP et CIDR normalisés, hôtes triés, doublon de MAC refusé. Un écart de digest
signale donc une vraie divergence, pas une différence d'écriture.

Le listener pose un recover par connexion, plafonne les lignes à 64 Kio, refuse
une ligne malformée sans fermer la connexion, écoute en 0600 et supprime une
socket résiduelle avant le bind. Le client pose une deadline.

101 tests au total, -race propre, treize mutations toutes détectées.

Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
2026-09-05 23:17:59 +02:00
.forgejo/workflows f-46: ci: align go version with the module #46 2026-09-05 23:17:57 +02:00
api f-33: net: add multi net in dispatch et vms #33 2026-08-25 22:48:13 +02:00
cmd f-33: net: add multi net in dispatch et vms #33 2026-08-25 22:48:13 +02:00
conf/agent f-29: watchdog: add specific config #29 2026-08-17 23:52:48 +02:00
docs docs: configuration for orchestrator 2026-08-27 23:56:47 +02:00
internal f-46: dhcpapi: add the control socket, its protocol and its client #46 2026-09-05 23:17:59 +02:00
pkg f-46: statefile: add a generic atomic state file #46 2026-09-05 23:17:58 +02:00
release_notes 0.1.0: release 2026-08-26 00:21:30 +02:00
scripts f-33: dnsmasq: remove duplicated --no-daemon flag 2026-08-25 21:42:08 +02:00
systemd f-29: stop: add a proper stop 2026-08-18 00:41:01 +02:00
.gitignore f-21: git: add claude to gitignore 2026-04-21 23:36:33 +02:00
go.mod f-46: dhcpd: build dhcp replies over insomniacslk/dhcp #46 2026-09-05 23:17:58 +02:00
go.sum f-46: dhcpd: build dhcp replies over insomniacslk/dhcp #46 2026-09-05 23:17:58 +02:00
LICENSE update license 2026-04-21 23:19:36 +02:00
README.md 0.1.0: update release docs 2026-08-26 00:21:01 +02:00

syonad/two

Orchestrateur réseau et machines virtuelles mono-nœud, pensé pour être piloté par un logiciel plutôt que par un humain.

Il expose une API HTTP qui crée des VPC — isolés par network namespace —, des subnets — en VXLAN ou attachés à un bridge existant — et des VM QEMU/KVM raccordées à ces subnets, avec DHCP, routage et metadata cloud-init fournis automatiquement.

Installation

curl -O https://git.g3e.fr/syonad/two/raw/branch/main/scripts/deploy.sh
bash ./deploy.sh -t 0.1.0 -i

deploy.sh se met à jour lui-même depuis la branche, télécharge binaires, units systemd et scripts depuis la release, et les vérifie contre le manifeste SHA256SUMS. Le drapeau -i prépare l'host : paquets, module br_netfilter, sysctl, et bridges.

Options utiles :

Option Effet
-t <tag> déployer une release donnée
-b <branche> déployer depuis une branche au lieu d'une release
-i préparer l'host (paquets, noyau, réseau)
-u <iface> interface physique d'uplink, eno1 par défaut
-B <bridge> bridge principal auquel l'uplink est rattaché
-d dry-run : affiche les commandes sans les exécuter
-V désactiver la vérification des sommes de contrôle

Un déploiement relève les instances dnsmasq@ et metadata@ actives avant l'arrêt des services, et les redémarre ensuite — c'est la seule façon de savoir lesquelles relancer.

Configuration

Un seul fichier, /etc/two/agent.yml, partagé par les trois binaires. Voir conf/agent/config.exemple.yml pour l'ensemble des options : chemins de la base et des sockets QEMU, pool de workers, correspondance des types d'interface vers les bridges physiques, watchdog, API d'administration, journalisation.

Prise en main

# Un VPC, avec son CIDR interne
curl -X POST http://127.0.0.1:8080/vpcs \
  -d '{"name": "vp-admin", "cidr": "192.168.0.0/16"}'

# Un subnet en VXLAN dans ce VPC
curl -X POST http://127.0.0.1:8080/subnets \
  -d '{"name": "sn-000001", "vpc": "vp-admin", "mode": "vxlan", "vxlan_id": 1,
       "iface_type": "vms", "interface_ip": "10.1.1.1", "cidr": "10.1.0.0/23"}'

# Une VM, avec une clé SSH et un user-data cloud-init en base64
curl -X POST http://127.0.0.1:8080/vms \
  -d '{"name": "i-web", "memory": 2048, "cpus": 2,
       "metadata": {"sshkey": "ssh-ed25519 AAAA…",
                    "user_data": "'"$(base64 -w0 < user-data.yml)"'"},
       "interfaces": [{"subnet": "sn-000001", "ip": "10.1.1.2", "primary": true}],
       "storage": [{"path": "/data/disks/vms/i-web.qcow2", "dev": "vda"}]}'

Les créations sont asynchrones : l'API répond 202 et l'état de la ressource passe de creating à running en base. GET /vms/i-web renvoie l'état courant.

Une VM peut porter plusieurs interfaces, dans un même VPC ; exactement une doit être marquée primary — elle porte la route par défaut et le serveur de metadata.

La spécification complète est dans api/agent.yaml.

Composants

Binaire Rôle
agent processus principal : API, dispatcher, exécution, watchdog
metadata serveur de metadata cloud-init, une instance par VM dans le netns du VPC
db inspection de la base clé-valeur en ligne de commande

L'agent prend -config, les deux autres -conf.

Versions

Les notes de version sont dans release_notes/. Chaque version porte un nom de code, dérivé du rang de sa publication : anges et démons alternés, listés dans release_notes/codenames.md.