diff --git a/libvirtxml.go b/libvirtxml.go index 519ceba..b873583 100644 --- a/libvirtxml.go +++ b/libvirtxml.go @@ -367,6 +367,21 @@ func dumpNonStandardXML(domcfg *libvirtxml.Domain) (string, error) { if secnormal { domcfg.SecLabel = nil } + // ignore Metadata + // this is probably something about what kind of OS you might be running + // todo: get this directly from the disk image + if domcfg.Metadata != nil { + fmt.Printf("Not saving Domain.Metadata: %+v\n", domcfg.Metadata) + domcfg.Metadata = nil + } + // ignore Resource + if domcfg.Resource != nil { + if domcfg.Resource.Partition == "/machine" { + domcfg.Resource = nil + } else { + fmt.Printf("non-standard Domain.Resource: %+v\n", domcfg.Resource) + } + } // this will move elsewhere in the protobuf someday // ignore all these for now @@ -650,10 +665,6 @@ func finalEmptyCheck(domcfg *libvirtxml.Domain) (string, error) { } if libvirtxmlDomainEmpty(*domcfg) { - log.Info("CPU THIS SHOULD NEVER HAPPEN") - log.Info("CPU THIS SHOULD NEVER HAPPEN") - log.Info("CPU THIS SHOULD NEVER HAPPEN") - // fmt.Println("Domain Devices are empty") domcfg = nil return warnUserOfNonStandardXML(domcfg) } @@ -785,7 +796,7 @@ func libvirtxmlDomainEmpty(mydom libvirtxml.Domain) bool { // Ensure that we are working with a struct if v.Kind() == reflect.Struct { - fmt.Println("Fields and values in libvirtxml.DomainDeviceList:") + // fmt.Println("Fields and values in libvirtxml.DomainDeviceList:") // Loop through each field in the struct for i := 0; i < v.NumField(); i++ { @@ -796,15 +807,14 @@ func libvirtxmlDomainEmpty(mydom libvirtxml.Domain) bool { value := v.Field(i) if !value.IsValid() { - fmt.Printf("Field: %s is nil or invalid\n", field) - continue - } - if (field == "IOThreads") || (field == "XMLName") { - fmt.Printf("Field: %s is nil or invalid\n", field) - fmt.Printf("Field: %s is nil or invalid\n", field) - fmt.Printf("Field: %s is a String with value: %s\n", field, value.String()) + fmt.Printf("Field: %s is invalid\n", field) continue } + // processed as Domain.Metadata & Domain.Resource + // if (field == "IOThreads") || (field == "XMLName") { + // fmt.Printf("Field: %s is: %s\n", field, value.String()) + // continue + // } // Check if the field is a string, array, or slice switch value.Kind() { @@ -823,6 +833,15 @@ func libvirtxmlDomainEmpty(mydom libvirtxml.Domain) bool { fmt.Printf("Field: %s is an Array with length: %d\n", field, value.Len()) empty = false } + case reflect.Struct: + if IsStructEmptyOrNil(value) { + fmt.Printf("XML Field ignore empty Struct %s\n", field) + } else { + fmt.Printf("Field Struct is not empty %s is %+v\n", field, value) + empty = false + } + case reflect.Uint: + // probably ignore ints. when has that ever gone wrong? case reflect.Ptr: if value.IsValid() { if value.IsNil() { @@ -850,3 +869,35 @@ func libvirtxmlDomainEmpty(mydom libvirtxml.Domain) bool { } return empty } + +// IsStructEmptyOrNil checks if a struct or pointer to struct is empty, blank, or nil +func IsStructEmptyOrNil(value interface{}) bool { + val := reflect.ValueOf(value) + + // If the value is a pointer, check if it's nil and dereference it if not + if val.Kind() == reflect.Ptr { + if val.IsNil() { + return true + } + val = val.Elem() + } + + // Ensure we're dealing with a struct after potential dereferencing + if val.Kind() != reflect.Struct { + return false // Not a struct + } + + // Check each field in the struct for its zero value + for i := 0; i < val.NumField(); i++ { + field := val.Field(i) + // Skip unexported fields as we can't access them + if !field.CanInterface() { + continue + } + if !reflect.DeepEqual(field.Interface(), reflect.Zero(field.Type()).Interface()) { + return false // Found a non-zero field + } + } + + return true // All fields are zero values +}