This commit is contained in:
@@ -38,7 +38,7 @@ func Header() templ.Component {
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs("/assets/js/web3-charts.js?v=" + version.Value)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `core/header.templ`, Line: 15, Col: 62}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/core/header.templ`, Line: 15, Col: 62}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -51,7 +51,7 @@ func Header() templ.Component {
|
||||
var templ_7745c5c3_Var3 templ.SafeURL
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs("/assets/css/output@" + version.Value + ".css")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `core/header.templ`, Line: 16, Col: 61}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/core/header.templ`, Line: 16, Col: 61}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
|
||||
@@ -54,7 +54,7 @@ func Index(info BuildInfo) templ.Component {
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(info.BuildTime)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/index.templ`, Line: 40, Col: 59}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/index.templ`, Line: 40, Col: 59}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -67,7 +67,7 @@ func Index(info BuildInfo) templ.Component {
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(info.SHA1Ver)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/index.templ`, Line: 44, Col: 57}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/index.templ`, Line: 44, Col: 57}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -80,7 +80,7 @@ func Index(info BuildInfo) templ.Component {
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(info.GoVersion)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/index.templ`, Line: 48, Col: 59}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/index.templ`, Line: 48, Col: 59}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
|
||||
@@ -166,7 +166,7 @@ func SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) te
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 60, Col: 50}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 60, Col: 50}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -179,7 +179,7 @@ func SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) te
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(subtitle)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 61, Col: 56}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 61, Col: 56}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -192,7 +192,7 @@ func SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) te
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(len(entries))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 69, Col: 45}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 69, Col: 45}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -211,7 +211,7 @@ func SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) te
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Group)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 84, Col: 77}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 84, Col: 77}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -229,7 +229,7 @@ func SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) te
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Label)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 90, Col: 76}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 90, Col: 76}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -242,7 +242,7 @@ func SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) te
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Count)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 94, Col: 49}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 94, Col: 49}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -255,7 +255,7 @@ func SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) te
|
||||
var templ_7745c5c3_Var11 templ.SafeURL
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinURLErrs(entry.Link)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 97, Col: 49}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 97, Col: 49}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -318,7 +318,7 @@ func VcenterList(links []VcenterLink) templ.Component {
|
||||
var templ_7745c5c3_Var13 string
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(len(links))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 130, Col: 43}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 130, Col: 43}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -336,7 +336,7 @@ func VcenterList(links []VcenterLink) templ.Component {
|
||||
var templ_7745c5c3_Var14 string
|
||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(link.Name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 143, Col: 62}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 143, Col: 62}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -349,7 +349,7 @@ func VcenterList(links []VcenterLink) templ.Component {
|
||||
var templ_7745c5c3_Var15 templ.SafeURL
|
||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinURLErrs(link.Link)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 145, Col: 48}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 145, Col: 48}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -412,7 +412,7 @@ func VcenterTotalsPage(vcenter string, entries []VcenterTotalsEntry, chart Vcent
|
||||
var templ_7745c5c3_Var17 string
|
||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(vcenter)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 169, Col: 63}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 169, Col: 63}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -425,7 +425,7 @@ func VcenterTotalsPage(vcenter string, entries []VcenterTotalsEntry, chart Vcent
|
||||
var templ_7745c5c3_Var18 string
|
||||
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(meta.TypeLabel)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 170, Col: 62}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 170, Col: 62}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -447,7 +447,7 @@ func VcenterTotalsPage(vcenter string, entries []VcenterTotalsEntry, chart Vcent
|
||||
var templ_7745c5c3_Var20 string
|
||||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var19).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 1, Col: 0}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -460,7 +460,7 @@ func VcenterTotalsPage(vcenter string, entries []VcenterTotalsEntry, chart Vcent
|
||||
var templ_7745c5c3_Var21 templ.SafeURL
|
||||
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinURLErrs(meta.HourlyLink)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 178, Col: 59}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 178, Col: 59}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -482,7 +482,7 @@ func VcenterTotalsPage(vcenter string, entries []VcenterTotalsEntry, chart Vcent
|
||||
var templ_7745c5c3_Var23 string
|
||||
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var22).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 1, Col: 0}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -495,7 +495,7 @@ func VcenterTotalsPage(vcenter string, entries []VcenterTotalsEntry, chart Vcent
|
||||
var templ_7745c5c3_Var24 templ.SafeURL
|
||||
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinURLErrs(meta.DailyLink)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 179, Col: 57}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 179, Col: 57}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -508,7 +508,7 @@ func VcenterTotalsPage(vcenter string, entries []VcenterTotalsEntry, chart Vcent
|
||||
var templ_7745c5c3_Var25 string
|
||||
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(meta.TypeLabel)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 184, Col: 56}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 184, Col: 56}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -521,7 +521,7 @@ func VcenterTotalsPage(vcenter string, entries []VcenterTotalsEntry, chart Vcent
|
||||
var templ_7745c5c3_Var26 string
|
||||
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(len(entries))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 185, Col: 45}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 185, Col: 45}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -539,7 +539,7 @@ func VcenterTotalsPage(vcenter string, entries []VcenterTotalsEntry, chart Vcent
|
||||
var templ_7745c5c3_Var27 string
|
||||
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(chart.ConfigJSON)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 190, Col: 145}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 190, Col: 145}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -562,7 +562,7 @@ func VcenterTotalsPage(vcenter string, entries []VcenterTotalsEntry, chart Vcent
|
||||
var templ_7745c5c3_Var28 string
|
||||
templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Snapshot)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 214, Col: 30}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 214, Col: 30}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -575,7 +575,7 @@ func VcenterTotalsPage(vcenter string, entries []VcenterTotalsEntry, chart Vcent
|
||||
var templ_7745c5c3_Var29 string
|
||||
templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(entry.VmCount)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 215, Col: 48}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 215, Col: 48}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -588,7 +588,7 @@ func VcenterTotalsPage(vcenter string, entries []VcenterTotalsEntry, chart Vcent
|
||||
var templ_7745c5c3_Var30 string
|
||||
templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(entry.VcpuTotal)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 216, Col: 50}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 216, Col: 50}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -601,7 +601,7 @@ func VcenterTotalsPage(vcenter string, entries []VcenterTotalsEntry, chart Vcent
|
||||
var templ_7745c5c3_Var31 string
|
||||
templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(entry.RamTotalGB)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 217, Col: 51}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 217, Col: 51}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
|
||||
@@ -33,7 +33,17 @@ type VmTraceMeta struct {
|
||||
DailyClass string
|
||||
}
|
||||
|
||||
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) {
|
||||
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()
|
||||
@@ -107,6 +117,23 @@ templ VmTracePage(query string, display_query string, vm_id string, vm_uuid stri
|
||||
<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>
|
||||
|
||||
@@ -41,7 +41,17 @@ type VmTraceMeta struct {
|
||||
DailyClass string
|
||||
}
|
||||
|
||||
func 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) templ.Component {
|
||||
type VmTraceDiagnosticLine struct {
|
||||
Label string
|
||||
Value string
|
||||
}
|
||||
|
||||
type VmTraceDiagnostics struct {
|
||||
Visible bool
|
||||
Lines []VmTraceDiagnosticLine
|
||||
}
|
||||
|
||||
func 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) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
@@ -77,7 +87,7 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(display_query)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 46, Col: 74}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 56, Col: 74}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -90,7 +100,7 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(meta.TypeLabel)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 47, Col: 119}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 57, Col: 119}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -103,7 +113,7 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(meta.ViewType)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 54, Col: 61}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 64, Col: 61}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -116,7 +126,7 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(vm_id)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 57, Col: 123}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 67, Col: 123}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -129,7 +139,7 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(vm_uuid)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 61, Col: 129}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 71, Col: 129}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -142,7 +152,7 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(vm_name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 65, Col: 123}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 75, Col: 123}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -164,7 +174,7 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var8).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 1, Col: 0}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -177,7 +187,7 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
var templ_7745c5c3_Var10 templ.SafeURL
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(meta.HourlyLink)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 73, Col: 59}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 83, Col: 59}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -199,7 +209,7 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
var templ_7745c5c3_Var12 string
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var11).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 1, Col: 0}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -212,7 +222,7 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
var templ_7745c5c3_Var13 templ.SafeURL
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinURLErrs(meta.DailyLink)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 74, Col: 57}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 84, Col: 57}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -225,7 +235,7 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
var templ_7745c5c3_Var14 string
|
||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(meta.TypeLabel)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 80, Col: 56}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 90, Col: 56}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -238,7 +248,7 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
var templ_7745c5c3_Var15 string
|
||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(len(entries))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 81, Col: 44}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 91, Col: 44}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -256,7 +266,7 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
var templ_7745c5c3_Var16 string
|
||||
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(chart.ConfigJSON)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 86, Col: 133}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 96, Col: 133}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -274,7 +284,7 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
var templ_7745c5c3_Var17 string
|
||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(creationLabel)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 100, Col: 76}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 110, Col: 76}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -297,140 +307,186 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
var templ_7745c5c3_Var18 string
|
||||
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(deletionLabel)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 107, Col: 76}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 117, Col: 76}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</p></div></div><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>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</p></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
for _, e := range entries {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "<tr><td>")
|
||||
if diagnostics.Visible && len(diagnostics.Lines) > 0 {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "<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>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
for _, line := range diagnostics.Lines {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<tr><td class=\"font-semibold text-slate-700 w-72\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var19 string
|
||||
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(e.Snapshot)
|
||||
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(line.Label)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 128, Col: 25}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 128, Col: 70}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</td><td>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</td><td class=\"text-slate-600\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var20 string
|
||||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(e.Name)
|
||||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(line.Value)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 129, Col: 21}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 129, Col: 51}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</td><td>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</td></tr>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</tbody></table></div></details>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "<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>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
for _, e := range entries {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<tr><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var21 string
|
||||
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(e.VmId)
|
||||
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(e.Snapshot)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 130, Col: 21}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 155, Col: 25}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</td><td>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var22 string
|
||||
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(e.VmUuid)
|
||||
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(e.Name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 131, Col: 23}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 156, Col: 21}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</td><td>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var23 string
|
||||
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(e.Vcenter)
|
||||
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(e.VmId)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 132, Col: 24}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 157, Col: 21}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</td><td>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var24 string
|
||||
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(e.ResourcePool)
|
||||
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(e.VmUuid)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 133, Col: 29}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 158, Col: 23}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "</td><td class=\"text-right\">")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var25 string
|
||||
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(e.VcpuCount)
|
||||
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(e.Vcenter)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 134, Col: 45}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 159, Col: 24}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "</td><td class=\"text-right\">")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var26 string
|
||||
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(e.RamGB)
|
||||
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(e.ResourcePool)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 135, Col: 41}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 160, Col: 29}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "</td><td class=\"text-right\">")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "</td><td class=\"text-right\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var27 string
|
||||
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f", e.ProvisionedDisk))
|
||||
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(e.VcpuCount)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/vm_trace.templ`, Line: 136, Col: 72}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 161, Col: 45}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</td></tr>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "</td><td class=\"text-right\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var28 string
|
||||
templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(e.RamGB)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 162, Col: 41}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "</td><td class=\"text-right\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var29 string
|
||||
templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f", e.ProvisionedDisk))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/vm_trace.templ`, Line: 163, Col: 72}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</td></tr>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</tbody></table></div></section></main></body>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "</tbody></table></div></section></main></body>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -438,7 +494,7 @@ func VmTracePage(query string, display_query string, vm_id string, vm_uuid strin
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</html>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</html>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
||||
224
db/helpers.go
224
db/helpers.go
@@ -1672,6 +1672,33 @@ type VmLifecycle struct {
|
||||
DeletionTime int64
|
||||
}
|
||||
|
||||
// VmLifecycleSourceDiagnostics captures how one lifecycle source contributed to the final lifecycle decision.
|
||||
type VmLifecycleSourceDiagnostics struct {
|
||||
Source string
|
||||
Used bool
|
||||
Error string
|
||||
MatchedRows int64
|
||||
FirstSeen int64
|
||||
LastSeen int64
|
||||
CreationTime int64
|
||||
CreationApprox bool
|
||||
DeletionRows int64
|
||||
DeletionMin int64
|
||||
DeletionMax int64
|
||||
SelectedDeletionTime int64
|
||||
StaleDeletionIgnored bool
|
||||
}
|
||||
|
||||
// VmLifecycleDiagnostics captures per-source lifecycle diagnostics for a VM lookup.
|
||||
type VmLifecycleDiagnostics struct {
|
||||
LookupField string
|
||||
LookupValue string
|
||||
HourlyCache VmLifecycleSourceDiagnostics
|
||||
LifecycleCache VmLifecycleSourceDiagnostics
|
||||
SnapshotFallback VmLifecycleSourceDiagnostics
|
||||
FinalLifecycle VmLifecycle
|
||||
}
|
||||
|
||||
func vmLookupPredicate(vmID, vmUUID, name string) (string, []interface{}, bool) {
|
||||
vmID = strings.TrimSpace(vmID)
|
||||
vmUUID = strings.TrimSpace(vmUUID)
|
||||
@@ -1688,6 +1715,22 @@ func vmLookupPredicate(vmID, vmUUID, name string) (string, []interface{}, bool)
|
||||
}
|
||||
}
|
||||
|
||||
func vmLookupDescriptor(vmID, vmUUID, name string) (string, string) {
|
||||
vmID = strings.TrimSpace(vmID)
|
||||
vmUUID = strings.TrimSpace(vmUUID)
|
||||
name = strings.TrimSpace(name)
|
||||
switch {
|
||||
case vmID != "":
|
||||
return "vm_id", vmID
|
||||
case vmUUID != "":
|
||||
return "vm_uuid", vmUUID
|
||||
case name != "":
|
||||
return "name", name
|
||||
default:
|
||||
return "", ""
|
||||
}
|
||||
}
|
||||
|
||||
// FetchVmTrace returns combined hourly snapshot records for a VM (by id/uuid/name) ordered by snapshot time.
|
||||
// It prefers the shared vm_hourly_stats history table and falls back to per-snapshot tables.
|
||||
func FetchVmTrace(ctx context.Context, dbConn *sqlx.DB, vmID, vmUUID, name string) ([]VmTraceRow, error) {
|
||||
@@ -1892,36 +1935,75 @@ WHERE %s
|
||||
// FetchVmLifecycle walks VM history data to determine lifecycle bounds for a VM.
|
||||
// It prefers vm_hourly_stats + vm_lifecycle_cache and falls back to per-snapshot table probes.
|
||||
func FetchVmLifecycle(ctx context.Context, dbConn *sqlx.DB, vmID, vmUUID, name string) (VmLifecycle, error) {
|
||||
lifecycle, _, err := FetchVmLifecycleWithDiagnostics(ctx, dbConn, vmID, vmUUID, name)
|
||||
return lifecycle, err
|
||||
}
|
||||
|
||||
// FetchVmLifecycleWithDiagnostics returns lifecycle details plus source-level diagnostics.
|
||||
func FetchVmLifecycleWithDiagnostics(ctx context.Context, dbConn *sqlx.DB, vmID, vmUUID, name string) (VmLifecycle, VmLifecycleDiagnostics, error) {
|
||||
lookupField, lookupValue := vmLookupDescriptor(vmID, vmUUID, name)
|
||||
diagnostics := VmLifecycleDiagnostics{
|
||||
LookupField: lookupField,
|
||||
LookupValue: lookupValue,
|
||||
HourlyCache: VmLifecycleSourceDiagnostics{
|
||||
Source: "vm_hourly_stats",
|
||||
},
|
||||
LifecycleCache: VmLifecycleSourceDiagnostics{
|
||||
Source: "vm_lifecycle_cache",
|
||||
},
|
||||
SnapshotFallback: VmLifecycleSourceDiagnostics{
|
||||
Source: "snapshot_registry/hourly_tables",
|
||||
},
|
||||
}
|
||||
|
||||
if TableExists(ctx, dbConn, "vm_hourly_stats") {
|
||||
lifecycle, found, err := fetchVmLifecycleFromHourlyCache(ctx, dbConn, vmID, vmUUID, name)
|
||||
lifecycle, sourceDiag, found, err := fetchVmLifecycleFromHourlyCache(ctx, dbConn, vmID, vmUUID, name)
|
||||
diagnostics.HourlyCache = sourceDiag
|
||||
if err != nil {
|
||||
diagnostics.HourlyCache.Error = err.Error()
|
||||
slog.Warn("vm lifecycle cache query failed; falling back to hourly tables", "error", err)
|
||||
} else if found {
|
||||
diagnostics.HourlyCache.Used = true
|
||||
if TableExists(ctx, dbConn, "vm_lifecycle_cache") {
|
||||
cached, cachedFound, cacheErr := fetchVmLifecycleFromLifecycleCache(ctx, dbConn, vmID, vmUUID, name)
|
||||
cached, cachedDiag, cachedFound, cacheErr := fetchVmLifecycleFromLifecycleCache(ctx, dbConn, vmID, vmUUID, name)
|
||||
diagnostics.LifecycleCache = cachedDiag
|
||||
if cacheErr != nil {
|
||||
diagnostics.LifecycleCache.Error = cacheErr.Error()
|
||||
slog.Warn("vm lifecycle cache lookup failed", "error", cacheErr)
|
||||
} else if cachedFound {
|
||||
diagnostics.LifecycleCache.Used = true
|
||||
lifecycle = mergeVmLifecycle(lifecycle, cached)
|
||||
}
|
||||
}
|
||||
return lifecycle, nil
|
||||
diagnostics.FinalLifecycle = lifecycle
|
||||
return lifecycle, diagnostics, nil
|
||||
}
|
||||
}
|
||||
return fetchVmLifecycleFromSnapshotTables(ctx, dbConn, vmID, vmUUID, name)
|
||||
lifecycle, fallbackDiag, err := fetchVmLifecycleFromSnapshotTables(ctx, dbConn, vmID, vmUUID, name)
|
||||
diagnostics.SnapshotFallback = fallbackDiag
|
||||
if err != nil {
|
||||
diagnostics.SnapshotFallback.Error = err.Error()
|
||||
return lifecycle, diagnostics, err
|
||||
}
|
||||
diagnostics.SnapshotFallback.Used = true
|
||||
diagnostics.FinalLifecycle = lifecycle
|
||||
return lifecycle, diagnostics, nil
|
||||
}
|
||||
|
||||
func fetchVmLifecycleFromHourlyCache(ctx context.Context, dbConn *sqlx.DB, vmID, vmUUID, name string) (VmLifecycle, bool, error) {
|
||||
func fetchVmLifecycleFromHourlyCache(ctx context.Context, dbConn *sqlx.DB, vmID, vmUUID, name string) (VmLifecycle, VmLifecycleSourceDiagnostics, bool, error) {
|
||||
diag := VmLifecycleSourceDiagnostics{Source: "vm_hourly_stats"}
|
||||
matchWhere, args, ok := vmLookupPredicate(vmID, vmUUID, name)
|
||||
if !ok {
|
||||
return VmLifecycle{}, false, nil
|
||||
return VmLifecycle{}, diag, false, nil
|
||||
}
|
||||
var row struct {
|
||||
Rows int64 `db:"rows"`
|
||||
Creation sql.NullInt64 `db:"creation_time"`
|
||||
FirstSeen sql.NullInt64 `db:"first_seen"`
|
||||
LastSeen sql.NullInt64 `db:"last_seen"`
|
||||
Deletion sql.NullInt64 `db:"deletion_time"`
|
||||
DeletionRows int64 `db:"deletion_rows"`
|
||||
DeletionMin sql.NullInt64 `db:"deletion_min"`
|
||||
DeletionMax sql.NullInt64 `db:"deletion_max"`
|
||||
}
|
||||
query := `
|
||||
SELECT
|
||||
@@ -1929,16 +2011,29 @@ SELECT
|
||||
MIN(NULLIF("CreationTime",0)) AS creation_time,
|
||||
MIN("SnapshotTime") AS first_seen,
|
||||
MAX("SnapshotTime") AS last_seen,
|
||||
MIN(NULLIF("DeletionTime",0)) AS deletion_time
|
||||
SUM(CASE WHEN COALESCE("DeletionTime",0) > 0 THEN 1 ELSE 0 END) AS deletion_rows,
|
||||
MIN(NULLIF("DeletionTime",0)) AS deletion_min,
|
||||
MAX(NULLIF("DeletionTime",0)) AS deletion_max
|
||||
FROM vm_hourly_stats
|
||||
WHERE ` + matchWhere + `
|
||||
`
|
||||
query = dbConn.Rebind(query)
|
||||
if err := getLog(ctx, dbConn, &row, query, args...); err != nil {
|
||||
return VmLifecycle{}, false, err
|
||||
diag.Error = err.Error()
|
||||
return VmLifecycle{}, diag, false, err
|
||||
}
|
||||
diag.MatchedRows = row.Rows
|
||||
diag.FirstSeen = row.FirstSeen.Int64
|
||||
diag.LastSeen = row.LastSeen.Int64
|
||||
diag.DeletionRows = row.DeletionRows
|
||||
if row.DeletionMin.Valid {
|
||||
diag.DeletionMin = row.DeletionMin.Int64
|
||||
}
|
||||
if row.DeletionMax.Valid {
|
||||
diag.DeletionMax = row.DeletionMax.Int64
|
||||
}
|
||||
if row.Rows == 0 {
|
||||
return VmLifecycle{}, false, nil
|
||||
return VmLifecycle{}, diag, false, nil
|
||||
}
|
||||
lifecycle := VmLifecycle{
|
||||
FirstSeen: row.FirstSeen.Int64,
|
||||
@@ -1951,38 +2046,70 @@ WHERE ` + matchWhere + `
|
||||
lifecycle.CreationTime = row.FirstSeen.Int64
|
||||
lifecycle.CreationApprox = true
|
||||
}
|
||||
if row.Deletion.Valid && row.Deletion.Int64 > 0 {
|
||||
lifecycle.DeletionTime = row.Deletion.Int64
|
||||
diag.CreationTime = lifecycle.CreationTime
|
||||
diag.CreationApprox = lifecycle.CreationApprox
|
||||
if row.DeletionMax.Valid && row.DeletionMax.Int64 > 0 {
|
||||
if row.LastSeen.Valid && row.LastSeen.Int64 > 0 && row.DeletionMax.Int64 <= row.LastSeen.Int64 {
|
||||
diag.StaleDeletionIgnored = true
|
||||
slog.Warn("ignoring stale VM deletion from hourly cache",
|
||||
"vm_id", vmID,
|
||||
"vm_uuid", vmUUID,
|
||||
"name", name,
|
||||
"deletion_rows", row.DeletionRows,
|
||||
"deletion_min", row.DeletionMin.Int64,
|
||||
"deletion_max", row.DeletionMax.Int64,
|
||||
"last_seen", row.LastSeen.Int64,
|
||||
)
|
||||
} else {
|
||||
lifecycle.DeletionTime = row.DeletionMax.Int64
|
||||
}
|
||||
return lifecycle, true, nil
|
||||
}
|
||||
diag.SelectedDeletionTime = lifecycle.DeletionTime
|
||||
return lifecycle, diag, true, nil
|
||||
}
|
||||
|
||||
func fetchVmLifecycleFromLifecycleCache(ctx context.Context, dbConn *sqlx.DB, vmID, vmUUID, name string) (VmLifecycle, bool, error) {
|
||||
func fetchVmLifecycleFromLifecycleCache(ctx context.Context, dbConn *sqlx.DB, vmID, vmUUID, name string) (VmLifecycle, VmLifecycleSourceDiagnostics, bool, error) {
|
||||
diag := VmLifecycleSourceDiagnostics{Source: "vm_lifecycle_cache"}
|
||||
matchWhere, args, ok := vmLookupPredicate(vmID, vmUUID, name)
|
||||
if !ok {
|
||||
return VmLifecycle{}, false, nil
|
||||
return VmLifecycle{}, diag, false, nil
|
||||
}
|
||||
var row struct {
|
||||
Rows int64 `db:"rows"`
|
||||
FirstSeen sql.NullInt64 `db:"first_seen"`
|
||||
LastSeen sql.NullInt64 `db:"last_seen"`
|
||||
Deletion sql.NullInt64 `db:"deletion_time"`
|
||||
DeletionRows int64 `db:"deletion_rows"`
|
||||
DeletionMin sql.NullInt64 `db:"deletion_min"`
|
||||
DeletionMax sql.NullInt64 `db:"deletion_max"`
|
||||
}
|
||||
query := `
|
||||
SELECT
|
||||
COUNT(1) AS rows,
|
||||
MIN(NULLIF("FirstSeen",0)) AS first_seen,
|
||||
MAX(NULLIF("LastSeen",0)) AS last_seen,
|
||||
MIN(NULLIF("DeletedAt",0)) AS deletion_time
|
||||
SUM(CASE WHEN COALESCE("DeletedAt",0) > 0 THEN 1 ELSE 0 END) AS deletion_rows,
|
||||
MIN(NULLIF("DeletedAt",0)) AS deletion_min,
|
||||
MAX(NULLIF("DeletedAt",0)) AS deletion_max
|
||||
FROM vm_lifecycle_cache
|
||||
WHERE ` + matchWhere + `
|
||||
`
|
||||
query = dbConn.Rebind(query)
|
||||
if err := getLog(ctx, dbConn, &row, query, args...); err != nil {
|
||||
return VmLifecycle{}, false, err
|
||||
diag.Error = err.Error()
|
||||
return VmLifecycle{}, diag, false, err
|
||||
}
|
||||
diag.MatchedRows = row.Rows
|
||||
diag.FirstSeen = row.FirstSeen.Int64
|
||||
diag.LastSeen = row.LastSeen.Int64
|
||||
diag.DeletionRows = row.DeletionRows
|
||||
if row.DeletionMin.Valid {
|
||||
diag.DeletionMin = row.DeletionMin.Int64
|
||||
}
|
||||
if row.DeletionMax.Valid {
|
||||
diag.DeletionMax = row.DeletionMax.Int64
|
||||
}
|
||||
if row.Rows == 0 {
|
||||
return VmLifecycle{}, false, nil
|
||||
return VmLifecycle{}, diag, false, nil
|
||||
}
|
||||
lifecycle := VmLifecycle{
|
||||
FirstSeen: row.FirstSeen.Int64,
|
||||
@@ -1992,10 +2119,26 @@ WHERE ` + matchWhere + `
|
||||
lifecycle.CreationTime = row.FirstSeen.Int64
|
||||
lifecycle.CreationApprox = true
|
||||
}
|
||||
if row.Deletion.Valid && row.Deletion.Int64 > 0 {
|
||||
lifecycle.DeletionTime = row.Deletion.Int64
|
||||
diag.CreationTime = lifecycle.CreationTime
|
||||
diag.CreationApprox = lifecycle.CreationApprox
|
||||
if row.DeletionMax.Valid && row.DeletionMax.Int64 > 0 {
|
||||
if row.LastSeen.Valid && row.LastSeen.Int64 > 0 && row.DeletionMax.Int64 <= row.LastSeen.Int64 {
|
||||
diag.StaleDeletionIgnored = true
|
||||
slog.Warn("ignoring stale VM deletion from lifecycle cache",
|
||||
"vm_id", vmID,
|
||||
"vm_uuid", vmUUID,
|
||||
"name", name,
|
||||
"deletion_rows", row.DeletionRows,
|
||||
"deletion_min", row.DeletionMin.Int64,
|
||||
"deletion_max", row.DeletionMax.Int64,
|
||||
"last_seen", row.LastSeen.Int64,
|
||||
)
|
||||
} else {
|
||||
lifecycle.DeletionTime = row.DeletionMax.Int64
|
||||
}
|
||||
return lifecycle, true, nil
|
||||
}
|
||||
diag.SelectedDeletionTime = lifecycle.DeletionTime
|
||||
return lifecycle, diag, true, nil
|
||||
}
|
||||
|
||||
func mergeVmLifecycle(base, overlay VmLifecycle) VmLifecycle {
|
||||
@@ -2006,7 +2149,7 @@ func mergeVmLifecycle(base, overlay VmLifecycle) VmLifecycle {
|
||||
if overlay.LastSeen > out.LastSeen {
|
||||
out.LastSeen = overlay.LastSeen
|
||||
}
|
||||
if overlay.DeletionTime > 0 && (out.DeletionTime == 0 || overlay.DeletionTime < out.DeletionTime) {
|
||||
if overlay.DeletionTime > 0 && (out.DeletionTime == 0 || overlay.DeletionTime > out.DeletionTime) {
|
||||
out.DeletionTime = overlay.DeletionTime
|
||||
}
|
||||
if overlay.CreationTime > 0 {
|
||||
@@ -2021,14 +2164,18 @@ func mergeVmLifecycle(base, overlay VmLifecycle) VmLifecycle {
|
||||
out.CreationTime = out.FirstSeen
|
||||
out.CreationApprox = true
|
||||
}
|
||||
if out.DeletionTime > 0 && out.LastSeen > 0 && out.DeletionTime <= out.LastSeen {
|
||||
out.DeletionTime = 0
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func fetchVmLifecycleFromSnapshotTables(ctx context.Context, dbConn *sqlx.DB, vmID, vmUUID, name string) (VmLifecycle, error) {
|
||||
func fetchVmLifecycleFromSnapshotTables(ctx context.Context, dbConn *sqlx.DB, vmID, vmUUID, name string) (VmLifecycle, VmLifecycleSourceDiagnostics, error) {
|
||||
var lifecycle VmLifecycle
|
||||
diag := VmLifecycleSourceDiagnostics{Source: "snapshot_registry/hourly_tables"}
|
||||
matchWhere, args, ok := vmLookupPredicate(vmID, vmUUID, name)
|
||||
if !ok {
|
||||
return lifecycle, nil
|
||||
return lifecycle, diag, nil
|
||||
}
|
||||
var tables []struct {
|
||||
TableName string `db:"table_name"`
|
||||
@@ -2040,11 +2187,14 @@ FROM snapshot_registry
|
||||
WHERE snapshot_type = 'hourly'
|
||||
ORDER BY snapshot_time
|
||||
`); err != nil {
|
||||
return lifecycle, err
|
||||
diag.Error = err.Error()
|
||||
return lifecycle, diag, err
|
||||
}
|
||||
|
||||
minCreation := int64(0)
|
||||
consecutiveMissing := 0
|
||||
firstMissingAfterLastSeen := int64(0)
|
||||
matchedRows := int64(0)
|
||||
for _, t := range tables {
|
||||
if err := ValidateTableName(t.TableName); err != nil {
|
||||
continue
|
||||
@@ -2063,11 +2213,18 @@ WHERE %s
|
||||
continue
|
||||
}
|
||||
if probe.Cnt > 0 {
|
||||
matchedRows++
|
||||
if lifecycle.FirstSeen == 0 {
|
||||
lifecycle.FirstSeen = t.SnapshotTime
|
||||
}
|
||||
if lifecycle.DeletionTime > 0 && t.SnapshotTime > lifecycle.DeletionTime {
|
||||
diag.StaleDeletionIgnored = true
|
||||
slog.Warn("ignoring stale VM deletion from snapshot-table fallback", "vm_id", vmID, "vm_uuid", vmUUID, "name", name, "deletion_time", lifecycle.DeletionTime, "seen_again_at", t.SnapshotTime)
|
||||
lifecycle.DeletionTime = 0
|
||||
}
|
||||
lifecycle.LastSeen = t.SnapshotTime
|
||||
consecutiveMissing = 0
|
||||
firstMissingAfterLastSeen = 0
|
||||
if probe.MinCreation.Valid {
|
||||
if minCreation == 0 || probe.MinCreation.Int64 < minCreation {
|
||||
minCreation = probe.MinCreation.Int64
|
||||
@@ -2075,12 +2232,15 @@ WHERE %s
|
||||
}
|
||||
} else if lifecycle.LastSeen > 0 && lifecycle.DeletionTime == 0 && t.SnapshotTime > lifecycle.LastSeen {
|
||||
consecutiveMissing++
|
||||
if firstMissingAfterLastSeen == 0 {
|
||||
firstMissingAfterLastSeen = t.SnapshotTime
|
||||
}
|
||||
if consecutiveMissing >= 2 {
|
||||
lifecycle.DeletionTime = t.SnapshotTime
|
||||
break
|
||||
lifecycle.DeletionTime = firstMissingAfterLastSeen
|
||||
}
|
||||
} else {
|
||||
consecutiveMissing = 0
|
||||
firstMissingAfterLastSeen = 0
|
||||
}
|
||||
}
|
||||
if minCreation > 0 {
|
||||
@@ -2090,7 +2250,13 @@ WHERE %s
|
||||
lifecycle.CreationTime = lifecycle.FirstSeen
|
||||
lifecycle.CreationApprox = true
|
||||
}
|
||||
return lifecycle, nil
|
||||
diag.MatchedRows = matchedRows
|
||||
diag.FirstSeen = lifecycle.FirstSeen
|
||||
diag.LastSeen = lifecycle.LastSeen
|
||||
diag.CreationTime = lifecycle.CreationTime
|
||||
diag.CreationApprox = lifecycle.CreationApprox
|
||||
diag.SelectedDeletionTime = lifecycle.DeletionTime
|
||||
return lifecycle, diag, nil
|
||||
}
|
||||
|
||||
// SyncVcenterTotalsFromSnapshots backfills vcenter_totals using hourly snapshot tables in snapshot_registry.
|
||||
|
||||
@@ -278,6 +278,60 @@ VALUES (?,?,?,?,?,?,?,?,?,?)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchVmLifecycleIgnoresStaleDeletionFromHourlyCache(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
dbConn := newTestSQLiteDB(t)
|
||||
|
||||
if err := EnsureVmHourlyStats(ctx, dbConn); err != nil {
|
||||
t.Fatalf("failed to ensure vm_hourly_stats: %v", err)
|
||||
}
|
||||
|
||||
insertSQL := `
|
||||
INSERT INTO vm_hourly_stats (
|
||||
"SnapshotTime","Vcenter","VmId","VmUuid","Name","CreationTime","DeletionTime","ResourcePool",
|
||||
"Datacenter","Cluster","Folder","ProvisionedDisk","VcpuCount","RamGB","IsTemplate","PoweredOn","SrmPlaceholder"
|
||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
`
|
||||
// First row carries an old deletion marker, later row proves VM is still present.
|
||||
rows := [][]interface{}{
|
||||
{int64(1700000000), "vc-a", "vm-1", "uuid-1", "demo-vm", int64(1699999000), int64(1700003600), "Tin", "dc", "cluster", "folder", 100.0, int64(2), int64(4), "FALSE", "TRUE", "FALSE"},
|
||||
{int64(1700100000), "vc-a", "vm-1", "uuid-1", "demo-vm", int64(1699999000), int64(0), "Gold", "dc", "cluster", "folder", 120.0, int64(4), int64(8), "FALSE", "TRUE", "FALSE"},
|
||||
}
|
||||
for _, args := range rows {
|
||||
if _, err := dbConn.ExecContext(ctx, insertSQL, args...); err != nil {
|
||||
t.Fatalf("failed to insert hourly cache row: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
lifecycle, err := FetchVmLifecycle(ctx, dbConn, "vm-1", "", "")
|
||||
if err != nil {
|
||||
t.Fatalf("FetchVmLifecycle failed: %v", err)
|
||||
}
|
||||
if lifecycle.LastSeen != 1700100000 {
|
||||
t.Fatalf("expected LastSeen=1700100000, got %d", lifecycle.LastSeen)
|
||||
}
|
||||
if lifecycle.DeletionTime != 0 {
|
||||
t.Fatalf("expected stale deletion to be ignored, got %d", lifecycle.DeletionTime)
|
||||
}
|
||||
|
||||
lifecycleDiag, diag, err := FetchVmLifecycleWithDiagnostics(ctx, dbConn, "vm-1", "", "")
|
||||
if err != nil {
|
||||
t.Fatalf("FetchVmLifecycleWithDiagnostics failed: %v", err)
|
||||
}
|
||||
if lifecycleDiag.DeletionTime != 0 {
|
||||
t.Fatalf("expected stale deletion to be ignored in diagnostics path, got %d", lifecycleDiag.DeletionTime)
|
||||
}
|
||||
if !diag.HourlyCache.StaleDeletionIgnored {
|
||||
t.Fatalf("expected hourly cache diagnostics to flag stale deletion ignore, got %#v", diag.HourlyCache)
|
||||
}
|
||||
if diag.HourlyCache.DeletionMax != 1700003600 {
|
||||
t.Fatalf("expected hourly cache deletion max 1700003600, got %d", diag.HourlyCache.DeletionMax)
|
||||
}
|
||||
if diag.FinalLifecycle.LastSeen != 1700100000 || diag.FinalLifecycle.DeletionTime != 0 {
|
||||
t.Fatalf("unexpected final diagnostics lifecycle: %#v", diag.FinalLifecycle)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseHourlySnapshotUnix(t *testing.T) {
|
||||
cases := []struct {
|
||||
table string
|
||||
|
||||
@@ -35,6 +35,7 @@ func (h *Handler) VmTrace(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var entries []views.VmTraceEntry
|
||||
chart := views.VmTraceChart{}
|
||||
diagnostics := views.VmTraceDiagnostics{}
|
||||
queryLabel := firstNonEmpty(vmID, vmUUID, name)
|
||||
displayQuery := ""
|
||||
if queryLabel != "" {
|
||||
@@ -47,10 +48,11 @@ func (h *Handler) VmTrace(w http.ResponseWriter, r *http.Request) {
|
||||
// Only fetch data when a query is provided; otherwise render empty page with form.
|
||||
if vmID != "" || vmUUID != "" || name != "" {
|
||||
h.Logger.Info("vm trace request", "view", viewType, "vm_id", vmID, "vm_uuid", vmUUID, "name", name)
|
||||
lifecycle, lifeErr := db.FetchVmLifecycle(ctx, h.Database.DB(), vmID, vmUUID, name)
|
||||
lifecycle, lifecycleDiag, lifeErr := db.FetchVmLifecycleWithDiagnostics(ctx, h.Database.DB(), vmID, vmUUID, name)
|
||||
if lifeErr != nil {
|
||||
h.Logger.Warn("failed to fetch VM lifecycle", "error", lifeErr)
|
||||
}
|
||||
diagnostics = buildVmTraceDiagnostics(lifecycleDiag)
|
||||
var (
|
||||
rows []db.VmTraceRow
|
||||
err error
|
||||
@@ -114,7 +116,7 @@ func (h *Handler) VmTrace(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
if err := views.VmTracePage(queryLabel, displayQuery, vmID, vmUUID, name, creationLabel, deletionLabel, creationApprox, entries, chart, meta).Render(ctx, w); err != nil {
|
||||
if err := views.VmTracePage(queryLabel, displayQuery, vmID, vmUUID, name, creationLabel, deletionLabel, creationApprox, entries, chart, meta, diagnostics).Render(ctx, w); err != nil {
|
||||
http.Error(w, "Failed to render template", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
@@ -155,6 +157,65 @@ func buildVmTraceMeta(viewType, vmID, vmUUID, name string) views.VmTraceMeta {
|
||||
return meta
|
||||
}
|
||||
|
||||
func buildVmTraceDiagnostics(diag db.VmLifecycleDiagnostics) views.VmTraceDiagnostics {
|
||||
lines := make([]views.VmTraceDiagnosticLine, 0, 24)
|
||||
lookup := "-"
|
||||
if diag.LookupField != "" {
|
||||
lookup = diag.LookupField + "=" + diag.LookupValue
|
||||
}
|
||||
lines = append(lines, views.VmTraceDiagnosticLine{Label: "Lookup", Value: lookup})
|
||||
lines = append(lines, views.VmTraceDiagnosticLine{Label: "Final First Seen", Value: formatDiagUnix(diag.FinalLifecycle.FirstSeen)})
|
||||
lines = append(lines, views.VmTraceDiagnosticLine{Label: "Final Last Seen", Value: formatDiagUnix(diag.FinalLifecycle.LastSeen)})
|
||||
lines = append(lines, views.VmTraceDiagnosticLine{Label: "Final Creation Time", Value: formatDiagUnix(diag.FinalLifecycle.CreationTime)})
|
||||
lines = append(lines, views.VmTraceDiagnosticLine{Label: "Final Creation Approx", Value: fmt.Sprintf("%t", diag.FinalLifecycle.CreationApprox)})
|
||||
lines = append(lines, views.VmTraceDiagnosticLine{Label: "Final Deletion Time", Value: formatDiagUnix(diag.FinalLifecycle.DeletionTime)})
|
||||
|
||||
lines = append(lines, summarizeLifecycleSource(diag.HourlyCache)...)
|
||||
lines = append(lines, summarizeLifecycleSource(diag.LifecycleCache)...)
|
||||
lines = append(lines, summarizeLifecycleSource(diag.SnapshotFallback)...)
|
||||
|
||||
return views.VmTraceDiagnostics{
|
||||
Visible: len(lines) > 0,
|
||||
Lines: lines,
|
||||
}
|
||||
}
|
||||
|
||||
func summarizeLifecycleSource(src db.VmLifecycleSourceDiagnostics) []views.VmTraceDiagnosticLine {
|
||||
prefix := src.Source
|
||||
if strings.TrimSpace(prefix) == "" {
|
||||
prefix = "source"
|
||||
}
|
||||
out := []views.VmTraceDiagnosticLine{
|
||||
{Label: prefix + " used", Value: fmt.Sprintf("%t", src.Used)},
|
||||
{Label: prefix + " error", Value: defaultString(src.Error, "-")},
|
||||
{Label: prefix + " matched rows", Value: fmt.Sprintf("%d", src.MatchedRows)},
|
||||
{Label: prefix + " first seen", Value: formatDiagUnix(src.FirstSeen)},
|
||||
{Label: prefix + " last seen", Value: formatDiagUnix(src.LastSeen)},
|
||||
{Label: prefix + " creation", Value: formatDiagUnix(src.CreationTime)},
|
||||
{Label: prefix + " creation approx", Value: fmt.Sprintf("%t", src.CreationApprox)},
|
||||
{Label: prefix + " deletion rows", Value: fmt.Sprintf("%d", src.DeletionRows)},
|
||||
{Label: prefix + " deletion min", Value: formatDiagUnix(src.DeletionMin)},
|
||||
{Label: prefix + " deletion max", Value: formatDiagUnix(src.DeletionMax)},
|
||||
{Label: prefix + " selected deletion", Value: formatDiagUnix(src.SelectedDeletionTime)},
|
||||
{Label: prefix + " stale deletion ignored", Value: fmt.Sprintf("%t", src.StaleDeletionIgnored)},
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func formatDiagUnix(ts int64) string {
|
||||
if ts <= 0 {
|
||||
return "-"
|
||||
}
|
||||
return fmt.Sprintf("%s (%d)", time.Unix(ts, 0).Local().Format("2006-01-02 15:04:05"), ts)
|
||||
}
|
||||
|
||||
func defaultString(value string, fallback string) string {
|
||||
if strings.TrimSpace(value) == "" {
|
||||
return fallback
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func buildVmTraceChart(entries []views.VmTraceEntry) views.VmTraceChart {
|
||||
if len(entries) == 0 {
|
||||
return views.VmTraceChart{}
|
||||
|
||||
Reference in New Issue
Block a user