podman-build/vendor/github.com/containers/libhvee/pkg/hypervctl/kvp.go
2025-10-11 12:30:35 +09:00

139 lines
3.0 KiB
Go

//go:build windows
// +build windows
package hypervctl
import (
"encoding/xml"
"fmt"
"io"
"strings"
"github.com/containers/libhvee/pkg/wmiext"
)
const (
KvpOperationFailed = 32768
KvpAccessDenied = 32769
KvpNotSupported = 32770
KvpStatusUnknown = 32771
KvpTimeoutOccurred = 32772
KvpIllegalArgument = 32773
KvpSystemInUse = 32774
KvpInvalidState = 32775
KvpIncorrectDataType = 32776
KvpSystemNotAvailable = 32777
KvpOutOfMemory = 32778
KvpNotFound = 32779
KvpExchangeDataItemName = "Msvm_KvpExchangeDataItem"
MemorySettingDataName = "Msvm_MemorySettingData"
)
type CimKvpItems struct {
Instances []CimKvpItem `xml:"INSTANCE"`
}
type CimKvpItem struct {
Properties []CimKvpItemProperty `xml:"PROPERTY"`
}
type CimKvpItemProperty struct {
Name string `xml:"NAME,attr"`
Value string `xml:"VALUE"`
}
type KvpError struct {
ErrorCode int
message string
}
func (k *KvpError) Error() string {
return fmt.Sprintf("%s (%d)", k.message, k.ErrorCode)
}
func createKvpItem(service *wmiext.Service, key string, value string) (string, error) {
item, err := service.SpawnInstance(KvpExchangeDataItemName)
if err != nil {
return "", err
}
defer item.Close()
_ = item.Put("Name", key)
_ = item.Put("Data", value)
_ = item.Put("Source", 0)
itemStr := item.GetCimText()
return itemStr, nil
}
func parseKvpMapXml(kvpXml string) (map[string]string, error) {
// Workaround XML decoder's inability to handle multiple root elements
r := io.MultiReader(
strings.NewReader("<root>"),
strings.NewReader(kvpXml),
strings.NewReader("</root>"),
)
var items CimKvpItems
if err := xml.NewDecoder(r).Decode(&items); err != nil {
return nil, err
}
ret := make(map[string]string)
for _, item := range items.Instances {
var key, value string
for _, prop := range item.Properties {
if strings.EqualFold(prop.Name, "Name") {
key = prop.Value
} else if strings.EqualFold(prop.Name, "Data") {
value = prop.Value
}
}
if len(key) > 0 {
ret[key] = value
}
}
return ret, nil
}
func translateKvpError(source error, illegalSuggestion string) error {
j, ok := source.(*wmiext.JobError)
if !ok {
return source
}
var message string
switch j.ErrorCode {
case KvpOperationFailed:
message = "Operation failed"
case KvpAccessDenied:
message = "Access denied"
case KvpNotSupported:
message = "Not supported"
case KvpStatusUnknown:
message = "Status is unknown"
case KvpTimeoutOccurred:
message = "Timeout occurred"
case KvpIllegalArgument:
message = "Illegal argument (" + illegalSuggestion + ")"
case KvpSystemInUse:
message = "System is in use"
case KvpInvalidState:
message = "Invalid state for this operation"
case KvpIncorrectDataType:
message = "Incorrect data type"
case KvpSystemNotAvailable:
message = "System is not available"
case KvpOutOfMemory:
message = "Out of memory"
case KvpNotFound:
message = "Not found"
default:
return source
}
return &KvpError{j.ErrorCode, message}
}