github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/hypervisor/httpd/showVM.go (about)

     1  package httpd
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"net"
     8  	"net/http"
     9  	"sort"
    10  	"strings"
    11  
    12  	"github.com/Cloud-Foundations/Dominator/lib/format"
    13  	"github.com/Cloud-Foundations/Dominator/lib/html"
    14  	"github.com/Cloud-Foundations/Dominator/lib/json"
    15  	"github.com/Cloud-Foundations/Dominator/lib/url"
    16  )
    17  
    18  func (s state) showVMHandler(w http.ResponseWriter, req *http.Request) {
    19  	parsedQuery := url.ParseQuery(req.URL)
    20  	if len(parsedQuery.Flags) != 1 {
    21  		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    22  		w.WriteHeader(http.StatusBadRequest)
    23  		return
    24  	}
    25  	var ipAddr string
    26  	for name := range parsedQuery.Flags {
    27  		ipAddr = name
    28  	}
    29  	netIpAddr := net.ParseIP(ipAddr)
    30  	vm, err := s.manager.GetVmInfo(netIpAddr)
    31  	if err != nil {
    32  		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    33  		w.WriteHeader(http.StatusNotFound)
    34  		return
    35  	}
    36  	writer := bufio.NewWriter(w)
    37  	defer writer.Flush()
    38  	if parsedQuery.OutputType() == url.OutputTypeJson {
    39  		json.WriteWithIndent(writer, "    ", vm)
    40  	} else {
    41  		var storage uint64
    42  		volumeSizes := make([]string, 0, len(vm.Volumes))
    43  		for _, volume := range vm.Volumes {
    44  			storage += volume.Size
    45  			volumeSizes = append(volumeSizes, format.FormatBytes(volume.Size))
    46  		}
    47  		var tagNames []string
    48  		for name := range vm.Tags {
    49  			tagNames = append(tagNames, name)
    50  		}
    51  		sort.Strings(tagNames)
    52  		fmt.Fprintf(writer, "<title>Information for VM %s</title>\n", ipAddr)
    53  		fmt.Fprintln(writer, `<style>
    54                            table, th, td {
    55                            border-collapse: collapse;
    56                            }
    57                            </style>`)
    58  		fmt.Fprintln(writer, "<body>")
    59  		fmt.Fprintln(writer, `<table border="0">`)
    60  		if len(vm.Address.IpAddress) < 1 {
    61  			writeString(writer, "IP Address", ipAddr+" (externally allocated)")
    62  		} else if vm.Uncommitted {
    63  			writeString(writer, "IP Address", ipAddr+" (uncommitted)")
    64  		} else {
    65  			writeString(writer, "IP Address", ipAddr)
    66  		}
    67  		if vm.Hostname != "" {
    68  			writeString(writer, "Hostname", vm.Hostname)
    69  		}
    70  		writeString(writer, "MAC Address", vm.Address.MacAddress)
    71  		if vm.ImageName != "" {
    72  			image := fmt.Sprintf("<a href=\"http://%s/showImage?%s\">%s</a>",
    73  				s.manager.GetImageServerAddress(), vm.ImageName, vm.ImageName)
    74  			writeString(writer, "Boot image", image)
    75  		} else if vm.ImageURL != "" {
    76  			writeString(writer, "Boot image URL", vm.ImageURL)
    77  		} else {
    78  			writeString(writer, "Boot image", "was streamed in")
    79  		}
    80  		writeString(writer, "State", vm.State.String())
    81  		writeString(writer, "RAM", format.FormatBytes(vm.MemoryInMiB<<20))
    82  		writeFloat(writer, "CPU", float64(vm.MilliCPUs)*1e-3)
    83  		writeStrings(writer, "Volume sizes", volumeSizes)
    84  		writeString(writer, "Total storage", format.FormatBytes(storage))
    85  		writeStrings(writer, "Owner users", vm.OwnerGroups)
    86  		writeStrings(writer, "Owner users", vm.OwnerUsers)
    87  		writeBool(writer, "Spread volumes", vm.SpreadVolumes)
    88  		writeString(writer, "Latest boot",
    89  			fmt.Sprintf("<a href=\"showVmBootLog?%s\">log</a>", ipAddr))
    90  		if ok, _ := s.manager.CheckVmHasHealthAgent(netIpAddr); ok {
    91  			writeString(writer, "Health Agent",
    92  				fmt.Sprintf("<a href=\"http://%s:6910/\">detected</a>",
    93  					ipAddr))
    94  		}
    95  		fmt.Fprintln(writer, "</table>")
    96  		fmt.Fprintln(writer, "Tags:<br>")
    97  		fmt.Fprintln(writer, `<table border="1">`)
    98  		tw, _ := html.NewTableWriter(writer, true, "Name", "Value")
    99  		for _, name := range tagNames {
   100  			tw.WriteRow("", "", name, vm.Tags[name])
   101  		}
   102  		fmt.Fprintln(writer, "</table><br>")
   103  		fmt.Fprintf(writer,
   104  			"<a href=\"showVM?%s&output=json\">VM info:</a><br>\n",
   105  			vm.Address.IpAddress)
   106  		fmt.Fprintln(writer, `<pre style="background-color: #eee; border: 1px solid #999; display: block; float: left;">`)
   107  		json.WriteWithIndent(writer, "    ", vm)
   108  		fmt.Fprintln(writer, `</pre><p style="clear: both;">`)
   109  		fmt.Fprintln(writer, "</body>")
   110  	}
   111  }
   112  
   113  func writeBool(writer io.Writer, name string, value bool) {
   114  	fmt.Fprintf(writer, "  <tr><td>%s</td><td>%t</td></tr>\n", name, value)
   115  }
   116  
   117  func writeInt(writer io.Writer, name string, value int) {
   118  	fmt.Fprintf(writer, "  <tr><td>%s</td><td>%d</td></tr>\n", name, value)
   119  }
   120  
   121  func writeFloat(writer io.Writer, name string, value float64) {
   122  	fmt.Fprintf(writer, "  <tr><td>%s</td><td>%g</td></tr>\n", name, value)
   123  }
   124  
   125  func writeString(writer io.Writer, name, value string) {
   126  	fmt.Fprintf(writer, "  <tr><td>%s</td><td>%s</td></tr>\n", name, value)
   127  }
   128  
   129  func writeStrings(writer io.Writer, name string, value []string) {
   130  	if len(value) < 1 {
   131  		return
   132  	}
   133  	fmt.Fprintf(writer, "  <tr><td>%s</td><td>%s</td></tr>\n",
   134  		name, strings.Join(value, ", "))
   135  }
   136  
   137  func writeUint64(writer io.Writer, name string, value uint64) {
   138  	fmt.Fprintf(writer, "  <tr><td>%s</td><td>%d</td></tr>\n", name, value)
   139  }