summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Carr <[email protected]>2025-06-04 06:18:55 -0500
committerJeff Carr <[email protected]>2025-06-04 06:29:52 -0500
commit65563eb8e267896c308839b7cc984f73a4d101b6 (patch)
treee0d41331df701892ceea19963e75209e79017f56
parentbf01596f307ada684019ab863b4c447855c465b5 (diff)
droplet create makes the network and disksv0.2.56
-rw-r--r--doDroplet.go137
-rw-r--r--start.go13
-rw-r--r--validate.go35
3 files changed, 132 insertions, 53 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)
+ }
+}
diff --git a/start.go b/start.go
index a7cf493..76ba91c 100644
--- a/start.go
+++ b/start.go
@@ -52,14 +52,13 @@ func Start(id string) (string, error) {
}
if d.Current == nil {
- // result = d.Hostname + " d.Current == nil"
- // return result, errors.New(result)
+ d.Current = new(virtpb.Current)
+ }
- // is the droplet already on?
- if d.Current.State == virtpb.DropletState_ON {
- result = "EVENT start droplet " + d.Hostname + " is already ON"
- return result, errors.New(result)
- }
+ // is the droplet already on?
+ if d.Current.State == virtpb.DropletState_ON {
+ result = "EVENT start droplet " + d.Hostname + " is already ON"
+ return result, errors.New(result)
}
// make the list of hypervisors that are active and can start new droplets
diff --git a/validate.go b/validate.go
index e648813..c2f788b 100644
--- a/validate.go
+++ b/validate.go
@@ -15,7 +15,6 @@ package main
import (
"errors"
- "fmt"
"os"
"path/filepath"
"strings"
@@ -163,40 +162,6 @@ func ValidateDiskFilenames() ([]*virtpb.Event, error) {
return alle, 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
- }
- }
-
- var i int = 9
- var mac string
- for {
- mac = fmt.Sprintf("22:22:22:22:22:%02d", i)
- if _, ok := macs[mac]; ok {
- log.Info("MAC already defined", mac, macs[mac])
- i += 1
- continue
- }
- log.Info("using new MAC:", mac)
- return mac
- }
-}
-
// consistancy check. run on a regular basis
//
// runs on startup. dies if there are duplicates