create volume
diff --git a/acceptance/openstack/blockstorage_test.go b/acceptance/openstack/blockstorage_test.go
new file mode 100644
index 0000000..ad40590
--- /dev/null
+++ b/acceptance/openstack/blockstorage_test.go
@@ -0,0 +1,70 @@
+// +build acceptance
+
+package openstack
+
+import (
+ "fmt"
+ blockstorage "github.com/rackspace/gophercloud/openstack/blockstorage/v1"
+ "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
+ "github.com/rackspace/gophercloud/openstack/identity"
+ "github.com/rackspace/gophercloud/openstack/utils"
+ "os"
+ "testing"
+)
+
+func getClient() (*blockstorage.Client, error) {
+ ao, err := utils.AuthOptions()
+ if err != nil {
+ return nil, err
+ }
+
+ r, err := identity.Authenticate(ao)
+ if err != nil {
+ return nil, err
+ }
+
+ sc, err := identity.GetServiceCatalog(r)
+ if err != nil {
+ return nil, err
+ }
+
+ ces, err := sc.CatalogEntries()
+ if err != nil {
+ return nil, err
+ }
+
+ var eps []identity.Endpoint
+ for _, ce := range ces {
+ if ce.Type == "volume" {
+ eps = ce.Endpoints
+ }
+ }
+
+ region := os.Getenv("OS_REGION_NAME")
+ rep := ""
+ for _, ep := range eps {
+ if ep.Region == region {
+ rep = ep.PublicURL
+ }
+ }
+
+ client := blockstorage.NewClient(rep, r, ao)
+
+ return client, nil
+
+}
+
+func TestVolumes(t *testing.T) {
+ client, err := getClient()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ v, err := volumes.Create(client, volumes.CreateOpts{
+ Size: 1,
+ })
+ if err != nil {
+ t.Error(err)
+ return
+ }
+}
diff --git a/openstack/blockstorage/v1/client.go b/openstack/blockstorage/v1/client.go
new file mode 100644
index 0000000..4547d0b
--- /dev/null
+++ b/openstack/blockstorage/v1/client.go
@@ -0,0 +1,51 @@
+package blockstorage
+
+import (
+ "fmt"
+ "github.com/rackspace/gophercloud/openstack/identity"
+)
+
+// Client abstracts the connection information needed to make API requests for OpenStack compute endpoints.
+type Client struct {
+ endpoint string
+ authority identity.AuthResults
+ options identity.AuthOptions
+ token *identity.Token
+}
+
+// NewClient creates a new Client structure to use when issuing requests to the server.
+func NewClient(e string, a identity.AuthResults, o identity.AuthOptions) *Client {
+ return &Client{
+ endpoint: e,
+ authority: a,
+ options: o,
+ }
+}
+
+func (c *Client) GetVolumeURL() string {
+ return fmt.Sprintf("%s/volumes", c.endpoint)
+}
+
+func (c *Client) GetHeaders() (map[string]string, error) {
+ t, err := c.getAuthToken()
+ if err != nil {
+ return map[string]string{}, err
+ }
+
+ return map[string]string{
+ "X-Auth-Token": t,
+ }, nil
+}
+
+func (c *Client) getAuthToken() (string, error) {
+ var err error
+
+ if c.token == nil {
+ c.token, err = identity.GetToken(c.authority)
+ if err != nil {
+ return "", err
+ }
+ }
+
+ return c.token.Id, err
+}
diff --git a/openstack/blockstorage/v1/volumes/requests.go b/openstack/blockstorage/v1/volumes/requests.go
new file mode 100644
index 0000000..b1f45cd
--- /dev/null
+++ b/openstack/blockstorage/v1/volumes/requests.go
@@ -0,0 +1,23 @@
+package volumes
+
+import (
+ "github.com/racker/perigee"
+ blockstorage "github.com/rackspace/gophercloud/openstack/blockstorage/v1"
+)
+
+func Create(c *blockstorage.Client, opts CreateOpts) (Volume, error) {
+ var v Volume
+ h, err := c.GetHeaders()
+ if err != nil {
+ return v, err
+ }
+ url := c.GetVolumeURL()
+ _, err = perigee.Request("POST", url, perigee.Options{
+ Results: &v,
+ ReqBody: map[string]interface{}{
+ "volume": opts,
+ },
+ MoreHeaders: h,
+ })
+ return v, err
+}
diff --git a/openstack/blockstorage/v1/volumes/volumes.go b/openstack/blockstorage/v1/volumes/volumes.go
new file mode 100644
index 0000000..35c416b
--- /dev/null
+++ b/openstack/blockstorage/v1/volumes/volumes.go
@@ -0,0 +1,16 @@
+package volumes
+
+type Volume map[string]interface{}
+
+type CreateOpts struct {
+ Availability_zone string `json:"size"`
+ Source_volid string `json:"source_volid"`
+ Display_description string `json:"display_description"`
+ Snapshot_id string `json:"snapshot_id"`
+ Size int `json:"size"`
+ Display_name string `json:"display_name"`
+ ImageRef string `json:"imageRef"`
+ Volume_type string `json:"volume_type"`
+ Bootable bool `json:"bootable"`
+ Metadata map[string]string `json:"metadata"`
+}