Adds StoragePools() (#27)

* Adds StoragePools()

This adds the ability to list storage pools.
This commit is contained in:
Ben LeMasurier 2017-01-06 15:58:27 -06:00 committed by GitHub
parent 85674d25f7
commit 591f6798f1
8 changed files with 203 additions and 15 deletions

View File

@ -36,8 +36,9 @@ install:
before_script: before_script:
- go get -d ./... - go get -d ./...
- sudo qemu-img create -f raw -o size=10M /var/lib/libvirt/images/test.raw - sudo qemu-img create -f raw -o size=10M /var/lib/libvirt/images/test.raw
- sudo virsh define ./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
script: script:
- ./scripts/licensecheck.sh - ./scripts/licensecheck.sh

7
.travis/test-pool.xml Normal file
View File

@ -0,0 +1,7 @@
<!-- storage pool used for CI testing -->
<pool type="dir">
<name>test</name>
<target>
<path>/tmp</path>
</target>
</pool>

View File

@ -48,6 +48,7 @@ const (
ProcDomainUndefineFlags = 231 ProcDomainUndefineFlags = 231
ProcDomainDestroyFlags = 234 ProcDomainDestroyFlags = 234
ProcConnectListAllDomains = 273 ProcConnectListAllDomains = 273
ProcConnectListAllStoragePools = 281
ProcMigratePerformParams = 305 ProcMigratePerformParams = 305
ProcDomainDefineXMLFlags = 350 ProcDomainDefineXMLFlags = 350
) )

View File

@ -70,6 +70,12 @@ type DomainEvent struct {
Details []byte Details []byte
} }
// StoragePool represents a storage pool as seen by libvirt.
type StoragePool struct {
Name string
UUID [constants.UUIDSize]byte
}
// qemuError represents a QEMU process error. // qemuError represents a QEMU process error.
type qemuError struct { type qemuError struct {
Error struct { Error struct {
@ -203,6 +209,36 @@ const (
DomainStateLast DomainStateLast
) )
// StoragePoolsFlags specifies storage pools to list.
type StoragePoolsFlags uint32
// These flags come in groups; if all bits from a group are 0,
// then that group is not used to filter results.
const (
StoragePoolsFlagInactive = 1 << iota
StoragePoolsFlagActive
StoragePoolsFlagPersistent
StoragePoolsFlagTransient
StoragePoolsFlagAutostart
StoragePoolsFlagNoAutostart
// pools by type
StoragePoolsFlagDir
StoragePoolsFlagFS
StoragePoolsFlagNETFS
StoragePoolsFlagLogical
StoragePoolsFlagDisk
StoragePoolsFlagISCSI
StoragePoolsFlagSCSI
StoragePoolsFlagMPATH
StoragePoolsFlagRBD
StoragePoolsFlagSheepdog
StoragePoolsFlagGluster
StoragePoolsFlagZFS
)
// Capabilities returns an XML document describing the host's capabilties. // Capabilities returns an XML document describing the host's capabilties.
func (l *Libvirt) Capabilities() ([]byte, error) { func (l *Libvirt) Capabilities() ([]byte, error) {
resp, err := l.request(constants.ProcConnectGetCapabilties, constants.ProgramRemote, nil) resp, err := l.request(constants.ProcConnectGetCapabilties, constants.ProgramRemote, nil)
@ -536,6 +572,46 @@ func (l *Libvirt) Run(dom string, cmd []byte) ([]byte, error) {
return bytes.TrimRight(data[4:], "\x00"), nil return bytes.TrimRight(data[4:], "\x00"), nil
} }
// StoragePools returns a list of defined storage pools. Pools are filtered by
// the provided flags. See StoragePools*.
func (l *Libvirt) StoragePools(flags StoragePoolsFlags) ([]StoragePool, error) {
req := struct {
NeedResults uint32
Flags StoragePoolsFlags
}{
NeedResults: 1,
Flags: flags,
}
buf, err := encode(&req)
if err != nil {
return nil, err
}
resp, err := l.request(constants.ProcConnectListAllStoragePools, constants.ProgramRemote, &buf)
if err != nil {
return nil, err
}
r := <-resp
if r.Status != StatusOK {
return nil, decodeError(r.Payload)
}
result := struct {
Pools []StoragePool
Count uint32
}{}
dec := xdr.NewDecoder(bytes.NewReader(r.Payload))
_, err = dec.Decode(&result)
if err != nil {
return nil, err
}
return result.Pools, nil
}
// Undefine undefines the domain specified by dom, e.g., 'prod-lb-01'. // Undefine undefines the domain specified by dom, e.g., 'prod-lb-01'.
// The flags argument allows additional options to be specified such as // The flags argument allows additional options to be specified such as
// cleaning up snapshot metadata. For more information on available // cleaning up snapshot metadata. For more information on available

View File

@ -70,6 +70,52 @@ func TestCapabilities(t *testing.T) {
} }
} }
func TestStoragePoolsIntegration(t *testing.T) {
l := New(testConn(t))
defer l.Disconnect()
if err := l.Connect(); err != nil {
t.Fatal(err)
}
pools, err := l.StoragePools(StoragePoolsFlagActive)
if err != nil {
t.Error(err)
}
wantLen := 1
gotLen := len(pools)
if gotLen != wantLen {
t.Fatalf("expected %d storage pool, got %d", wantLen, gotLen)
}
wantName := "test"
gotName := pools[0].Name
if gotName != wantName {
t.Errorf("expected name %q, got %q", wantName, gotName)
}
}
func TestStoragePoolsAutostartIntegration(t *testing.T) {
l := New(testConn(t))
defer l.Disconnect()
if err := l.Connect(); err != nil {
t.Fatal(err)
}
pools, err := l.StoragePools(StoragePoolsFlagAutostart)
if err != nil {
t.Error(err)
}
wantLen := 0
gotLen := len(pools)
if gotLen != wantLen {
t.Errorf("expected %d storage pool, got %d", wantLen, gotLen)
}
}
func TestXMLIntegration(t *testing.T) { func TestXMLIntegration(t *testing.T) {
l := New(testConn(t)) l := New(testConn(t))

View File

@ -20,6 +20,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/digitalocean/go-libvirt/internal/constants"
"github.com/digitalocean/go-libvirt/libvirttest" "github.com/digitalocean/go-libvirt/libvirttest"
) )
@ -220,6 +221,38 @@ func TestRunFail(t *testing.T) {
} }
} }
func TestStoragePools(t *testing.T) {
conn := libvirttest.New()
l := New(conn)
pools, err := l.StoragePools(StoragePoolsFlagActive)
if err != nil {
t.Error(err)
}
wantLen := 1
gotLen := len(pools)
if gotLen != wantLen {
t.Errorf("expected %d storage pool, got %d", wantLen, gotLen)
}
wantName := "default"
gotName := pools[0].Name
if gotName != wantName {
t.Errorf("expected name %q, got %q", wantName, gotName)
}
// bb30a11c-0846-4827-8bba-3e6b5cf1b65f
wantUUID := [constants.UUIDSize]byte{
0xbb, 0x30, 0xa1, 0x1c, 0x08, 0x46, 0x48, 0x27,
0x8b, 0xba, 0x3e, 0x6b, 0x5c, 0xf1, 0xb6, 0x5f,
}
gotUUID := pools[0].UUID
if gotUUID != wantUUID {
t.Errorf("expected UUID %q, got %q", wantUUID, gotUUID)
}
}
func TestUndefine(t *testing.T) { func TestUndefine(t *testing.T) {
conn := libvirttest.New() conn := libvirttest.New()
l := New(conn) l := New(conn)

View File

@ -217,6 +217,28 @@ var testDomainStateReply = []byte{
0x00, 0x00, 0x00, 0x01, // reason 0x00, 0x00, 0x00, 0x01, // reason
} }
var testListPoolsReply = []byte{
0x00, 0x00, 0x00, 0x40, // length
0x20, 0x00, 0x80, 0x86, // program
0x00, 0x00, 0x00, 0x01, // version
0x00, 0x00, 0x01, 0x19, // procedure
0x00, 0x00, 0x00, 0x01, // type
0x00, 0x00, 0x00, 0x00, // serial
0x00, 0x00, 0x00, 0x00, // status
0x00, 0x00, 0x00, 0x01, // pools
// first pool, name: "default"
0x00, 0x00, 0x00, 0x07, 0x64, 0x65, 0x66, 0x61,
0x75, 0x6c, 0x74, 0x00,
// uuid: bb30a11c084648278bba3e6b5cf1b65f
0xbb, 0x30, 0xa1, 0x1c, 0x08, 0x46, 0x48, 0x27,
0x8b, 0xba, 0x3e, 0x6b, 0x5c, 0xf1, 0xb6, 0x5f,
0x00, 0x00, 0x00, 0x01, // count
}
var testUndefineReply = []byte{ var testUndefineReply = []byte{
0x00, 0x00, 0x00, 0x1c, // length 0x00, 0x00, 0x00, 0x1c, // length
0x20, 0x00, 0x80, 0x86, // program 0x20, 0x00, 0x80, 0x86, // program
@ -321,6 +343,8 @@ func (m *MockLibvirt) handleRemote(procedure uint32, conn net.Conn) {
conn.Write(m.reply(testDomainResponse)) conn.Write(m.reply(testDomainResponse))
case constants.ProcConnectListAllDomains: case constants.ProcConnectListAllDomains:
conn.Write(m.reply(testDomainsReply)) conn.Write(m.reply(testDomainsReply))
case constants.ProcConnectListAllStoragePools:
conn.Write(m.reply(testListPoolsReply))
case constants.ProcDomainGetState: case constants.ProcDomainGetState:
conn.Write(m.reply(testDomainStateReply)) conn.Write(m.reply(testDomainStateReply))
case constants.ProcDomainMigrateSetMaxSpeed: case constants.ProcDomainMigrateSetMaxSpeed: