All checks were successful
continuous-integration/drone/push Build is passing
175 lines
6.0 KiB
Plaintext
175 lines
6.0 KiB
Plaintext
package views
|
|
|
|
import (
|
|
"fmt"
|
|
"vctp/components/core"
|
|
)
|
|
|
|
type VmTraceEntry struct {
|
|
Snapshot string
|
|
RawTime int64
|
|
Name string
|
|
VmId string
|
|
VmUuid string
|
|
Vcenter string
|
|
ResourcePool string
|
|
VcpuCount int64
|
|
RamGB int64
|
|
ProvisionedDisk float64
|
|
CreationTime string
|
|
DeletionTime string
|
|
}
|
|
|
|
type VmTraceChart struct {
|
|
ConfigJSON string
|
|
}
|
|
|
|
type VmTraceMeta struct {
|
|
ViewType string
|
|
TypeLabel string
|
|
HourlyLink string
|
|
DailyLink string
|
|
HourlyClass string
|
|
DailyClass string
|
|
}
|
|
|
|
type VmTraceDiagnosticLine struct {
|
|
Label string
|
|
Value string
|
|
}
|
|
|
|
type VmTraceDiagnostics struct {
|
|
Visible bool
|
|
Lines []VmTraceDiagnosticLine
|
|
}
|
|
|
|
templ VmTracePage(query string, display_query string, vm_id string, vm_uuid string, vm_name string, creationLabel string, deletionLabel string, creationApprox bool, entries []VmTraceEntry, chart VmTraceChart, meta VmTraceMeta, diagnostics VmTraceDiagnostics) {
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
@core.Header()
|
|
<body class="flex flex-col min-h-screen web2-bg">
|
|
<main class="flex-grow web2-shell web2-shell-wide space-y-8 max-w-screen-2xl mx-auto">
|
|
<section class="web2-header">
|
|
<div class="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
|
<div>
|
|
<div class="web2-pill">VM Trace</div>
|
|
<h1 class="mt-3 text-4xl font-bold">Snapshot history{display_query}</h1>
|
|
<p class="mt-2 text-sm text-slate-600">Timeline of vCPU, RAM, and resource pool changes across { meta.TypeLabel } snapshots.</p>
|
|
</div>
|
|
<div class="flex gap-3 flex-wrap">
|
|
<a class="web2-button" href="/">Dashboard</a>
|
|
</div>
|
|
</div>
|
|
<form method="get" action="/vm/trace" class="mt-4 grid gap-3 md:grid-cols-3">
|
|
<input type="hidden" name="view" value={ meta.ViewType }/>
|
|
<div class="flex flex-col gap-1">
|
|
<label class="text-sm text-slate-600" for="vm_id">VM ID</label>
|
|
<input class="web2-card border border-slate-200 px-3 py-2 rounded" type="text" id="vm_id" name="vm_id" value={vm_id} placeholder="vm-12345"/>
|
|
</div>
|
|
<div class="flex flex-col gap-1">
|
|
<label class="text-sm text-slate-600" for="vm_uuid">VM UUID</label>
|
|
<input class="web2-card border border-slate-200 px-3 py-2 rounded" type="text" id="vm_uuid" name="vm_uuid" value={vm_uuid} placeholder="uuid..."/>
|
|
</div>
|
|
<div class="flex flex-col gap-1">
|
|
<label class="text-sm text-slate-600" for="name">Name</label>
|
|
<input class="web2-card border border-slate-200 px-3 py-2 rounded" type="text" id="name" name="name" value={vm_name} placeholder="VM name"/>
|
|
</div>
|
|
<div class="md:col-span-3 flex gap-2">
|
|
<button class="web3-button active" type="submit">Load VM Trace</button>
|
|
<a class="web3-button" href="/vm/trace">Clear</a>
|
|
</div>
|
|
</form>
|
|
<div class="web3-button-group mt-5 mb-1">
|
|
<a class={ meta.HourlyClass } href={ meta.HourlyLink }>Hourly Detail</a>
|
|
<a class={ meta.DailyClass } href={ meta.DailyLink }>Daily Aggregated</a>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="web2-card">
|
|
<div class="flex items-center justify-between gap-3 mb-4 flex-wrap">
|
|
<h2 class="text-lg font-semibold">{ meta.TypeLabel } Timeline</h2>
|
|
<span class="web2-badge">{len(entries)} samples</span>
|
|
</div>
|
|
if chart.ConfigJSON != "" {
|
|
<div class="mb-6 overflow-auto">
|
|
<div class="web3-chart-frame">
|
|
<canvas id="vm-trace-chart" class="web3-chart-canvas" role="img" aria-label="VM timeline" data-chart-config={chart.ConfigJSON}></canvas>
|
|
<div id="vm-trace-tooltip" class="web3-chart-tooltip" aria-hidden="true"></div>
|
|
</div>
|
|
<script>
|
|
window.Web3Charts.renderFromDataset({
|
|
canvasId: "vm-trace-chart",
|
|
tooltipId: "vm-trace-tooltip",
|
|
})
|
|
</script>
|
|
</div>
|
|
}
|
|
<div class="grid gap-3 md:grid-cols-2 mb-4">
|
|
<div class="web2-card">
|
|
<p class="text-xs uppercase tracking-[0.15em] text-slate-500">Creation time</p>
|
|
<p class="mt-2 text-base font-semibold text-slate-800">{creationLabel}</p>
|
|
if creationApprox {
|
|
<p class="text-xs text-slate-500 mt-1">Approximate (earliest snapshot)</p>
|
|
}
|
|
</div>
|
|
<div class="web2-card">
|
|
<p class="text-xs uppercase tracking-[0.15em] text-slate-500">Deletion time</p>
|
|
<p class="mt-2 text-base font-semibold text-slate-800">{deletionLabel}</p>
|
|
</div>
|
|
</div>
|
|
if diagnostics.Visible && len(diagnostics.Lines) > 0 {
|
|
<details class="web2-card mb-4">
|
|
<summary class="cursor-pointer text-sm font-semibold text-slate-700">Lifecycle diagnostics</summary>
|
|
<div class="mt-3 overflow-hidden border border-slate-200 rounded">
|
|
<table class="web2-table">
|
|
<tbody>
|
|
for _, line := range diagnostics.Lines {
|
|
<tr>
|
|
<td class="font-semibold text-slate-700 w-72">{ line.Label }</td>
|
|
<td class="text-slate-600">{ line.Value }</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</details>
|
|
}
|
|
<div class="overflow-hidden border border-slate-200 rounded">
|
|
<table class="web2-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Snapshot</th>
|
|
<th>VM Name</th>
|
|
<th>VmId</th>
|
|
<th>VmUuid</th>
|
|
<th>Vcenter</th>
|
|
<th>Resource Pool</th>
|
|
<th class="text-right">vCPUs</th>
|
|
<th class="text-right">RAM (GB)</th>
|
|
<th class="text-right">Disk</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
for _, e := range entries {
|
|
<tr>
|
|
<td>{e.Snapshot}</td>
|
|
<td>{e.Name}</td>
|
|
<td>{e.VmId}</td>
|
|
<td>{e.VmUuid}</td>
|
|
<td>{e.Vcenter}</td>
|
|
<td>{e.ResourcePool}</td>
|
|
<td class="text-right">{e.VcpuCount}</td>
|
|
<td class="text-right">{e.RamGB}</td>
|
|
<td class="text-right">{fmt.Sprintf("%.1f", e.ProvisionedDisk)}</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
</body>
|
|
@core.Footer()
|
|
</html>
|
|
}
|