pretty output for humans d.SprintHeader()

Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
Jeff Carr 2024-11-01 00:41:34 -05:00
parent b6f5594fe6
commit 706dbbc533
5 changed files with 196 additions and 96 deletions

33
add.go
View File

@ -22,11 +22,6 @@ func (x *Hypervisor) SetMemoryGB(gb int) {
x.Memory = int64(gb * 1024 * 1024 * 1024) x.Memory = int64(gb * 1024 * 1024 * 1024)
} }
func (x *Hypervisor) GetMemoryPrintable() string {
i := x.Memory / (1024 * 1024 * 1024)
return fmt.Sprintf("%d GB", i)
}
func (all *Droplets) oldFindDroplet(name string) *Droplet { func (all *Droplets) oldFindDroplet(name string) *Droplet {
for _, d := range all.Droplets { for _, d := range all.Droplets {
if d.Hostname == name { if d.Hostname == name {
@ -111,7 +106,7 @@ func (c *NewCluster) AddDropletLocal(name string, hypername string) *Droplet {
d := &Droplet{ d := &Droplet{
Hostname: name, Hostname: name,
} }
d.LocalOnly = hypername d.LocalOnly = "yes on: " + hypername
d.Current = new(Current) d.Current = new(Current)
d.Current.Hypervisor = hypername d.Current.Hypervisor = hypername
d.StartState = DropletState_OFF d.StartState = DropletState_OFF
@ -121,32 +116,6 @@ func (c *NewCluster) AddDropletLocal(name string, hypername string) *Droplet {
return d return d
} }
// This isn't for the marketing department
// so this isn't going to use 'MiB' and 'GiB'
func HumanFormatBytes(b int64) string {
if b < 2000 {
return fmt.Sprintf("%d B", b)
}
kb := int(b / 1024)
if kb < 2000 {
return fmt.Sprintf("%d KB", kb)
}
mb := int(b / (1024 * 1024))
if mb < 2000 {
return fmt.Sprintf("%d MB", mb)
}
gb := int(b / (1024 * 1024 * 1024))
if gb < 2000 {
return fmt.Sprintf("%d GB", gb)
}
tb := int(b / (1024 * 1024 * 1024 * 1024))
return fmt.Sprintf("%d TB", tb)
}
func (c *NewCluster) BlankFields() { func (c *NewCluster) BlankFields() {
loop := c.DropletsAll() // get the list of droplets loop := c.DropletsAll() // get the list of droplets
for loop.Scan() { for loop.Scan() {

View File

@ -49,6 +49,14 @@ func convertToString(x any) string {
return fmt.Sprintf("%d", x.(int)) return fmt.Sprintf("%d", x.(int))
case uint: case uint:
return fmt.Sprintf("%d", x.(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: case bool:
if x.(bool) { if x.(bool) {
return "true" return "true"
@ -128,6 +136,34 @@ func (d *Droplet) SetCpus(b int64) {
log.Info("Set the number of cpus for the droplet", b) 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) // records an event that the droplet changed state (aka turned on, turned off, etc)
func (c *NewCluster) ChangeDropletState(d *Droplet, newState DropletState) error { func (c *NewCluster) ChangeDropletState(d *Droplet, newState DropletState) error {
if c == nil { if c == nil {

View File

@ -44,6 +44,8 @@ message Current {
string full_xml = 4; // the full libvirt xml to import string full_xml = 4; // the full libvirt xml to import
google.protobuf.Timestamp last_poll = 5; // the last time we heard anything from this droplet google.protobuf.Timestamp last_poll = 5; // the last time we heard anything from this droplet
string image_url = 6; // url to the image string image_url = 6; // url to the image
google.protobuf.Timestamp off_since = 7; // when the droplet was turned off
google.protobuf.Timestamp on_since = 8; // when the droplet was turned on
} }
message Archive { message Archive {

157
human.go Normal file
View File

@ -0,0 +1,157 @@
package virtbuf
// mostly just functions related to making STDOUT
// more readable by us humans
// also function shortcuts the do limited formatting (haha, who remembers COBOL?)
// so reporting tables of the status of what droplets and hypervisors
// are in text columns and rows that can be easily read in a terminal
import (
"fmt"
"strings"
"time"
)
func oldGetDurationStamp(t time.Time) string {
// Get the current time
currentTime := time.Now()
// Calculate the duration between t current time
duration := currentTime.Sub(t)
return FormatDuration(duration)
}
// This isn't for the marketing department
// so this isn't going to use 'MiB' and 'GiB'
func HumanFormatBytes(b int64) string {
if b < 2000 {
return fmt.Sprintf("%d B", b)
}
kb := int(b / 1024)
if kb < 2000 {
return fmt.Sprintf("%d KB", kb)
}
mb := int(b / (1024 * 1024))
if mb < 2000 {
return fmt.Sprintf("%d MB", mb)
}
gb := int(b / (1024 * 1024 * 1024))
if gb < 2000 {
return fmt.Sprintf("%d GB", gb)
}
tb := int(b / (1024 * 1024 * 1024 * 1024))
return fmt.Sprintf("%d TB", tb)
}
func FormatDuration(d time.Duration) string {
result := ""
// check if it's more than a year
years := int(d.Hours()) / (24 * 365)
if years > 0 {
result += fmt.Sprintf("%dy", years)
return result
}
// check if it's more than a day
days := int(d.Hours()) / 24
if days > 0 {
result += fmt.Sprintf("%dd", days)
return result
}
// check if it's more than an hour
hours := int(d.Hours()) % 24
if hours > 0 {
result += fmt.Sprintf("%dh", hours)
return result
}
// check if it's more than a minute
minutes := int(d.Minutes()) % 60
if minutes > 0 {
result += fmt.Sprintf("%dm", minutes)
return result
}
// check if it's more than a second
seconds := int(d.Seconds()) % 60
if seconds > 0 {
result += fmt.Sprintf("%ds", seconds)
return result
}
// report in milliseconds
ms := int(d.Milliseconds())
if ms > 100 {
// todo: print .3s, etc ?
return fmt.Sprintf("%1.2fs", seconds/1000)
}
if ms > 0 {
result += fmt.Sprintf("%dms", ms)
}
// totally not necessary but wth
var t time.Duration
t = time.Duration(ms) * time.Millisecond
nanos := d - t
result += fmt.Sprintf("%dnanos", nanos)
return result
}
func (d *Droplet) SprintHeader() string {
header := fmt.Sprintf("%-3.3s %-9.9s %-20.20s", d.Current.State, d.Current.Hypervisor, d.Hostname)
if d.Current == nil {
d.Current = new(Current)
}
switch d.Current.State {
case DropletState_ON:
dur := time.Since(d.Current.OnSince.AsTime()) // time since 'ON'
header += " (on :" + FormatDuration(dur) + ")"
case DropletState_OFF:
// everything is as it should be with this vm
dur := time.Since(d.Current.OffSince.AsTime()) // time since 'OFF'
header += " (off:" + FormatDuration(dur) + ")"
default:
dur := time.Since(d.Current.OffSince.AsTime()) // use 'OFF' here?
header += " (???:" + FormatDuration(dur) + ")"
}
return header
}
func (d *Droplet) SprintDumpHeader() string {
var macs []string
for _, n := range d.Networks {
macs = append(macs, n.Mac)
}
// this line in golang could replace 80 lines of COBOL
header := fmt.Sprintf("%-4.4s%20s %-8s", d.Current.State, strings.Join(macs, " "), d.Current.Hypervisor)
if d.Current == nil {
d.Current = new(Current)
}
switch d.Current.State {
case DropletState_ON:
dur := time.Since(d.Current.OnSince.AsTime()) // time since 'ON'
header += " (on :" + FormatDuration(dur) + ")"
case DropletState_OFF:
// everything is as it should be with this vm
dur := time.Since(d.Current.OffSince.AsTime()) // time since 'OFF'
header += " (off:" + FormatDuration(dur) + ")"
default:
dur := time.Since(d.Current.OffSince.AsTime()) // use 'OFF' here?
header += " (???:" + FormatDuration(dur) + ")"
}
return header
}

64
time.go
View File

@ -1,64 +0,0 @@
package virtbuf
import (
"fmt"
"time"
)
func FormatDuration(d time.Duration) string {
result := ""
// check if it's more than a year
years := int(d.Hours()) / (24 * 365)
if years > 0 {
result += fmt.Sprintf("%dy ", years)
return result
}
// check if it's more than a day
days := int(d.Hours()) / 24
if days > 0 {
result += fmt.Sprintf("%dd ", days)
return result
}
// check if it's more than an hour
hours := int(d.Hours()) % 24
if hours > 0 {
result += fmt.Sprintf("%dh ", hours)
return result
}
// check if it's more than a minute
minutes := int(d.Minutes()) % 60
if minutes > 0 {
result += fmt.Sprintf("%dm ", minutes)
return result
}
// check if it's more than a second
seconds := int(d.Seconds()) % 60
if seconds > 0 {
result += fmt.Sprintf("%ds", seconds)
return result
}
// report in milliseconds
ms := int(d.Milliseconds())
if ms > 100 {
// todo: print .3s, etc ?
return fmt.Sprintf("%1.2fs", seconds/1000)
}
result += fmt.Sprintf("%dms", ms)
return result
}
func GetDurationStamp(t time.Time) string {
// Get the current time
currentTime := time.Now()
// Calculate the duration between t current time
duration := currentTime.Sub(t)
return FormatDuration(duration)
}