diff --git a/internal/monitoring/container_parsing.go b/internal/monitoring/container_parsing.go index d904db278..cadb35844 100644 --- a/internal/monitoring/container_parsing.go +++ b/internal/monitoring/container_parsing.go @@ -558,3 +558,39 @@ func isOCITemplate(template string) bool { return false } + +// isOCIContainerByConfig detects OCI containers by examining their configuration. +// Proxmox VE 9.1+ OCI containers have specific config markers: +// - "entrypoint" field is set (only OCI containers have this) +// - "ostype" is often "unmanaged" for OCI containers +// - "cmode" is often "console" for OCI containers +// +// This is useful because Proxmox doesn't persist the ostemplate after container creation. +func isOCIContainerByConfig(config map[string]interface{}) bool { + if len(config) == 0 { + return false + } + + // Primary indicator: OCI containers have an "entrypoint" field + // Traditional LXC containers don't have this field + if _, hasEntrypoint := config["entrypoint"]; hasEntrypoint { + return true + } + + // Secondary check: "unmanaged" ostype with console cmode is a strong hint + // (though not definitive as users could manually configure this) + ostype, _ := config["ostype"].(string) + cmode, _ := config["cmode"].(string) + if ostype == "unmanaged" && cmode == "console" { + // Check for other OCI indicators like lxc.signal.halt: SIGTERM + // (which is set by Proxmox for OCI containers) + if lxc, ok := config["lxc"]; ok { + lxcStr := fmt.Sprint(lxc) + if strings.Contains(lxcStr, "lxc.signal.halt") { + return true + } + } + } + + return false +} diff --git a/internal/monitoring/monitor.go b/internal/monitoring/monitor.go index 1baaa9684..ca922ea49 100644 --- a/internal/monitoring/monitor.go +++ b/internal/monitoring/monitor.go @@ -2484,20 +2484,29 @@ func (m *Monitor) enrichContainerMetadata(ctx context.Context, client PVEClientI container.OSName = osName } // Detect OCI containers (Proxmox VE 9.1+) - // OCI containers have ostemplate pointing to an OCI registry (e.g., "oci:docker.io/library/alpine:latest") + // Method 1: Check ostemplate for OCI registry patterns if osTemplate := extractContainerOSTemplate(configData); osTemplate != "" { container.OSTemplate = osTemplate - // Check if this is an OCI container based on template format if isOCITemplate(osTemplate) { container.IsOCI = true - container.Type = "oci" // Override type from "lxc" to "oci" + container.Type = "oci" log.Debug(). Str("container", container.Name). Int("vmid", container.VMID). Str("osTemplate", osTemplate). - Msg("Detected OCI container") + Msg("Detected OCI container by template") } } + // Method 2: Check config fields (entrypoint, ostype, cmode) + // This is needed because Proxmox doesn't persist ostemplate after creation + if !container.IsOCI && isOCIContainerByConfig(configData) { + container.IsOCI = true + container.Type = "oci" + log.Debug(). + Str("container", container.Name). + Int("vmid", container.VMID). + Msg("Detected OCI container by config (entrypoint/ostype)") + } } if len(addressOrder) == 0 {