feature-8 #9
27 changed files with 523 additions and 57 deletions
|
|
@ -32,7 +32,7 @@ jobs:
|
|||
matrix:
|
||||
goos: [linux]
|
||||
goarch: [amd64]
|
||||
binaries: [db, metadata]
|
||||
binaries: [db, metadata, meta_cli, agent]
|
||||
uses: ./.forgejo/workflows/build.yml
|
||||
with:
|
||||
tag: ${{ needs.set-release-target.outputs.release_cible }}
|
||||
|
|
|
|||
17
cmd/agent/main.go
Normal file
17
cmd/agent/main.go
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
bin_name = os.Args[0]
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
fmt.Printf("%s: Start process\n", bin_name)
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
|
@ -51,17 +52,13 @@ func AddInDB(dbName string, line string) error {
|
|||
id := strings.Split(line, ";")[0] + "/bash"
|
||||
key := []byte(dbName + "/" + id)
|
||||
|
||||
return DB.Update(func(txn *badger.Txn) error {
|
||||
return txn.Set(key, []byte(line))
|
||||
})
|
||||
return kv.AddInDB(DB, string(key), line)
|
||||
}
|
||||
|
||||
func DeleteInDB(dbName, id string) error {
|
||||
key := []byte(dbName + "/" + id + "/bash")
|
||||
|
||||
return DB.Update(func(txn *badger.Txn) error {
|
||||
return txn.Delete(key)
|
||||
})
|
||||
return kv.DeleteInDB(DB, string(key))
|
||||
}
|
||||
|
||||
func CountInDB(dbName, id string) int {
|
||||
|
|
@ -125,7 +122,13 @@ func printDB() {
|
|||
}
|
||||
|
||||
func main() {
|
||||
conf, err := configuration.LoadConfig("/etc/two/agent.yml")
|
||||
conf_file := flag.String("conf", "/etc/two/agent.yml", "configuration file")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
args := flag.Args()
|
||||
|
||||
conf, err := configuration.LoadConfig(*conf_file)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
|
|
@ -133,56 +136,56 @@ func main() {
|
|||
|
||||
DB = kv.InitDB(kv.Config{
|
||||
Path: conf.Database.Path,
|
||||
})
|
||||
}, false)
|
||||
defer DB.Close()
|
||||
|
||||
if len(os.Args) < 2 {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Usage: db <cmd> [args...]")
|
||||
return
|
||||
}
|
||||
|
||||
cmd := os.Args[1]
|
||||
cmd := args[0]
|
||||
|
||||
switch cmd {
|
||||
case "check_in_db":
|
||||
if len(os.Args) != 4 {
|
||||
if len(args) != 3 {
|
||||
fmt.Println("Usage: check_in_db <db_name> <id>")
|
||||
os.Exit(1)
|
||||
}
|
||||
ret := CheckInDB(os.Args[2], os.Args[3])
|
||||
ret := CheckInDB(args[1], args[2])
|
||||
os.Exit(ret)
|
||||
case "add_in_db":
|
||||
if len(os.Args) < 4 {
|
||||
if len(args) < 3 {
|
||||
fmt.Println("Usage: add_in_db <db_name> <line...>")
|
||||
os.Exit(1)
|
||||
}
|
||||
line := strings.Join(os.Args[3:], ";")
|
||||
if err := AddInDB(os.Args[2], line); err != nil {
|
||||
line := strings.Join(args[2:], ";")
|
||||
if err := AddInDB(args[1], line); err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
case "delete_in_db":
|
||||
if len(os.Args) != 4 {
|
||||
if len(args) != 3 {
|
||||
fmt.Println("Usage: delete_in_db <db_name> <id>")
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := DeleteInDB(os.Args[2], os.Args[3]); err != nil {
|
||||
if err := DeleteInDB(args[1], args[2]); err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
case "count_in_db":
|
||||
if len(os.Args) != 4 {
|
||||
if len(args) != 3 {
|
||||
fmt.Println("Usage: count_in_db <db_name> <id>")
|
||||
os.Exit(1)
|
||||
}
|
||||
count := CountInDB(os.Args[2], os.Args[3])
|
||||
count := CountInDB(args[1], args[2])
|
||||
fmt.Println(count)
|
||||
case "get_from_db":
|
||||
if len(os.Args) != 4 {
|
||||
if len(args) != 3 {
|
||||
fmt.Println("Usage: get_from_db <db_name> <id>")
|
||||
os.Exit(1)
|
||||
}
|
||||
line, _ := GetFromDB(os.Args[2], os.Args[3])
|
||||
line, _ := GetFromDB(args[1], args[2])
|
||||
fmt.Println(line)
|
||||
case "print":
|
||||
printDB()
|
||||
|
|
|
|||
54
cmd/meta_cli/main.go
Normal file
54
cmd/meta_cli/main.go
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
configuration "git.g3e.fr/syonad/two/internal/config/agent"
|
||||
"git.g3e.fr/syonad/two/internal/load_db/nocloud"
|
||||
"git.g3e.fr/syonad/two/pkg/db/kv"
|
||||
"git.g3e.fr/syonad/two/pkg/systemd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conf_file := flag.String("conf", "/etc/two/agent.yml", "configuration file")
|
||||
vm_name := flag.String("vm_name", "", "Nom de la vm")
|
||||
vpc := flag.String("vpc_name", "", "vpc name")
|
||||
bind_ip := flag.String("ip", "", "bind ip")
|
||||
bind_port := flag.String("port", "", "bind port")
|
||||
ssh_key := flag.String("key", "", "Clef ssh")
|
||||
password := flag.String("pass", "", "password user")
|
||||
start := flag.Bool("start", false, "start metadata server")
|
||||
stop := flag.Bool("stop", false, "stop metadata server")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
service, _ := systemd.New()
|
||||
|
||||
conf, err := configuration.LoadConfig(*conf_file)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
fmt.Print(conf)
|
||||
|
||||
db := kv.InitDB(kv.Config{
|
||||
Path: conf.Database.Path,
|
||||
}, false)
|
||||
defer db.Close()
|
||||
|
||||
if *start {
|
||||
nocloud.LoadNcCloudInDB(nocloud.Config{
|
||||
VpcName: *vpc,
|
||||
Name: *vm_name,
|
||||
BindIP: *bind_ip,
|
||||
BindPort: *bind_port,
|
||||
Password: *password,
|
||||
SSHKEY: *ssh_key,
|
||||
}, db)
|
||||
service.Start("metadata@" + *vm_name)
|
||||
} else if *stop {
|
||||
nocloud.UnLoadNoCloudInDB(*vm_name, db)
|
||||
service.Stop("metadata@" + *vm_name)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,27 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"git.g3e.fr/syonad/two/internal/metadata"
|
||||
)
|
||||
|
||||
var (
|
||||
iface = flag.String("interface", "0.0.0.0", "Interface IP à écouter")
|
||||
port = flag.Int("port", 0, "Port à utiliser")
|
||||
netns_name = flag.String("netns", "", "Network namespace à utiliser")
|
||||
conf_file = flag.String("conf", "/etc/two/agent.yml", "configuration file")
|
||||
vm_name = flag.String("vm", "", "Name of the vm")
|
||||
)
|
||||
|
||||
func main() {
|
||||
metadata.StartServer()
|
||||
flag.Parse()
|
||||
|
||||
metadata.StartServer(metadata.Config{
|
||||
Netns: *netns_name,
|
||||
Iface: *iface,
|
||||
Port: *port,
|
||||
ConfFile: *conf_file,
|
||||
VmName: *vm_name,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
2
conf/agent/config.dev.yml
Normal file
2
conf/agent/config.dev.yml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
database:
|
||||
path: "./data/"
|
||||
8
go.mod
8
go.mod
|
|
@ -1,9 +1,12 @@
|
|||
module git.g3e.fr/syonad/two
|
||||
|
||||
go 1.23.8
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.24.11
|
||||
|
||||
require (
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.6.0 // indirect
|
||||
github.com/dgraph-io/badger/v4 v4.8.0 // indirect
|
||||
github.com/dgraph-io/ristretto/v2 v2.2.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
|
|
@ -11,6 +14,7 @@ require (
|
|||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/google/flatbuffers v25.2.10+incompatible // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
|
|
@ -27,7 +31,7 @@ require (
|
|||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/sys v0.39.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
)
|
||||
|
|
|
|||
6
go.sum
6
go.sum
|
|
@ -1,5 +1,7 @@
|
|||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
|
||||
github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=
|
||||
github.com/dgraph-io/badger/v4 v4.8.0 h1:JYph1ChBijCw8SLeybvPINizbDKWZ5n/GYbz2yhN/bs=
|
||||
github.com/dgraph-io/badger/v4 v4.8.0/go.mod h1:U6on6e8k/RTbUWxqKR0MvugJuVmkxSNc79ap4917h4w=
|
||||
github.com/dgraph-io/ristretto/v2 v2.2.0 h1:bkY3XzJcXoMuELV8F+vS8kzNgicwQFAaGINAEJdWGOM=
|
||||
|
|
@ -15,6 +17,8 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
|||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q=
|
||||
github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
|
|
@ -49,6 +53,8 @@ golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
|||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
|
|
|
|||
|
|
@ -17,9 +17,7 @@ func LoadConfig(path string) (*Config, error) {
|
|||
|
||||
v.SetDefault("database.path", "/var/lib/two/data/")
|
||||
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v.ReadInConfig()
|
||||
|
||||
var cfg Config
|
||||
if err := v.Unmarshal(&cfg); err != nil {
|
||||
|
|
|
|||
50
internal/load_db/nocloud/render.go
Normal file
50
internal/load_db/nocloud/render.go
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package nocloud
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"embed"
|
||||
"text/template"
|
||||
|
||||
"git.g3e.fr/syonad/two/pkg/db/kv"
|
||||
"github.com/dgraph-io/badger/v4"
|
||||
)
|
||||
|
||||
//go:embed templates/*.tmpl
|
||||
var templateFS embed.FS
|
||||
|
||||
func renderConfig(path string, cfg Config) (string, error) {
|
||||
tpl, err := template.ParseFS(templateFS, path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := tpl.Execute(&buf, cfg); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
var DB *badger.DB
|
||||
|
||||
func LoadNcCloudInDB(config Config, db *badger.DB) {
|
||||
meta_data, _ := renderConfig("templates/meta-data.tmpl", config)
|
||||
user_data, _ := renderConfig("templates/user-data.tmpl", config)
|
||||
network_config, _ := renderConfig("templates/network-config.tmpl", config)
|
||||
vendor_data, _ := renderConfig("templates/vendor-data.tmpl", config)
|
||||
|
||||
DB = db
|
||||
|
||||
kv.AddInDB(DB, "metadata/"+config.Name+"/meta-data", meta_data)
|
||||
kv.AddInDB(DB, "metadata/"+config.Name+"/user-data", user_data)
|
||||
kv.AddInDB(DB, "metadata/"+config.Name+"/network-config", network_config)
|
||||
kv.AddInDB(DB, "metadata/"+config.Name+"/vendor-data", vendor_data)
|
||||
kv.AddInDB(DB, "metadata/"+config.Name+"/vpc", config.VpcName)
|
||||
kv.AddInDB(DB, "metadata/"+config.Name+"/bind_ip", config.BindIP)
|
||||
kv.AddInDB(DB, "metadata/"+config.Name+"/bind_port", config.BindPort)
|
||||
}
|
||||
|
||||
func UnLoadNoCloudInDB(vm_name string, db *badger.DB) {
|
||||
kv.DeleteInDB(DB, "metadata/"+vm_name)
|
||||
}
|
||||
10
internal/load_db/nocloud/struct.go
Normal file
10
internal/load_db/nocloud/struct.go
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
package nocloud
|
||||
|
||||
type Config struct {
|
||||
VpcName string
|
||||
BindIP string
|
||||
BindPort string
|
||||
Name string
|
||||
Password string
|
||||
SSHKEY string
|
||||
}
|
||||
2
internal/load_db/nocloud/templates/meta-data.tmpl
Normal file
2
internal/load_db/nocloud/templates/meta-data.tmpl
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
instance-id: {{ .Name }}
|
||||
local-hostname: {{ .Name }}
|
||||
4
internal/load_db/nocloud/templates/network-config.tmpl
Normal file
4
internal/load_db/nocloud/templates/network-config.tmpl
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
version: 2
|
||||
ethernets:
|
||||
eth0:
|
||||
dhcp4: true
|
||||
3
internal/load_db/nocloud/templates/user-data.tmpl
Normal file
3
internal/load_db/nocloud/templates/user-data.tmpl
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
passwd -d root
|
||||
13
internal/load_db/nocloud/templates/vendor-data.tmpl
Normal file
13
internal/load_db/nocloud/templates/vendor-data.tmpl
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#cloud-config
|
||||
users:
|
||||
- name: syonad
|
||||
lock_passwd: false
|
||||
gecos: alpine Cloud User
|
||||
groups: [adm, wheel]
|
||||
doas:
|
||||
- permit nopass syonad
|
||||
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
|
||||
shell: /bin/ash
|
||||
passwd: "{{ .Password }}"
|
||||
ssh_authorized_keys:
|
||||
- "{{ .SSHKEY }}"
|
||||
|
|
@ -1,24 +1,20 @@
|
|||
package metadata
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
configuration "git.g3e.fr/syonad/two/internal/config/agent"
|
||||
"git.g3e.fr/syonad/two/internal/netns"
|
||||
"git.g3e.fr/syonad/two/pkg/db/kv"
|
||||
)
|
||||
|
||||
var data NoCloudData
|
||||
|
||||
var (
|
||||
iface = flag.String("interface", "0.0.0.0", "Interface IP à écouter")
|
||||
port = flag.Int("port", 8080, "Port à utiliser")
|
||||
file = flag.String("file", "", "Fichier JSON contenant les données NoCloud")
|
||||
)
|
||||
|
||||
func getIP(r *http.Request) string {
|
||||
ip, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||
if err != nil {
|
||||
|
|
@ -27,6 +23,51 @@ func getIP(r *http.Request) string {
|
|||
return ip
|
||||
}
|
||||
|
||||
func getFromDB(config Config) NoCloudData {
|
||||
var netns_name string
|
||||
var port int
|
||||
var iface string
|
||||
|
||||
conf_db, _ := configuration.LoadConfig(config.ConfFile)
|
||||
|
||||
db := kv.InitDB(kv.Config{Path: conf_db.Database.Path}, true)
|
||||
defer db.Close()
|
||||
|
||||
metadata, _ := kv.GetFromDB(db, "metadata/"+config.VmName+"/meta-data")
|
||||
userdata, _ := kv.GetFromDB(db, "metadata/"+config.VmName+"/user-data")
|
||||
networkconfig, _ := kv.GetFromDB(db, "metadata/"+config.VmName+"/network-config")
|
||||
vendordata, _ := kv.GetFromDB(db, "metadata/"+config.VmName+"/vendor-data")
|
||||
|
||||
if config.Netns == "" {
|
||||
netns_name, _ = kv.GetFromDB(db, "metadata/"+config.VmName+"/vpc")
|
||||
} else {
|
||||
netns_name = config.Netns
|
||||
}
|
||||
|
||||
if config.Iface == "" {
|
||||
iface, _ = kv.GetFromDB(db, "metadata/"+config.VmName+"/bind_ip")
|
||||
} else {
|
||||
iface = config.Iface
|
||||
}
|
||||
|
||||
if config.Port == 0 {
|
||||
sport, _ := kv.GetFromDB(db, "metadata/"+config.VmName+"/bind_port")
|
||||
port, _ = strconv.Atoi(sport)
|
||||
} else {
|
||||
port = config.Port
|
||||
}
|
||||
|
||||
return NoCloudData{
|
||||
MetaData: metadata,
|
||||
UserData: userdata,
|
||||
NetworkConfig: networkconfig,
|
||||
VendorData: vendordata,
|
||||
NetNs: netns_name,
|
||||
Iface: iface,
|
||||
Port: port,
|
||||
}
|
||||
}
|
||||
|
||||
func rootHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ip := getIP(r)
|
||||
path := r.URL.Path
|
||||
|
|
@ -51,25 +92,18 @@ func rootHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
func StartServer() {
|
||||
flag.Parse()
|
||||
func StartServer(config Config) {
|
||||
data = getFromDB(config)
|
||||
|
||||
if *file == "" {
|
||||
log.Fatal("Vous devez spécifier un fichier via --file")
|
||||
}
|
||||
|
||||
raw, err := ioutil.ReadFile(*file)
|
||||
if err != nil {
|
||||
log.Fatalf("Erreur de lecture du fichier: %v", err)
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(raw, &data); err != nil {
|
||||
log.Fatalf("Erreur de parsing JSON: %v", err)
|
||||
if data.NetNs != "" {
|
||||
if err := netns.Enter(data.NetNs); err != nil {
|
||||
log.Fatalf("Impossible d'entrer dans le netns: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
http.HandleFunc("/", rootHandler)
|
||||
|
||||
address := fmt.Sprintf("%s:%d", *iface, *port)
|
||||
address := fmt.Sprintf("%s:%d", data.Iface, data.Port)
|
||||
log.Printf("Serveur NoCloud démarré sur http://%s/", address)
|
||||
log.Fatal(http.ListenAndServe(address, nil))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,20 @@
|
|||
package metadata
|
||||
|
||||
type NoCloudData struct {
|
||||
MetaData string `json:"meta-data"`
|
||||
UserData string `json:"user-data"`
|
||||
NetworkConfig string `json:"network-config"`
|
||||
VendorData string `json:"vendor-data"`
|
||||
MetaData string
|
||||
UserData string
|
||||
NetworkConfig string
|
||||
VendorData string
|
||||
NetNs string
|
||||
Iface string
|
||||
Port int
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Netns string
|
||||
File string
|
||||
Iface string
|
||||
Port int
|
||||
ConfFile string
|
||||
VmName string
|
||||
}
|
||||
|
|
|
|||
5
internal/netns/enter.go
Normal file
5
internal/netns/enter.go
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
package netns
|
||||
|
||||
func Enter(name string) error {
|
||||
return enter(name)
|
||||
}
|
||||
26
internal/netns/enter_linux.go
Normal file
26
internal/netns/enter_linux.go
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
//go:build linux
|
||||
|
||||
package netns
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func enter(name string) error {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
path := fmt.Sprintf("/var/run/netns/%s", name)
|
||||
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return unix.Setns(int(f.Fd()), unix.CLONE_NEWNET)
|
||||
}
|
||||
8
internal/netns/enter_other.go
Normal file
8
internal/netns/enter_other.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
//go:build !linux
|
||||
|
||||
package netns
|
||||
|
||||
func enter(name string) error {
|
||||
// Ignoré hors Linux
|
||||
return nil
|
||||
}
|
||||
11
pkg/db/kv/addInDB.go
Normal file
11
pkg/db/kv/addInDB.go
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package kv
|
||||
|
||||
import (
|
||||
"github.com/dgraph-io/badger/v4"
|
||||
)
|
||||
|
||||
func AddInDB(db *badger.DB, key string, value string) error {
|
||||
return db.Update(func(txn *badger.Txn) error {
|
||||
return txn.Set([]byte(key), []byte(value))
|
||||
})
|
||||
}
|
||||
44
pkg/db/kv/deleteInDB.go
Normal file
44
pkg/db/kv/deleteInDB.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package kv
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/dgraph-io/badger/v4"
|
||||
)
|
||||
|
||||
func deleteKey(db *badger.DB, key string) error {
|
||||
return db.Update(func(txn *badger.Txn) error {
|
||||
return txn.Delete([]byte(key))
|
||||
})
|
||||
}
|
||||
|
||||
func DeleteInDB(db *badger.DB, key string) error {
|
||||
|
||||
prefix := []byte(key + "/")
|
||||
|
||||
err := db.View(func(txn *badger.Txn) error {
|
||||
opts := badger.DefaultIteratorOptions
|
||||
opts.PrefetchValues = false
|
||||
|
||||
it := txn.NewIterator(opts)
|
||||
defer it.Close()
|
||||
|
||||
for it.Seek(prefix); it.ValidForPrefix(prefix); it.Next() {
|
||||
item := it.Item()
|
||||
key := item.Key()
|
||||
|
||||
k := append([]byte{}, key...)
|
||||
fmt.Println(string(k))
|
||||
if err := deleteKey(db, string(k)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return deleteKey(db, key)
|
||||
}
|
||||
22
pkg/db/kv/getInDB.go
Normal file
22
pkg/db/kv/getInDB.go
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
package kv
|
||||
|
||||
import (
|
||||
"github.com/dgraph-io/badger/v4"
|
||||
)
|
||||
|
||||
func GetFromDB(db *badger.DB, key string) (string, error) {
|
||||
var result string
|
||||
|
||||
err := db.View(func(txn *badger.Txn) error {
|
||||
item, err := txn.Get([]byte(key))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return item.Value(func(val []byte) error {
|
||||
result = string(val)
|
||||
return nil
|
||||
})
|
||||
})
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
|
@ -4,8 +4,9 @@ import (
|
|||
"github.com/dgraph-io/badger/v4"
|
||||
)
|
||||
|
||||
func InitDB(conf Config) *badger.DB {
|
||||
opts := badger.DefaultOptions(conf.Path)
|
||||
func InitDB(conf Config, readonly bool) *badger.DB {
|
||||
opts := badger.DefaultOptions(conf.Path).
|
||||
WithReadOnly(readonly)
|
||||
opts.Logger = nil
|
||||
opts.ValueLogFileSize = 10 << 20 // 10 Mo par fichier vlog
|
||||
opts.NumMemtables = 1
|
||||
|
|
|
|||
109
pkg/systemd/main.go
Normal file
109
pkg/systemd/main.go
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
package systemd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-systemd/v22/dbus"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTimeout = 5 * time.Second
|
||||
jobMode = "replace"
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
conn *dbus.Conn
|
||||
}
|
||||
|
||||
type ServiceStatus struct {
|
||||
Name string
|
||||
LoadState string
|
||||
ActiveState string
|
||||
SubState string
|
||||
MainPID uint32
|
||||
}
|
||||
|
||||
// New crée une connexion D-Bus systemd (scope système)
|
||||
func New() (*Manager, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
|
||||
defer cancel()
|
||||
|
||||
conn, err := dbus.NewSystemConnectionContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Manager{conn: conn}, nil
|
||||
}
|
||||
|
||||
// Close ferme la connexion D-Bus
|
||||
func (m *Manager) Close() {
|
||||
if m.conn != nil {
|
||||
m.conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Start démarre un service systemd
|
||||
func (m *Manager) Start(service string) error {
|
||||
return m.job("StartUnit", service)
|
||||
}
|
||||
|
||||
// Stop arrête un service systemd
|
||||
func (m *Manager) Stop(service string) error {
|
||||
return m.job("StopUnit", service)
|
||||
}
|
||||
|
||||
func (m *Manager) job(method, service string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
|
||||
defer cancel()
|
||||
|
||||
ch := make(chan string, 1)
|
||||
|
||||
var err error
|
||||
switch method {
|
||||
case "StartUnit":
|
||||
_, err = m.conn.StartUnitContext(ctx, service, jobMode, ch)
|
||||
case "StopUnit":
|
||||
_, err = m.conn.StopUnitContext(ctx, service, jobMode, ch)
|
||||
default:
|
||||
return errors.New("unsupported job method")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result := <-ch
|
||||
if result != "done" {
|
||||
return fmt.Errorf("%s %s failed: %s", method, service, result)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Status retourne l’état courant du service
|
||||
func (m *Manager) Status(service string) (*ServiceStatus, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
|
||||
defer cancel()
|
||||
|
||||
props, err := m.conn.GetUnitPropertiesContext(ctx, service)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
status := &ServiceStatus{
|
||||
Name: service,
|
||||
LoadState: props["LoadState"].(string),
|
||||
ActiveState: props["ActiveState"].(string),
|
||||
SubState: props["SubState"].(string),
|
||||
}
|
||||
|
||||
if pid, ok := props["MainPID"].(uint32); ok {
|
||||
status.MainPID = pid
|
||||
}
|
||||
|
||||
return status, nil
|
||||
}
|
||||
10
systemd/metadata@.service
Normal file
10
systemd/metadata@.service
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[Unit]
|
||||
Description=metadata in netns %i
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/opt/two/bin/metadata --vm %i
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Loading…
Add table
Add a link
Reference in a new issue