github.com/Cloud-Foundations/Dominator@v0.3.4/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  	"time"
    12  
    13  	"github.com/Cloud-Foundations/Dominator/lib/format"
    14  	"github.com/Cloud-Foundations/Dominator/lib/html"
    15  	"github.com/Cloud-Foundations/Dominator/lib/json"
    16  	"github.com/Cloud-Foundations/Dominator/lib/url"
    17  )
    18  
    19  var timeFormat string = "02 Jan 2006 15:04:05.99 MST"
    20  
    21  func (s state) showVMHandler(w http.ResponseWriter, req *http.Request) {
    22  	parsedQuery := url.ParseQuery(req.URL)
    23  	if len(parsedQuery.Flags) != 1 {
    24  		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    25  		w.WriteHeader(http.StatusBadRequest)
    26  		return
    27  	}
    28  	var ipAddr string
    29  	for name := range parsedQuery.Flags {
    30  		ipAddr = name
    31  	}
    32  	netIpAddr := net.ParseIP(ipAddr)
    33  	vm, err := s.manager.GetVmInfo(netIpAddr)
    34  	if err != nil {
    35  		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    36  		w.WriteHeader(http.StatusNotFound)
    37  		return
    38  	}
    39  	writer := bufio.NewWriter(w)
    40  	defer writer.Flush()
    41  	if parsedQuery.OutputType() == url.OutputTypeJson {
    42  		json.WriteWithIndent(writer, "    ", vm)
    43  	} else {
    44  		var storage uint64
    45  		volumeSizes := make([]string, 0, len(vm.Volumes))
    46  		for _, volume := range vm.Volumes {
    47  			storage += volume.Size
    48  			volumeSizes = append(volumeSizes, format.FormatBytes(volume.Size))
    49  		}
    50  		var tagNames []string
    51  		for name := range vm.Tags {
    52  			tagNames = append(tagNames, name)
    53  		}
    54  		sort.Strings(tagNames)
    55  		fmt.Fprintf(writer, "<title>Information for VM %s</title>\n", ipAddr)
    56  		fmt.Fprintln(writer, `<style>
    57                            table, th, td {
    58                            border-collapse: collapse;
    59                            }
    60                            </style>`)
    61  		fmt.Fprintln(writer, "<body>")
    62  		if lw, _ := s.manager.GetVmLockWatcher(netIpAddr); lw != nil {
    63  			if wroteSomething, _ := lw.WriteHtml(writer, ""); wroteSomething {
    64  				fmt.Fprintln(writer, "<br>")
    65  			}
    66  		}
    67  		fmt.Fprintln(writer, `<table border="0">`)
    68  		if len(vm.Address.IpAddress) < 1 {
    69  			writeString(writer, "IP Address", ipAddr+" (externally allocated)")
    70  		} else if vm.Uncommitted {
    71  			writeString(writer, "IP Address", ipAddr+" (uncommitted)")
    72  		} else {
    73  			writeString(writer, "IP Address", ipAddr)
    74  		}
    75  		if vm.Hostname != "" {
    76  			writeString(writer, "Hostname", vm.Hostname)
    77  		}
    78  		writeString(writer, "MAC Address", vm.Address.MacAddress)
    79  		if vm.ImageName != "" {
    80  			image := fmt.Sprintf("<a href=\"http://%s/showImage?%s\">%s</a>",
    81  				s.manager.GetImageServerAddress(), vm.ImageName, vm.ImageName)
    82  			writeString(writer, "Boot image", image)
    83  		} else if vm.ImageURL != "" {
    84  			writeString(writer, "Boot image URL", vm.ImageURL)
    85  		} else {
    86  			writeString(writer, "Boot image", "was streamed in")
    87  		}
    88  		writeTime(writer, "Created on", vm.CreatedOn)
    89  		writeTime(writer, "Last state change", vm.ChangedStateOn)
    90  		writeString(writer, "State", vm.State.String())
    91  		writeString(writer, "RAM", format.FormatBytes(vm.MemoryInMiB<<20))
    92  		writeString(writer, "CPU", format.FormatMilli(uint64(vm.MilliCPUs)))
    93  		writeStrings(writer, "Volume sizes", volumeSizes)
    94  		writeString(writer, "Total storage", format.FormatBytes(storage))
    95  		writeStrings(writer, "Owner users", vm.OwnerGroups)
    96  		writeStrings(writer, "Owner users", vm.OwnerUsers)
    97  		if vm.IdentityName != "" {
    98  			writeString(writer, "Identity name",
    99  				fmt.Sprintf("%s, %s",
   100  					vm.IdentityName, makeExpiration(vm.IdentityExpires)))
   101  		}
   102  		writeBool(writer, "Spread volumes", vm.SpreadVolumes)
   103  		writeString(writer, "Latest boot",
   104  			fmt.Sprintf("<a href=\"showVmBootLog?%s\">log</a>", ipAddr))
   105  		rc, size, lastPatchTime, err := s.manager.GetVmLastPatchLog(netIpAddr)
   106  		if err == nil {
   107  			rc.Close()
   108  			writeString(writer, "Last patch",
   109  				fmt.Sprintf(
   110  					"<a href=\"showVmLastPatchLog?%s\">log</a> (%s, at: %s, age: %s)",
   111  					ipAddr, format.FormatBytes(size),
   112  					lastPatchTime.Format(timeFormat),
   113  					format.Duration(time.Since(lastPatchTime))))
   114  		}
   115  		if ok, _ := s.manager.CheckVmHasHealthAgent(netIpAddr); ok {
   116  			writeString(writer, "Health Agent",
   117  				fmt.Sprintf("<a href=\"http://%s:6910/\">detected</a>",
   118  					ipAddr))
   119  		}
   120  		fmt.Fprintln(writer, "</table>")
   121  		fmt.Fprintln(writer, "<br>Tags:<br>")
   122  		fmt.Fprintln(writer, `<table border="1">`)
   123  		tw, _ := html.NewTableWriter(writer, true, "Name", "Value")
   124  		for _, name := range tagNames {
   125  			tw.WriteRow("", "", name, vm.Tags[name])
   126  		}
   127  		tw.Close()
   128  		fmt.Fprintln(writer, "<br>")
   129  		fmt.Fprintf(writer,
   130  			"<a href=\"showVM?%s&output=json\">VM info:</a><br>\n",
   131  			vm.Address.IpAddress)
   132  		fmt.Fprintln(writer, `<pre style="background-color: #eee; border: 1px solid #999; display: block; float: left;">`)
   133  		json.WriteWithIndent(writer, "    ", vm)
   134  		fmt.Fprintln(writer, `</pre><p style="clear: both;">`)
   135  		fmt.Fprintln(writer, "</body>")
   136  	}
   137  }
   138  
   139  func makeExpiration(value time.Time) string {
   140  	expiresIn := time.Until(value)
   141  	if expiresIn >= 0 {
   142  		return fmt.Sprintf("expires at %s (in %s)",
   143  			value, format.Duration(expiresIn))
   144  	}
   145  	return fmt.Sprintf("expired at %s (%s ago)",
   146  		value, format.Duration(-expiresIn))
   147  }
   148  
   149  func writeBool(writer io.Writer, name string, value bool) {
   150  	fmt.Fprintf(writer, "  <tr><td>%s</td><td>%t</td></tr>\n", name, value)
   151  }
   152  
   153  func writeInt(writer io.Writer, name string, value int) {
   154  	fmt.Fprintf(writer, "  <tr><td>%s</td><td>%d</td></tr>\n", name, value)
   155  }
   156  
   157  func writeString(writer io.Writer, name, value string) {
   158  	fmt.Fprintf(writer, "  <tr><td>%s</td><td>%s</td></tr>\n", name, value)
   159  }
   160  
   161  func writeStrings(writer io.Writer, name string, value []string) {
   162  	if len(value) < 1 {
   163  		return
   164  	}
   165  	fmt.Fprintf(writer, "  <tr><td>%s</td><td>%s</td></tr>\n",
   166  		name, strings.Join(value, ", "))
   167  }
   168  
   169  func writeTime(writer io.Writer, name string, value time.Time) {
   170  	if value.IsZero() {
   171  		return
   172  	}
   173  	fmt.Fprintf(writer, "  <tr><td>%s</td><td>%s (%s ago)</td></tr>\n",
   174  		name, value.Format(timeFormat), format.Duration(time.Since(value)))
   175  }
   176  
   177  func writeUint64(writer io.Writer, name string, value uint64) {
   178  	fmt.Fprintf(writer, "  <tr><td>%s</td><td>%d</td></tr>\n", name, value)
   179  }