f-25: code: move load data to dedicated function
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
This commit is contained in:
parent
2efaf20098
commit
cc9998028d
6 changed files with 222 additions and 208 deletions
|
|
@ -2,9 +2,6 @@ package subnet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.g3e.fr/syonad/two/internal/dhcp"
|
"git.g3e.fr/syonad/two/internal/dhcp"
|
||||||
"git.g3e.fr/syonad/two/internal/ebtables"
|
"git.g3e.fr/syonad/two/internal/ebtables"
|
||||||
|
|
@ -25,94 +22,51 @@ func CreateSubnet(db *badger.DB, subnetName string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// lecture des paramètres depuis la DB
|
d, err := loadSubnet(db, subnetName)
|
||||||
vpcName, err := kv.GetFromDB(db, "subnet/"+subnetName+"/vpc")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get vpc: %w", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
vxlanIDStr, err := kv.GetFromDB(db, "subnet/"+subnetName+"/vxlan_id")
|
vxlanIface := fmt.Sprintf("vxlan-%d", d.vxlanID)
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get vxlan_id: %w", err)
|
|
||||||
}
|
|
||||||
vxlanID, err := strconv.Atoi(vxlanIDStr)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("parse vxlan_id: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
localIface, err := kv.GetFromDB(db, "subnet/"+subnetName+"/local_iface")
|
if err := netif.CreateVethToNetns("v-"+d.subnetID+"-e", "v-"+d.subnetID+"-i", "/var/run/netns/"+d.vpc, 1500); err != nil {
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get local_iface: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
gatewayIPStr, err := kv.GetFromDB(db, "subnet/"+subnetName+"/gateway_ip")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get gateway_ip: %w", err)
|
|
||||||
}
|
|
||||||
gatewayIP := net.ParseIP(gatewayIPStr)
|
|
||||||
if gatewayIP == nil {
|
|
||||||
return fmt.Errorf("invalid gateway_ip: %s", gatewayIPStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
cidr, err := kv.GetFromDB(db, "subnet/"+subnetName+"/cidr")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get cidr: %w", err)
|
|
||||||
}
|
|
||||||
_, subnet, err := net.ParseCIDR(cidr)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("parse cidr: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// subnet_id = partie après le premier '-' (ex: "sn-00001" -> "00001")
|
|
||||||
subnetID := strings.SplitN(subnetName, "-", 2)[1]
|
|
||||||
bridge := "br-" + subnetID
|
|
||||||
vxlanIface := fmt.Sprintf("vxlan-%d", vxlanID)
|
|
||||||
|
|
||||||
// veth pair
|
|
||||||
if err := netif.CreateVethToNetns("v-"+subnetID+"-e", "v-"+subnetID+"-i", "/var/run/netns/"+vpcName, 1500); err != nil {
|
|
||||||
return fmt.Errorf("create veth: %w", err)
|
return fmt.Errorf("create veth: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// bridge dans le root netns
|
if err := netif.CreateBridge(d.bridge, 1500); err != nil {
|
||||||
if err := netif.CreateBridge(bridge, 1500); err != nil {
|
|
||||||
return fmt.Errorf("create bridge: %w", err)
|
return fmt.Errorf("create bridge: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// bridge dans le netns VPC
|
if err := netns.Call(d.vpc, func() error {
|
||||||
if err := netns.Call(vpcName, func() error {
|
return netif.CreateBridge(d.bridge, 1500)
|
||||||
return netif.CreateBridge(bridge, 1500)
|
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("create bridge in netns: %w", err)
|
return fmt.Errorf("create bridge in netns: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// vxlan
|
if err := netif.CreateVxlan(vxlanIface, d.vxlanID, d.localIface, 1500); err != nil {
|
||||||
if err := netif.CreateVxlan(vxlanIface, vxlanID, localIface, 1500); err != nil {
|
|
||||||
return fmt.Errorf("create vxlan: %w", err)
|
return fmt.Errorf("create vxlan: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ajout des interfaces dans les bridges
|
if err := netif.BridgeSetMaster("v-"+d.subnetID+"-e", d.bridge); err != nil {
|
||||||
if err := netif.BridgeSetMaster("v-"+subnetID+"-e", bridge); err != nil {
|
|
||||||
return fmt.Errorf("add veth-e to bridge: %w", err)
|
return fmt.Errorf("add veth-e to bridge: %w", err)
|
||||||
}
|
}
|
||||||
if err := netns.Call(vpcName, func() error {
|
if err := netns.Call(d.vpc, func() error {
|
||||||
return netif.BridgeSetMaster("v-"+subnetID+"-i", bridge)
|
return netif.BridgeSetMaster("v-"+d.subnetID+"-i", d.bridge)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("add veth-i to bridge in netns: %w", err)
|
return fmt.Errorf("add veth-i to bridge in netns: %w", err)
|
||||||
}
|
}
|
||||||
if err := netif.BridgeSetMaster(vxlanIface, bridge); err != nil {
|
if err := netif.BridgeSetMaster(vxlanIface, d.bridge); err != nil {
|
||||||
return fmt.Errorf("add vxlan to bridge: %w", err)
|
return fmt.Errorf("add vxlan to bridge: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// montée des interfaces dans le root netns
|
for _, iface := range []string{"v-" + d.subnetID + "-e", vxlanIface, d.bridge} {
|
||||||
for _, iface := range []string{"v-" + subnetID + "-e", vxlanIface, bridge} {
|
|
||||||
if err := netif.LinkSetUp(iface); err != nil {
|
if err := netif.LinkSetUp(iface); err != nil {
|
||||||
return fmt.Errorf("set up %s: %w", iface, err)
|
return fmt.Errorf("set up %s: %w", iface, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// montée des interfaces dans le netns VPC
|
if err := netns.Call(d.vpc, func() error {
|
||||||
if err := netns.Call(vpcName, func() error {
|
for _, iface := range []string{"v-" + d.subnetID + "-i", d.bridge} {
|
||||||
for _, iface := range []string{"v-" + subnetID + "-i", bridge} {
|
|
||||||
if err := netif.LinkSetUp(iface); err != nil {
|
if err := netif.LinkSetUp(iface); err != nil {
|
||||||
return fmt.Errorf("set up %s: %w", iface, err)
|
return fmt.Errorf("set up %s: %w", iface, err)
|
||||||
}
|
}
|
||||||
|
|
@ -122,32 +76,29 @@ func CreateSubnet(db *badger.DB, subnetName string) error {
|
||||||
return fmt.Errorf("set up interfaces in netns: %w", err)
|
return fmt.Errorf("set up interfaces in netns: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IP gateway (/32) sur le bridge interne
|
if err := netns.Call(d.vpc, func() error {
|
||||||
if err := netns.Call(vpcName, func() error {
|
return netif.AddrAdd(d.bridge, d.gatewayIP)
|
||||||
return netif.AddrAdd(bridge, gatewayIP)
|
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("add addr to bridge in netns: %w", err)
|
return fmt.Errorf("add addr to bridge in netns: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// route subnet (scope link) dans le netns VPC
|
if err := netns.Call(d.vpc, func() error {
|
||||||
if err := netns.Call(vpcName, func() error {
|
return netif.RouteAdd(d.bridge, d.cidr)
|
||||||
return netif.RouteAdd(bridge, subnet)
|
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("add route in netns: %w", err)
|
return fmt.Errorf("add route in netns: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ebtables.DropARPToGateway(bridge, gatewayIP.String()); err != nil {
|
if err := ebtables.DropARPToGateway(d.bridge, d.gatewayIP.String()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ebtables.DropDHCP(bridge); err != nil {
|
if err := ebtables.DropDHCP(d.bridge); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// génération de la config dnsmasq et démarrage du service
|
|
||||||
conf := dhcp.Config{
|
conf := dhcp.Config{
|
||||||
Network: subnet,
|
Network: d.cidr,
|
||||||
Gateway: gatewayIP,
|
Gateway: d.gatewayIP,
|
||||||
Name: vpcName + "_" + bridge,
|
Name: d.vpc + "_" + d.bridge,
|
||||||
ConfDir: "/etc/dnsmasq.d",
|
ConfDir: "/etc/dnsmasq.d",
|
||||||
}
|
}
|
||||||
if _, err := dhcp.GenerateConfig(conf); err != nil {
|
if _, err := dhcp.GenerateConfig(conf); err != nil {
|
||||||
|
|
|
||||||
72
internal/subnet/data.go
Normal file
72
internal/subnet/data.go
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
package subnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.g3e.fr/syonad/two/pkg/db/kv"
|
||||||
|
"github.com/dgraph-io/badger/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
type subnetData struct {
|
||||||
|
vpc string
|
||||||
|
subnetID string
|
||||||
|
bridge string
|
||||||
|
vxlanID int
|
||||||
|
localIface string
|
||||||
|
gatewayIP net.IP
|
||||||
|
cidr *net.IPNet
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadSubnet(db *badger.DB, name string) (subnetData, error) {
|
||||||
|
var d subnetData
|
||||||
|
|
||||||
|
d.subnetID = strings.SplitN(name, "-", 2)[1]
|
||||||
|
d.bridge = "br-" + d.subnetID
|
||||||
|
|
||||||
|
vpc, err := kv.GetFromDB(db, "subnet/"+name+"/vpc")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get vpc: %w", err)
|
||||||
|
}
|
||||||
|
d.vpc = vpc
|
||||||
|
|
||||||
|
vxlanIDStr, err := kv.GetFromDB(db, "subnet/"+name+"/vxlan_id")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get vxlan_id: %w", err)
|
||||||
|
}
|
||||||
|
vxlanID, err := strconv.Atoi(vxlanIDStr)
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("parse vxlan_id: %w", err)
|
||||||
|
}
|
||||||
|
d.vxlanID = vxlanID
|
||||||
|
|
||||||
|
localIface, err := kv.GetFromDB(db, "subnet/"+name+"/local_iface")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get local_iface: %w", err)
|
||||||
|
}
|
||||||
|
d.localIface = localIface
|
||||||
|
|
||||||
|
gatewayIPStr, err := kv.GetFromDB(db, "subnet/"+name+"/gateway_ip")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get gateway_ip: %w", err)
|
||||||
|
}
|
||||||
|
gatewayIP := net.ParseIP(gatewayIPStr)
|
||||||
|
if gatewayIP == nil {
|
||||||
|
return d, fmt.Errorf("invalid gateway_ip: %s", gatewayIPStr)
|
||||||
|
}
|
||||||
|
d.gatewayIP = gatewayIP
|
||||||
|
|
||||||
|
cidrStr, err := kv.GetFromDB(db, "subnet/"+name+"/cidr")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get cidr: %w", err)
|
||||||
|
}
|
||||||
|
_, ipNet, err := net.ParseCIDR(cidrStr)
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("parse cidr: %w", err)
|
||||||
|
}
|
||||||
|
d.cidr = ipNet
|
||||||
|
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,6 @@ package subnet
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.g3e.fr/syonad/two/internal/ebtables"
|
"git.g3e.fr/syonad/two/internal/ebtables"
|
||||||
"git.g3e.fr/syonad/two/internal/netif"
|
"git.g3e.fr/syonad/two/internal/netif"
|
||||||
|
|
@ -23,69 +22,49 @@ func DeleteSubnet(db *badger.DB, subnetName string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
vpcName, err := kv.GetFromDB(db, "subnet/"+subnetName+"/vpc")
|
d, err := loadSubnet(db, subnetName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get vpc: %w", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
vxlanIDStr, err := kv.GetFromDB(db, "subnet/"+subnetName+"/vxlan_id")
|
vxlanIface := fmt.Sprintf("vxlan-%d", d.vxlanID)
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get vxlan_id: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
gatewayIP, err := kv.GetFromDB(db, "subnet/"+subnetName+"/gateway_ip")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get gateway_ip: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
subnetID := strings.SplitN(subnetName, "-", 2)[1]
|
|
||||||
bridge := "br-" + subnetID
|
|
||||||
vxlanIface := "vxlan-" + vxlanIDStr
|
|
||||||
|
|
||||||
// arrêt du service dnsmasq
|
|
||||||
svc, err := systemd.New()
|
svc, err := systemd.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("connect to systemd: %w", err)
|
return fmt.Errorf("connect to systemd: %w", err)
|
||||||
}
|
}
|
||||||
defer svc.Close()
|
defer svc.Close()
|
||||||
|
|
||||||
svcName := "dnsmasq@" + vpcName + "_" + bridge + ".service"
|
if err := svc.Stop("dnsmasq@" + d.vpc + "_" + d.bridge + ".service"); err != nil {
|
||||||
if err := svc.Stop(svcName); err != nil {
|
|
||||||
return fmt.Errorf("stop dnsmasq: %w", err)
|
return fmt.Errorf("stop dnsmasq: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// suppression de la config dnsmasq
|
if err := os.Remove("/etc/dnsmasq.d/" + d.vpc + "_" + d.bridge + ".conf"); err != nil && !os.IsNotExist(err) {
|
||||||
if err := os.Remove("/etc/dnsmasq.d/" + vpcName + "_" + bridge + ".conf"); err != nil && !os.IsNotExist(err) {
|
|
||||||
return fmt.Errorf("remove dnsmasq config: %w", err)
|
return fmt.Errorf("remove dnsmasq config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// suppression des règles ebtables
|
if err := ebtables.DeleteARPToGateway(d.bridge, d.gatewayIP.String()); err != nil {
|
||||||
if err := ebtables.DeleteARPToGateway(bridge, gatewayIP); err != nil {
|
|
||||||
return fmt.Errorf("delete ebtables arp rule: %w", err)
|
return fmt.Errorf("delete ebtables arp rule: %w", err)
|
||||||
}
|
}
|
||||||
if err := ebtables.DeleteDHCP(bridge); err != nil {
|
if err := ebtables.DeleteDHCP(d.bridge); err != nil {
|
||||||
return fmt.Errorf("delete ebtables dhcp rule: %w", err)
|
return fmt.Errorf("delete ebtables dhcp rule: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// suppression du bridge dans le netns VPC
|
if err := netns.Call(d.vpc, func() error {
|
||||||
if err := netns.Call(vpcName, func() error {
|
return netif.DeleteLink(d.bridge)
|
||||||
return netif.DeleteLink(bridge)
|
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("delete bridge in netns: %w", err)
|
return fmt.Errorf("delete bridge in netns: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// suppression du vxlan
|
|
||||||
if err := netif.DeleteLink(vxlanIface); err != nil {
|
if err := netif.DeleteLink(vxlanIface); err != nil {
|
||||||
return fmt.Errorf("delete vxlan: %w", err)
|
return fmt.Errorf("delete vxlan: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// suppression du veth pair (supprime les deux côtés)
|
if err := netif.DeleteLink("v-" + d.subnetID + "-e"); err != nil {
|
||||||
if err := netif.DeleteLink("v-" + subnetID + "-e"); err != nil {
|
|
||||||
return fmt.Errorf("delete veth: %w", err)
|
return fmt.Errorf("delete veth: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// suppression du bridge dans le root netns
|
if err := netif.DeleteLink(d.bridge); err != nil {
|
||||||
if err := netif.DeleteLink(bridge); err != nil {
|
|
||||||
return fmt.Errorf("delete bridge: %w", err)
|
return fmt.Errorf("delete bridge: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@ package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.g3e.fr/syonad/two/internal/iptables"
|
"git.g3e.fr/syonad/two/internal/iptables"
|
||||||
"git.g3e.fr/syonad/two/internal/metadata"
|
"git.g3e.fr/syonad/two/internal/metadata"
|
||||||
|
|
@ -24,84 +22,28 @@ func StartVM(db *badger.DB, name string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
subnetName, err := kv.GetFromDB(db, "vm/"+name+"/subnet")
|
d, err := loadVM(db, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get subnet: %w", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
vpcName, err := kv.GetFromDB(db, "subnet/"+subnetName+"/vpc")
|
if err := netif.CreateTap(d.tapID, d.bridge, d.vpcName); err != nil {
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get vpc: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
gatewayIP, err := kv.GetFromDB(db, "subnet/"+subnetName+"/gateway_ip")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get gateway_ip: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
bridge := "br-" + strings.SplitN(subnetName, "-", 2)[1]
|
|
||||||
|
|
||||||
tapIDStr, err := kv.GetFromDB(db, "vm/"+name+"/tap_id")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get tap_id: %w", err)
|
|
||||||
}
|
|
||||||
tapID, err := strconv.Atoi(tapIDStr)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("parse tap_id: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
vmIP, err := kv.GetFromDB(db, "vm/"+name+"/ip")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get ip: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
metadataPort, err := kv.GetFromDB(db, "vm/"+name+"/metadata_port")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get metadata_port: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
mac, err := kv.GetFromDB(db, "vm/"+name+"/mac")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get mac: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
volumePath, err := kv.GetFromDB(db, "vm/"+name+"/volume_path")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get volume_path: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
memoryStr, err := kv.GetFromDB(db, "vm/"+name+"/memory")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get memory: %w", err)
|
|
||||||
}
|
|
||||||
memory, _ := strconv.Atoi(memoryStr)
|
|
||||||
|
|
||||||
cpusStr, err := kv.GetFromDB(db, "vm/"+name+"/cpus")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get cpus: %w", err)
|
|
||||||
}
|
|
||||||
cpus, _ := strconv.Atoi(cpusStr)
|
|
||||||
|
|
||||||
password, _ := kv.GetFromDB(db, "vm/"+name+"/password")
|
|
||||||
sshkey, _ := kv.GetFromDB(db, "vm/"+name+"/sshkey")
|
|
||||||
|
|
||||||
if err := netif.CreateTap(tapID, bridge, vpcName); err != nil {
|
|
||||||
return fmt.Errorf("create tap: %w", err)
|
return fmt.Errorf("create tap: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := netns.Call(vpcName, func() error {
|
if err := netns.Call(d.vpcName, func() error {
|
||||||
return iptables.AddMetadataRedirect(vmIP, gatewayIP, metadataPort)
|
return iptables.AddMetadataRedirect(d.ip, d.gatewayIP, d.metadataPort)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("add metadata redirect: %w", err)
|
return fmt.Errorf("add metadata redirect: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := metadata.StartMetadata(metadata.NoCloudConfig{
|
if err := metadata.StartMetadata(metadata.NoCloudConfig{
|
||||||
Name: name,
|
Name: name,
|
||||||
VpcName: vpcName,
|
VpcName: d.vpcName,
|
||||||
BindIP: gatewayIP,
|
BindIP: d.gatewayIP,
|
||||||
BindPort: metadataPort,
|
BindPort: d.metadataPort,
|
||||||
Password: password,
|
Password: d.password,
|
||||||
SSHKEY: sshkey,
|
SSHKEY: d.sshkey,
|
||||||
}, db, false); err != nil {
|
}, db, false); err != nil {
|
||||||
return fmt.Errorf("start metadata: %w", err)
|
return fmt.Errorf("start metadata: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
100
internal/vm/data.go
Normal file
100
internal/vm/data.go
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
package vm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.g3e.fr/syonad/two/pkg/db/kv"
|
||||||
|
"github.com/dgraph-io/badger/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
type vmData struct {
|
||||||
|
subnetName string
|
||||||
|
vpcName string
|
||||||
|
gatewayIP string
|
||||||
|
bridge string
|
||||||
|
tapID int
|
||||||
|
ip string
|
||||||
|
metadataPort string
|
||||||
|
mac string
|
||||||
|
volumePath string
|
||||||
|
memory int
|
||||||
|
cpus int
|
||||||
|
password string
|
||||||
|
sshkey string
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadVM(db *badger.DB, name string) (vmData, error) {
|
||||||
|
var d vmData
|
||||||
|
|
||||||
|
subnetName, err := kv.GetFromDB(db, "vm/"+name+"/subnet")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get subnet: %w", err)
|
||||||
|
}
|
||||||
|
d.subnetName = subnetName
|
||||||
|
d.bridge = "br-" + strings.SplitN(subnetName, "-", 2)[1]
|
||||||
|
|
||||||
|
vpcName, err := kv.GetFromDB(db, "subnet/"+subnetName+"/vpc")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get vpc: %w", err)
|
||||||
|
}
|
||||||
|
d.vpcName = vpcName
|
||||||
|
|
||||||
|
gatewayIP, err := kv.GetFromDB(db, "subnet/"+subnetName+"/gateway_ip")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get gateway_ip: %w", err)
|
||||||
|
}
|
||||||
|
d.gatewayIP = gatewayIP
|
||||||
|
|
||||||
|
tapIDStr, err := kv.GetFromDB(db, "vm/"+name+"/tap_id")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get tap_id: %w", err)
|
||||||
|
}
|
||||||
|
tapID, err := strconv.Atoi(tapIDStr)
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("parse tap_id: %w", err)
|
||||||
|
}
|
||||||
|
d.tapID = tapID
|
||||||
|
|
||||||
|
ip, err := kv.GetFromDB(db, "vm/"+name+"/ip")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get ip: %w", err)
|
||||||
|
}
|
||||||
|
d.ip = ip
|
||||||
|
|
||||||
|
metadataPort, err := kv.GetFromDB(db, "vm/"+name+"/metadata_port")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get metadata_port: %w", err)
|
||||||
|
}
|
||||||
|
d.metadataPort = metadataPort
|
||||||
|
|
||||||
|
mac, err := kv.GetFromDB(db, "vm/"+name+"/mac")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get mac: %w", err)
|
||||||
|
}
|
||||||
|
d.mac = mac
|
||||||
|
|
||||||
|
volumePath, err := kv.GetFromDB(db, "vm/"+name+"/volume_path")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get volume_path: %w", err)
|
||||||
|
}
|
||||||
|
d.volumePath = volumePath
|
||||||
|
|
||||||
|
memoryStr, err := kv.GetFromDB(db, "vm/"+name+"/memory")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get memory: %w", err)
|
||||||
|
}
|
||||||
|
d.memory, _ = strconv.Atoi(memoryStr)
|
||||||
|
|
||||||
|
cpusStr, err := kv.GetFromDB(db, "vm/"+name+"/cpus")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get cpus: %w", err)
|
||||||
|
}
|
||||||
|
d.cpus, _ = strconv.Atoi(cpusStr)
|
||||||
|
|
||||||
|
d.password, _ = kv.GetFromDB(db, "vm/"+name+"/password")
|
||||||
|
d.sshkey, _ = kv.GetFromDB(db, "vm/"+name+"/sshkey")
|
||||||
|
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,6 @@ package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
configuration "git.g3e.fr/syonad/two/internal/config/agent"
|
configuration "git.g3e.fr/syonad/two/internal/config/agent"
|
||||||
|
|
@ -25,38 +24,9 @@ func StopVM(db *badger.DB, name string, cfg *configuration.Config) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
subnetName, err := kv.GetFromDB(db, "vm/"+name+"/subnet")
|
d, err := loadVM(db, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get subnet: %w", err)
|
return err
|
||||||
}
|
|
||||||
|
|
||||||
vpcName, err := kv.GetFromDB(db, "subnet/"+subnetName+"/vpc")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get vpc: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
gatewayIP, err := kv.GetFromDB(db, "subnet/"+subnetName+"/gateway_ip")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get gateway_ip: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tapIDStr, err := kv.GetFromDB(db, "vm/"+name+"/tap_id")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get tap_id: %w", err)
|
|
||||||
}
|
|
||||||
tapID, err := strconv.Atoi(tapIDStr)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("parse tap_id: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
vmIP, err := kv.GetFromDB(db, "vm/"+name+"/ip")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get ip: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
metadataPort, err := kv.GetFromDB(db, "vm/"+name+"/metadata_port")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get metadata_port: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
socketPath := fmt.Sprintf("/tmp/%s.qmp-sock", name)
|
socketPath := fmt.Sprintf("/tmp/%s.qmp-sock", name)
|
||||||
|
|
@ -81,8 +51,8 @@ func StopVM(db *badger.DB, name string, cfg *configuration.Config) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := netns.Call(vpcName, func() error {
|
if err := netns.Call(d.vpcName, func() error {
|
||||||
return iptables.DeleteMetadataRedirect(vmIP, gatewayIP, metadataPort)
|
return iptables.DeleteMetadataRedirect(d.ip, d.gatewayIP, d.metadataPort)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("delete metadata redirect: %w", err)
|
return fmt.Errorf("delete metadata redirect: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -91,7 +61,7 @@ func StopVM(db *badger.DB, name string, cfg *configuration.Config) error {
|
||||||
return fmt.Errorf("stop metadata: %w", err)
|
return fmt.Errorf("stop metadata: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := netif.DeleteTap(tapID, vpcName); err != nil {
|
if err := netif.DeleteTap(d.tapID, d.vpcName); err != nil {
|
||||||
return fmt.Errorf("delete tap: %w", err)
|
return fmt.Errorf("delete tap: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue