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  }