Adds StoragePool(), StoragePoolRefresh() (#28)

This adds two new methods:
- `StoragePool()`, used to lookup a storage pool by name.
- `StoragePoolRefresh()`, used to refresh a storage pool by name.
This commit is contained in:
Ben LeMasurier 2017-01-09 14:54:30 -07:00 committed by GitHub
parent 591f6798f1
commit cfa567708b
5 changed files with 202 additions and 0 deletions

View File

@ -42,6 +42,8 @@ const (
ProcDomainGetXMLDesc = 14 ProcDomainGetXMLDesc = 14
ProcDomainLookupByName = 23 ProcDomainLookupByName = 23
ProcAuthList = 66 ProcAuthList = 66
ProcStoragePoolRefresh = 83
ProcStoragePoolLookupByName = 84
ProcConnectGetLibVersion = 157 ProcConnectGetLibVersion = 157
ProcDomainMigrateSetMaxSpeed = 207 ProcDomainMigrateSetMaxSpeed = 207
ProcDomainGetState = 212 ProcDomainGetState = 212

View File

@ -572,6 +572,76 @@ func (l *Libvirt) Run(dom string, cmd []byte) ([]byte, error) {
return bytes.TrimRight(data[4:], "\x00"), nil return bytes.TrimRight(data[4:], "\x00"), nil
} }
// StoragePool returns the storage pool associated with the provided name.
// An error is returned if the requested storage pool is not found.
func (l *Libvirt) StoragePool(name string) (*StoragePool, error) {
req := struct {
Name string
}{
Name: name,
}
buf, err := encode(&req)
if err != nil {
return nil, err
}
resp, err := l.request(constants.ProcStoragePoolLookupByName, constants.ProgramRemote, &buf)
if err != nil {
return nil, err
}
r := <-resp
if r.Status != StatusOK {
return nil, decodeError(r.Payload)
}
result := struct {
Pool StoragePool
}{}
dec := xdr.NewDecoder(bytes.NewReader(r.Payload))
_, err = dec.Decode(&result)
if err != nil {
return nil, err
}
return &result.Pool, nil
}
// StoragePoolRefresh refreshes the storage pool specified by name.
func (l *Libvirt) StoragePoolRefresh(name string) error {
pool, err := l.StoragePool(name)
if err != nil {
return err
}
req := struct {
Pool StoragePool
Flags uint32
}{
Pool: *pool,
Flags: 0, // unused per libvirt source, callers should pass 0
}
buf, err := encode(&req)
if err != nil {
return err
}
resp, err := l.request(constants.ProcStoragePoolRefresh, constants.ProgramRemote, &buf)
if err != nil {
return err
}
r := <-resp
if r.Status != StatusOK {
return decodeError(r.Payload)
}
return nil
}
// StoragePools returns a list of defined storage pools. Pools are filtered by // StoragePools returns a list of defined storage pools. Pools are filtered by
// the provided flags. See StoragePools*. // the provided flags. See StoragePools*.
func (l *Libvirt) StoragePools(flags StoragePoolsFlags) ([]StoragePool, error) { func (l *Libvirt) StoragePools(flags StoragePoolsFlags) ([]StoragePool, error) {

View File

@ -70,6 +70,40 @@ func TestCapabilities(t *testing.T) {
} }
} }
func TestStoragePoolIntegration(t *testing.T) {
l := New(testConn(t))
defer l.Disconnect()
if err := l.Connect(); err != nil {
t.Fatal(err)
}
wantName := "test"
pool, err := l.StoragePool(wantName)
if err != nil {
t.Fatal(err)
}
gotName := pool.Name
if gotName != wantName {
t.Errorf("expected name %q, got %q", wantName, gotName)
}
}
func TestStoragePoolInvalidIntegration(t *testing.T) {
l := New(testConn(t))
defer l.Disconnect()
if err := l.Connect(); err != nil {
t.Fatal(err)
}
_, err := l.StoragePool("test-does-not-exist")
if err == nil {
t.Errorf("expected non-existent storage pool return error")
}
}
func TestStoragePoolsIntegration(t *testing.T) { func TestStoragePoolsIntegration(t *testing.T) {
l := New(testConn(t)) l := New(testConn(t))
defer l.Disconnect() defer l.Disconnect()
@ -116,6 +150,34 @@ func TestStoragePoolsAutostartIntegration(t *testing.T) {
} }
} }
func TestStoragePoolRefreshIntegration(t *testing.T) {
l := New(testConn(t))
defer l.Disconnect()
if err := l.Connect(); err != nil {
t.Fatal(err)
}
err := l.StoragePoolRefresh("test")
if err != nil {
t.Error(err)
}
}
func TestStoragePoolRefreshInvalidIntegration(t *testing.T) {
l := New(testConn(t))
defer l.Disconnect()
if err := l.Connect(); err != nil {
t.Fatal(err)
}
err := l.StoragePoolRefresh("test-does-not-exist")
if err == nil {
t.Error("expected non-existent storage pool to fail refresh")
}
}
func TestXMLIntegration(t *testing.T) { func TestXMLIntegration(t *testing.T) {
l := New(testConn(t)) l := New(testConn(t))

View File

@ -221,6 +221,32 @@ func TestRunFail(t *testing.T) {
} }
} }
func TestStoragePool(t *testing.T) {
conn := libvirttest.New()
l := New(conn)
wantName := "default"
pool, err := l.StoragePool(wantName)
if err != nil {
t.Error(err)
}
gotName := pool.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 := pool.UUID
if gotUUID != wantUUID {
t.Errorf("expected UUID %q, got %q", wantUUID, gotUUID)
}
}
func TestStoragePools(t *testing.T) { func TestStoragePools(t *testing.T) {
conn := libvirttest.New() conn := libvirttest.New()
l := New(conn) l := New(conn)
@ -253,6 +279,16 @@ func TestStoragePools(t *testing.T) {
} }
} }
func TestStoragePoolRefresh(t *testing.T) {
conn := libvirttest.New()
l := New(conn)
err := l.StoragePoolRefresh("default")
if err != nil {
t.Error(err)
}
}
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,34 @@ var testDomainStateReply = []byte{
0x00, 0x00, 0x00, 0x01, // reason 0x00, 0x00, 0x00, 0x01, // reason
} }
var testStoragePoolLookup = []byte{
0x00, 0x00, 0x00, 0x38, // length
0x20, 0x00, 0x80, 0x86, // program
0x00, 0x00, 0x00, 0x01, // version
0x00, 0x00, 0x00, 0x54, // procedure
0x00, 0x00, 0x00, 0x01, // type
0x00, 0x00, 0x00, 0x00, // serial
0x00, 0x00, 0x00, 0x00, // status
// 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,
}
var testStoragePoolRefresh = []byte{
0x00, 0x00, 0x00, 0x1c, // length
0x20, 0x00, 0x80, 0x86, // program
0x00, 0x00, 0x00, 0x01, // version
0x00, 0x00, 0x00, 0x53, // procedure
0x00, 0x00, 0x00, 0x01, // type
0x00, 0x00, 0x00, 0x00, // serial
0x00, 0x00, 0x00, 0x00, // status
}
var testListPoolsReply = []byte{ var testListPoolsReply = []byte{
0x00, 0x00, 0x00, 0x40, // length 0x00, 0x00, 0x00, 0x40, // length
0x20, 0x00, 0x80, 0x86, // program 0x20, 0x00, 0x80, 0x86, // program
@ -333,6 +361,10 @@ func (m *MockLibvirt) handleRemote(procedure uint32, conn net.Conn) {
switch procedure { switch procedure {
case constants.ProcAuthList: case constants.ProcAuthList:
conn.Write(m.reply(testAuthReply)) conn.Write(m.reply(testAuthReply))
case constants.ProcStoragePoolRefresh:
conn.Write(m.reply(testStoragePoolRefresh))
case constants.ProcStoragePoolLookupByName:
conn.Write(m.reply(testStoragePoolLookup))
case constants.ProcConnectOpen: case constants.ProcConnectOpen:
conn.Write(m.reply(testConnectReply)) conn.Write(m.reply(testConnectReply))
case constants.ProcConnectClose: case constants.ProcConnectClose: