package virtbuf import ( "errors" "fmt" "time" "github.com/google/uuid" "go.wit.com/log" ) func (c *Cluster) InitDroplet(hostname string) (*Droplet, error) { var d *Droplet d = new(Droplet) d.Current = new(Current) d = c.FindDropletByName(hostname) if d != nil { return d, errors.New("duplicate hostname: " + hostname) } d.Hostname = hostname // d.Uuid = uuid.New() // not appropriate here // set some defaults d.StartState = DropletState_OFF d.Current.State = DropletState_UNKNOWN c.appendDroplet(d) return d, nil } func (c *Cluster) appendDroplet(d *Droplet) { c.Lock() defer c.Unlock() c.d.Droplets = append(c.d.Droplets, d) } // can the json protobuf output use a string and have a type handler // to convert it back to int64? func SetGB(gb int) int64 { return int64(gb * 1024 * 1024 * 1024) } func SetMB(mb int) int64 { return int64(mb * 1024 * 1024) } func (x *Hypervisor) SetMemoryGB(gb int) { x.Memory = int64(gb * 1024 * 1024 * 1024) } func (c *Cluster) FindDropletByName(name string) *Droplet { loop := c.DropletsAll() // get the list of droplets for loop.Scan() { d := loop.Droplet() if d.Hostname == name { return d } } return nil } func (c *Cluster) FindHypervisorByName(name string) *Hypervisor { for _, h := range c.H.Hypervisors { if h.Hostname == name { return h } } return nil } func (c *Cluster) AddHypervisor(hostname string, cpus int, mem int) *Hypervisor { h := c.FindHypervisorByName(hostname) if h != nil { return h } // Generate a new UUID id := uuid.New() h = &Hypervisor{ Uuid: id.String(), Hostname: hostname, Cpus: int64(cpus), Comment: "this is a fake hypervisor", } if cpus < 0 { h.Cpus = 1 } h.SetMemoryGB(mem * 32) c.H.Hypervisors = append(c.H.Hypervisors, h) return h } func (c *Cluster) AddEvent(e *Event) { c.e.Events = append(c.e.Events, e) } func (c *Cluster) AddDroplet(d *Droplet) { c.d.Droplets = append(c.d.Droplets, d) } func (c *Cluster) AddDropletSimple(uuid string, hostname string, cpus int, mem int) *Droplet { d := c.FindDropletByName(hostname) if d != nil { return d } d = &Droplet{ Uuid: uuid, Hostname: hostname, Cpus: int64(cpus), } if cpus < 0 { d.Cpus = 1 } d.Memory = SetGB(mem * 32) d.StartState = DropletState_OFF c.AddDroplet(d) return d } // This isn't for the marketing department func (c *Cluster) AddDropletLocal(name string, hypername string) *Droplet { d := &Droplet{ Hostname: name, } d.LocalOnly = "yes on: " + hypername // by default, on locally imported domains, set the preferred hypervisor! d.PreferredHypervisor = hypername d.Current = new(Current) d.Current.Hypervisor = hypername d.StartState = DropletState_OFF d.Current.State = DropletState_OFF c.AddDroplet(d) return d } func (c *Cluster) BlankFields() { loop := c.DropletsAll() // get the list of droplets for loop.Scan() { d := loop.Droplet() d.Current = nil } } func (epb *Events) AppendEvent(e *Event) { epb.Events = append(epb.Events, e) } func (c *Cluster) ClusterStable() (bool, string) { last := time.Since(c.Unstable.AsTime()) if last > c.UnstableTimeout.AsDuration() { // the cluster has not been stable for 133 seconds log.Warn("clusterReady() is stable for ", FormatDuration(c.UnstableTimeout.AsDuration()), " secs") return true, fmt.Sprintln("clusterReady() is stable ", FormatDuration(c.UnstableTimeout.AsDuration()), " secs") } log.Warn("clusterReady() is unstable for", FormatDuration(last)) return false, "clusterReady() is unstable for " + FormatDuration(last) } // check the cluster and droplet to make sure it's ready to start func (c *Cluster) DropletReady(d *Droplet) (bool, string) { if c == nil { return false, "cluster == nil" } if d == nil { return false, "droplet == nil" } if d.Current == nil { return false, "droplet.Current == nil" } // can't start already started droplet if d.Current.State == DropletState_ON { return false, "EVENT start droplet is already ON" } if d.Current.State != DropletState_OFF { return false, "EVENT start droplet is not OFF state = " + string(d.Current.State) } if d.Current.StartAttempts > 2 { // reason := "EVENT start droplet has already been started " + d.starts + " times" return false, fmt.Sprintln("EVENT start droplet has already been started ", d.Current.StartAttempts, " times") } return true, "" }