- Go 95.1%
- Shell 4.8%
|
All checks were successful
Release Pipeline / set-release-target (push) Successful in 39s
Release Pipeline / upload-assets (agent.service, systemd/agent.service) (push) Successful in 4s
Release Pipeline / upload-assets (dhcp@.service, systemd/dhcp@.service) (push) Successful in 4s
Release Pipeline / upload-assets (dnsmasq@.service, systemd/dnsmasq@.service) (push) Successful in 4s
Release Pipeline / upload-assets (metadata@.service, systemd/metadata@.service) (push) Successful in 4s
Release Pipeline / upload-assets (run-dhcp-in-netns.sh, scripts/run-dhcp-in-netns.sh) (push) Successful in 4s
Release Pipeline / upload-assets (run-dnsmasq-in-netns.sh, scripts/run-dnsmasq-in-netns.sh) (push) Successful in 4s
Release Pipeline / build (dhcp, amd64, linux) (push) Successful in 0s
Release Pipeline / build (agent, amd64, linux) (push) Successful in 0s
Release Pipeline / build (metadata, amd64, linux) (push) Successful in 0s
Release Pipeline / checksums (push) Successful in 4s
Release Pipeline / release (push) Successful in 13s
Release Pipeline / publish (push) Successful in 0s
Release Pipeline / build (push) Successful in 1m2s
internal/subnet et internal/vm ne parlent plus à dnsmasq en direct mais à une interface Backend, choisie au démarrage par dhcp.backend. Le défaut restant dnsmasq, un agent.yml de 0.1.0 se comporte à l'identique ; ValidBackend refuse toute autre valeur que dnsmasq ou two. Les entrées ip→mac sont écrites hors du backend : elles font autorité pour les deux, internal/vm/data.go les lisant par GetMACForIP quel que soit le serveur. D'où l'extraction de dhcp.Entries, que GenerateConfig mêlait à l'écriture du fichier dnsmasq. Reservation porte Index et DefaultRoute : dnsmasq en dérive ses tags et n'en pose que sur les interfaces sans route par défaut, le backend two transmet le drapeau tel quel. La notion de tag ne remonte plus jusqu'à internal/vm. Two.ConfigureSubnet sonde get-state avant de pousser la configuration : le job systemd d'une unit Type=simple est done dès le fork, avant que la socket existe. TeardownSubnet arrête l'unit avant de supprimer le .state. Le backend two est testé contre un vrai serveur sur une vraie socket. Onze mutations, toutes détectées. Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr> |
||
|---|---|---|
| .forgejo/workflows | ||
| api | ||
| cmd | ||
| conf/agent | ||
| docs | ||
| internal | ||
| pkg | ||
| release_notes | ||
| scripts | ||
| systemd | ||
| .gitignore | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| README.md | ||
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.