diff options
| author | Jeff Carr <[email protected]> | 2025-06-04 06:18:55 -0500 |
|---|---|---|
| committer | Jeff Carr <[email protected]> | 2025-06-04 06:29:52 -0500 |
| commit | 65563eb8e267896c308839b7cc984f73a4d101b6 (patch) | |
| tree | e0d41331df701892ceea19963e75209e79017f56 /doDroplet.go | |
| parent | bf01596f307ada684019ab863b4c447855c465b5 (diff) | |
droplet create makes the network and disksv0.2.56
Diffstat (limited to 'doDroplet.go')
| -rw-r--r-- | doDroplet.go | 137 |
1 files changed, 126 insertions, 11 deletions
diff --git a/doDroplet.go b/doDroplet.go index adba47c..7e40242 100644 --- a/doDroplet.go +++ b/doDroplet.go @@ -7,11 +7,15 @@ package main import ( "fmt" + "math/rand" "net/http" "net/url" + "path/filepath" + "strings" "time" "github.com/google/uuid" + "go.wit.com/lib/gui/shell" "go.wit.com/lib/protobuf/virtpb" "go.wit.com/log" ) @@ -132,12 +136,12 @@ func doEvent(e *virtpb.Event) *virtpb.Event { } result.DropletName = e.Droplet.Hostname result.Error = e.Droplet.FormatTEXT() // feedback to the other side for debugging - if e.Droplet != nil { - if err := createDroplet(e.Droplet, result); err != nil { - result.Error += fmt.Sprintf("createDroplet() err: %v", err) - result.State = virtpb.Event_FAIL - return result - } + + // attempt to create the new droplet + if err := createDroplet(e.Droplet, result); err != nil { + result.Error += fmt.Sprintf("createDroplet() err: %v", err) + result.State = virtpb.Event_FAIL + return result } log.Println("create droplet worked", e.Droplet.FormatTEXT()) result.State = virtpb.Event_DONE @@ -224,23 +228,134 @@ func createDroplet(newd *virtpb.Droplet, result *virtpb.Event) error { return fmt.Errorf("hostname already defined") } + // by default, on locally imported domains, set the preferred hypervisor! newd.LocalOnly = "yes on: " + "farm03" - // by default, on locally imported domains, set the preferred hypervisor! newd.PreferredHypervisor = "farm03" + newd.StartState = virtpb.DropletState_OFF newd.Current = new(virtpb.Current) - newd.Current.Hypervisor = "farm03" - newd.StartState = virtpb.DropletState_OFF newd.Current.State = virtpb.DropletState_OFF - me.cluster.AddDroplet(newd) + // create the network + if err := createNetwork(newd); err != nil { + return err + } + // create the disks + if err := createDisks(newd); err != nil { + return err + } + + // append the protobuf and save it + me.cluster.AddDroplet(newd) if err := me.cluster.ConfigSave(); err != nil { log.Info("configsave error", err) return fmt.Errorf("ConfigSave() error: %v", err) } - result.State = virtpb.Event_DONE return nil } + +func findDisks(d *virtpb.Droplet) error { + log.Info("need to do this") + return nil +} + +func createDisks(d *virtpb.Droplet) error { + if d.Disks != nil { + return findDisks(d) + } + + newdisk := new(virtpb.Disk) + newdisk.Filename = d.Hostname + ".qcow2" + newdisk.Filepath = "/home/nfs2" + d.Disks = append(d.Disks, newdisk) + + basefile := "/home/nfs2/base2025.wit-5.qcow2" + newfile := filepath.Join(newdisk.Filepath, newdisk.Filename) + + if !shell.Exists(newdisk.Filepath) { + return fmt.Errorf("disk image path missing: %s", newdisk.Filepath) + } + + if !shell.Exists(basefile) { + return fmt.Errorf("basefile %s missing", basefile) + } + + if shell.Exists(newfile) { + return fmt.Errorf("disk image already exists: %s", newfile) + } + + cmd := []string{"dd", "bs=100M", "status=progress", "oflag=dsync", "if=" + basefile, "of=" + newfile} + result := shell.RunRealtime(cmd) + if result.Exit != 0 { + return fmt.Errorf("dd to %s failed %d\n%s\n%s", newfile, result.Exit, strings.Join(result.Stdout, "\n"), strings.Join(result.Stderr, "\n")) + } + + return nil +} + +func createNetwork(d *virtpb.Droplet) error { + if d.Networks != nil { + // network already done + return nil + } + if len(d.Networks) > 0 { + // network already done + return nil + } + + n := new(virtpb.Network) + n.Mac = getNewMac() + n.Name = "worldbr" + d.Networks = append(d.Networks, n) + + return nil +} + +func getNewMac() string { + // mac address map to check for duplicates + var macs map[string]string + macs = make(map[string]string) + + loop := me.cluster.DropletsAll() // get the list of droplets + for loop.Scan() { + d := loop.Next() + for _, n := range d.Networks { + // log.Println("network:", n.Mac, d.Uuid, d.Hostname) + if _, ok := macs[n.Mac]; ok { + // UUID already exists + log.Info("duplicate MAC", n.Mac, macs[n.Mac]) + log.Info("duplicate MAC", n.Mac, d.Hostname) + return "" + } + macs[n.Mac] = d.Hostname + } + } + + return generateMAC(macs) +} + +func generateMAC(macs map[string]string) string { + prefix := []byte{0x22, 0x22, 0x22} + for { + // Generate last 3 bytes randomly + suffix := make([]byte, 3) + if _, err := rand.Read(suffix); err != nil { + log.Fatalf("Failed to generate random bytes: %v", err) + } + + // Format full MAC address + mac := fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", + prefix[0], prefix[1], prefix[2], + suffix[0], suffix[1], suffix[2]) + + // Check if MAC is already used + if _, exists := macs[mac]; !exists { + log.Println("Using new MAC:", mac) + return mac + } + log.Println("MAC already defined:", mac) + } +} |
