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 }