diff --git a/const.gen.go b/const.gen.go index 7a6cad6..6b00859 100644 --- a/const.gen.go +++ b/const.gen.go @@ -1963,3 +1963,193 @@ const ( StreamEventError StreamEventType = 4 StreamEventHangup StreamEventType = 8 ) + +// errorLevel as declared in libvirt/virterror.h:44 +type errorLevel int32 + +// errorLevel enumeration from libvirt/virterror.h:44 +const ( + errNone errorLevel = iota + errWarning errorLevel = 1 + errError errorLevel = 2 +) + +// errorDomain as declared in libvirt/virterror.h:139 +type errorDomain int32 + +// errorDomain enumeration from libvirt/virterror.h:139 +const ( + fromNone errorDomain = iota + fromXen errorDomain = 1 + fromXend errorDomain = 2 + fromXenstore errorDomain = 3 + fromSexpr errorDomain = 4 + fromXML errorDomain = 5 + fromDom errorDomain = 6 + fromRPC errorDomain = 7 + fromProxy errorDomain = 8 + fromConf errorDomain = 9 + fromQemu errorDomain = 10 + fromNet errorDomain = 11 + fromTest errorDomain = 12 + fromRemote errorDomain = 13 + fromOpenvz errorDomain = 14 + fromXenxm errorDomain = 15 + fromStatsLinux errorDomain = 16 + fromLxc errorDomain = 17 + fromStorage errorDomain = 18 + fromNetwork errorDomain = 19 + fromDomain errorDomain = 20 + fromUml errorDomain = 21 + fromNodedev errorDomain = 22 + fromXenInotify errorDomain = 23 + fromSecurity errorDomain = 24 + fromVbox errorDomain = 25 + fromInterface errorDomain = 26 + fromOne errorDomain = 27 + fromEsx errorDomain = 28 + fromPhyp errorDomain = 29 + fromSecret errorDomain = 30 + fromCPU errorDomain = 31 + fromXenapi errorDomain = 32 + fromNwfilter errorDomain = 33 + fromHook errorDomain = 34 + fromDomainSnapshot errorDomain = 35 + fromAudit errorDomain = 36 + fromSysinfo errorDomain = 37 + fromStreams errorDomain = 38 + fromVmware errorDomain = 39 + fromEvent errorDomain = 40 + fromLibxl errorDomain = 41 + fromLocking errorDomain = 42 + fromHyperv errorDomain = 43 + fromCapabilities errorDomain = 44 + fromURI errorDomain = 45 + fromAuth errorDomain = 46 + fromDbus errorDomain = 47 + fromParallels errorDomain = 48 + fromDevice errorDomain = 49 + fromSSH errorDomain = 50 + fromLockspace errorDomain = 51 + fromInitctl errorDomain = 52 + fromIdentity errorDomain = 53 + fromCgroup errorDomain = 54 + fromAccess errorDomain = 55 + fromSystemd errorDomain = 56 + fromBhyve errorDomain = 57 + fromCrypto errorDomain = 58 + fromFirewall errorDomain = 59 + fromPolkit errorDomain = 60 + fromThread errorDomain = 61 + fromAdmin errorDomain = 62 + fromLogging errorDomain = 63 + fromXenxl errorDomain = 64 + fromPerf errorDomain = 65 + fromLibssh errorDomain = 66 +) + +// errorNumber as declared in libvirt/virterror.h:322 +type errorNumber int32 + +// errorNumber enumeration from libvirt/virterror.h:322 +const ( + errOk errorNumber = iota + errInternalError errorNumber = 1 + errNoMemory errorNumber = 2 + errNoSupport errorNumber = 3 + errUnknownHost errorNumber = 4 + errNoConnect errorNumber = 5 + errInvalidConn errorNumber = 6 + errInvalidDomain errorNumber = 7 + errInvalidArg errorNumber = 8 + errOperationFailed errorNumber = 9 + errGetFailed errorNumber = 10 + errPostFailed errorNumber = 11 + errHTTPError errorNumber = 12 + errSexprSerial errorNumber = 13 + errNoXen errorNumber = 14 + errXenCall errorNumber = 15 + errOsType errorNumber = 16 + errNoKernel errorNumber = 17 + errNoRoot errorNumber = 18 + errNoSource errorNumber = 19 + errNoTarget errorNumber = 20 + errNoName errorNumber = 21 + errNoOs errorNumber = 22 + errNoDevice errorNumber = 23 + errNoXenstore errorNumber = 24 + errDriverFull errorNumber = 25 + errCallFailed errorNumber = 26 + errXMLError errorNumber = 27 + errDomExist errorNumber = 28 + errOperationDenied errorNumber = 29 + errOpenFailed errorNumber = 30 + errReadFailed errorNumber = 31 + errParseFailed errorNumber = 32 + errConfSyntax errorNumber = 33 + errWriteFailed errorNumber = 34 + errXMLDetail errorNumber = 35 + errInvalidNetwork errorNumber = 36 + errNetworkExist errorNumber = 37 + errSystemError errorNumber = 38 + errRPC errorNumber = 39 + errGnutlsError errorNumber = 40 + warNoNetwork errorNumber = 41 + errNoDomain errorNumber = 42 + errNoNetwork errorNumber = 43 + errInvalidMac errorNumber = 44 + errAuthFailed errorNumber = 45 + errInvalidStoragePool errorNumber = 46 + errInvalidStorageVol errorNumber = 47 + warNoStorage errorNumber = 48 + errNoStoragePool errorNumber = 49 + errNoStorageVol errorNumber = 50 + warNoNode errorNumber = 51 + errInvalidNodeDevice errorNumber = 52 + errNoNodeDevice errorNumber = 53 + errNoSecurityModel errorNumber = 54 + errOperationInvalid errorNumber = 55 + warNoInterface errorNumber = 56 + errNoInterface errorNumber = 57 + errInvalidInterface errorNumber = 58 + errMultipleInterfaces errorNumber = 59 + warNoNwfilter errorNumber = 60 + errInvalidNwfilter errorNumber = 61 + errNoNwfilter errorNumber = 62 + errBuildFirewall errorNumber = 63 + warNoSecret errorNumber = 64 + errInvalidSecret errorNumber = 65 + errNoSecret errorNumber = 66 + errConfigUnsupported errorNumber = 67 + errOperationTimeout errorNumber = 68 + errMigratePersistFailed errorNumber = 69 + errHookScriptFailed errorNumber = 70 + errInvalidDomainSnapshot errorNumber = 71 + errNoDomainSnapshot errorNumber = 72 + errInvalidStream errorNumber = 73 + errArgumentUnsupported errorNumber = 74 + errStorageProbeFailed errorNumber = 75 + errStoragePoolBuilt errorNumber = 76 + errSnapshotRevertRisky errorNumber = 77 + errOperationAborted errorNumber = 78 + errAuthCancelled errorNumber = 79 + errNoDomainMetadata errorNumber = 80 + errMigrateUnsafe errorNumber = 81 + errOverflow errorNumber = 82 + errBlockCopyActive errorNumber = 83 + errOperationUnsupported errorNumber = 84 + errSSH errorNumber = 85 + errAgentUnresponsive errorNumber = 86 + errResourceBusy errorNumber = 87 + errAccessDenied errorNumber = 88 + errDbusService errorNumber = 89 + errStorageVolExist errorNumber = 90 + errCPUIncompatible errorNumber = 91 + errXMLInvalidSchema errorNumber = 92 + errMigrateFinishOk errorNumber = 93 + errAuthUnavailable errorNumber = 94 + errNoServer errorNumber = 95 + errNoClient errorNumber = 96 + errAgentUnsynced errorNumber = 97 + errLibssh errorNumber = 98 +) diff --git a/libvirt.yml b/libvirt.yml index 28c2532..149225d 100644 --- a/libvirt.yml +++ b/libvirt.yml @@ -30,6 +30,7 @@ PARSER: IncludePaths: [./lv_source/include] SourcesPaths: - libvirt/libvirt.h + - libvirt/virterror.h TRANSLATOR: ConstRules: @@ -52,6 +53,10 @@ TRANSLATOR: - {action: replace, from: "Uri([A-Z]|$)", to: "URI$1"} - {action: replace, from: "Vcpu([A-Z]|$)", to: "VCPU$1"} - {action: replace, from: "Xml([A-Z]|$)", to: "XML$1"} + - {action: replace, from: "Rpc([A-Z]|$)", to: "RPC$1"} + - {action: replace, from: "Ssh([A-Z]|$)", to: "SSH$1"} + - {action: replace, from: "Http([A-Z]|$)", to: "HTTP$1"} + - {transform: unexport, from: "^(Err|From|War)"} const: - {action: accept, from: "^VIR_"} # Special case to prevent a collision with a type: diff --git a/rpc.go b/rpc.go index 9593be2..72119ae 100644 --- a/rpc.go +++ b/rpc.go @@ -113,6 +113,23 @@ type libvirtError struct { Level uint32 } +func (e libvirtError) Error() string { + return e.Message +} + +func checkError(err error, expectedError errorNumber) bool { + e, ok := err.(libvirtError) + if ok { + return e.Code == uint32(expectedError) + } + return false +} + +// IsNotFound detects libvirt's ERR_NO_DOMAIN. +func IsNotFound(err error) bool { + return checkError(err, errNoDomain) +} + // listen processes incoming data and routes // responses to their respective callback handler. func (l *Libvirt) listen() { @@ -328,8 +345,12 @@ func decodeError(buf []byte) error { if strings.Contains(e.Message, "unknown procedure") { return ErrUnsupported } + // if libvirt returns ERR_OK, ignore the error + if checkError(e, errOk) { + return nil + } - return errors.New(e.Message) + return e } // decodeEvent extracts an event from the given byte slice. diff --git a/rpc_test.go b/rpc_test.go index 104e3dd..4393512 100644 --- a/rpc_test.go +++ b/rpc_test.go @@ -89,7 +89,7 @@ var ( } testErrorMessage = []byte{ - 0x00, 0x00, 0x00, 0x37, // code + 0x00, 0x00, 0x00, 0x37, // code (55, errOperationInvalid) 0x00, 0x00, 0x00, 0x0a, // domain id // message ("Requested operation is not valid: domain is not running") @@ -106,6 +106,25 @@ var ( 0x00, 0x00, 0x00, 0x02, } + testErrorNotFoundMessage = []byte{ + 0x00, 0x00, 0x00, 0x2a, // code (42 errDoDmain) + 0x00, 0x00, 0x00, 0x0a, // domain id + + // message + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, + 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x6e, + 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, + 0x3a, 0x20, 0x6e, 0x6f, 0x20, 0x64, 0x6f, 0x6d, + 0x61, 0x69, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, + 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, + 0x67, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x27, + 0x74, 0x65, 0x73, 0x74, 0x2d, 0x2d, 0x2d, 0x27, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + + // error level + 0x00, 0x00, 0x00, 0x01, + } + testDomain = &Domain{ Name: "test-domain", UUID: testUUID, @@ -204,11 +223,24 @@ func TestDecodeEvent(t *testing.T) { } func TestDecodeError(t *testing.T) { - expected := "Requested operation is not valid: domain is not running" + expectedMsg := "Requested operation is not valid: domain is not running" + expectedCode := errOperationInvalid err := decodeError(testErrorMessage) - if err.Error() != expected { - t.Errorf("expected error %s, got %s", expected, err.Error()) + e := err.(libvirtError) + if e.Message != expectedMsg { + t.Errorf("expected error message %s, got %s", expectedMsg, err.Error()) + } + if e.Code != uint32(expectedCode) { + t.Errorf("expected code %d, got %d", expectedCode, e.Code) + } +} + +func TestErrNotFound(t *testing.T) { + err := decodeError(testErrorNotFoundMessage) + ok := IsNotFound(err) + if !ok { + t.Errorf("expected true, got %t", ok) } }