Compare commits
8 Commits
Author | SHA1 | Date |
---|---|---|
|
e6fb7352ae | |
|
c9ef4f0b82 | |
|
688b5039a0 | |
|
814d36b9c9 | |
|
a07033d181 | |
|
7cdb2a33ef | |
|
63148556af | |
|
a510dd6474 |
13
add.go
13
add.go
|
@ -61,6 +61,19 @@ func (c *OldCluster) FindDropletByName(name string) *Droplet {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
func (c *OldCluster) FindHypervisorByName(name string) *Hypervisor {
|
||||||
for _, h := range c.H.Hypervisors {
|
for _, h := range c.H.Hypervisors {
|
||||||
if h.Hostname == name {
|
if h.Hostname == name {
|
||||||
|
|
12
change.go
12
change.go
|
@ -73,7 +73,7 @@ func (d *Droplet) NewChangeEvent(fname string, origval any, newval any) *Event {
|
||||||
var e *Event
|
var e *Event
|
||||||
e = new(Event)
|
e = new(Event)
|
||||||
|
|
||||||
e.Droplet = d.Hostname
|
e.DropletName = d.Hostname
|
||||||
e.OrigVal = convertToString(origval)
|
e.OrigVal = convertToString(origval)
|
||||||
e.NewVal = convertToString(newval)
|
e.NewVal = convertToString(newval)
|
||||||
e.FieldName = fname
|
e.FieldName = fname
|
||||||
|
@ -99,12 +99,12 @@ func NewAddEvent(a any, fname string, newval any) *Event {
|
||||||
case *Droplet:
|
case *Droplet:
|
||||||
var d *Droplet
|
var d *Droplet
|
||||||
d = a.(*Droplet)
|
d = a.(*Droplet)
|
||||||
e.Droplet = d.Hostname
|
e.DropletName = d.Hostname
|
||||||
case nil:
|
case nil:
|
||||||
e.Droplet = "<nil>"
|
e.DropletName = "<nil>"
|
||||||
default:
|
default:
|
||||||
log.Info("newAddEvent() unknown type", v)
|
log.Info("newAddEvent() unknown type", v)
|
||||||
e.Droplet = "on something somewhere"
|
e.DropletName = "on something somewhere"
|
||||||
}
|
}
|
||||||
|
|
||||||
e.NewVal = convertToString(newval)
|
e.NewVal = convertToString(newval)
|
||||||
|
@ -177,7 +177,7 @@ func (c *OldCluster) ChangeDropletState(d *Droplet, newState DropletState) error
|
||||||
var e *Event
|
var e *Event
|
||||||
e = new(Event)
|
e = new(Event)
|
||||||
|
|
||||||
e.Droplet = d.Hostname
|
e.DropletName = d.Hostname
|
||||||
e.OrigVal = convertToString(d.Current.State)
|
e.OrigVal = convertToString(d.Current.State)
|
||||||
e.NewVal = convertToString(newState)
|
e.NewVal = convertToString(newState)
|
||||||
e.FieldName = "status"
|
e.FieldName = "status"
|
||||||
|
@ -209,7 +209,7 @@ func (c *OldCluster) DropletMoved(d *Droplet, newh *Hypervisor) error {
|
||||||
var e *Event
|
var e *Event
|
||||||
e = new(Event)
|
e = new(Event)
|
||||||
|
|
||||||
e.Droplet = d.Hostname
|
e.DropletName = d.Hostname
|
||||||
e.OrigVal = d.Current.Hypervisor
|
e.OrigVal = d.Current.Hypervisor
|
||||||
e.NewVal = newh.Hostname
|
e.NewVal = newh.Hostname
|
||||||
e.FieldName = "droplet migrate"
|
e.FieldName = "droplet migrate"
|
||||||
|
|
|
@ -2,15 +2,22 @@ syntax = "proto3";
|
||||||
package virtpb;
|
package virtpb;
|
||||||
|
|
||||||
import "google/protobuf/timestamp.proto";
|
import "google/protobuf/timestamp.proto";
|
||||||
|
import "droplet.proto";
|
||||||
|
import "hypervisor.proto";
|
||||||
|
import "event.proto";
|
||||||
|
|
||||||
message Cluster {
|
message Cluster { // `autogenpb:marshal`
|
||||||
string uuid = 1; // `autogenpb:unique`
|
string uuid = 1; // `autogenpb:unique`
|
||||||
string URL = 2; // `autogenpb:unique`
|
string name = 2;
|
||||||
google.protobuf.Timestamp ctime = 3; // when the cluster was created
|
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`
|
message Clusters { // `autogenpb:marshal`
|
||||||
string uuid = 1; // `autogenpb:uuid:57ddd763-75f6-4003-bf0e-8dd0f8a44044`
|
string uuid = 1; // `autogenpb:uuid:57ddd763-75f6-4003-bf0e-8dd0f8a44044`
|
||||||
string version = 2; // `autogenpb:version:v0.0.1`
|
string version = 2; // `autogenpb:version:v0.0.1`
|
||||||
repeated Cluster clusters = 3;
|
repeated Cluster clusters = 3;
|
||||||
}
|
}
|
||||||
|
|
50
config.go
50
config.go
|
@ -9,11 +9,34 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"go.wit.com/log"
|
||||||
"google.golang.org/protobuf/encoding/protojson"
|
"google.golang.org/protobuf/encoding/protojson"
|
||||||
"google.golang.org/protobuf/encoding/prototext"
|
"google.golang.org/protobuf/encoding/prototext"
|
||||||
"google.golang.org/protobuf/reflect/protoreflect"
|
"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
|
// writes out the cluster information it seperate files
|
||||||
// to make it humanly possible to hand edit things as needed
|
// to make it humanly possible to hand edit things as needed
|
||||||
func (c *OldCluster) ConfigSave() error {
|
func (c *OldCluster) ConfigSave() error {
|
||||||
|
@ -34,20 +57,12 @@ func (c *OldCluster) ConfigSave() error {
|
||||||
for _, drop := range dcopy.Droplets {
|
for _, drop := range dcopy.Droplets {
|
||||||
drop.Current = nil
|
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 {
|
if err := ConfigWriteTEXT(dcopy, "droplets.text"); err != nil {
|
||||||
fmt.Println("droplets.json write failed")
|
fmt.Println("droplets.json write failed")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.configWriteDroplets()
|
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 {
|
if err := ConfigWriteTEXT(c.H, "hypervisors.text"); err != nil {
|
||||||
fmt.Println("hypervisors.json write failed")
|
fmt.Println("hypervisors.json write failed")
|
||||||
return err
|
return err
|
||||||
|
@ -69,22 +84,22 @@ func (c *OldCluster) ConfigLoad() error {
|
||||||
return errors.New("It's not safe to run ConfigLoad() on a nil cluster")
|
return errors.New("It's not safe to run ConfigLoad() on a nil cluster")
|
||||||
}
|
}
|
||||||
|
|
||||||
if data, err := loadFile("droplets.json"); err == nil {
|
if data, err := loadFile("droplets.text"); err == nil {
|
||||||
if err = protojson.Unmarshal(data, c.d); err != nil {
|
if err = prototext.Unmarshal(data, c.d); err != nil {
|
||||||
fmt.Println("broken droplets.json config file")
|
fmt.Println("broken droplets.text config file")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if data, err := loadFile("hypervisors.json"); err == nil {
|
if data, err := loadFile("hypervisors.text"); err == nil {
|
||||||
if err = protojson.Unmarshal(data, c.H); err != nil {
|
if err = prototext.Unmarshal(data, c.H); err != nil {
|
||||||
fmt.Println("broken hypervisors.json config file")
|
fmt.Println("broken hypervisors.text config file")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("ERROR HERE IN Hypervisors")
|
log.Warn("ERROR HERE IN Hypervisors")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,8 +108,11 @@ func (c *OldCluster) ConfigLoad() error {
|
||||||
// does it not stay allocated after this function ends?
|
// does it not stay allocated after this function ends?
|
||||||
c.e = new(Events)
|
c.e = new(Events)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.e.loadEvents(); err != nil {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,19 +55,18 @@ message Archive {
|
||||||
google.protobuf.Timestamp when = 2; // when it was archived
|
google.protobuf.Timestamp when = 2; // when it was archived
|
||||||
}
|
}
|
||||||
|
|
||||||
// virtual machine state
|
|
||||||
enum DropletState {
|
enum DropletState {
|
||||||
ON = 0;
|
ON = 0;
|
||||||
OFF = 1;
|
OFF = 1;
|
||||||
UNKNOWN = 2; // qemu says 'Shutdown'
|
UNKNOWN = 2; // qemu says 'Shutdown'
|
||||||
PAUSED = 3;
|
PAUSED = 3;
|
||||||
CRASHED = 4;
|
CRASHED = 4;
|
||||||
INMIGRATE = 5;
|
INMIGRATE = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DropletArchive {
|
enum DropletArchive {
|
||||||
DUP = 0;
|
DUP = 0;
|
||||||
USER = 1;
|
USER = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Network {
|
message Network {
|
||||||
|
|
41
event.proto
41
event.proto
|
@ -3,6 +3,7 @@ package virtpb;
|
||||||
|
|
||||||
import "google/protobuf/timestamp.proto"; // Import the well-known type for Timestamp
|
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 "google/protobuf/any.proto"; // Import the well-known type for Timestamp
|
||||||
|
import "droplet.proto";
|
||||||
|
|
||||||
// global settings for autogenpb `autogenpb:no-sort` `autogenpb:mutex`
|
// 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.
|
// at least for now in the early days. but maybe forever.
|
||||||
// homelab clouds normally don't have many events.
|
// homelab clouds normally don't have many events.
|
||||||
// we are talking less than 1 a minute. even 1 an hour is often a lot
|
// 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
|
int32 id = 1; // `autogenpb:unique` // should be unique across the cluster
|
||||||
EventType etype = 2;
|
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 dropletUuid = 4; // uuid of the droplet
|
||||||
string hypervisor = 5; // name of the hypervisor
|
string hypervisor = 5; // name of the hypervisor
|
||||||
string hypervisorUuid = 6; // uuid of the hypervisor
|
string hypervisorUuid = 6; // uuid of the hypervisor
|
||||||
|
@ -32,20 +38,23 @@ message Event {
|
||||||
string newVal = 11; // new value
|
string newVal = 11; // new value
|
||||||
google.protobuf.Any origAny = 12; // anypb format. probably overkill
|
google.protobuf.Any origAny = 12; // anypb format. probably overkill
|
||||||
google.protobuf.Any newAny = 13; // anypb format
|
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 {
|
enum EventType {
|
||||||
ADD = 0;
|
ADD = 0;
|
||||||
DELETE = 1;
|
DELETE = 1;
|
||||||
POWERON = 2;
|
POWERON = 2;
|
||||||
POWEROFF = 3; // should indicate a "normal" shutdown
|
POWEROFF = 3; // should indicate a "normal" shutdown
|
||||||
HIBERNATE = 4;
|
HIBERNATE = 4;
|
||||||
MIGRATE = 5;
|
MIGRATE = 5;
|
||||||
DEMO = 6;
|
DEMO = 6;
|
||||||
GET = 7; // request something
|
GET = 7; // request something
|
||||||
LOGIN = 8; // attempt to login
|
LOGIN = 8; // attempt to login
|
||||||
OK = 9; // everything is ok
|
OK = 9; // everything is ok
|
||||||
FAIL = 10; // everything failed
|
FAIL = 10; // everything failed
|
||||||
CRASH = 11; // droplet hard crashed
|
CRASH = 11; // droplet hard crashed
|
||||||
CHANGE = 12; // droplet or hypervisor config change
|
CHANGE = 12; // droplet or hypervisor config change
|
||||||
|
EDIT = 13; // edit droplet settings
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,6 @@ func InitCluster() *OldCluster {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *OldCluster) DropletsAll() *DropletIterator {
|
func (c *OldCluster) DropletsAll() *DropletScanner {
|
||||||
return c.d.All()
|
return c.d.All()
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,8 @@ message Hypervisor {
|
||||||
google.protobuf.Timestamp lastPoll = 10; // the last time we heard anything
|
google.protobuf.Timestamp lastPoll = 10; // the last time we heard anything
|
||||||
}
|
}
|
||||||
|
|
||||||
// think about this more
|
|
||||||
enum HypervisorArch {
|
enum HypervisorArch {
|
||||||
RISCV64 = 0;
|
RISCV64 = 0;
|
||||||
X86_64 = 1;
|
X86_64 = 1;
|
||||||
ARM64 = 2;
|
ARM64 = 2;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue