initial paging implementation and create volume rewrite
diff --git a/openstack/blockstorage/v1/volumes/requests.go b/openstack/blockstorage/v1/volumes/requests.go
index c4a72c2..18f8a41 100644
--- a/openstack/blockstorage/v1/volumes/requests.go
+++ b/openstack/blockstorage/v1/volumes/requests.go
@@ -2,47 +2,95 @@
import (
"github.com/racker/perigee"
- blockstorage "github.com/rackspace/gophercloud/openstack/blockstorage/v1"
+ "github.com/rackspace/gophercloud"
+ "github.com/rackspace/gophercloud/pagination"
+ "github.com/rackspace/gophercloud/utils"
)
-func Create(c *blockstorage.Client, opts CreateOpts) (Volume, error) {
- var v Volume
- h, err := c.GetHeaders()
- if err != nil {
- return v, err
- }
- url := c.GetVolumesURL()
- _, err = perigee.Request("POST", url, perigee.Options{
- Results: &struct {
- Volume *Volume `json:"volume"`
- }{&v},
- ReqBody: map[string]interface{}{
- "volume": opts,
- },
- MoreHeaders: h,
- })
- return v, err
+type VolumeOpts struct {
+ Availability string
+ Description string
+ ImageID string
+ Metadata map[string]string
+ Name string
+ Size int
+ SnapshotID string
+ Type string
}
-func List(c *blockstorage.Client, opts ListOpts) ([]Volume, error) {
- var v []Volume
- var url string
- h, err := c.GetHeaders()
- if err != nil {
- return v, err
+func Create(client *gophercloud.ServiceClient, opts VolumeOpts) (Volume, error) {
+
+ type volume struct {
+ Availability *string `json:"availability_zone,omitempty"`
+ Description *string `json:"display_description,omitempty"`
+ ImageID *string `json:"imageRef,omitempty"`
+ Metadata map[string]string `json:"metadata,omitempty"`
+ Name *string `json:"display_name,omitempty"`
+ Size *int `json:"size,omitempty"`
+ SnapshotID *string `json:"snapshot_id,omitempty"`
+ SourceVolID *string `json:"source_volid,omitempty"`
+ VolumeType *string `json:"volume_type,omitempty"`
}
- if full := opts["full"]; full {
- url = c.GetVolumesURL()
- } else {
- url = c.GetVolumeURL("detail")
+
+ type request struct {
+ Volume volume `json:"volume"`
}
- _, err = perigee.Request("GET", url, perigee.Options{
- Results: &struct {
- Volume *[]Volume `json:"volumes"`
- }{&v},
- MoreHeaders: h,
+
+ reqBody := request{
+ Volume: volume{},
+ }
+
+ reqBody.Volume.Availability = utils.MaybeString(opts.Availability)
+ reqBody.Volume.Description = utils.MaybeString(opts.Description)
+ reqBody.Volume.ImageID = utils.MaybeString(opts.ImageID)
+ reqBody.Volume.Name = utils.MaybeString(opts.Name)
+ reqBody.Volume.Size = utils.MaybeInt(opts.Size)
+ reqBody.Volume.SnapshotID = utils.MaybeString(opts.SnapshotID)
+ reqBody.Volume.SourceVolID = utils.MaybeString(opts.SourceVolID)
+ reqBody.Volume.VolumeType = utils.MaybeString(opts.VolumeType)
+
+ type response struct {
+ Volume Volume `json:"volume"`
+ }
+
+ var respBody response
+
+ _, err = perigee.Request("POST", volumesURL(client), perigee.Options{
+ MoreHeaders: c.Provider.AuthenticatedHeaders(),
+ OkCodes: []int{201},
+ ReqBody: &reqBody,
+ Results: &respBody,
})
- return v, err
+ if err != nil {
+ return nil, err
+ }
+
+ return &respBody.Volume, nil
+}
+
+func List(client *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
+ var url string
+
+ query := utils.BuildQuery(opts.Params)
+
+ if !opts.Full {
+ url = c.volumesURL()
+ } else {
+ url = c.volumeURL("detail")
+ }
+
+ createPage := func(r pagination.LastHTTPResponse) pagination.Page {
+ p := ListResult{
+ pagination.MarkerPageBase{
+ LastHTTPResponse: r,
+ },
+ }
+ p.MarkerPageBase.Owner = p
+ return p
+ }
+
+ pager := pagination.NewPager(client, url, createPage)
+ return pager
}
func Get(c *blockstorage.Client, opts GetOpts) (Volume, error) {
diff --git a/openstack/blockstorage/v1/volumes/volumes.go b/openstack/blockstorage/v1/volumes/volumes.go
index 8120863..230543c 100644
--- a/openstack/blockstorage/v1/volumes/volumes.go
+++ b/openstack/blockstorage/v1/volumes/volumes.go
@@ -1,20 +1,48 @@
package volumes
+import (
+ "github.com/rackspace/gophercloud/pagination"
+
+ "github.com/mitchellh/mapstructure"
+)
+
type Volume struct {
- Status string
- Display_name string
- Attachments []string
- Availability_zone string
- Bootable bool
- Created_at string
- Display_description string
- Volume_type string
- Snapshot_id string
- Source_volid string
- Metadata map[string]string
- Id string
- Size int
+ Status string
+ Name string
+ Attachments []string
+ AvailabilityZone string
+ Bootable bool
+ CreatedAt string
+ Description string
+ VolumeType string
+ SnapshotID string
+ SourceVolID string
+ Metadata map[string]string
+ Id string
+ Size int
}
+
+type VolumePage struct {
+ pagination.LinkedPageBase
+}
+
+func (p VolumPage) IsEmpty() (bool, error) {
+ volumes, err := ExtractVolumes(p)
+ if err != nil {
+ return true, err
+ }
+ return len(volumes) == 0, nil
+}
+
+func ExtractVolumes(page pagination.page) ([]Volume, error) {
+ var response struct {
+ Volumes []Volume `json:"volumes"`
+ }
+
+ err := mapstructure.Decode(page.(VolumePage).Body, &response)
+ return response.Volumes, err
+}
+
type CreateOpts map[string]interface{}
type ListOpts map[string]bool
type GetOpts map[string]string