github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/fleetmanager/hypervisors/listHypervisors.go (about) 1 package hypervisors 2 3 import ( 4 "bufio" 5 "fmt" 6 "net/http" 7 "sort" 8 9 "github.com/Cloud-Foundations/Dominator/lib/constants" 10 "github.com/Cloud-Foundations/Dominator/lib/html" 11 "github.com/Cloud-Foundations/Dominator/lib/json" 12 "github.com/Cloud-Foundations/Dominator/lib/url" 13 proto "github.com/Cloud-Foundations/Dominator/proto/fleetmanager" 14 ) 15 16 const ( 17 showOK = iota 18 showConnected 19 showAll 20 showOff 21 ) 22 23 type hypervisorList []*hypervisorType 24 25 func (h *hypervisorType) getHealthStatus() string { 26 healthStatus := h.probeStatus.String() 27 if h.probeStatus == probeStatusConnected { 28 if h.healthStatus != "" { 29 healthStatus = h.healthStatus 30 } 31 } 32 return healthStatus 33 } 34 35 func (h *hypervisorType) getNumVMs() uint { 36 h.mutex.RLock() 37 defer h.mutex.RUnlock() 38 return uint(len(h.vms)) 39 } 40 41 func (m *Manager) listHypervisors(topologyDir string, showFilter int, 42 subnetId string) (hypervisorList, error) { 43 m.mutex.RLock() 44 defer m.mutex.RUnlock() 45 machines, err := m.topology.ListMachines(topologyDir) 46 if err != nil { 47 return nil, err 48 } 49 hypervisors := make([]*hypervisorType, 0, len(machines)) 50 for _, machine := range machines { 51 if subnetId != "" { 52 hasSubnet, _ := m.topology.CheckIfMachineHasSubnet( 53 machine.Hostname, subnetId) 54 if !hasSubnet { 55 continue 56 } 57 } 58 hypervisor := m.hypervisors[machine.Hostname] 59 switch showFilter { 60 case showOK: 61 if hypervisor.probeStatus == probeStatusConnected && 62 (hypervisor.healthStatus == "" || 63 hypervisor.healthStatus == "healthy") { 64 hypervisors = append(hypervisors, hypervisor) 65 } 66 case showConnected: 67 if hypervisor.probeStatus == probeStatusConnected { 68 hypervisors = append(hypervisors, hypervisor) 69 } 70 case showAll: 71 hypervisors = append(hypervisors, hypervisor) 72 case showOff: 73 if hypervisor.probeStatus == probeStatusOff { 74 hypervisors = append(hypervisors, hypervisor) 75 } 76 } 77 } 78 return hypervisors, nil 79 } 80 81 func (m *Manager) listHypervisorsHandler(w http.ResponseWriter, 82 req *http.Request) { 83 writer := bufio.NewWriter(w) 84 defer writer.Flush() 85 _, err := m.getTopology() 86 if err != nil { 87 fmt.Fprintln(writer, err) 88 return 89 } 90 parsedQuery := url.ParseQuery(req.URL) 91 showFilter := showAll 92 switch parsedQuery.Table["state"] { 93 case "connected": 94 showFilter = showConnected 95 case "OK": 96 showFilter = showOK 97 case "off": 98 showFilter = showOff 99 } 100 hypervisors, err := m.listHypervisors("", showFilter, "") 101 if err != nil { 102 fmt.Fprintln(writer, err) 103 return 104 } 105 sort.Sort(hypervisors) 106 if parsedQuery.OutputType() == url.OutputTypeText { 107 for _, hypervisor := range hypervisors { 108 fmt.Fprintln(writer, hypervisor.machine.Hostname) 109 } 110 return 111 } 112 if parsedQuery.OutputType() == url.OutputTypeJson { 113 json.WriteWithIndent(writer, " ", hypervisors) 114 return 115 } 116 fmt.Fprintf(writer, "<title>List of hypervisors</title>\n") 117 writer.WriteString(commonStyleSheet) 118 fmt.Fprintln(writer, "<body>") 119 fmt.Fprintln(writer, `<table border="1" style="width:100%">`) 120 tw, _ := html.NewTableWriter(writer, true, 121 "Name", "Status", "IP Addr", "Serial Number", "Location", "NumVMs") 122 for _, hypervisor := range hypervisors { 123 machine := hypervisor.machine 124 tw.WriteRow("", "", 125 fmt.Sprintf("<a href=\"showHypervisor?%s\">%s</a>", 126 machine.Hostname, machine.Hostname), 127 fmt.Sprintf("<a href=\"http://%s:%d/\">%s</a>", 128 machine.Hostname, constants.HypervisorPortNumber, 129 hypervisor.getHealthStatus()), 130 machine.HostIpAddress.String(), 131 hypervisor.serialNumber, 132 hypervisor.location, 133 fmt.Sprintf("<a href=\"http://%s:%d/listVMs\">%d</a>", 134 machine.Hostname, constants.HypervisorPortNumber, 135 hypervisor.getNumVMs()), 136 ) 137 } 138 fmt.Fprintln(writer, "</table>") 139 fmt.Fprintln(writer, "</body>") 140 } 141 142 func (m *Manager) listHypervisorsInLocation( 143 request proto.ListHypervisorsInLocationRequest) ([]string, error) { 144 showFilter := showOK 145 if request.IncludeUnhealthy { 146 showFilter = showConnected 147 } 148 hypervisors, err := m.listHypervisors(request.Location, showFilter, 149 request.SubnetId) 150 if err != nil { 151 return nil, err 152 } 153 addresses := make([]string, 0, len(hypervisors)) 154 for _, hypervisor := range hypervisors { 155 addresses = append(addresses, 156 fmt.Sprintf("%s:%d", 157 hypervisor.machine.Hostname, constants.HypervisorPortNumber)) 158 } 159 return addresses, nil 160 } 161 162 func (list hypervisorList) Len() int { 163 return len(list) 164 } 165 166 func (list hypervisorList) Less(i, j int) bool { 167 if list[i].location < list[j].location { 168 return true 169 } else if list[i].location > list[j].location { 170 return false 171 } else { 172 return list[i].machine.Hostname < list[j].machine.Hostname 173 } 174 } 175 176 func (list hypervisorList) Swap(i, j int) { 177 list[i], list[j] = list[j], list[i] 178 }