github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/dom/herd/showSubs.go (about) 1 package herd 2 3 import ( 4 "fmt" 5 "io" 6 "net/http" 7 "strings" 8 "time" 9 10 "github.com/Cloud-Foundations/Dominator/lib/constants" 11 "github.com/Cloud-Foundations/Dominator/lib/format" 12 "github.com/Cloud-Foundations/Dominator/lib/html" 13 "github.com/Cloud-Foundations/Dominator/lib/json" 14 "github.com/Cloud-Foundations/Dominator/lib/srpc" 15 "github.com/Cloud-Foundations/Dominator/lib/url" 16 ) 17 18 func (herd *Herd) showAliveSubsHandler(w io.Writer, req *http.Request) { 19 herd.showSubs(w, "alive ", selectAliveSub) 20 } 21 22 func (herd *Herd) showAllSubsHandler(w io.Writer, req *http.Request) { 23 herd.showSubs(w, "", nil) 24 } 25 26 func (herd *Herd) showCompliantSubsHandler(w io.Writer, req *http.Request) { 27 herd.showSubs(w, "compliant ", selectCompliantSub) 28 } 29 30 func (herd *Herd) showDeviantSubsHandler(w io.Writer, req *http.Request) { 31 herd.showSubs(w, "deviant ", selectDeviantSub) 32 } 33 34 func (herd *Herd) showReachableSubsHandler(w io.Writer, req *http.Request) { 35 selector, err := herd.getReachableSelector(url.ParseQuery(req.URL)) 36 if err != nil { 37 fmt.Fprintln(w, err) 38 return 39 } 40 herd.showSubs(w, "reachable ", selector) 41 } 42 43 func (herd *Herd) showSubs(writer io.Writer, subType string, 44 selectFunc func(*Sub) bool) { 45 fmt.Fprintf(writer, "<title>Dominator %s subs</title>", subType) 46 fmt.Fprintln(writer, `<style> 47 table, th, td { 48 border-collapse: collapse; 49 } 50 </style>`) 51 if srpc.CheckTlsRequired() { 52 fmt.Fprintln(writer, "<body>") 53 } else { 54 fmt.Fprintln(writer, "<body bgcolor=\"#ffb0b0\">") 55 fmt.Fprintln(writer, 56 `<h1><center><font color="red">Running in insecure mode. You can get pwned!!!</center></font></h1>`) 57 } 58 if herd.updatesDisabledReason != "" { 59 fmt.Fprintf(writer, "<center>") 60 herd.writeDisableStatus(writer) 61 fmt.Fprintln(writer, "</center>") 62 } 63 fmt.Fprintln(writer, `<table border="1" style="width:100%">`) 64 tw, _ := html.NewTableWriter(writer, true, "Name", "Required Image", 65 "Planned Image", "Busy", "Status", "Uptime", "Last Scan Duration", 66 "Staleness", "Last Update", "Last Sync", "Connect", "Short Poll", 67 "Full Poll", "Update Compute") 68 subs := herd.getSelectedSubs(selectFunc) 69 for _, sub := range subs { 70 showSub(tw, sub) 71 } 72 fmt.Fprintln(writer, "</table>") 73 } 74 75 func showSub(tw *html.TableWriter, sub *Sub) { 76 var background string 77 if sub.isInsecure { 78 background = "yellow" 79 } 80 tw.OpenRow("", background) 81 defer tw.CloseRow() 82 subURL := fmt.Sprintf("http://%s:%d/", 83 strings.SplitN(sub.String(), "*", 2)[0], constants.SubPortNumber) 84 timeNow := time.Now() 85 tw.WriteData("", fmt.Sprintf("<a href=\"%s\">%s</a>", subURL, sub)) 86 sub.herd.showImage(tw, sub.mdb.RequiredImage, true) 87 sub.herd.showImage(tw, sub.mdb.PlannedImage, false) 88 sub.showBusy(tw) 89 tw.WriteData("", 90 fmt.Sprintf("<a href=\"showSub?%s\">%s</a>", 91 sub.mdb.Hostname, sub.publishedStatus.html())) 92 showSince(tw, sub.pollTime, sub.startTime) 93 showDuration(tw, sub.lastScanDuration, false) 94 showSince(tw, timeNow, sub.lastPollSucceededTime) 95 showSince(tw, timeNow, sub.lastUpdateTime) 96 showSince(tw, timeNow, sub.lastSyncTime) 97 showDuration(tw, sub.lastConnectDuration, false) 98 showDuration(tw, sub.lastShortPollDuration, !sub.lastPollWasFull) 99 showDuration(tw, sub.lastFullPollDuration, sub.lastPollWasFull) 100 showDuration(tw, sub.lastComputeUpdateCpuDuration, false) 101 } 102 103 func (herd *Herd) showImage(tw *html.TableWriter, name string, 104 showDefault bool) error { 105 if name == "" { 106 if showDefault && herd.defaultImageName != "" { 107 return tw.WriteData("", fmt.Sprintf( 108 "<a style=\"color: #CCCC00\" href=\"http://%s/showImage?%s\">%s</a>", 109 herd.imageManager, herd.defaultImageName, 110 herd.defaultImageName)) 111 } else { 112 return tw.WriteData("", "") 113 } 114 } else if image, err := herd.imageManager.Get(name, false); err != nil { 115 return tw.WriteData("red", err.Error()) 116 } else if image != nil { 117 return tw.WriteData("", 118 fmt.Sprintf("<a href=\"http://%s/showImage?%s\">%s</a>", 119 herd.imageManager, name, name)) 120 } else { 121 return tw.WriteData("grey", name) 122 } 123 } 124 125 func (herd *Herd) showSubHandler(w io.Writer, req *http.Request) { 126 subName := req.URL.RawQuery 127 fmt.Fprintf(w, "<title>sub %s</title>", subName) 128 if srpc.CheckTlsRequired() { 129 fmt.Fprintln(w, "<body>") 130 } else { 131 fmt.Fprintln(w, "<body bgcolor=\"#ffb0b0\">") 132 fmt.Fprintln(w, 133 `<h1><center><font color="red">Running in insecure mode. You can get pwned!!!</center></font></h1>`) 134 } 135 if herd.updatesDisabledReason != "" { 136 fmt.Fprintf(w, "<center>") 137 herd.writeDisableStatus(w) 138 fmt.Fprintln(w, "</center>") 139 } 140 fmt.Fprintln(w, "<h3>") 141 sub := herd.getSub(subName) 142 if sub == nil { 143 fmt.Fprintf(w, "Sub: %s UNKNOWN!\n", subName) 144 return 145 } 146 timeNow := time.Now() 147 subURL := fmt.Sprintf("http://%s:%d/", 148 strings.SplitN(sub.String(), "*", 2)[0], constants.SubPortNumber) 149 fmt.Fprintf(w, "Information for sub: <a href=\"%s\">%s</a><br>\n", 150 subURL, subName) 151 fmt.Fprintln(w, "</h3>") 152 fmt.Fprint(w, "<table border=\"0\">\n") 153 tw, _ := html.NewTableWriter(w, false) 154 newRow(w, "Required Image", true) 155 sub.herd.showImage(tw, sub.mdb.RequiredImage, true) 156 newRow(w, "Planned Image", false) 157 sub.herd.showImage(tw, sub.mdb.PlannedImage, false) 158 newRow(w, "Busy time", false) 159 sub.showBusy(tw) 160 newRow(w, "Status", false) 161 tw.WriteData("", sub.publishedStatus.html()) 162 newRow(w, "Uptime", false) 163 showSince(tw, sub.pollTime, sub.startTime) 164 newRow(w, "Last scan duration", false) 165 showDuration(tw, sub.lastScanDuration, false) 166 newRow(w, "Time since last successful poll", false) 167 showSince(tw, timeNow, sub.lastPollSucceededTime) 168 newRow(w, "Time since last update", false) 169 showSince(tw, timeNow, sub.lastUpdateTime) 170 newRow(w, "Time since last sync", false) 171 showSince(tw, timeNow, sub.lastSyncTime) 172 newRow(w, "Last connection duration", false) 173 showDuration(tw, sub.lastConnectDuration, false) 174 newRow(w, "Last short poll duration", false) 175 showDuration(tw, sub.lastShortPollDuration, !sub.lastPollWasFull) 176 newRow(w, "Last full poll duration", false) 177 showDuration(tw, sub.lastFullPollDuration, sub.lastPollWasFull) 178 newRow(w, "Last compute duration", false) 179 showDuration(tw, sub.lastComputeUpdateCpuDuration, false) 180 fmt.Fprint(w, " </tr>\n") 181 fmt.Fprint(w, "</table>\n") 182 fmt.Fprintln(w, "MDB Data:") 183 fmt.Fprintln(w, "<pre>") 184 json.WriteWithIndent(w, " ", sub.mdb) 185 fmt.Fprintln(w, "</pre>") 186 } 187 188 func newRow(w io.Writer, row string, first bool) { 189 if !first { 190 fmt.Fprint(w, " </tr>\n") 191 } 192 fmt.Fprint(w, " <tr>\n") 193 fmt.Fprintf(w, " <td>%s:</td>\n", row) 194 } 195 196 func (sub *Sub) showBusy(tw *html.TableWriter) { 197 if sub.busy { 198 if sub.busyStartTime.IsZero() { 199 tw.WriteData("", "busy") 200 } else { 201 tw.WriteData("", format.Duration(time.Since(sub.busyStartTime))) 202 } 203 } else { 204 if sub.busyStartTime.IsZero() { 205 tw.WriteData("", "") 206 } else { 207 tw.WriteData("grey", 208 format.Duration(sub.busyStopTime.Sub(sub.busyStartTime))) 209 } 210 } 211 } 212 213 func showSince(tw *html.TableWriter, now time.Time, since time.Time) { 214 if now.IsZero() || since.IsZero() { 215 tw.WriteData("", "") 216 } else { 217 showDuration(tw, now.Sub(since), false) 218 } 219 } 220 221 func showDuration(tw *html.TableWriter, duration time.Duration, 222 highlight bool) { 223 if duration < 1 { 224 tw.WriteData("", "") 225 } else { 226 str := format.Duration(duration) 227 if highlight { 228 str = "<b>" + str + "</b>" 229 } 230 tw.WriteData("", str) 231 } 232 }