Merge pull request #66 from liaoishere/feat/export-libvirt-error

Add helper function for error detection
This commit is contained in:
Geoff Hickey 2018-03-23 18:03:13 -04:00 committed by GitHub
commit 201d94aa6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 253 additions and 5 deletions

View File

@ -1963,3 +1963,193 @@ const (
StreamEventError StreamEventType = 4 StreamEventError StreamEventType = 4
StreamEventHangup StreamEventType = 8 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
)

View File

@ -30,6 +30,7 @@ PARSER:
IncludePaths: [./lv_source/include] IncludePaths: [./lv_source/include]
SourcesPaths: SourcesPaths:
- libvirt/libvirt.h - libvirt/libvirt.h
- libvirt/virterror.h
TRANSLATOR: TRANSLATOR:
ConstRules: ConstRules:
@ -52,6 +53,10 @@ TRANSLATOR:
- {action: replace, from: "Uri([A-Z]|$)", to: "URI$1"} - {action: replace, from: "Uri([A-Z]|$)", to: "URI$1"}
- {action: replace, from: "Vcpu([A-Z]|$)", to: "VCPU$1"} - {action: replace, from: "Vcpu([A-Z]|$)", to: "VCPU$1"}
- {action: replace, from: "Xml([A-Z]|$)", to: "XML$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: const:
- {action: accept, from: "^VIR_"} - {action: accept, from: "^VIR_"}
# Special case to prevent a collision with a type: # Special case to prevent a collision with a type:

23
rpc.go
View File

@ -113,6 +113,23 @@ type libvirtError struct {
Level uint32 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 // listen processes incoming data and routes
// responses to their respective callback handler. // responses to their respective callback handler.
func (l *Libvirt) listen() { func (l *Libvirt) listen() {
@ -328,8 +345,12 @@ func decodeError(buf []byte) error {
if strings.Contains(e.Message, "unknown procedure") { if strings.Contains(e.Message, "unknown procedure") {
return ErrUnsupported 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. // decodeEvent extracts an event from the given byte slice.

View File

@ -89,7 +89,7 @@ var (
} }
testErrorMessage = []byte{ testErrorMessage = []byte{
0x00, 0x00, 0x00, 0x37, // code 0x00, 0x00, 0x00, 0x37, // code (55, errOperationInvalid)
0x00, 0x00, 0x00, 0x0a, // domain id 0x00, 0x00, 0x00, 0x0a, // domain id
// message ("Requested operation is not valid: domain is not running") // message ("Requested operation is not valid: domain is not running")
@ -106,6 +106,25 @@ var (
0x00, 0x00, 0x00, 0x02, 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{ testDomain = &Domain{
Name: "test-domain", Name: "test-domain",
UUID: testUUID, UUID: testUUID,
@ -204,11 +223,24 @@ func TestDecodeEvent(t *testing.T) {
} }
func TestDecodeError(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) err := decodeError(testErrorMessage)
if err.Error() != expected { e := err.(libvirtError)
t.Errorf("expected error %s, got %s", expected, err.Error()) 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)
} }
} }