summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--add.go28
-rw-r--r--change.go10
-rw-r--r--cluster.proto4
-rw-r--r--config.go77
-rw-r--r--droplet.proto10
-rwxr-xr-xexample/configfilebin5544235 -> 0 bytes
-rw-r--r--example/main.go62
-rw-r--r--helpers.go16
-rw-r--r--newCluster.go19
-rw-r--r--sampleData.go13
-rw-r--r--scanIterator.go106
11 files changed, 205 insertions, 140 deletions
diff --git a/add.go b/add.go
index e1c0298..1543341 100644
--- a/add.go
+++ b/add.go
@@ -36,8 +36,10 @@ func (all *Droplets) oldFindDroplet(name string) *Droplet {
return nil
}
-func (c *Cluster) FindDropletByName(name string) *Droplet {
- for _, d := range c.Droplets {
+func (c *NewCluster) FindDropletByName(name string) *Droplet {
+ loop := c.DropletsAll() // get the list of droplets
+ for loop.Scan() {
+ d := loop.Droplet()
if d.Hostname == name {
return d
}
@@ -45,8 +47,8 @@ func (c *Cluster) FindDropletByName(name string) *Droplet {
return nil
}
-func (c *Cluster) FindHypervisorByName(name string) *Hypervisor {
- for _, h := range c.Hypervisors {
+func (c *NewCluster) FindHypervisorByName(name string) *Hypervisor {
+ for _, h := range c.h.Hypervisors {
if h.Hostname == name {
return h
}
@@ -54,7 +56,7 @@ func (c *Cluster) FindHypervisorByName(name string) *Hypervisor {
return nil
}
-func (c *Cluster) AddHypervisor(hostname string, cpus int, mem int) *Hypervisor {
+func (c *NewCluster) AddHypervisor(hostname string, cpus int, mem int) *Hypervisor {
h := c.FindHypervisorByName(hostname)
if h != nil {
return h
@@ -71,11 +73,11 @@ func (c *Cluster) AddHypervisor(hostname string, cpus int, mem int) *Hypervisor
h.Cpus = 1
}
h.SetMemoryGB(mem * 32)
- c.Hypervisors = append(c.Hypervisors, h)
+ c.h.Hypervisors = append(c.h.Hypervisors, h)
return h
}
-func (c *Cluster) AddDroplet(uuid string, hostname string, cpus int, mem int) *Droplet {
+func (c *NewCluster) AddDroplet(uuid string, hostname string, cpus int, mem int) *Droplet {
d := c.FindDropletByName(hostname)
if d != nil {
return d
@@ -91,7 +93,7 @@ func (c *Cluster) AddDroplet(uuid string, hostname string, cpus int, mem int) *D
d.Cpus = 1
}
d.Memory = SetGB(mem * 32)
- c.Droplets = append(c.Droplets, d)
+ c.d.Droplets = append(c.d.Droplets, d)
return d
}
@@ -121,8 +123,10 @@ func HumanFormatBytes(b int64) string {
return fmt.Sprintf("%d TB", tb)
}
-func (c *Cluster) BlankFields() {
- for _, d := range c.Droplets {
+func (c *NewCluster) BlankFields() {
+ loop := c.DropletsAll() // get the list of droplets
+ for loop.Scan() {
+ d := loop.Droplet()
d.Current = nil
}
}
@@ -131,7 +135,7 @@ func (epb *Events) AppendEvent(e *Event) {
epb.Events = append(epb.Events, e)
}
-func (c *Cluster) ClusterStable() (bool, string) {
+func (c *NewCluster) ClusterStable() (bool, string) {
last := time.Since(c.Unstable.AsTime())
if last > c.UnstableTimeout.AsDuration() {
// the cluster has not been stable for 133 seconds
@@ -143,7 +147,7 @@ func (c *Cluster) ClusterStable() (bool, string) {
}
// check the cluster and droplet to make sure it's ready to start
-func (c *Cluster) DropletReady(d *Droplet) (bool, string) {
+func (c *NewCluster) DropletReady(d *Droplet) (bool, string) {
if c == nil {
return false, "cluster == nil"
}
diff --git a/change.go b/change.go
index 25cd57b..dc77b0c 100644
--- a/change.go
+++ b/change.go
@@ -94,8 +94,6 @@ func NewAddEvent(a any, fname string, newval any) *Event {
var d *Droplet
d = a.(*Droplet)
e.Droplet = d.Hostname
- case *Cluster:
- e.Droplet = "Cluster"
case nil:
e.Droplet = "<nil>"
default:
@@ -131,7 +129,7 @@ func (d *Droplet) SetCpus(b int64) {
}
// records an event that the droplet changed state (aka turned on, turned off, etc)
-func (c *Cluster) ChangeDropletState(d *Droplet, newState DropletState) error {
+func (c *NewCluster) ChangeDropletState(d *Droplet, newState DropletState) error {
if c == nil {
return errors.New("cluster is nil")
}
@@ -153,12 +151,12 @@ func (c *Cluster) ChangeDropletState(d *Droplet, newState DropletState) error {
now := time.Now()
e.Start = timestamppb.New(now)
- c.E.Events = append(c.E.Events, e)
+ c.e.Events = append(c.e.Events, e)
return nil
}
// records an event that the droplet migrated to another hypervisor
-func (c *Cluster) DropletMoved(d *Droplet, newh *Hypervisor) error {
+func (c *NewCluster) DropletMoved(d *Droplet, newh *Hypervisor) error {
if c == nil {
return errors.New("cluster is nil")
}
@@ -185,7 +183,7 @@ func (c *Cluster) DropletMoved(d *Droplet, newh *Hypervisor) error {
now := time.Now()
e.Start = timestamppb.New(now)
- c.E.Events = append(c.E.Events, e)
+ c.e.Events = append(c.e.Events, e)
// update the droplet record
d.Current.Hypervisor = newh.Hostname
diff --git a/cluster.proto b/cluster.proto
index 8658597..9569465 100644
--- a/cluster.proto
+++ b/cluster.proto
@@ -7,7 +7,7 @@ import "event.proto";
import "google/protobuf/timestamp.proto"; // Import the well-known type for Timestamp
import "google/protobuf/duration.proto"; // Import the well-known type for Timestamp
-message Cluster {
+message OldCluster {
int64 id = 1;
repeated string dirs = 2;
@@ -15,7 +15,7 @@ message Cluster {
repeated Hypervisor hypervisors = 4;
// repeated Event events = 5;
- Droplets d = 6;
+ // Droplets d = 6;
Hypervisors h = 7;
Events e = 8;
google.protobuf.Timestamp unstable = 9; // the last time we heard anything from this droplet
diff --git a/config.go b/config.go
index 7973da9..8fc9d27 100644
--- a/config.go
+++ b/config.go
@@ -16,7 +16,7 @@ import (
// writes out the cluster information it seperate files
// to make it humanly possible to hand edit things as needed
-func (c *Cluster) ConfigSave() error {
+func (c *NewCluster) ConfigSave() error {
// try to backup the current cluster config files
if err := backupConfig(); err != nil {
return err
@@ -25,9 +25,8 @@ func (c *Cluster) ConfigSave() error {
// make a new droplets struct
var d *Droplets
d = new(Droplets)
- d.Droplets = c.Droplets
// copy all the records over to the new struct
- for _, drop := range c.Droplets {
+ for _, drop := range c.d.Droplets {
d.Droplets = append(d.Droplets, drop)
}
// delete all the Current data so it's not put in the config file
@@ -43,83 +42,42 @@ func (c *Cluster) ConfigSave() error {
return err
}
- var h *Hypervisors
- h = new(Hypervisors)
- h.Hypervisors = c.Hypervisors
- if err := ConfigWriteJSON(h, "hypervisors.json"); err != nil {
+ if err := ConfigWriteJSON(c.h, "hypervisors.json"); err != nil {
fmt.Println("hypervisors.json write failed")
return err
}
- if err := ConfigWriteTEXT(h, "hypervisors.text"); err != nil {
+ if err := ConfigWriteTEXT(c.h, "hypervisors.text"); err != nil {
fmt.Println("hypervisors.json write failed")
return err
}
- if err := ConfigWriteJSON(c.E, "events.json"); err != nil {
+ if err := ConfigWriteJSON(c.e, "events.json"); err != nil {
fmt.Println("events.json write failed")
return err
}
- if err := ConfigWriteTEXT(c.E, "events.text"); err != nil {
+ if err := ConfigWriteTEXT(c.e, "events.text"); err != nil {
fmt.Println("events.json write failed")
return err
}
-
- if err := ConfigWriteTEXT(c, "cluster.full.text"); err != nil {
- fmt.Println("Cluster.json write failed")
- return err
- }
-
- var newc Cluster
- newc.Dirs = c.Dirs
- newc.Droplets = nil
- newc.Hypervisors = nil
- newc.E = nil
- if err := ConfigWriteTEXT(&newc, "cluster.text"); err != nil {
- fmt.Println("cluster.json write failed")
- return err
- }
-
return nil
}
-func (c *Cluster) ConfigLoad() error {
+func (c *NewCluster) ConfigLoad() error {
if c == nil {
return errors.New("It's not safe to run ConfigLoad() on a nil cluster")
}
- // load the cluster config file
- if data, err := loadFile("cluster.text"); err == nil {
- if err = prototext.Unmarshal(data, c); err != nil {
- fmt.Println("broken cluster.text config file")
- fmt.Println(err)
- return errors.New("cluster.text file is broken")
- }
- } else {
- return err
- }
-
- var d *Droplets
- d = new(Droplets)
- // load the droplet config file
if data, err := loadFile("droplets.json"); err == nil {
- if err = protojson.Unmarshal(data, d); err != nil {
+ if err = protojson.Unmarshal(data, c.d); err != nil {
fmt.Println("broken droplets.json config file")
return err
}
} else {
return err
}
- // copy them over. is this needed? does the memory free otherwise?
- // also set initial values
- for _, drop := range d.Droplets {
- c.Droplets = append(c.Droplets, drop)
- }
- var h *Hypervisors
- h = new(Hypervisors)
- // load the hypervisors config file
if data, err := loadFile("hypervisors.json"); err == nil {
- if err = protojson.Unmarshal(data, h); err != nil {
+ if err = protojson.Unmarshal(data, c.h); err != nil {
fmt.Println("broken hypervisors.json config file")
return err
}
@@ -127,26 +85,15 @@ func (c *Cluster) ConfigLoad() error {
fmt.Println("ERROR HERE IN Hypervisors")
return err
}
- // copy them over. is this needed? does the memory free otherwise?
- for _, a := range h.Hypervisors {
- c.Hypervisors = append(c.Hypervisors, a)
- }
- var e *Events
- e = new(Events)
-
- if c.E == nil {
+ if c.e == nil {
// this seems to panic on nil. something is wrong about doing this
// does it not stay allocated after this function ends?
- c.E = new(Events)
+ c.e = new(Events)
}
- if err := e.loadEvents(); err != nil {
+ if err := c.e.loadEvents(); err != nil {
return err
}
- // copy them over. is this needed? does the memory free otherwise?
- for _, e := range e.Events {
- c.E.Events = append(c.E.Events, e)
- }
return nil
}
diff --git a/droplet.proto b/droplet.proto
index adf1299..f52fa7f 100644
--- a/droplet.proto
+++ b/droplet.proto
@@ -1,6 +1,7 @@
syntax = "proto3";
package virtbuf;
+import "google/protobuf/duration.proto"; // Import the well-known type for Timestamp
import "google/protobuf/timestamp.proto"; // Import the well-known type for Timestamp
message Droplets {
@@ -27,7 +28,10 @@ message Droplet {
string local_only = 14; // this is only defined locally on the hypervisor
string custom_xml = 15; // if needed,
- DropletArchive archive = 16; // what the state of the droplet is SUPPOSED TO BE ('on' or 'off')
+ Archive archive = 16; // what the state of the droplet is SUPPOSED TO BE ('on' or 'off')
+
+ google.protobuf.Timestamp unstable = 39; // the last time we heard anything from this droplet
+ google.protobuf.Duration unstable_timeout = 40; // the last time we heard anything from this droplet
}
// volatile data. the current settings and values of things.
@@ -58,8 +62,8 @@ enum DropletState {
}
enum DropletArchive {
- ARCHIVE_DUP = 0;
- ARCHIVE_USER = 1;
+ DUP = 0;
+ USER = 1;
}
message Network {
diff --git a/example/configfile b/example/configfile
deleted file mode 100755
index 81377e3..0000000
--- a/example/configfile
+++ /dev/null
Binary files differ
diff --git a/example/main.go b/example/main.go
index d54803d..8327628 100644
--- a/example/main.go
+++ b/example/main.go
@@ -1,15 +1,11 @@
package main
import (
- "bufio"
- "bytes"
"fmt"
"io/ioutil"
"log"
"os"
- "google.golang.org/protobuf/proto"
-
pb "go.wit.com/lib/protobuf/virtbuf"
)
@@ -20,38 +16,43 @@ import (
func main() {
TestWriteCluster()
- in, err := ioutil.ReadFile("/tmp/testing4.protobuf")
+ _, err := ioutil.ReadFile("/tmp/testing4.protobuf")
if err != nil {
log.Fatalln("Error reading file:", err)
}
- var aCluster pb.Cluster
- if err := proto.Unmarshal(in, &aCluster); err != nil {
- log.Fatalln("Failed to parse droplet:", err)
- }
+ var c *pb.NewCluster
+ c = new(pb.NewCluster)
- log.Println(aCluster.String())
+ // log.Println(aCluster.String())
// show the droplets to STDOUT
- for _, d := range aCluster.Droplets {
+ loop := c.DropletsAll() // get the list of droplets
+ for loop.Scan() {
+ d := loop.Droplet()
fmt.Println("\tdroplet =", d.Hostname, "preffered host:", d.PreferredHypervisor)
}
- // show the hypervisors to STDOUT
- for _, h := range aCluster.Hypervisors {
- fmt.Println("\thypervisor =", h.Hostname, h.GetMemoryPrintable())
- }
+ /*
+ // show the hypervisors to STDOUT
+ for _, h := range aCluster.Hypervisors {
+ fmt.Println("\thypervisor =", h.Hostname, h.GetMemoryPrintable())
+ }
+ */
- json := aCluster.FormatJSON()
- fmt.Println(json)
+ /*
+ json := aCluster.FormatJSON()
+ fmt.Println(json)
- data, _ := aCluster.MarshalJSON()
- fmt.Println(string(data))
+ data, _ := aCluster.MarshalJSON()
+ fmt.Println(string(data))
- text := aCluster.FormatTEXT()
- fmt.Println(text)
+ text := aCluster.FormatTEXT()
+ fmt.Println(text)
+ */
}
-func marshalWriteToFile(myWriter *bufio.Writer, c *pb.Cluster) {
+/*
+func marshalWriteToFile(myWriter *bufio.Writer, c *pb.NewCluster) {
buf, err := proto.Marshal(c)
if err != nil {
log.Fatal("marshaling error: ", err)
@@ -65,22 +66,20 @@ func marshalWriteToFile(myWriter *bufio.Writer, c *pb.Cluster) {
myWriter.Flush()
log.Println("bufio.Write() tmp2, err = ", tmp2, err)
}
+*/
func TestWriteCluster() {
- buf := new(bytes.Buffer)
-
c := pb.CreateSampleCluster(7)
+ os.Setenv("VIRTIGO_HOME", "/tmp/virtigo/")
- got := buf.String()
- log.Println(got)
-
- newfile, _ := os.Create("/tmp/testing4.protobuf")
- myWriter := bufio.NewWriter(newfile)
- marshalWriteToFile(myWriter, c)
-
+ if err := c.ConfigSave(); err != nil {
+ fmt.Println("configsave error", err)
+ os.Exit(-1)
+ }
// marshalUnmarshal()
}
+/*
func marshalUnmarshal() {
test := pb.CreateSampleCluster(7)
data, err := proto.Marshal(test)
@@ -96,3 +95,4 @@ func marshalUnmarshal() {
log.Println("proto.Marshal() and proto.Unmarshal() worked")
}
}
+*/
diff --git a/helpers.go b/helpers.go
index 6a8fe69..72d4008 100644
--- a/helpers.go
+++ b/helpers.go
@@ -10,10 +10,6 @@ import (
)
// human readable JSON
-func (c *Cluster) FormatJSON() string {
- return protojson.Format(c)
-}
-
func (d *Droplets) FormatJSON() string {
return protojson.Format(d)
}
@@ -33,10 +29,6 @@ func (h *Hypervisors) FormatJSON() string {
// apparently this isn't supposed to be used?
// https://protobuf.dev/reference/go/faq/#unstable-text
// this is a shame because this is much nicer output than JSON Format()
-func (c *Cluster) FormatTEXT() string {
- return prototext.Format(c)
-}
-
func (d *Droplets) FormatTEXT() string {
return prototext.Format(d)
}
@@ -46,10 +38,6 @@ func (e *Events) FormatTEXT() string {
}
// marshal
-func (c *Cluster) MarshalJSON() ([]byte, error) {
- return protojson.Marshal(c)
-}
-
func (d *Droplets) MarshalJSON() ([]byte, error) {
return protojson.Marshal(d)
}
@@ -63,10 +51,6 @@ func (e *Events) MarshalJSON() ([]byte, error) {
}
// unmarshal
-func (c *Cluster) UnmarshalJSON(data []byte) error {
- return protojson.Unmarshal(data, c)
-}
-
func (d *Droplets) UnmarshalJSON(data []byte) error {
return protojson.Unmarshal(data, d)
}
diff --git a/newCluster.go b/newCluster.go
new file mode 100644
index 0000000..245638d
--- /dev/null
+++ b/newCluster.go
@@ -0,0 +1,19 @@
+package virtbuf
+
+import (
+ sync "sync"
+
+ durationpb "google.golang.org/protobuf/types/known/durationpb"
+ "google.golang.org/protobuf/types/known/timestamppb"
+)
+
+type NewCluster struct {
+ sync.RWMutex
+
+ Dirs []string
+ d *Droplets
+ h *Hypervisors
+ e *Events
+ Unstable *timestamppb.Timestamp
+ UnstableTimeout *durationpb.Duration
+}
diff --git a/sampleData.go b/sampleData.go
index 0085822..dedd7c0 100644
--- a/sampleData.go
+++ b/sampleData.go
@@ -67,9 +67,12 @@ func CreateSampleEvents(total int) *Events {
return e
}
-func CreateSampleCluster(total int) *Cluster {
- var c *Cluster
- c = new(Cluster)
+func CreateSampleCluster(total int) *NewCluster {
+ var c *NewCluster
+ c = new(NewCluster)
+ c.d = new(Droplets)
+ c.h = new(Hypervisors)
+ c.e = new(Events)
for i := 0; i < total; i++ {
hostname := fmt.Sprintf("bmath%d.wit.com", i)
@@ -80,7 +83,7 @@ func CreateSampleCluster(total int) *Cluster {
d.Memory = SetGB(256)
}
- c.Droplets = append(c.Droplets, d)
+ c.d.Droplets = append(c.d.Droplets, d)
}
for i := 0; i < 3; i++ {
@@ -88,7 +91,7 @@ func CreateSampleCluster(total int) *Cluster {
h := CreateSampleHypervisor(hostname, i+1)
h.Comment = fmt.Sprintf("Sample hypervisor %d", i)
- c.Hypervisors = append(c.Hypervisors, h)
+ c.h.Hypervisors = append(c.h.Hypervisors, h)
}
return c
diff --git a/scanIterator.go b/scanIterator.go
new file mode 100644
index 0000000..3bbaeef
--- /dev/null
+++ b/scanIterator.go
@@ -0,0 +1,106 @@
+package virtbuf
+
+import (
+ "fmt"
+ "os"
+
+ "go.wit.com/log"
+)
+
+type DropletIterator struct {
+ droplets []*Droplet
+ index int
+}
+
+// NewDropletIterator initializes a new iterator.
+func NewDropletIterator(droplets []*Droplet) *DropletIterator {
+ return &DropletIterator{droplets: droplets}
+}
+
+// Scan moves to the next element and returns false if there are no more droplets.
+func (it *DropletIterator) Scan() bool {
+ if it.index >= len(it.droplets) {
+ return false
+ }
+ it.index++
+ return true
+}
+
+// Droplet returns the current droplet.
+func (it *DropletIterator) Droplet() *Droplet {
+ if it.droplets[it.index-1] == nil {
+ for i, d := range it.droplets {
+ fmt.Println("i =", i, d)
+ }
+ fmt.Println("len =", len(it.droplets))
+ fmt.Println("droplet == nil", it.index, it.index-1)
+ os.Exit(-1)
+ }
+ return it.droplets[it.index-1]
+}
+
+// Use Scan() in a loop, similar to a while loop
+//
+// for iterator.Scan() {
+// d := iterator.Droplet()
+// fmt.Println("Droplet UUID:", d.Uuid)
+// }
+func (c *NewCluster) GetDropletIterator() *DropletIterator {
+ dropletPointers := c.SelectDropletPointers()
+
+ iterator := NewDropletIterator(dropletPointers)
+
+ return iterator
+}
+
+func (c *NewCluster) DropletsAll() *DropletIterator {
+ dropletPointers := c.SelectDropletAll()
+
+ iterator := NewDropletIterator(dropletPointers)
+
+ return iterator
+}
+
+// SelectDropletPointers safely returns a slice of pointers to Droplet records.
+func (c *NewCluster) SelectDropletAll() []*Droplet {
+ c.RLock()
+ defer c.RUnlock()
+
+ // Create a new slice to hold pointers to each Droplet
+ // dropletPointers := make([]*Droplet, len(c.E.Droplets))
+ var dropletPointers []*Droplet
+ if c.d == nil {
+ log.Info("SelectDropletsAll() c.d == nil")
+ os.Exit(-1)
+ }
+ for _, d := range c.d.Droplets {
+ if d == nil {
+ continue
+ }
+ if d.Archive != nil {
+ continue
+ }
+ dropletPointers = append(dropletPointers, d) // Copy pointers for safe iteration
+ }
+
+ return dropletPointers
+}
+
+// SelectDropletPointers safely returns a slice of pointers to Droplet records.
+func (c *NewCluster) SelectDropletPointers() []*Droplet {
+ c.RLock()
+ defer c.RUnlock()
+
+ // Create a new slice to hold pointers to each Droplet
+ // dropletPointers := make([]*Droplet, len(c.E.Droplets))
+ dropletPointers := make([]*Droplet, 1)
+ if c.d == nil {
+ log.Info("c.d == nil")
+ os.Exit(-1)
+ }
+ for _, d := range c.d.Droplets {
+ dropletPointers = append(dropletPointers, d) // Copy pointers for safe iteration
+ }
+
+ return dropletPointers
+}