virtbuf/change.go

228 lines
5.1 KiB
Go
Raw Permalink Normal View History

package virtbuf
import (
// "reflect"
"errors"
"fmt"
"time"
"google.golang.org/protobuf/types/known/anypb"
"google.golang.org/protobuf/types/known/timestamppb"
"google.golang.org/protobuf/types/known/wrapperspb"
"go.wit.com/log"
)
func convertToAnypb(x any) *anypb.Any {
switch v := x.(type) {
case int64:
var a *anypb.Any
a, _ = anypb.New(wrapperspb.Int64(x.(int64)))
return a
case string:
var a *anypb.Any
a, _ = anypb.New(wrapperspb.String(x.(string)))
return a
case int:
var a *anypb.Any
a, _ = anypb.New(wrapperspb.Int64(x.(int64)))
return a
case bool:
var a *anypb.Any
a, _ = anypb.New(wrapperspb.Bool(x.(bool)))
return a
default:
log.Error(errors.New("convertToAnypb() unknown type"), "v =", v, "x =", x)
return nil
}
return nil
}
func convertToString(x any) string {
switch v := x.(type) {
case int64:
return fmt.Sprintf("%d", x.(int64))
case string:
return x.(string)
case int:
return fmt.Sprintf("%d", x.(int))
case uint:
return fmt.Sprintf("%d", x.(uint))
case *DropletState:
var s *DropletState
s = x.(*DropletState)
return s.String()
case DropletState:
var s DropletState
s = x.(DropletState)
return s.String()
case bool:
if x.(bool) {
return "true"
}
return "false"
default:
log.Info("convertToSTring() unknown type", v)
log.Error(errors.New("convertToSTring() unknown type"), "v =", v, "x =", x)
return ""
}
return ""
}
// Wrapping the int into a protobuf message
func (d *Droplet) NewChangeEvent(fname string, origval any, newval any) *Event {
var e *Event
e = new(Event)
e.Droplet = d.Hostname
e.OrigVal = convertToString(origval)
e.NewVal = convertToString(newval)
e.FieldName = fname
now := time.Now()
e.Start = timestamppb.New(now)
// this also works, but it's a bit overkill
// e.NewAny = convertToAnypb(newval)
// me.events.Events = append(me.events.Events, e)
// stuff := me.events.FormatJSON()
// log.Info("events:", stuff)
return e
}
// work in progress
func NewAddEvent(a any, fname string, newval any) *Event {
var e *Event
e = new(Event)
switch v := a.(type) {
case *Droplet:
var d *Droplet
d = a.(*Droplet)
e.Droplet = d.Hostname
case nil:
e.Droplet = "<nil>"
default:
log.Info("newAddEvent() unknown type", v)
e.Droplet = "on something somewhere"
}
e.NewVal = convertToString(newval)
e.FieldName = fname
now := time.Now()
e.Start = timestamppb.New(now)
return e
}
// update the droplet memory
func (d *Droplet) SetMemory(b int64) *Event {
oldm := HumanFormatBytes(d.Memory)
newm := HumanFormatBytes(b)
if d.Memory == b {
// log.Info("droplet", d.Hostname, "memory unchanged", oldm, "to", newm)
return nil
}
log.Info("droplet", d.Hostname, "memory change from", oldm, "to", newm)
return d.NewChangeEvent("Droplet.Memory", d.Memory, b)
}
// update the droplet memory
func (d *Droplet) SetCpus(b int64) {
log.Info("Set the number of cpus for the droplet", b)
}
// update the droplet memory
func (d *Droplet) SetState(newState DropletState) {
if d.Current == nil {
d.Current = new(Current)
}
if d.Current.State == newState {
// nothing has changed
return
}
switch newState {
case DropletState_ON:
d.Current.OnSince = timestamppb.New(time.Now())
d.Current.OffSince = nil
case DropletState_OFF:
d.Current.OffSince = timestamppb.New(time.Now())
d.Current.OnSince = nil
default:
// zero on OnSince to indicate something hickup'd?
// not sure if this should be done here. probably trust qemu dom0 instead
// but I can't do that right now so for now this will work
d.Current.OnSince = timestamppb.New(time.Now())
d.Current.OffSince = timestamppb.New(time.Now())
}
d.Current.State = newState
d.NewChangeEvent("STATE", d.Current.State, newState)
log.Info("Droplet", d.Hostname, "changed state from", d.Current.State, "to", newState)
}
// records an event that the droplet changed state (aka turned on, turned off, etc)
func (c *NewCluster) ChangeDropletState(d *Droplet, newState DropletState) error {
if c == nil {
return errors.New("cluster is nil")
}
if d == nil {
return errors.New("droplet is nil")
}
if d.Current.State == newState {
// droplet status didn't change
return nil
}
var e *Event
e = new(Event)
e.Droplet = d.Hostname
e.OrigVal = convertToString(d.Current.State)
e.NewVal = convertToString(newState)
e.FieldName = "status"
now := time.Now()
e.Start = timestamppb.New(now)
c.e.Events = append(c.e.Events, e)
return nil
}
// records an event that the droplet migrated to another hypervisor
func (c *NewCluster) DropletMoved(d *Droplet, newh *Hypervisor) error {
if c == nil {
return errors.New("cluster is nil")
}
if d == nil {
return errors.New("droplet is nil")
}
if newh == nil {
return errors.New("hypervisor is nil")
}
if d.Current.Hypervisor == newh.Hostname {
// droplet didn't move
return nil
}
// make a change event
var e *Event
e = new(Event)
e.Droplet = d.Hostname
e.OrigVal = d.Current.Hypervisor
e.NewVal = newh.Hostname
e.FieldName = "droplet migrate"
now := time.Now()
e.Start = timestamppb.New(now)
c.e.Events = append(c.e.Events, e)
// update the droplet record
d.Current.Hypervisor = newh.Hostname
return nil
}