Add Secrets() (#29)
This adds the `Secrets()` method, used to retrieve all secrets managed by the libvirt daemon.
This commit is contained in:
parent
cfa567708b
commit
2609dd2697
@ -39,6 +39,7 @@ before_script:
|
|||||||
- sudo virsh define .travis/test-domain.xml
|
- sudo virsh define .travis/test-domain.xml
|
||||||
- sudo virsh start test
|
- sudo virsh start test
|
||||||
- sudo virsh pool-create .travis/test-pool.xml
|
- sudo virsh pool-create .travis/test-pool.xml
|
||||||
|
- sudo virsh secret-define .travis/test-secret.xml
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- ./scripts/licensecheck.sh
|
- ./scripts/licensecheck.sh
|
||||||
|
7
.travis/test-secret.xml
Normal file
7
.travis/test-secret.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<secret ephemeral='no' private='yes'>
|
||||||
|
<description>test</description>
|
||||||
|
<uuid>19fdc2f2-fa64-46f3-bacf-42a8aafca6dd</uuid>
|
||||||
|
<usage type='volume'>
|
||||||
|
<volume>/tmp</volume>
|
||||||
|
</usage>
|
||||||
|
</secret>
|
@ -51,6 +51,7 @@ const (
|
|||||||
ProcDomainDestroyFlags = 234
|
ProcDomainDestroyFlags = 234
|
||||||
ProcConnectListAllDomains = 273
|
ProcConnectListAllDomains = 273
|
||||||
ProcConnectListAllStoragePools = 281
|
ProcConnectListAllStoragePools = 281
|
||||||
|
ProcConnectListAllSecrets = 287
|
||||||
ProcMigratePerformParams = 305
|
ProcMigratePerformParams = 305
|
||||||
ProcDomainDefineXMLFlags = 350
|
ProcDomainDefineXMLFlags = 350
|
||||||
)
|
)
|
||||||
|
60
libvirt.go
60
libvirt.go
@ -70,6 +70,13 @@ type DomainEvent struct {
|
|||||||
Details []byte
|
Details []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Secret represents a secret managed by the libvirt daemon.
|
||||||
|
type Secret struct {
|
||||||
|
UUID [constants.UUIDSize]byte
|
||||||
|
UsageType SecretUsageType
|
||||||
|
UsageID string
|
||||||
|
}
|
||||||
|
|
||||||
// StoragePool represents a storage pool as seen by libvirt.
|
// StoragePool represents a storage pool as seen by libvirt.
|
||||||
type StoragePool struct {
|
type StoragePool struct {
|
||||||
Name string
|
Name string
|
||||||
@ -209,6 +216,20 @@ const (
|
|||||||
DomainStateLast
|
DomainStateLast
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SecretUsageType specifies the usage for a libvirt secret.
|
||||||
|
type SecretUsageType uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SecretUsageTypeNone specifies no usage.
|
||||||
|
SecretUsageTypeNone SecretUsageType = iota
|
||||||
|
// SecretUsageTypeVolume specifies a volume secret.
|
||||||
|
SecretUsageTypeVolume
|
||||||
|
// SecretUsageTypeCeph specifies secrets for ceph devices.
|
||||||
|
SecretUsageTypeCeph
|
||||||
|
// SecretUsageTypeISCSI specifies secrets for ISCSI devices.
|
||||||
|
SecretUsageTypeISCSI
|
||||||
|
)
|
||||||
|
|
||||||
// StoragePoolsFlags specifies storage pools to list.
|
// StoragePoolsFlags specifies storage pools to list.
|
||||||
type StoragePoolsFlags uint32
|
type StoragePoolsFlags uint32
|
||||||
|
|
||||||
@ -572,6 +593,45 @@ func (l *Libvirt) Run(dom string, cmd []byte) ([]byte, error) {
|
|||||||
return bytes.TrimRight(data[4:], "\x00"), nil
|
return bytes.TrimRight(data[4:], "\x00"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Secrets returns all secrets managed by the libvirt daemon.
|
||||||
|
func (l *Libvirt) Secrets() ([]Secret, error) {
|
||||||
|
req := struct {
|
||||||
|
NeedResults uint32
|
||||||
|
Flags uint32
|
||||||
|
}{
|
||||||
|
NeedResults: 1,
|
||||||
|
Flags: 0, // unused per libvirt source, callers should pass 0
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := encode(&req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := l.request(constants.ProcConnectListAllSecrets, constants.ProgramRemote, &buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
r := <-resp
|
||||||
|
if r.Status != StatusOK {
|
||||||
|
return nil, decodeError(r.Payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := struct {
|
||||||
|
Secrets []Secret
|
||||||
|
Count uint32
|
||||||
|
}{}
|
||||||
|
|
||||||
|
dec := xdr.NewDecoder(bytes.NewReader(r.Payload))
|
||||||
|
_, err = dec.Decode(&result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.Secrets, nil
|
||||||
|
}
|
||||||
|
|
||||||
// StoragePool returns the storage pool associated with the provided name.
|
// StoragePool returns the storage pool associated with the provided name.
|
||||||
// An error is returned if the requested storage pool is not found.
|
// An error is returned if the requested storage pool is not found.
|
||||||
func (l *Libvirt) StoragePool(name string) (*StoragePool, error) {
|
func (l *Libvirt) StoragePool(name string) (*StoragePool, error) {
|
||||||
|
@ -21,6 +21,8 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/digitalocean/go-libvirt/internal/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
const testAddr = "127.0.0.1:16509"
|
const testAddr = "127.0.0.1:16509"
|
||||||
@ -70,6 +72,47 @@ func TestCapabilities(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSecretsIntegration(t *testing.T) {
|
||||||
|
l := New(testConn(t))
|
||||||
|
defer l.Disconnect()
|
||||||
|
|
||||||
|
if err := l.Connect(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
secrets, err := l.Secrets()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
wantLen := 1
|
||||||
|
gotLen := len(secrets)
|
||||||
|
if gotLen != wantLen {
|
||||||
|
t.Fatal("expected %d secrets, got %d", wantLen, gotLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := secrets[0]
|
||||||
|
|
||||||
|
wantType := SecretUsageTypeVolume
|
||||||
|
if s.UsageType != wantType {
|
||||||
|
t.Error("expected usage type: %d, got %d", wantType, s.UsageType)
|
||||||
|
}
|
||||||
|
|
||||||
|
wantID := "/tmp"
|
||||||
|
if s.UsageID != wantID {
|
||||||
|
t.Error("expected usage id: %q, got %q", wantID, s.UsageID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 19fdc2f2-fa64-46f3-bacf-42a8aafca6dd
|
||||||
|
wantUUID := [constants.UUIDSize]byte{
|
||||||
|
0x19, 0xfd, 0xc2, 0xf2, 0xfa, 0x64, 0x46, 0xf3,
|
||||||
|
0xba, 0xcf, 0x42, 0xa8, 0xaa, 0xfc, 0xa6, 0xdd,
|
||||||
|
}
|
||||||
|
if s.UUID != wantUUID {
|
||||||
|
t.Errorf("expected UUID %q, got %q", wantUUID, s.UUID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestStoragePoolIntegration(t *testing.T) {
|
func TestStoragePoolIntegration(t *testing.T) {
|
||||||
l := New(testConn(t))
|
l := New(testConn(t))
|
||||||
defer l.Disconnect()
|
defer l.Disconnect()
|
||||||
|
@ -221,6 +221,42 @@ func TestRunFail(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSecrets(t *testing.T) {
|
||||||
|
conn := libvirttest.New()
|
||||||
|
l := New(conn)
|
||||||
|
|
||||||
|
secrets, err := l.Secrets()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
wantLen := 1
|
||||||
|
gotLen := len(secrets)
|
||||||
|
if gotLen != wantLen {
|
||||||
|
t.Fatalf("expected %d secrets, got %d", wantLen, gotLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := secrets[0]
|
||||||
|
wantType := SecretUsageTypeVolume
|
||||||
|
if s.UsageType != wantType {
|
||||||
|
t.Errorf("expected usage type %d, got %d", wantType, s.UsageType)
|
||||||
|
}
|
||||||
|
|
||||||
|
wantID := "/tmp"
|
||||||
|
if s.UsageID != wantID {
|
||||||
|
t.Errorf("expected usage id %q, got %q", wantID, s.UsageID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 19fdc2f2-fa64-46f3-bacf-42a8aafca6dd
|
||||||
|
wantUUID := [constants.UUIDSize]byte{
|
||||||
|
0x19, 0xfd, 0xc2, 0xf2, 0xfa, 0x64, 0x46, 0xf3,
|
||||||
|
0xba, 0xcf, 0x42, 0xa8, 0xaa, 0xfc, 0xa6, 0xdd,
|
||||||
|
}
|
||||||
|
if s.UUID != wantUUID {
|
||||||
|
t.Errorf("expected UUID %q, got %q", wantUUID, s.UUID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestStoragePool(t *testing.T) {
|
func TestStoragePool(t *testing.T) {
|
||||||
conn := libvirttest.New()
|
conn := libvirttest.New()
|
||||||
l := New(conn)
|
l := New(conn)
|
||||||
|
@ -217,6 +217,33 @@ var testDomainStateReply = []byte{
|
|||||||
0x00, 0x00, 0x00, 0x01, // reason
|
0x00, 0x00, 0x00, 0x01, // reason
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var testSecretsReply = []byte{
|
||||||
|
0x00, 0x00, 0x00, 0x40, // length
|
||||||
|
0x20, 0x00, 0x80, 0x86, // program
|
||||||
|
0x00, 0x00, 0x00, 0x01, // version
|
||||||
|
0x00, 0x00, 0x01, 0x1f, // procedure
|
||||||
|
0x00, 0x00, 0x00, 0x01, // type
|
||||||
|
0x00, 0x00, 0x00, 0x00, // serial
|
||||||
|
0x00, 0x00, 0x00, 0x00, // status
|
||||||
|
|
||||||
|
// list of secrets
|
||||||
|
0x00, 0x00, 0x00, 0x01,
|
||||||
|
|
||||||
|
// first secret
|
||||||
|
// UUID: 19fdc2f2fa64-46f3bacf42a8aafca6dd
|
||||||
|
0x19, 0xfd, 0xc2, 0xf2, 0xfa, 0x64, 0x46, 0xf3,
|
||||||
|
0xba, 0xcf, 0x42, 0xa8, 0xaa, 0xfc, 0xa6, 0xdd,
|
||||||
|
|
||||||
|
// usage type: (1, volume)
|
||||||
|
0x00, 0x00, 0x00, 0x01,
|
||||||
|
|
||||||
|
// usage id: "/tmp"
|
||||||
|
0x00, 0x00, 0x00, 0x04, 0x2f, 0x74, 0x6d, 0x70,
|
||||||
|
|
||||||
|
// end of secrets
|
||||||
|
0x00, 0x00, 0x00, 0x01,
|
||||||
|
}
|
||||||
|
|
||||||
var testStoragePoolLookup = []byte{
|
var testStoragePoolLookup = []byte{
|
||||||
0x00, 0x00, 0x00, 0x38, // length
|
0x00, 0x00, 0x00, 0x38, // length
|
||||||
0x20, 0x00, 0x80, 0x86, // program
|
0x20, 0x00, 0x80, 0x86, // program
|
||||||
@ -377,6 +404,8 @@ func (m *MockLibvirt) handleRemote(procedure uint32, conn net.Conn) {
|
|||||||
conn.Write(m.reply(testDomainsReply))
|
conn.Write(m.reply(testDomainsReply))
|
||||||
case constants.ProcConnectListAllStoragePools:
|
case constants.ProcConnectListAllStoragePools:
|
||||||
conn.Write(m.reply(testListPoolsReply))
|
conn.Write(m.reply(testListPoolsReply))
|
||||||
|
case constants.ProcConnectListAllSecrets:
|
||||||
|
conn.Write(m.reply(testSecretsReply))
|
||||||
case constants.ProcDomainGetState:
|
case constants.ProcDomainGetState:
|
||||||
conn.Write(m.reply(testDomainStateReply))
|
conn.Write(m.reply(testDomainStateReply))
|
||||||
case constants.ProcDomainMigrateSetMaxSpeed:
|
case constants.ProcDomainMigrateSetMaxSpeed:
|
||||||
|
Loading…
Reference in New Issue
Block a user