github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/cmd/mdbd/loadHypervisor.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "sync" 6 "time" 7 8 "github.com/Cloud-Foundations/Dominator/lib/constants" 9 "github.com/Cloud-Foundations/Dominator/lib/log" 10 "github.com/Cloud-Foundations/Dominator/lib/mdb" 11 "github.com/Cloud-Foundations/Dominator/lib/srpc" 12 proto "github.com/Cloud-Foundations/Dominator/proto/hypervisor" 13 ) 14 15 var emptyTags = make(map[string]string) 16 17 type hypervisorGeneratorType struct { 18 logger log.DebugLogger 19 eventChannel chan<- struct{} 20 mutex sync.Mutex 21 vms map[string]*proto.VmInfo 22 } 23 24 func newHypervisorGenerator(args []string, 25 logger log.DebugLogger) (generator, error) { 26 g := &hypervisorGeneratorType{ 27 logger: logger, 28 vms: make(map[string]*proto.VmInfo), 29 } 30 go g.daemon() 31 return g, nil 32 } 33 34 func (g *hypervisorGeneratorType) daemon() { 35 address := fmt.Sprintf(":%d", constants.HypervisorPortNumber) 36 for { 37 if err := g.getUpdates(address); err != nil { 38 g.logger.Println(err) 39 time.Sleep(time.Second) 40 } 41 } 42 } 43 44 func (g *hypervisorGeneratorType) getUpdates(hypervisor string) error { 45 client, err := srpc.DialHTTP("tcp", hypervisor, 0) 46 if err != nil { 47 return err 48 } 49 defer client.Close() 50 conn, err := client.Call("Hypervisor.GetUpdates") 51 if err != nil { 52 return err 53 } 54 defer conn.Close() 55 initialUpdate := true 56 for { 57 var update proto.Update 58 if err := conn.Decode(&update); err != nil { 59 return err 60 } 61 g.updateVMs(update.VMs, initialUpdate) 62 initialUpdate = false 63 select { 64 case g.eventChannel <- struct{}{}: 65 default: 66 } 67 } 68 } 69 70 func (g *hypervisorGeneratorType) Generate(unused_datacentre string, 71 logger log.Logger) (*mdb.Mdb, error) { 72 var newMdb mdb.Mdb 73 g.mutex.Lock() 74 defer g.mutex.Unlock() 75 for ipAddr, vm := range g.vms { 76 if vm.State == proto.StateRunning { 77 tags := vm.Tags 78 if tags == nil { 79 tags = emptyTags 80 } 81 _, disableUpdates := tags["DisableUpdates"] 82 var ownerGroup string 83 if len(vm.OwnerGroups) > 0 { 84 ownerGroup = vm.OwnerGroups[0] 85 } 86 newMdb.Machines = append(newMdb.Machines, mdb.Machine{ 87 Hostname: ipAddr, 88 IpAddress: ipAddr, 89 RequiredImage: tags["RequiredImage"], 90 PlannedImage: tags["PlannedImage"], 91 DisableUpdates: disableUpdates, 92 OwnerGroup: ownerGroup, 93 Tags: vm.Tags, 94 }) 95 } 96 } 97 return &newMdb, nil 98 } 99 100 func (g *hypervisorGeneratorType) RegisterEventChannel(events chan<- struct{}) { 101 g.eventChannel = events 102 } 103 104 func (g *hypervisorGeneratorType) updateVMs(vms map[string]*proto.VmInfo, 105 initialUpdate bool) { 106 vmsToDelete := make(map[string]struct{}, len(g.vms)) 107 if initialUpdate { 108 for ipAddr := range g.vms { 109 vmsToDelete[ipAddr] = struct{}{} 110 } 111 } 112 g.mutex.Lock() 113 defer g.mutex.Unlock() 114 for ipAddr, vm := range vms { 115 if vm == nil || len(vm.Volumes) < 1 { 116 delete(g.vms, ipAddr) 117 } else { 118 g.vms[ipAddr] = vm 119 delete(vmsToDelete, ipAddr) 120 } 121 } 122 for ipAddr := range vmsToDelete { 123 delete(g.vms, ipAddr) 124 } 125 }