From f54e10b7e8e9c555283b28f66868b74c0f6cedba Mon Sep 17 00:00:00 2001 From: Rohit Jnagal Date: Tue, 19 May 2015 04:48:42 +0000 Subject: [PATCH] Add docker status and images info to /docker page. --- pages/containers_html.go | 31 ++++++++++++++++++++++ pages/docker.go | 41 ++++++++++++++++++++++++++--- pages/pages.go | 8 ++++++ pages/static/containers_css.go | 11 ++++++++ pages/static/containers_js.go | 48 +++++++++++++++++++++++++++++++--- 5 files changed, 132 insertions(+), 7 deletions(-) diff --git a/pages/containers_html.go b/pages/containers_html.go index ba7e9356..3627faa3 100644 --- a/pages/containers_html.go +++ b/pages/containers_html.go @@ -64,6 +64,36 @@ const containersHtmlTemplate = ` {{end}} + {{if .DockerStatus}} +
+ + + {{end}} +
+ {{end}} + {{if .DockerImages}} +
+ +
+

+
+ {{end}} {{if .ResourcesAvailable}}
diff --git a/pages/docker.go b/pages/docker.go index 472b34f2..d02f1cee 100644 --- a/pages/docker.go +++ b/pages/docker.go @@ -19,6 +19,7 @@ import ( "net/http" "net/url" "path" + "strconv" "time" "github.com/golang/glog" @@ -29,6 +30,25 @@ import ( const DockerPage = "/docker/" +func toStatusKV(status manager.DockerStatus) ([]keyVal, []keyVal) { + ds := []keyVal{ + {Key: "Driver", Value: status.Driver}, + } + for k, v := range status.DriverStatus { + ds = append(ds, keyVal{Key: k, Value: v}) + } + return []keyVal{ + {Key: "Docker Version", Value: status.Version}, + {Key: "Kernel Version", Value: status.KernelVersion}, + {Key: "OS Version", Value: status.OS}, + {Key: "Host Name", Value: status.Hostname}, + {Key: "Docker Root Directory", Value: status.RootDir}, + {Key: "Execution Driver", Value: status.ExecDriver}, + {Key: "Number of Images", Value: strconv.Itoa(status.NumImages)}, + {Key: "Number of Containers", Value: strconv.Itoa(status.NumContainers)}, + }, ds +} + func serveDockerPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error { start := time.Now() @@ -54,6 +74,19 @@ func serveDockerPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error }) } + // Get Docker status + status, err := m.DockerInfo() + if err != nil { + return err + } + + dockerStatus, driverStatus := toStatusKV(status) + // Get Docker Images + images, err := m.DockerImages() + if err != nil { + return err + } + dockerContainersText := "Docker Containers" data = &pageData{ DisplayName: dockerContainersText, @@ -62,8 +95,11 @@ func serveDockerPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error Text: dockerContainersText, Link: DockerPage, }}, - Subcontainers: subcontainers, - Root: rootDir, + Subcontainers: subcontainers, + Root: rootDir, + DockerStatus: dockerStatus, + DockerDriverStatus: driverStatus, + DockerImages: images, } } else { // Get the container. @@ -92,7 +128,6 @@ func serveDockerPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error if err != nil { return err } - data = &pageData{ DisplayName: displayName, ContainerName: cont.Name, diff --git a/pages/pages.go b/pages/pages.go index 2086f8a6..fed0401f 100644 --- a/pages/pages.go +++ b/pages/pages.go @@ -37,6 +37,11 @@ type link struct { Link string } +type keyVal struct { + Key string + Value string +} + type pageData struct { DisplayName string ContainerName string @@ -52,6 +57,9 @@ type pageData struct { NetworkAvailable bool FsAvailable bool Root string + DockerStatus []keyVal + DockerDriverStatus []keyVal + DockerImages []manager.DockerImage } func init() { diff --git a/pages/static/containers_css.go b/pages/static/containers_css.go index 48da8a9d..98f0175c 100644 --- a/pages/static/containers_css.go +++ b/pages/static/containers_css.go @@ -39,6 +39,17 @@ const containersCss = ` .isolation-title { color:#FFFFFF; } +.table-row { + font-family: "courier", "monospace"; + font-size: 15px; + text-align: right; + vertical-align: top; + border: 5px; + margin-left: 3px; + margin-right: 3px; + margin-top: 3px; + margin-bottom: 3px; +} #logo { height: 200px; margin-top: 20px; diff --git a/pages/static/containers_js.go b/pages/static/containers_js.go index a0576374..a653b311 100644 --- a/pages/static/containers_js.go +++ b/pages/static/containers_js.go @@ -35,7 +35,7 @@ function humanizeMetric(num) { } // Draw a table. -function drawTable(seriesTitles, titleTypes, data, elementId) { +function drawTable(seriesTitles, titleTypes, data, elementId, numPages) { var dataTable = new google.visualization.DataTable(); for (var i = 0; i < seriesTitles.length; i++) { dataTable.addColumn(titleTypes[i], seriesTitles[i]); @@ -45,10 +45,17 @@ function drawTable(seriesTitles, titleTypes, data, elementId) { window.charts[elementId] = new google.visualization.Table(document.getElementById(elementId)); } + var cssClassNames = { + 'headerRow': '', + 'tableRow': 'table-row', + 'oddTableRow': 'table-row' + }; var opts = { alternatingRowStyle: true, page: 'enable', - pageSize: 25, + pageSize: numPages, + allowHtml: true, + cssClassNames: cssClassNames, }; window.charts[elementId].draw(dataTable, opts); } @@ -425,11 +432,44 @@ function drawFileSystemUsage(machineInfo, stats) { } } +function drawImages(images) { + if (images == null || images.length == 0) { + return; + } + window.charts = {}; + var titles = ["Repository", "Tags", "ID", "Virtual Size", "Creation Time"]; + var titleTypes = ['string', 'string', 'string', 'number', 'number']; + var data = []; + for (var i = 0; i < images.length; i++) { + var elements = []; + var tags = []; + var repos = images[i].repo_tags[0].split(":"); + repos.splice(-1,1) + for (var j = 0; j < images[i].repo_tags.length; j++) { + var splits = images[i].repo_tags[j].split(":") + if (splits.length > 1) { + tags.push(splits[splits.length - 1]) + } + } + elements.push(repos.join(":")); + elements.push(tags.join(", ")); + elements.push(images[i].id.substr(0,24)); + elements.push({v: images[i].virtual_size, f: humanizeIEC(images[i].virtual_size)}); + var d = new Date(images[i].created * 1000); + elements.push({v: images[i].created, f: d.toLocaleString()}); + data.push(elements); + } + drawTable(titles, titleTypes, data, "docker-images", 30); +} + function drawProcesses(processInfo) { + if (processInfo.length == 0) { + return; + } var titles = ["User", "PID", "PPID", "Start Time", "CPU %", "MEM %", "RSS", "Virtual Size", "Status", "Running Time", "Command"]; var titleTypes = ['string', 'number', 'number', 'string', 'number', 'number', 'number', 'number', 'string', 'string', 'string']; var data = [] - for (var i = 1; i < processInfo.length; i++) { + for (var i = 0; i < processInfo.length; i++) { var elements = []; elements.push(processInfo[i].user); elements.push(processInfo[i].pid); @@ -444,7 +484,7 @@ function drawProcesses(processInfo) { elements.push(processInfo[i].cmd); data.push(elements); } - drawTable(titles, titleTypes, data, "processes-top"); + drawTable(titles, titleTypes, data, "processes-top", 25); } // Draw the filesystem usage nodes.