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:
		| @@ -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 | ||||||
|   | |||||||
							
								
								
									
										70
									
								
								libvirt.go
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								libvirt.go
									
									
									
									
									
								
							| @@ -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) { | ||||||
|   | |||||||
| @@ -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)) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user