Add docker status and images info to /docker page.
This commit is contained in:
parent
8164fac617
commit
f54e10b7e8
@ -64,6 +64,36 @@ const containersHtmlTemplate = `
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .DockerStatus}}
|
||||
<div class="col-sm-12">
|
||||
<div class="page-header">
|
||||
<h3>Driver Status</h3>
|
||||
</div>
|
||||
<ul class="list-group">
|
||||
{{range $dockerstatus := .DockerStatus}}
|
||||
<li class ="list-group-item"><span class="stat-label">{{$dockerstatus.Key}}</span> {{$dockerstatus.Value}}</li>
|
||||
{{end}}
|
||||
{{if .DockerDriverStatus}}
|
||||
<li class ="list-group-item"><span class="stat-label">Storage<br></span>
|
||||
<ul class="list-group">
|
||||
{{range $driverstatus := .DockerDriverStatus}}
|
||||
<li class="list-group-item"><span class="stat-label">{{$driverstatus.Key}}</span> {{$driverstatus.Value}}</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .DockerImages}}
|
||||
<div class="col-sm-12">
|
||||
<div class="page-header">
|
||||
<h3>Images</h3>
|
||||
</div>
|
||||
<div id="docker-images"></div>
|
||||
<br><br>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .ResourcesAvailable}}
|
||||
<div class="col-sm-12">
|
||||
<div class="page-header">
|
||||
@ -186,6 +216,7 @@ const containersHtmlTemplate = `
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
startPage({{.ContainerName}}, {{.CpuAvailable}}, {{.MemoryAvailable}}, {{.Root}});
|
||||
drawImages({{.DockerImages}});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -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,
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user