Adds StoragePools() (#27)
* Adds StoragePools() This adds the ability to list storage pools.
This commit is contained in:
parent
85674d25f7
commit
591f6798f1
@ -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
7
.travis/test-pool.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<!-- storage pool used for CI testing -->
|
||||||
|
<pool type="dir">
|
||||||
|
<name>test</name>
|
||||||
|
<target>
|
||||||
|
<path>/tmp</path>
|
||||||
|
</target>
|
||||||
|
</pool>
|
@ -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
|
||||||
)
|
)
|
||||||
|
76
libvirt.go
76
libvirt.go
@ -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
|
||||||
|
@ -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))
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user