forked from lei.chen/myxce
345 lines
9.6 KiB
Go
345 lines
9.6 KiB
Go
package output
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"xcecli/models"
|
|
)
|
|
|
|
// HostsPagePrinter
|
|
type HostsPagePrinter struct {
|
|
*BasePagePrinter
|
|
}
|
|
|
|
// NewHostsPagePrinter
|
|
func NewHostsPagePrinter(opt ...BasePageOption) *HostsPagePrinter {
|
|
return &HostsPagePrinter{
|
|
BasePagePrinter: newBasePagePrinter(opt...),
|
|
}
|
|
}
|
|
|
|
// PrepareForPrinting
|
|
func (p *HostsPagePrinter) PrepareForPrinting(firstPage interface{}) {
|
|
hosts, ok := firstPage.(*models.HostsResponse)
|
|
if !ok {
|
|
fmt.Println("error: wrong data type to HostsPagePrinter")
|
|
return
|
|
}
|
|
|
|
// set field formats
|
|
p.fieldFormats = p.prepareFieldFormats()
|
|
|
|
// init column widths
|
|
p.initColumnWidths(hosts)
|
|
|
|
// prepare headers
|
|
p.prepareHeaders()
|
|
}
|
|
|
|
// prepare field formats
|
|
func (p *HostsPagePrinter) prepareFieldFormats() []*fieldFormat {
|
|
// here define the default fields based on the host data
|
|
var fieldFormats []*fieldFormat
|
|
if p.fields == "" {
|
|
// default fields
|
|
defaultFields := []string{
|
|
models.HEADER_HOST_NAME,
|
|
models.HEADER_HOST_STATUS,
|
|
models.HEADER_HOST_NCPUS,
|
|
models.HEADER_HOST_MAX_SLOT,
|
|
models.HEADER_HOST_NUM_RUN,
|
|
models.HEADER_HOST_NUM_SSUSP,
|
|
models.HEADER_HOST_NUM_USUSP,
|
|
models.HEADER_HOST_HOST_TYPE,
|
|
}
|
|
for _, field := range defaultFields {
|
|
fieldFormats = append(fieldFormats, &fieldFormat{name: field, align: "-"})
|
|
}
|
|
} else {
|
|
// parse user specified fields
|
|
for _, field := range strings.Split(p.fields, ",") {
|
|
fieldFormats = append(fieldFormats, parseFieldFormat(field))
|
|
}
|
|
}
|
|
return fieldFormats
|
|
}
|
|
|
|
// init column widths
|
|
func (p *HostsPagePrinter) initColumnWidths(hosts *models.HostsResponse) {
|
|
// init column widths to header length
|
|
for _, format := range p.fieldFormats {
|
|
p.columnWidths[format.name] = len(format.name)
|
|
if format.width > 0 {
|
|
p.columnWidths[format.name] = format.width
|
|
}
|
|
}
|
|
|
|
// calculate the max width of the first page data
|
|
for _, host := range hosts.Data.Rows {
|
|
for _, format := range p.fieldFormats {
|
|
width := 0
|
|
switch format.name {
|
|
case models.HEADER_HOST_NAME:
|
|
width = len(host.HostName)
|
|
case models.HEADER_HOST_STATUS:
|
|
width = len(host.HostStatus)
|
|
case models.HEADER_HOST_HOST_TYPE:
|
|
width = len(host.HostType)
|
|
case models.HEADER_HOST_NCPUS:
|
|
width = len(fmt.Sprintf("%d", host.NumCPUs))
|
|
case models.HEADER_HOST_MAX_SLOT:
|
|
width = len(fmt.Sprintf("%d", host.MaxSlot))
|
|
case models.HEADER_HOST_NUM_RUN:
|
|
width = len(fmt.Sprintf("%d", host.NumRun))
|
|
case models.HEADER_HOST_NUM_SSUSP:
|
|
width = len(fmt.Sprintf("%d", host.NumSSusp))
|
|
case models.HEADER_HOST_NUM_USUSP:
|
|
width = len(fmt.Sprintf("%d", host.NumUSusp))
|
|
}
|
|
|
|
if !p.wideFormat && width > 15 {
|
|
width = 15
|
|
}
|
|
|
|
if width > p.columnWidths[format.name] && format.width == 0 {
|
|
p.columnWidths[format.name] = width
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// PrintPage
|
|
func (p *HostsPagePrinter) PrintPage(page interface{}) {
|
|
hosts, ok := page.(*models.HostsResponse)
|
|
if !ok {
|
|
fmt.Println("error: wrong data type to HostsPagePrinter")
|
|
return
|
|
}
|
|
|
|
p.pageCount++
|
|
|
|
if p.verbose {
|
|
printHostsVerboseOutput(hosts)
|
|
return
|
|
}
|
|
|
|
if p.formatJson {
|
|
p.printJsonPage(hosts)
|
|
return
|
|
} else {
|
|
// print header (if needed)
|
|
p.printHeader()
|
|
|
|
// print data rows
|
|
rows := p.formatRows(hosts, true)
|
|
for _, row := range rows {
|
|
fmt.Fprintln(p.w, strings.Join(row, "\t"))
|
|
}
|
|
p.w.Flush()
|
|
}
|
|
}
|
|
|
|
// format data rows
|
|
func (p *HostsPagePrinter) formatRows(hosts *models.HostsResponse, truncatFlag bool) [][]string {
|
|
var rows [][]string
|
|
if p.wideFormat {
|
|
truncatFlag = false
|
|
}
|
|
for _, host := range hosts.Data.Rows {
|
|
isUnavail := host.HostStatus == "UNAVAIL"
|
|
row := make([]string, 0, len(p.fieldFormats))
|
|
for _, format := range p.fieldFormats {
|
|
width := p.columnWidths[format.name]
|
|
align := format.align
|
|
switch format.name {
|
|
case models.HEADER_HOST_NAME:
|
|
row = appendOrDefault(row, FormatStringField(host.HostName, width, truncatFlag, true), "-")
|
|
case models.HEADER_HOST_STATUS:
|
|
row = appendOrDefault(row, FormatStringField(host.HostStatus, width, truncatFlag, true), "-")
|
|
case models.HEADER_HOST_HOST_TYPE:
|
|
if isUnavail {
|
|
row = append(row, FormatStringField("UNKNOWN", width, truncatFlag, true))
|
|
} else {
|
|
row = appendOrDefault(row, FormatStringField(host.HostType, width, truncatFlag, true), "-")
|
|
}
|
|
case models.HEADER_HOST_NCPUS:
|
|
if isUnavail {
|
|
row = append(row, FormatStringField("-", width, truncatFlag, true))
|
|
} else {
|
|
row = appendOrDefault(row, fmt.Sprintf("%"+align+"*d", width, host.NumCPUs), "0")
|
|
}
|
|
case models.HEADER_HOST_MAX_SLOT:
|
|
if isUnavail {
|
|
row = append(row, FormatStringField("-", width, truncatFlag, true))
|
|
} else {
|
|
row = appendOrDefault(row, fmt.Sprintf("%"+align+"*d", width, host.MaxSlot), "0")
|
|
}
|
|
case models.HEADER_HOST_NUM_RUN:
|
|
if isUnavail {
|
|
row = append(row, FormatStringField("-", width, truncatFlag, true))
|
|
} else {
|
|
row = appendOrDefault(row, fmt.Sprintf("%"+align+"*d", width, host.NumRun), "0")
|
|
}
|
|
case models.HEADER_HOST_NUM_SSUSP:
|
|
if isUnavail {
|
|
row = append(row, FormatStringField("-", width, truncatFlag, true))
|
|
} else {
|
|
row = appendOrDefault(row, fmt.Sprintf("%"+align+"*d", width, host.NumSSusp), "0")
|
|
}
|
|
case models.HEADER_HOST_NUM_USUSP:
|
|
if isUnavail {
|
|
row = append(row, FormatStringField("-", width, truncatFlag, true))
|
|
} else {
|
|
row = appendOrDefault(row, fmt.Sprintf("%"+align+"*d", width, host.NumUSusp), "0")
|
|
}
|
|
}
|
|
}
|
|
rows = append(rows, row)
|
|
}
|
|
return rows
|
|
}
|
|
|
|
// print JSON page
|
|
func (p *HostsPagePrinter) printJsonPage(hosts *models.HostsResponse) {
|
|
// if the format is JSON, directly convert the current page to JSON
|
|
headers := make([]string, len(p.fieldFormats))
|
|
for i, format := range p.fieldFormats {
|
|
headers[i] = format.name
|
|
}
|
|
|
|
rows := p.formatRows(hosts, false)
|
|
p.PrintJsonPageGeneric(rows, headers)
|
|
}
|
|
|
|
func printHostsVerboseOutput(hosts *models.HostsResponse) {
|
|
for _, host := range hosts.Data.Rows {
|
|
isUnavail := host.HostStatus == "UNAVAIL"
|
|
fmt.Printf("HOST %s\n", host.HostName)
|
|
// table 1
|
|
headers := models.HostDetailHeaders
|
|
row1 := make([]string, 0, len(headers))
|
|
widths1 := make([]int, len(headers))
|
|
for i, h := range headers {
|
|
var val string
|
|
switch h {
|
|
case models.HEADER_HOST_STATUS:
|
|
val = host.HostStatus
|
|
case models.HEADER_HOST_CPUF:
|
|
if isUnavail {
|
|
val = "-"
|
|
} else {
|
|
val = fmt.Sprintf("%.2f", host.CPUFactor)
|
|
}
|
|
case models.HEADER_HOST_JLU:
|
|
val = "-"
|
|
case models.HEADER_HOST_MAX:
|
|
if isUnavail {
|
|
val = "-"
|
|
} else {
|
|
val = fmt.Sprintf("%d", host.MaxSlot)
|
|
}
|
|
case models.HEADER_HOST_NJOBS:
|
|
if isUnavail {
|
|
val = "-"
|
|
} else {
|
|
val = fmt.Sprintf("%d", host.NumRun)
|
|
}
|
|
case models.HEADER_HOST_RUN:
|
|
if isUnavail {
|
|
val = "-"
|
|
} else {
|
|
val = fmt.Sprintf("%d", host.NumRun)
|
|
}
|
|
case models.HEADER_HOST_SSUSP:
|
|
if isUnavail {
|
|
val = "-"
|
|
} else {
|
|
val = fmt.Sprintf("%d", host.NumSSusp)
|
|
}
|
|
case models.HEADER_HOST_USUSP:
|
|
if isUnavail {
|
|
val = "-"
|
|
} else {
|
|
val = fmt.Sprintf("%d", host.NumUSusp)
|
|
}
|
|
case models.HEADER_HOST_RSV:
|
|
val = "-"
|
|
case models.HEADER_HOST_DISPT_WINDOW:
|
|
if str, ok := host.DisptWindow.(string); ok {
|
|
val = str
|
|
} else {
|
|
val = "-"
|
|
}
|
|
default:
|
|
val = "-"
|
|
}
|
|
widths1[i] = max(len(h), len(val))
|
|
row1 = append(row1, FormatStringField(val, widths1[i], false, true))
|
|
}
|
|
tp1 := TablePrinter{Headers: headers, Rows: [][]string{row1}, ColWidths: widths1}
|
|
tp1.Print()
|
|
fmt.Println("")
|
|
|
|
fmt.Println("CURRENT LOAD USED FOR SCHEDULING:")
|
|
|
|
// table2
|
|
headers2 := append([]string{""}, models.HostLoadSchedulingHeaders...)
|
|
var totalVals, reserveVals []string
|
|
if isUnavail {
|
|
totalVals = []string{"Total", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"}
|
|
reserveVals = []string{"Reserved", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"}
|
|
} else {
|
|
totalVals = []string{"Total", "0.0", "0.0", "0.0", "1%", "0.0", "33", "1", "1137", "51G", "3.9G", "6.8G", "8", "0.0"}
|
|
reserveVals = []string{"Reserved", "0.0", "0.0", "0.0", "0%", "0.0", "0", "0", "0", "0M", "0M", "0M", "-", "-"}
|
|
}
|
|
|
|
widths2 := make([]int, len(headers2))
|
|
for i := range headers2 {
|
|
widths2[i] = max(len(headers2[i]), len(totalVals[i]))
|
|
widths2[i] = max(widths2[i], len(reserveVals[i]))
|
|
}
|
|
|
|
rowTotal := make([]string, len(headers2))
|
|
rowReserve := make([]string, len(headers2))
|
|
for i := range headers2 {
|
|
rowTotal[i] = FormatStringField(totalVals[i], widths2[i], false, true)
|
|
rowReserve[i] = FormatStringField(reserveVals[i], widths2[i], false, true)
|
|
}
|
|
|
|
tp2 := TablePrinter{Headers: headers2, Rows: [][]string{rowTotal, rowReserve}, ColWidths: widths2}
|
|
tp2.Print()
|
|
fmt.Println("")
|
|
|
|
// Table 3
|
|
fmt.Println("LOAD THRESHOLD USED FOR SCHEDULING:")
|
|
|
|
headers3 := append([]string{""}, models.HostLoadSchedulingHeaders...)
|
|
loadSched := []string{"loadSched", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"}
|
|
loadStop := []string{"loadStop", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"}
|
|
|
|
widths3 := make([]int, len(headers3))
|
|
for i := range headers3 {
|
|
widths3[i] = max(len(headers3[i]), len(loadSched[i]))
|
|
widths3[i] = max(widths3[i], len(loadStop[i]))
|
|
}
|
|
|
|
rowSched := make([]string, len(headers3))
|
|
rowStop := make([]string, len(headers3))
|
|
for i := range headers3 {
|
|
rowSched[i] = FormatStringField(loadSched[i], widths2[i], false, true)
|
|
rowStop[i] = FormatStringField(loadStop[i], widths2[i], false, true)
|
|
}
|
|
|
|
tp3 := TablePrinter{Headers: headers3, Rows: [][]string{rowSched, rowStop}, ColWidths: widths2}
|
|
tp3.Print()
|
|
fmt.Println("")
|
|
fmt.Println("CONFIGURED AFFINITY CPU LIST: all")
|
|
}
|
|
}
|
|
|
|
func max(a, b int) int {
|
|
if a > b {
|
|
return a
|
|
}
|
|
return b
|
|
}
|