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  }