Compare commits

...

9 Commits

12 changed files with 171 additions and 89 deletions

View File

@ -3,7 +3,7 @@
# cd ~/go/src/google.golang.org/protobuf/cmd/protoc-gen-go
# go install
all: droplet.pb.go hypervisor.pb.go event.pb.go goimports vet
all: proto goimports vet
vet:
@GO111MODULE=off go vet
@ -22,6 +22,8 @@ clean:
rm -f *.pb.go
-rm -f go.*
proto:droplet.pb.go hypervisor.pb.go event.pb.go cluster.pb.go
droplet.pb.go: droplet.proto
autogenpb --proto droplet.proto
@ -31,6 +33,9 @@ hypervisor.pb.go: hypervisor.proto
event.pb.go: event.proto
autogenpb --proto event.proto
cluster.pb.go: cluster.proto
autogenpb --proto cluster.proto
deps:
apt install golang-goprotobuf-dev
apt install protobuf-compiler

33
add.go
View File

@ -9,7 +9,7 @@ import (
)
/*
func (c *Cluster) InitDroplet(hostname string) (*Droplet, error) {
func (c *OldCluster) InitDroplet(hostname string) (*Droplet, error) {
var d *Droplet
d = new(Droplet)
d.Current = new(Current)
@ -50,7 +50,7 @@ func (x *Hypervisor) SetMemoryGB(gb int) {
x.Memory = int64(gb * 1024 * 1024 * 1024)
}
func (c *Cluster) FindDropletByName(name string) *Droplet {
func (c *OldCluster) FindDropletByName(name string) *Droplet {
loop := c.d.All() // get the list of droplets
for loop.Scan() {
d := loop.Next()
@ -61,7 +61,20 @@ func (c *Cluster) FindDropletByName(name string) *Droplet {
return nil
}
func (c *Cluster) FindHypervisorByName(name string) *Hypervisor {
func (c *OldCluster) FindDropletByUuid(id string) *Droplet {
/*
log.Info("START FIND", id)
loop := c.d.All() // get the list of droplets
for loop.Scan() {
d := loop.Next()
log.Info("droplet:", d.Hostname, d.Uuid)
}
log.Info("END FIND", id)
*/
return c.d.FindByUuid(id)
}
func (c *OldCluster) FindHypervisorByName(name string) *Hypervisor {
for _, h := range c.H.Hypervisors {
if h.Hostname == name {
return h
@ -70,7 +83,7 @@ func (c *Cluster) FindHypervisorByName(name string) *Hypervisor {
return nil
}
func (c *Cluster) AddHypervisor(hostname string, cpus int, mem int) *Hypervisor {
func (c *OldCluster) AddHypervisor(hostname string, cpus int, mem int) *Hypervisor {
h := c.FindHypervisorByName(hostname)
if h != nil {
return h
@ -91,7 +104,7 @@ func (c *Cluster) AddHypervisor(hostname string, cpus int, mem int) *Hypervisor
return h
}
func (c *Cluster) AddEvent(e *Event) {
func (c *OldCluster) AddEvent(e *Event) {
c.e.Events = append(c.e.Events, e)
}
@ -109,7 +122,7 @@ func NewDefaultDroplet(hostname string) *Droplet {
return d
}
func (c *Cluster) AddDropletSimple(uuid string, hostname string, cpus int, mem int) *Droplet {
func (c *OldCluster) AddDropletSimple(uuid string, hostname string, cpus int, mem int) *Droplet {
d := c.FindDropletByName(hostname)
if d != nil {
return d
@ -131,7 +144,7 @@ func (c *Cluster) AddDropletSimple(uuid string, hostname string, cpus int, mem i
}
// This isn't for the marketing department
func (c *Cluster) AddDropletLocal(name string, hypername string) *Droplet {
func (c *OldCluster) AddDropletLocal(name string, hypername string) *Droplet {
d := &Droplet{
Hostname: name,
}
@ -149,7 +162,7 @@ func (c *Cluster) AddDropletLocal(name string, hypername string) *Droplet {
return d
}
func (c *Cluster) BlankFields() {
func (c *OldCluster) BlankFields() {
loop := c.d.All() // get the list of droplets
for loop.Scan() {
d := loop.Next()
@ -161,7 +174,7 @@ func (epb *Events) AppendEvent(e *Event) {
epb.Events = append(epb.Events, e)
}
func (c *Cluster) ClusterStable() (bool, string) {
func (c *OldCluster) ClusterStable() (bool, string) {
last := time.Since(c.Unstable.AsTime())
if last > c.UnstableTimeout.AsDuration() {
// the cluster has not been stable for 133 seconds
@ -173,7 +186,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 *OldCluster) DropletReady(d *Droplet) (bool, string) {
if c == nil {
return false, "cluster == nil"
}

View File

@ -73,7 +73,7 @@ func (d *Droplet) NewChangeEvent(fname string, origval any, newval any) *Event {
var e *Event
e = new(Event)
e.Droplet = d.Hostname
e.DropletName = d.Hostname
e.OrigVal = convertToString(origval)
e.NewVal = convertToString(newval)
e.FieldName = fname
@ -99,12 +99,12 @@ func NewAddEvent(a any, fname string, newval any) *Event {
case *Droplet:
var d *Droplet
d = a.(*Droplet)
e.Droplet = d.Hostname
e.DropletName = d.Hostname
case nil:
e.Droplet = "<nil>"
e.DropletName = "<nil>"
default:
log.Info("newAddEvent() unknown type", v)
e.Droplet = "on something somewhere"
e.DropletName = "on something somewhere"
}
e.NewVal = convertToString(newval)
@ -163,7 +163,7 @@ func (d *Droplet) SetState(newState DropletState) {
}
// 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 *OldCluster) ChangeDropletState(d *Droplet, newState DropletState) error {
if c == nil {
return errors.New("cluster is nil")
}
@ -177,7 +177,7 @@ func (c *Cluster) ChangeDropletState(d *Droplet, newState DropletState) error {
var e *Event
e = new(Event)
e.Droplet = d.Hostname
e.DropletName = d.Hostname
e.OrigVal = convertToString(d.Current.State)
e.NewVal = convertToString(newState)
e.FieldName = "status"
@ -190,7 +190,7 @@ func (c *Cluster) ChangeDropletState(d *Droplet, newState DropletState) error {
}
// records an event that the droplet migrated to another hypervisor
func (c *Cluster) DropletMoved(d *Droplet, newh *Hypervisor) error {
func (c *OldCluster) DropletMoved(d *Droplet, newh *Hypervisor) error {
if c == nil {
return errors.New("cluster is nil")
}
@ -209,7 +209,7 @@ func (c *Cluster) DropletMoved(d *Droplet, newh *Hypervisor) error {
var e *Event
e = new(Event)
e.Droplet = d.Hostname
e.DropletName = d.Hostname
e.OrigVal = d.Current.Hypervisor
e.NewVal = newh.Hostname
e.FieldName = "droplet migrate"

23
cluster.proto Normal file
View File

@ -0,0 +1,23 @@
syntax = "proto3";
package virtpb;
import "google/protobuf/timestamp.proto";
import "droplet.proto";
import "hypervisor.proto";
import "event.proto";
message Cluster { // `autogenpb:marshal`
string uuid = 1; // `autogenpb:unique`
string name = 2;
repeated string URL = 3;
google.protobuf.Timestamp ctime = 4; // when the cluster was created
Droplets droplets = 5;
Hypervisors hypervisors = 6;
Events events = 7;
}
message Clusters { // `autogenpb:marshal`
string uuid = 1; // `autogenpb:uuid:57ddd763-75f6-4003-bf0e-8dd0f8a44044`
string version = 2; // `autogenpb:version:v0.0.1`
repeated Cluster clusters = 3;
}

View File

@ -9,14 +9,37 @@ import (
"os"
"path/filepath"
"go.wit.com/log"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/reflect/protoreflect"
)
func (c *Cluster) ConfigSave() error {
name := c.Name
if name == "" {
name = c.Uuid
}
fullname := filepath.Join(os.Getenv("VIRTIGO_HOME"), name+".pb")
cfgfile, err := os.OpenFile(fullname, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
defer cfgfile.Close()
if err != nil {
fmt.Println("open config file :", err)
return err
}
log.Info("ConfigSave()", fullname)
data, err := c.Marshal()
if err != nil {
fmt.Println("cluster Marshal() err:", err)
return err
}
fmt.Fprintln(cfgfile, data)
return nil
}
// 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 *OldCluster) ConfigSave() error {
// try to backup the current cluster config files
if err := backupConfig(); err != nil {
return err
@ -34,20 +57,12 @@ func (c *Cluster) ConfigSave() error {
for _, drop := range dcopy.Droplets {
drop.Current = nil
}
if err := ConfigWriteJSON(dcopy, "droplets.json"); err != nil {
fmt.Println("droplets.json write failed")
return err
}
if err := ConfigWriteTEXT(dcopy, "droplets.text"); err != nil {
fmt.Println("droplets.json write failed")
return err
}
c.configWriteDroplets()
if err := ConfigWriteJSON(c.H, "hypervisors.json"); err != nil {
fmt.Println("hypervisors.json write failed")
return err
}
if err := ConfigWriteTEXT(c.H, "hypervisors.text"); err != nil {
fmt.Println("hypervisors.json write failed")
return err
@ -64,27 +79,27 @@ func (c *Cluster) ConfigSave() error {
return nil
}
func (c *Cluster) ConfigLoad() error {
func (c *OldCluster) ConfigLoad() error {
if c == nil {
return errors.New("It's not safe to run ConfigLoad() on a nil cluster")
}
if data, err := loadFile("droplets.json"); err == nil {
if err = protojson.Unmarshal(data, c.d); err != nil {
fmt.Println("broken droplets.json config file")
if data, err := loadFile("droplets.text"); err == nil {
if err = prototext.Unmarshal(data, c.d); err != nil {
fmt.Println("broken droplets.text config file")
return err
}
} else {
return err
}
if data, err := loadFile("hypervisors.json"); err == nil {
if err = protojson.Unmarshal(data, c.H); err != nil {
fmt.Println("broken hypervisors.json config file")
if data, err := loadFile("hypervisors.text"); err == nil {
if err = prototext.Unmarshal(data, c.H); err != nil {
fmt.Println("broken hypervisors.text config file")
return err
}
} else {
fmt.Println("ERROR HERE IN Hypervisors")
log.Warn("ERROR HERE IN Hypervisors")
return err
}
@ -93,8 +108,11 @@ func (c *Cluster) ConfigLoad() error {
// does it not stay allocated after this function ends?
c.e = new(Events)
}
if err := c.e.loadEvents(); err != nil {
return err
// ignore events.pb since these should be sent elsewhere
log.Warn("Events failed to load, ignoring:", err)
return nil
}
return nil
}
@ -157,6 +175,23 @@ func ConfigWriteJSON(a any, filename string) error {
return nil
}
func (c *OldCluster) configWriteDroplets() error {
fullname := filepath.Join(os.Getenv("VIRTIGO_HOME"), "droplets.new.text")
cfgfile, err := os.OpenFile(fullname, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
defer cfgfile.Close()
if err != nil {
fmt.Println("open config file :", err)
return err
}
loop := c.d.All() // get the list of droplets
for loop.Scan() {
d := loop.Next()
text := prototext.Format(d)
fmt.Fprintln(cfgfile, text)
}
return nil
}
func ConfigWriteTEXT(a any, filename string) error {
fullname := filepath.Join(os.Getenv("VIRTIGO_HOME"), filename)
cfgfile, err := os.OpenFile(fullname, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
@ -174,19 +209,18 @@ func ConfigWriteTEXT(a any, filename string) error {
return nil
}
func (c *Cluster) configWriteDroplets() error {
fullname := filepath.Join(os.Getenv("VIRTIGO_HOME"), "droplets.new.text")
cfgfile, err := os.OpenFile(fullname, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
defer cfgfile.Close()
if err != nil {
fmt.Println("open config file :", err)
func (c *Clusters) ConfigLoad() error {
if c == nil {
return errors.New("It's not safe to run ConfigLoad() on a nil cluster")
}
if data, err := loadFile("cluster.text"); err == nil {
if err = prototext.Unmarshal(data, c); err != nil {
fmt.Println("broken cluster.textconfig file")
return err
}
loop := c.d.All() // get the list of droplets
for loop.Scan() {
d := loop.Next()
text := prototext.Format(d)
fmt.Fprintln(cfgfile, text)
} else {
return err
}
return nil
}

View File

@ -55,7 +55,6 @@ message Archive {
google.protobuf.Timestamp when = 2; // when it was archived
}
// virtual machine state
enum DropletState {
ON = 0;
OFF = 1;

View File

@ -3,6 +3,7 @@ package virtpb;
import "google/protobuf/timestamp.proto"; // Import the well-known type for Timestamp
import "google/protobuf/any.proto"; // Import the well-known type for Timestamp
import "droplet.proto";
// global settings for autogenpb `autogenpb:no-sort` `autogenpb:mutex`
@ -18,10 +19,15 @@ message Events { // `autogenpb:marsh
// at least for now in the early days. but maybe forever.
// homelab clouds normally don't have many events.
// we are talking less than 1 a minute. even 1 an hour is often a lot
message Event {
message Event { // `autogenpb:marshal`
enum status {
DONE = 0;
FAIL = 1;
RUNNING = 2;
}
int32 id = 1; // `autogenpb:unique` // should be unique across the cluster
EventType etype = 2;
string droplet = 3; // name of the droplet
string dropletName = 3; // name of the droplet
string dropletUuid = 4; // uuid of the droplet
string hypervisor = 5; // name of the hypervisor
string hypervisorUuid = 6; // uuid of the hypervisor
@ -32,8 +38,10 @@ message Event {
string newVal = 11; // new value
google.protobuf.Any origAny = 12; // anypb format. probably overkill
google.protobuf.Any newAny = 13; // anypb format
string error = 14; // what went wrong
status state = 15; // state of the event
Droplet droplet = 16; // droplet
}
enum EventType {
ADD = 0;
DELETE = 1;
@ -48,4 +56,5 @@ enum EventType {
FAIL = 10; // everything failed
CRASH = 11; // droplet hard crashed
CHANGE = 12; // droplet or hypervisor config change
EDIT = 13; // edit droplet settings
}

View File

@ -3,15 +3,15 @@ package virtpb
// functions to import and export the protobuf
// data to and from config files
func InitCluster() *Cluster {
var c *Cluster
c = new(Cluster)
func InitCluster() *OldCluster {
var c *OldCluster
c = new(OldCluster)
c.d = new(Droplets)
c.H = new(Hypervisors)
c.e = new(Events)
return c
}
func (c *Cluster) DropletsAll() *DropletIterator {
func (c *OldCluster) DropletsAll() *DropletScanner {
return c.d.All()
}

View File

@ -185,7 +185,7 @@ func (d *Droplet) DumpDroplet(w http.ResponseWriter, r *http.Request) (string, e
return t, nil
}
func (c *Cluster) DumpDroplet(w http.ResponseWriter, r *http.Request) (string, error) {
func (c *OldCluster) DumpDroplet(w http.ResponseWriter, r *http.Request) (string, error) {
hostname := r.URL.Query().Get("hostname")
d := c.FindDropletByName(hostname)
if d == nil {

View File

@ -22,7 +22,6 @@ message Hypervisor {
google.protobuf.Timestamp lastPoll = 10; // the last time we heard anything
}
// think about this more
enum HypervisorArch {
RISCV64 = 0;
X86_64 = 1;

View File

@ -7,7 +7,7 @@ import (
"google.golang.org/protobuf/types/known/timestamppb"
)
type Cluster struct {
type OldCluster struct {
sync.RWMutex
Dirs []string
@ -18,20 +18,20 @@ type Cluster struct {
UnstableTimeout *durationpb.Duration
}
func (c *Cluster) GetDropletsPB() *Droplets {
func (c *OldCluster) GetDropletsPB() *Droplets {
return c.d
}
func (c *Cluster) GetHypervisorsPB() *Hypervisors {
func (c *OldCluster) GetHypervisorsPB() *Hypervisors {
return c.H
}
func (c *Cluster) GetEventsPB() *Events {
func (c *OldCluster) GetEventsPB() *Events {
return c.e
}
// adds a new droplet. enforce unique hostnames
func (c *Cluster) AddDroplet(newd *Droplet) bool {
func (c *OldCluster) AddDroplet(newd *Droplet) bool {
c.Lock()
defer c.Unlock()

View File

@ -51,7 +51,7 @@ func CreateSampleEvents(total int) *Events {
return e
}
func CreateSampleCluster(total int) *Cluster {
func CreateSampleCluster(total int) *OldCluster {
c := InitCluster()
for i := 0; i < total; i++ {