447 lines
11 KiB
Go
447 lines
11 KiB
Go
package models
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// ToFrontend converts a State to StateFrontend
|
|
func (s *State) ToFrontend() StateFrontend {
|
|
return s.GetSnapshot().ToFrontend()
|
|
}
|
|
|
|
// ToFrontend converts a Node to NodeFrontend
|
|
func (n Node) ToFrontend() NodeFrontend {
|
|
nf := NodeFrontend{
|
|
ID: n.ID,
|
|
Node: n.Name,
|
|
Name: n.Name,
|
|
DisplayName: n.DisplayName,
|
|
Instance: n.Instance,
|
|
Host: n.Host,
|
|
Status: n.Status,
|
|
Type: n.Type,
|
|
CPU: n.CPU,
|
|
Mem: n.Memory.Used,
|
|
MaxMem: n.Memory.Total,
|
|
MaxDisk: n.Disk.Total,
|
|
Uptime: n.Uptime,
|
|
LoadAverage: n.LoadAverage,
|
|
KernelVersion: n.KernelVersion,
|
|
PVEVersion: n.PVEVersion,
|
|
CPUInfo: n.CPUInfo,
|
|
LastSeen: n.LastSeen.Unix() * 1000,
|
|
ConnectionHealth: n.ConnectionHealth,
|
|
IsClusterMember: n.IsClusterMember,
|
|
ClusterName: n.ClusterName,
|
|
}
|
|
|
|
// Include full Memory object if it has data
|
|
if n.Memory.Total > 0 {
|
|
nf.Memory = &n.Memory
|
|
}
|
|
|
|
// Include full Disk object if it has data
|
|
if n.Disk.Total > 0 {
|
|
nf.Disk = &n.Disk
|
|
}
|
|
|
|
// Include temperature data if available
|
|
if n.Temperature != nil && n.Temperature.Available {
|
|
nf.Temperature = n.Temperature
|
|
}
|
|
|
|
if nf.DisplayName == "" {
|
|
nf.DisplayName = nf.Name
|
|
}
|
|
|
|
return nf
|
|
}
|
|
|
|
// ToFrontend converts a VM to VMFrontend
|
|
func (v VM) ToFrontend() VMFrontend {
|
|
vm := VMFrontend{
|
|
ID: v.ID,
|
|
VMID: v.VMID,
|
|
Name: v.Name,
|
|
Node: v.Node,
|
|
Instance: v.Instance,
|
|
Status: v.Status,
|
|
Type: v.Type,
|
|
CPU: v.CPU,
|
|
CPUs: v.CPUs,
|
|
Mem: v.Memory.Used,
|
|
MaxMem: v.Memory.Total,
|
|
NetIn: zeroIfNegative(v.NetworkIn),
|
|
NetOut: zeroIfNegative(v.NetworkOut),
|
|
DiskRead: zeroIfNegative(v.DiskRead),
|
|
DiskWrite: zeroIfNegative(v.DiskWrite),
|
|
Uptime: v.Uptime,
|
|
Template: v.Template,
|
|
Lock: v.Lock,
|
|
LastSeen: v.LastSeen.Unix() * 1000,
|
|
DiskStatusReason: v.DiskStatusReason,
|
|
}
|
|
|
|
// Convert tags array to string
|
|
if len(v.Tags) > 0 {
|
|
vm.Tags = strings.Join(v.Tags, ",")
|
|
}
|
|
|
|
// Convert last backup time if not zero
|
|
if !v.LastBackup.IsZero() {
|
|
vm.LastBackup = v.LastBackup.Unix() * 1000
|
|
}
|
|
|
|
// Include full Memory object if it has data
|
|
if v.Memory.Total > 0 {
|
|
vm.Memory = &v.Memory
|
|
}
|
|
|
|
// Include full Disk object if it has data
|
|
if v.Disk.Total > 0 {
|
|
vm.DiskObj = &v.Disk
|
|
}
|
|
|
|
// Include individual disks array if available
|
|
if len(v.Disks) > 0 {
|
|
vm.Disks = v.Disks
|
|
}
|
|
|
|
if len(v.IPAddresses) > 0 {
|
|
vm.IPAddresses = append([]string(nil), v.IPAddresses...)
|
|
}
|
|
|
|
if v.OSName != "" {
|
|
vm.OSName = v.OSName
|
|
}
|
|
|
|
if v.OSVersion != "" {
|
|
vm.OSVersion = v.OSVersion
|
|
}
|
|
|
|
if v.AgentVersion != "" {
|
|
vm.AgentVersion = v.AgentVersion
|
|
}
|
|
|
|
if len(v.NetworkInterfaces) > 0 {
|
|
vm.NetworkInterfaces = make([]GuestNetworkInterface, len(v.NetworkInterfaces))
|
|
copy(vm.NetworkInterfaces, v.NetworkInterfaces)
|
|
}
|
|
|
|
return vm
|
|
}
|
|
|
|
// ToFrontend converts a Container to ContainerFrontend
|
|
func (c Container) ToFrontend() ContainerFrontend {
|
|
ct := ContainerFrontend{
|
|
ID: c.ID,
|
|
VMID: c.VMID,
|
|
Name: c.Name,
|
|
Node: c.Node,
|
|
Instance: c.Instance,
|
|
Status: c.Status,
|
|
Type: c.Type,
|
|
CPU: c.CPU,
|
|
CPUs: c.CPUs,
|
|
Mem: c.Memory.Used,
|
|
MaxMem: c.Memory.Total,
|
|
NetIn: zeroIfNegative(c.NetworkIn),
|
|
NetOut: zeroIfNegative(c.NetworkOut),
|
|
DiskRead: zeroIfNegative(c.DiskRead),
|
|
DiskWrite: zeroIfNegative(c.DiskWrite),
|
|
Uptime: c.Uptime,
|
|
Template: c.Template,
|
|
Lock: c.Lock,
|
|
LastSeen: c.LastSeen.Unix() * 1000,
|
|
}
|
|
|
|
// Convert tags array to string
|
|
if len(c.Tags) > 0 {
|
|
ct.Tags = strings.Join(c.Tags, ",")
|
|
}
|
|
|
|
// Convert last backup time if not zero
|
|
if !c.LastBackup.IsZero() {
|
|
ct.LastBackup = c.LastBackup.Unix() * 1000
|
|
}
|
|
|
|
// Include full Memory object if it has data
|
|
if c.Memory.Total > 0 {
|
|
ct.Memory = &c.Memory
|
|
}
|
|
|
|
// Include full Disk object if it has data
|
|
if c.Disk.Total > 0 {
|
|
ct.DiskObj = &c.Disk
|
|
}
|
|
|
|
// Include individual disks array if available
|
|
if len(c.Disks) > 0 {
|
|
ct.Disks = c.Disks
|
|
}
|
|
|
|
return ct
|
|
}
|
|
|
|
// ToFrontend converts a DockerHost to DockerHostFrontend
|
|
func (d DockerHost) ToFrontend() DockerHostFrontend {
|
|
h := DockerHostFrontend{
|
|
ID: d.ID,
|
|
AgentID: d.AgentID,
|
|
Hostname: d.Hostname,
|
|
DisplayName: d.DisplayName,
|
|
MachineID: d.MachineID,
|
|
OS: d.OS,
|
|
KernelVersion: d.KernelVersion,
|
|
Architecture: d.Architecture,
|
|
DockerVersion: d.DockerVersion,
|
|
CPUs: d.CPUs,
|
|
TotalMemoryBytes: d.TotalMemoryBytes,
|
|
UptimeSeconds: d.UptimeSeconds,
|
|
Status: d.Status,
|
|
LastSeen: d.LastSeen.Unix() * 1000,
|
|
IntervalSeconds: d.IntervalSeconds,
|
|
AgentVersion: d.AgentVersion,
|
|
Containers: make([]DockerContainerFrontend, len(d.Containers)),
|
|
}
|
|
|
|
if h.DisplayName == "" {
|
|
h.DisplayName = h.Hostname
|
|
}
|
|
|
|
h.PendingUninstall = d.PendingUninstall
|
|
|
|
if d.TokenID != "" {
|
|
h.TokenID = d.TokenID
|
|
h.TokenName = d.TokenName
|
|
h.TokenHint = d.TokenHint
|
|
if d.TokenLastUsedAt != nil && !d.TokenLastUsedAt.IsZero() {
|
|
ts := d.TokenLastUsedAt.Unix() * 1000
|
|
h.TokenLastUsedAt = &ts
|
|
}
|
|
}
|
|
|
|
for i, ct := range d.Containers {
|
|
h.Containers[i] = ct.ToFrontend()
|
|
}
|
|
|
|
if d.Command != nil {
|
|
h.Command = toDockerHostCommandFrontend(*d.Command)
|
|
}
|
|
|
|
return h
|
|
}
|
|
|
|
// ToFrontend converts a DockerContainer to DockerContainerFrontend
|
|
func (c DockerContainer) ToFrontend() DockerContainerFrontend {
|
|
container := DockerContainerFrontend{
|
|
ID: c.ID,
|
|
Name: c.Name,
|
|
Image: c.Image,
|
|
State: c.State,
|
|
Status: c.Status,
|
|
Health: c.Health,
|
|
CPUPercent: c.CPUPercent,
|
|
MemoryUsage: c.MemoryUsage,
|
|
MemoryLimit: c.MemoryLimit,
|
|
MemoryPercent: c.MemoryPercent,
|
|
UptimeSeconds: c.UptimeSeconds,
|
|
RestartCount: c.RestartCount,
|
|
ExitCode: c.ExitCode,
|
|
CreatedAt: c.CreatedAt.Unix() * 1000,
|
|
Labels: c.Labels,
|
|
}
|
|
|
|
if c.StartedAt != nil {
|
|
ms := c.StartedAt.Unix() * 1000
|
|
container.StartedAt = &ms
|
|
}
|
|
|
|
if c.FinishedAt != nil {
|
|
ms := c.FinishedAt.Unix() * 1000
|
|
container.FinishedAt = &ms
|
|
}
|
|
|
|
if len(c.Ports) > 0 {
|
|
ports := make([]DockerContainerPortFrontend, len(c.Ports))
|
|
for i, port := range c.Ports {
|
|
ports[i] = DockerContainerPortFrontend{
|
|
PrivatePort: port.PrivatePort,
|
|
PublicPort: port.PublicPort,
|
|
Protocol: port.Protocol,
|
|
IP: port.IP,
|
|
}
|
|
}
|
|
container.Ports = ports
|
|
}
|
|
|
|
if len(c.Networks) > 0 {
|
|
networks := make([]DockerContainerNetworkFrontend, len(c.Networks))
|
|
for i, net := range c.Networks {
|
|
networks[i] = DockerContainerNetworkFrontend{
|
|
Name: net.Name,
|
|
IPv4: net.IPv4,
|
|
IPv6: net.IPv6,
|
|
}
|
|
}
|
|
container.Networks = networks
|
|
}
|
|
|
|
return container
|
|
}
|
|
|
|
func toDockerHostCommandFrontend(cmd DockerHostCommandStatus) *DockerHostCommandFrontend {
|
|
result := &DockerHostCommandFrontend{
|
|
ID: cmd.ID,
|
|
Type: cmd.Type,
|
|
Status: cmd.Status,
|
|
Message: cmd.Message,
|
|
CreatedAt: cmd.CreatedAt.Unix() * 1000,
|
|
UpdatedAt: cmd.UpdatedAt.Unix() * 1000,
|
|
}
|
|
|
|
if cmd.DispatchedAt != nil {
|
|
ms := cmd.DispatchedAt.Unix() * 1000
|
|
result.DispatchedAt = &ms
|
|
}
|
|
if cmd.AcknowledgedAt != nil {
|
|
ms := cmd.AcknowledgedAt.Unix() * 1000
|
|
result.AcknowledgedAt = &ms
|
|
}
|
|
if cmd.CompletedAt != nil {
|
|
ms := cmd.CompletedAt.Unix() * 1000
|
|
result.CompletedAt = &ms
|
|
}
|
|
if cmd.FailedAt != nil {
|
|
ms := cmd.FailedAt.Unix() * 1000
|
|
result.FailedAt = &ms
|
|
}
|
|
if cmd.FailureReason != "" {
|
|
result.FailureReason = cmd.FailureReason
|
|
}
|
|
if cmd.ExpiresAt != nil {
|
|
ms := cmd.ExpiresAt.Unix() * 1000
|
|
result.ExpiresAt = &ms
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// ToFrontend converts Storage to StorageFrontend
|
|
func (s Storage) ToFrontend() StorageFrontend {
|
|
return StorageFrontend{
|
|
ID: s.ID,
|
|
Storage: s.Name,
|
|
Name: s.Name,
|
|
Node: s.Node,
|
|
Instance: s.Instance,
|
|
Nodes: s.Nodes,
|
|
NodeIDs: s.NodeIDs,
|
|
NodeCount: s.NodeCount,
|
|
Type: s.Type,
|
|
Status: s.Status,
|
|
Total: s.Total,
|
|
Used: s.Used,
|
|
Avail: s.Free,
|
|
Free: s.Free,
|
|
Usage: s.Usage,
|
|
Content: s.Content,
|
|
Shared: s.Shared,
|
|
Enabled: s.Enabled,
|
|
Active: s.Active,
|
|
}
|
|
}
|
|
|
|
// ToFrontend converts a CephCluster to CephClusterFrontend
|
|
func (c CephCluster) ToFrontend() CephClusterFrontend {
|
|
frontend := CephClusterFrontend{
|
|
ID: c.ID,
|
|
Instance: c.Instance,
|
|
Name: c.Name,
|
|
FSID: c.FSID,
|
|
Health: c.Health,
|
|
HealthMessage: c.HealthMessage,
|
|
TotalBytes: c.TotalBytes,
|
|
UsedBytes: c.UsedBytes,
|
|
AvailableBytes: c.AvailableBytes,
|
|
UsagePercent: c.UsagePercent,
|
|
NumMons: c.NumMons,
|
|
NumMgrs: c.NumMgrs,
|
|
NumOSDs: c.NumOSDs,
|
|
NumOSDsUp: c.NumOSDsUp,
|
|
NumOSDsIn: c.NumOSDsIn,
|
|
NumPGs: c.NumPGs,
|
|
LastUpdated: c.LastUpdated.Unix() * 1000,
|
|
}
|
|
|
|
if len(c.Pools) > 0 {
|
|
frontend.Pools = append([]CephPool(nil), c.Pools...)
|
|
}
|
|
|
|
if len(c.Services) > 0 {
|
|
frontend.Services = append([]CephServiceStatus(nil), c.Services...)
|
|
}
|
|
|
|
return frontend
|
|
}
|
|
|
|
// ToFrontend converts a replication job to a frontend representation.
|
|
func (r ReplicationJob) ToFrontend() ReplicationJobFrontend {
|
|
frontend := ReplicationJobFrontend{
|
|
ID: r.ID,
|
|
Instance: r.Instance,
|
|
JobID: r.JobID,
|
|
JobNumber: r.JobNumber,
|
|
Guest: r.Guest,
|
|
GuestID: r.GuestID,
|
|
GuestName: r.GuestName,
|
|
GuestType: r.GuestType,
|
|
GuestNode: r.GuestNode,
|
|
SourceNode: r.SourceNode,
|
|
SourceStorage: r.SourceStorage,
|
|
TargetNode: r.TargetNode,
|
|
TargetStorage: r.TargetStorage,
|
|
Schedule: r.Schedule,
|
|
Type: r.Type,
|
|
Enabled: r.Enabled,
|
|
State: r.State,
|
|
Status: r.Status,
|
|
LastSyncStatus: r.LastSyncStatus,
|
|
LastSyncUnix: r.LastSyncUnix,
|
|
LastSyncDurationSeconds: r.LastSyncDurationSeconds,
|
|
LastSyncDurationHuman: r.LastSyncDurationHuman,
|
|
NextSyncUnix: r.NextSyncUnix,
|
|
DurationSeconds: r.DurationSeconds,
|
|
DurationHuman: r.DurationHuman,
|
|
FailCount: r.FailCount,
|
|
Error: r.Error,
|
|
Comment: r.Comment,
|
|
RemoveJob: r.RemoveJob,
|
|
RateLimitMbps: r.RateLimitMbps,
|
|
}
|
|
|
|
if r.LastSyncTime != nil {
|
|
frontend.LastSyncTime = r.LastSyncTime.UnixMilli()
|
|
}
|
|
|
|
if r.NextSyncTime != nil {
|
|
frontend.NextSyncTime = r.NextSyncTime.UnixMilli()
|
|
}
|
|
|
|
polledAt := r.LastPolled
|
|
if polledAt.IsZero() {
|
|
polledAt = time.Now()
|
|
}
|
|
frontend.PolledAt = polledAt.UnixMilli()
|
|
|
|
return frontend
|
|
}
|
|
|
|
// zeroIfNegative returns 0 for negative values (used for I/O metrics)
|
|
func zeroIfNegative(val int64) int64 {
|
|
if val < 0 {
|
|
return 0
|
|
}
|
|
return val
|
|
}
|