diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 691bd76f46e..9a9d3aa2c2a 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -1633,123 +1633,123 @@
},
{
"ImportPath": "github.com/gophercloud/gophercloud",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/common/extensions",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/images",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/servers",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/networks",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/ports",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/utils",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/pagination",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gorilla/context",
diff --git a/staging/src/k8s.io/apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiserver/Godeps/Godeps.json
index 83c6b74dbaa..49ef5aaa071 100644
--- a/staging/src/k8s.io/apiserver/Godeps/Godeps.json
+++ b/staging/src/k8s.io/apiserver/Godeps/Godeps.json
@@ -408,31 +408,31 @@
},
{
"ImportPath": "github.com/gophercloud/gophercloud",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/utils",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/pagination",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gregjones/httpcache",
diff --git a/staging/src/k8s.io/client-go/Godeps/Godeps.json b/staging/src/k8s.io/client-go/Godeps/Godeps.json
index d9c1c4f0410..c3d9ca80a46 100644
--- a/staging/src/k8s.io/client-go/Godeps/Godeps.json
+++ b/staging/src/k8s.io/client-go/Godeps/Godeps.json
@@ -172,31 +172,31 @@
},
{
"ImportPath": "github.com/gophercloud/gophercloud",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/utils",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/pagination",
- "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb"
+ "Rev": "8e59687aa4b27ab22a0bf3295f1e165ff7bd5f97"
},
{
"ImportPath": "github.com/gregjones/httpcache",
diff --git a/vendor/github.com/gophercloud/gophercloud/README.md b/vendor/github.com/gophercloud/gophercloud/README.md
index 60ca479de89..bb218c3fe9e 100644
--- a/vendor/github.com/gophercloud/gophercloud/README.md
+++ b/vendor/github.com/gophercloud/gophercloud/README.md
@@ -141,3 +141,19 @@ See the [contributing guide](./.github/CONTRIBUTING.md).
If you're struggling with something or have spotted a potential bug, feel free
to submit an issue to our [bug tracker](/issues).
+
+## Thank You
+
+We'd like to extend special thanks and appreciation to the following:
+
+### OpenLab
+
+
+
+OpenLab is providing a full CI environment to test each PR and merge for a variety of OpenStack releases.
+
+### VEXXHOST
+
+
+
+VEXXHOST is providing their services to assist with the development and testing of Gophercloud.
diff --git a/vendor/github.com/gophercloud/gophercloud/STYLEGUIDE.md b/vendor/github.com/gophercloud/gophercloud/STYLEGUIDE.md
index e7531a83d9d..22a29009412 100644
--- a/vendor/github.com/gophercloud/gophercloud/STYLEGUIDE.md
+++ b/vendor/github.com/gophercloud/gophercloud/STYLEGUIDE.md
@@ -1,6 +1,8 @@
## On Pull Requests
+- Please make sure to read our [contributing guide](/.github/CONTRIBUTING.md).
+
- Before you start a PR there needs to be a Github issue and a discussion about it
on that issue with a core contributor, even if it's just a 'SGTM'.
@@ -34,6 +36,9 @@
append. It makes it difficult for the reviewer to see what's changed from one
review to the next.
+- See [#583](https://github.com/gophercloud/gophercloud/issues/583) as an example of a
+ well-formatted issue which contains all relevant information we need to review and approve.
+
## On Code
- In re design: follow as closely as is reasonable the code already in the library.
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/auth_env.go b/vendor/github.com/gophercloud/gophercloud/openstack/auth_env.go
index 95286041d66..b5482ba8c9f 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/auth_env.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/auth_env.go
@@ -16,7 +16,12 @@ The following variables provide sources of truth: OS_AUTH_URL, OS_USERNAME,
OS_PASSWORD, OS_TENANT_ID, and OS_TENANT_NAME.
Of these, OS_USERNAME, OS_PASSWORD, and OS_AUTH_URL must have settings,
-or an error will result. OS_TENANT_ID and OS_TENANT_NAME are optional.
+or an error will result. OS_TENANT_ID, OS_TENANT_NAME, OS_PROJECT_ID, and
+OS_PROJECT_NAME are optional.
+
+OS_TENANT_ID and OS_TENANT_NAME are mutually exclusive to OS_PROJECT_ID and
+OS_PROJECT_NAME. If OS_PROJECT_ID and OS_PROJECT_NAME are set, they will
+still be referred as "tenant" in Gophercloud.
To use this function, first set the OS_* environment variables (for example,
by sourcing an `openrc` file), then:
@@ -34,6 +39,16 @@ func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) {
domainID := os.Getenv("OS_DOMAIN_ID")
domainName := os.Getenv("OS_DOMAIN_NAME")
+ // If OS_PROJECT_ID is set, overwrite tenantID with the value.
+ if v := os.Getenv("OS_PROJECT_ID"); v != "" {
+ tenantID = v
+ }
+
+ // If OS_PROJECT_NAME is set, overwrite tenantName with the value.
+ if v := os.Getenv("OS_PROJECT_NAME"); v != "" {
+ tenantName = v
+ }
+
if authURL == "" {
err := gophercloud.ErrMissingInput{Argument: "authURL"}
return nilOptions, err
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions/requests.go
index a3916c77c16..d18bff555b5 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions/requests.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions/requests.go
@@ -47,7 +47,7 @@ func Attach(client *gophercloud.ServiceClient, id string, opts AttachOptsBuilder
r.Err = err
return
}
- _, r.Err = client.Post(attachURL(client, id), b, nil, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(actionURL(client, id), b, nil, &gophercloud.RequestOpts{
OkCodes: []int{202},
})
return
@@ -56,7 +56,7 @@ func Attach(client *gophercloud.ServiceClient, id string, opts AttachOptsBuilder
// BeginDetach will mark the volume as detaching.
func BeginDetaching(client *gophercloud.ServiceClient, id string) (r BeginDetachingResult) {
b := map[string]interface{}{"os-begin_detaching": make(map[string]interface{})}
- _, r.Err = client.Post(beginDetachingURL(client, id), b, nil, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(actionURL(client, id), b, nil, &gophercloud.RequestOpts{
OkCodes: []int{202},
})
return
@@ -87,7 +87,7 @@ func Detach(client *gophercloud.ServiceClient, id string, opts DetachOptsBuilder
r.Err = err
return
}
- _, r.Err = client.Post(detachURL(client, id), b, nil, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(actionURL(client, id), b, nil, &gophercloud.RequestOpts{
OkCodes: []int{202},
})
return
@@ -96,7 +96,7 @@ func Detach(client *gophercloud.ServiceClient, id string, opts DetachOptsBuilder
// Reserve will reserve a volume based on volume ID.
func Reserve(client *gophercloud.ServiceClient, id string) (r ReserveResult) {
b := map[string]interface{}{"os-reserve": make(map[string]interface{})}
- _, r.Err = client.Post(reserveURL(client, id), b, nil, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(actionURL(client, id), b, nil, &gophercloud.RequestOpts{
OkCodes: []int{200, 201, 202},
})
return
@@ -105,7 +105,7 @@ func Reserve(client *gophercloud.ServiceClient, id string) (r ReserveResult) {
// Unreserve will unreserve a volume based on volume ID.
func Unreserve(client *gophercloud.ServiceClient, id string) (r UnreserveResult) {
b := map[string]interface{}{"os-unreserve": make(map[string]interface{})}
- _, r.Err = client.Post(unreserveURL(client, id), b, nil, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(actionURL(client, id), b, nil, &gophercloud.RequestOpts{
OkCodes: []int{200, 201, 202},
})
return
@@ -145,7 +145,7 @@ func InitializeConnection(client *gophercloud.ServiceClient, id string, opts Ini
r.Err = err
return
}
- _, r.Err = client.Post(initializeConnectionURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(actionURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 201, 202},
})
return
@@ -183,7 +183,7 @@ func TerminateConnection(client *gophercloud.ServiceClient, id string, opts Term
r.Err = err
return
}
- _, r.Err = client.Post(teminateConnectionURL(client, id), b, nil, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(actionURL(client, id), b, nil, &gophercloud.RequestOpts{
OkCodes: []int{202},
})
return
@@ -216,7 +216,7 @@ func ExtendSize(client *gophercloud.ServiceClient, id string, opts ExtendSizeOpt
r.Err = err
return
}
- _, r.Err = client.Post(extendSizeURL(client, id), b, nil, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(actionURL(client, id), b, nil, &gophercloud.RequestOpts{
OkCodes: []int{202},
})
return
@@ -256,8 +256,14 @@ func UploadImage(client *gophercloud.ServiceClient, id string, opts UploadImageO
r.Err = err
return
}
- _, r.Err = client.Post(uploadURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(actionURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{202},
})
return
}
+
+// ForceDelete will delete the volume regardless of state.
+func ForceDelete(client *gophercloud.ServiceClient, id string) (r ForceDeleteResult) {
+ _, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"os-force_delete": ""}, nil, nil)
+ return
+}
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions/results.go
index 9815f0c26ac..5cadd360f20 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions/results.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions/results.go
@@ -184,3 +184,8 @@ func (r UploadImageResult) Extract() (VolumeImage, error) {
err := r.ExtractInto(&s)
return s.VolumeImage, err
}
+
+// ForceDeleteResult contains the response body and error from a ForceDelete request.
+type ForceDeleteResult struct {
+ gophercloud.ErrResult
+}
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions/urls.go b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions/urls.go
index 5efd2b25c05..20486ed7194 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions/urls.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions/urls.go
@@ -2,38 +2,6 @@ package volumeactions
import "github.com/gophercloud/gophercloud"
-func attachURL(c *gophercloud.ServiceClient, id string) string {
+func actionURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL("volumes", id, "action")
}
-
-func beginDetachingURL(c *gophercloud.ServiceClient, id string) string {
- return attachURL(c, id)
-}
-
-func detachURL(c *gophercloud.ServiceClient, id string) string {
- return attachURL(c, id)
-}
-
-func uploadURL(c *gophercloud.ServiceClient, id string) string {
- return attachURL(c, id)
-}
-
-func reserveURL(c *gophercloud.ServiceClient, id string) string {
- return attachURL(c, id)
-}
-
-func unreserveURL(c *gophercloud.ServiceClient, id string) string {
- return attachURL(c, id)
-}
-
-func initializeConnectionURL(c *gophercloud.ServiceClient, id string) string {
- return attachURL(c, id)
-}
-
-func teminateConnectionURL(c *gophercloud.ServiceClient, id string) string {
- return attachURL(c, id)
-}
-
-func extendSizeURL(c *gophercloud.ServiceClient, id string) string {
- return attachURL(c, id)
-}
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/requests.go
index 18c9cb272ec..2ec10ad55ed 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/requests.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/requests.go
@@ -83,14 +83,21 @@ type ListOptsBuilder interface {
// ListOpts holds options for listing Volumes. It is passed to the volumes.List
// function.
type ListOpts struct {
- // admin-only option. Set it to true to see all tenant volumes.
+ // AllTenants will retrieve volumes of all tenants/projects.
AllTenants bool `q:"all_tenants"`
- // List only volumes that contain Metadata.
+
+ // Metadata will filter results based on specified metadata.
Metadata map[string]string `q:"metadata"`
- // List only volumes that have Name as the display name.
+
+ // Name will filter by the specified volume name.
Name string `q:"name"`
- // List only volumes that have a status of Status.
+
+ // Status will filter by the specified status.
Status string `q:"status"`
+
+ // TenantID will filter by a specific tenant/project ID.
+ // Setting AllTenants is required for this.
+ TenantID string `q:"project_id"`
}
// ToVolumeListQuery formats a ListOpts into a query string.
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes/requests.go
index 18c9cb272ec..43727409dd9 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes/requests.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes/requests.go
@@ -83,14 +83,34 @@ type ListOptsBuilder interface {
// ListOpts holds options for listing Volumes. It is passed to the volumes.List
// function.
type ListOpts struct {
- // admin-only option. Set it to true to see all tenant volumes.
+ // AllTenants will retrieve volumes of all tenants/projects.
AllTenants bool `q:"all_tenants"`
- // List only volumes that contain Metadata.
+
+ // Metadata will filter results based on specified metadata.
Metadata map[string]string `q:"metadata"`
- // List only volumes that have Name as the display name.
+
+ // Name will filter by the specified volume name.
Name string `q:"name"`
- // List only volumes that have a status of Status.
+
+ // Status will filter by the specified status.
Status string `q:"status"`
+
+ // TenantID will filter by a specific tenant/project ID.
+ // Setting AllTenants is required for this.
+ TenantID string `q:"project_id"`
+
+ // Comma-separated list of sort keys and optional sort directions in the
+ // form of [:].
+ Sort string `q:"sort"`
+
+ // Requests a page size of items.
+ Limit int `q:"limit"`
+
+ // Used in conjunction with limit to return a slice of items.
+ Offset int `q:"offset"`
+
+ // The ID of the last-seen item.
+ Marker string `q:"marker"`
}
// ToVolumeListQuery formats a ListOpts into a query string.
@@ -111,7 +131,7 @@ func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pa
}
return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
- return VolumePage{pagination.SinglePageBase(r)}
+ return VolumePage{pagination.LinkedPageBase{PageResult: r}}
})
}
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes/results.go
index 5ebe36a3385..87f71262c1d 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes/results.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes/results.go
@@ -101,7 +101,7 @@ func (r *Volume) UnmarshalJSON(b []byte) error {
// VolumePage is a pagination.pager that is returned from a call to the List function.
type VolumePage struct {
- pagination.SinglePageBase
+ pagination.LinkedPageBase
}
// IsEmpty returns true if a ListResult contains no Volumes.
@@ -110,6 +110,17 @@ func (r VolumePage) IsEmpty() (bool, error) {
return len(volumes) == 0, err
}
+func (page VolumePage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"volumes_links"`
+ }
+ err := page.ExtractInto(&s)
+ if err != nil {
+ return "", err
+ }
+ return gophercloud.ExtractNextURL(s.Links)
+}
+
// ExtractVolumes extracts and returns Volumes. It is used while iterating over a volumes.List call.
func ExtractVolumes(r pagination.Page) ([]Volume, error) {
var s []Volume
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/client.go b/vendor/github.com/gophercloud/gophercloud/openstack/client.go
index c796795b8ee..5a52e579148 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/client.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/client.go
@@ -56,11 +56,12 @@ func NewClient(endpoint string) (*gophercloud.ProviderClient, error) {
endpoint = gophercloud.NormalizeURL(endpoint)
base = gophercloud.NormalizeURL(base)
- return &gophercloud.ProviderClient{
- IdentityBase: base,
- IdentityEndpoint: endpoint,
- }, nil
+ p := new(gophercloud.ProviderClient)
+ p.IdentityBase = base
+ p.IdentityEndpoint = endpoint
+ p.UseTokenLock()
+ return p, nil
}
/*
@@ -158,9 +159,21 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
}
if options.AllowReauth {
+ // here we're creating a throw-away client (tac). it's a copy of the user's provider client, but
+ // with the token and reauth func zeroed out. combined with setting `AllowReauth` to `false`,
+ // this should retry authentication only once
+ tac := *client
+ tac.ReauthFunc = nil
+ tac.TokenID = ""
+ tao := options
+ tao.AllowReauth = false
client.ReauthFunc = func() error {
- client.TokenID = ""
- return v2auth(client, endpoint, options, eo)
+ err := v2auth(&tac, endpoint, tao, eo)
+ if err != nil {
+ return err
+ }
+ client.TokenID = tac.TokenID
+ return nil
}
}
client.TokenID = token.ID
@@ -202,9 +215,32 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au
client.TokenID = token.ID
if opts.CanReauth() {
+ // here we're creating a throw-away client (tac). it's a copy of the user's provider client, but
+ // with the token and reauth func zeroed out. combined with setting `AllowReauth` to `false`,
+ // this should retry authentication only once
+ tac := *client
+ tac.ReauthFunc = nil
+ tac.TokenID = ""
+ var tao tokens3.AuthOptionsBuilder
+ switch ot := opts.(type) {
+ case *gophercloud.AuthOptions:
+ o := *ot
+ o.AllowReauth = false
+ tao = &o
+ case *tokens3.AuthOptions:
+ o := *ot
+ o.AllowReauth = false
+ tao = &o
+ default:
+ tao = opts
+ }
client.ReauthFunc = func() error {
- client.TokenID = ""
- return v3auth(client, endpoint, opts, eo)
+ err := v3auth(&tac, endpoint, tao, eo)
+ if err != nil {
+ return err
+ }
+ client.TokenID = tac.TokenID
+ return nil
}
}
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/doc.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/doc.go
index a9960137117..3653122bf30 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/doc.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/doc.go
@@ -18,5 +18,35 @@ Example of Listing a Server's Interfaces
for _, interface := range allInterfaces {
fmt.Printf("%+v\n", interface)
}
+
+Example to Get a Server's Interface
+
+ portID = "0dde1598-b374-474e-986f-5b8dd1df1d4e"
+ serverID := "b07e7a3b-d951-4efc-a4f9-ac9f001afb7f"
+ interface, err := attachinterfaces.Get(computeClient, serverID, portID).Extract()
+ if err != nil {
+ panic(err)
+ }
+
+Example to Create a new Interface attachment on the Server
+
+ networkID := "8a5fe506-7e9f-4091-899b-96336909d93c"
+ serverID := "b07e7a3b-d951-4efc-a4f9-ac9f001afb7f"
+ attachOpts := attachinterfaces.CreateOpts{
+ NetworkID: networkID,
+ }
+ interface, err := attachinterfaces.Create(computeClient, serverID, attachOpts).Extract()
+ if err != nil {
+ panic(err)
+ }
+
+Example to Delete an Interface attachment from the Server
+
+ portID = "0dde1598-b374-474e-986f-5b8dd1df1d4e"
+ serverID := "b07e7a3b-d951-4efc-a4f9-ac9f001afb7f"
+ err := attachinterfaces.Delete(computeClient, serverID, portID).ExtractErr()
+ if err != nil {
+ panic(err)
+ }
*/
package attachinterfaces
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/requests.go
index faf2747246a..18dade837c1 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/requests.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/requests.go
@@ -11,3 +11,62 @@ func List(client *gophercloud.ServiceClient, serverID string) pagination.Pager {
return InterfacePage{pagination.SinglePageBase(r)}
})
}
+
+// Get requests details on a single interface attachment by the server and port IDs.
+func Get(client *gophercloud.ServiceClient, serverID, portID string) (r GetResult) {
+ _, r.Err = client.Get(getInterfaceURL(client, serverID, portID), &r.Body, &gophercloud.RequestOpts{
+ OkCodes: []int{200},
+ })
+ return
+}
+
+// CreateOptsBuilder allows extensions to add additional parameters to the
+// Create request.
+type CreateOptsBuilder interface {
+ ToAttachInterfacesCreateMap() (map[string]interface{}, error)
+}
+
+// CreateOpts specifies parameters of a new interface attachment.
+type CreateOpts struct {
+
+ // PortID is the ID of the port for which you want to create an interface.
+ // The NetworkID and PortID parameters are mutually exclusive.
+ // If you do not specify the PortID parameter, the OpenStack Networking API
+ // v2.0 allocates a port and creates an interface for it on the network.
+ PortID string `json:"port_id,omitempty"`
+
+ // NetworkID is the ID of the network for which you want to create an interface.
+ // The NetworkID and PortID parameters are mutually exclusive.
+ // If you do not specify the NetworkID parameter, the OpenStack Networking
+ // API v2.0 uses the network information cache that is associated with the instance.
+ NetworkID string `json:"net_id,omitempty"`
+
+ // Slice of FixedIPs. If you request a specific FixedIP address without a
+ // NetworkID, the request returns a Bad Request (400) response code.
+ FixedIPs []FixedIP `json:"fixed_ips,omitempty"`
+}
+
+// ToAttachInterfacesCreateMap constructs a request body from CreateOpts.
+func (opts CreateOpts) ToAttachInterfacesCreateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "interfaceAttachment")
+}
+
+// Create requests the creation of a new interface attachment on the server.
+func Create(client *gophercloud.ServiceClient, serverID string, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToAttachInterfacesCreateMap()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ _, r.Err = client.Post(createInterfaceURL(client, serverID), b, &r.Body, &gophercloud.RequestOpts{
+ OkCodes: []int{200},
+ })
+ return
+}
+
+// Delete makes a request against the nova API to detach a single interface from the server.
+// It needs server and port IDs to make a such request.
+func Delete(client *gophercloud.ServiceClient, serverID, portID string) (r DeleteResult) {
+ _, r.Err = client.Delete(deleteInterfaceURL(client, serverID, portID), nil)
+ return
+}
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/results.go
index e3987eaca84..a16fa14f759 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/results.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/results.go
@@ -1,9 +1,41 @@
package attachinterfaces
import (
+ "github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)
+type attachInterfaceResult struct {
+ gophercloud.Result
+}
+
+// Extract interprets any attachInterfaceResult as an Interface, if possible.
+func (r attachInterfaceResult) Extract() (*Interface, error) {
+ var s struct {
+ Interface *Interface `json:"interfaceAttachment"`
+ }
+ err := r.ExtractInto(&s)
+ return s.Interface, err
+}
+
+// GetResult is the response from a Get operation. Call its Extract
+// method to interpret it as an Interface.
+type GetResult struct {
+ attachInterfaceResult
+}
+
+// CreateResult is the response from a Create operation. Call its Extract
+// method to interpret it as an Interface.
+type CreateResult struct {
+ attachInterfaceResult
+}
+
+// DeleteResult is the response from a Delete operation. Call its ExtractErr
+// method to determine if the call succeeded or failed.
+type DeleteResult struct {
+ gophercloud.ErrResult
+}
+
// FixedIP represents a Fixed IP Address.
type FixedIP struct {
SubnetID string `json:"subnet_id"`
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/urls.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/urls.go
index 7d376f99bb5..50292e8b5a5 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/urls.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces/urls.go
@@ -5,3 +5,14 @@ import "github.com/gophercloud/gophercloud"
func listInterfaceURL(client *gophercloud.ServiceClient, serverID string) string {
return client.ServiceURL("servers", serverID, "os-interface")
}
+
+func getInterfaceURL(client *gophercloud.ServiceClient, serverID, portID string) string {
+ return client.ServiceURL("servers", serverID, "os-interface", portID)
+}
+
+func createInterfaceURL(client *gophercloud.ServiceClient, serverID string) string {
+ return client.ServiceURL("servers", serverID, "os-interface")
+}
+func deleteInterfaceURL(client *gophercloud.ServiceClient, serverID, portID string) string {
+ return client.ServiceURL("servers", serverID, "os-interface", portID)
+}
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/doc.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/doc.go
index a7bc15c3e5c..867d53a8190 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/doc.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/doc.go
@@ -59,5 +59,45 @@ Example to List Flavor Access
for _, access := range allAccesses {
fmt.Printf("%+v", access)
}
+
+Example to Grant Access to a Flavor
+
+ flavorID := "e91758d6-a54a-4778-ad72-0c73a1cb695b"
+
+ accessOpts := flavors.AddAccessOpts{
+ Tenant: "15153a0979884b59b0592248ef947921",
+ }
+
+ accessList, err := flavors.AddAccess(computeClient, flavor.ID, accessOpts).Extract()
+ if err != nil {
+ panic(err)
+ }
+
+Example to Create Extra Specs for a Flavor
+
+ flavorID := "e91758d6-a54a-4778-ad72-0c73a1cb695b"
+
+ createOpts := flavors.ExtraSpecsOpts{
+ "hw:cpu_policy": "CPU-POLICY",
+ "hw:cpu_thread_policy": "CPU-THREAD-POLICY",
+ }
+ createdExtraSpecs, err := flavors.CreateExtraSpecs(computeClient, flavorID, createOpts).Extract()
+ if err != nil {
+ panic(err)
+ }
+
+ fmt.Printf("%+v", createdExtraSpecs)
+
+Example to Get Extra Specs for a Flavor
+
+ flavorID := "e91758d6-a54a-4778-ad72-0c73a1cb695b"
+
+ extraSpecs, err := flavors.ListExtraSpecs(computeClient, flavorID).Extract()
+ if err != nil {
+ panic(err)
+ }
+
+ fmt.Printf("%+v", extraSpecs)
+
*/
package flavors
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/requests.go
index 6eb3678b2bd..965d271d1d3 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/requests.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/requests.go
@@ -162,6 +162,75 @@ func ListAccesses(client *gophercloud.ServiceClient, id string) pagination.Pager
})
}
+// AddAccessOptsBuilder allows extensions to add additional parameters to the
+// AddAccess requests.
+type AddAccessOptsBuilder interface {
+ ToAddAccessMap() (map[string]interface{}, error)
+}
+
+// AddAccessOpts represents options for adding access to a flavor.
+type AddAccessOpts struct {
+ // Tenant is the project/tenant ID to grant access.
+ Tenant string `json:"tenant"`
+}
+
+// ToAddAccessMap constructs a request body from AddAccessOpts.
+func (opts AddAccessOpts) ToAddAccessMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "addTenantAccess")
+}
+
+// AddAccess grants a tenant/project access to a flavor.
+func AddAccess(client *gophercloud.ServiceClient, id string, opts AddAccessOptsBuilder) (r AddAccessResult) {
+ b, err := opts.ToAddAccessMap()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ _, r.Err = client.Post(accessActionURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
+ OkCodes: []int{200},
+ })
+ return
+}
+
+// ExtraSpecs requests all the extra-specs for the given flavor ID.
+func ListExtraSpecs(client *gophercloud.ServiceClient, flavorID string) (r ListExtraSpecsResult) {
+ _, r.Err = client.Get(extraSpecsListURL(client, flavorID), &r.Body, nil)
+ return
+}
+
+func GetExtraSpec(client *gophercloud.ServiceClient, flavorID string, key string) (r GetExtraSpecResult) {
+ _, r.Err = client.Get(extraSpecsGetURL(client, flavorID, key), &r.Body, nil)
+ return
+}
+
+// CreateExtraSpecsOptsBuilder allows extensions to add additional parameters to the
+// CreateExtraSpecs requests.
+type CreateExtraSpecsOptsBuilder interface {
+ ToExtraSpecsCreateMap() (map[string]interface{}, error)
+}
+
+// ExtraSpecsOpts is a map that contains key-value pairs.
+type ExtraSpecsOpts map[string]string
+
+// ToExtraSpecsCreateMap assembles a body for a Create request based on the
+// contents of a ExtraSpecsOpts
+func (opts ExtraSpecsOpts) ToExtraSpecsCreateMap() (map[string]interface{}, error) {
+ return map[string]interface{}{"extra_specs": opts}, nil
+}
+
+// CreateExtraSpecs will create or update the extra-specs key-value pairs for the specified Flavor
+func CreateExtraSpecs(client *gophercloud.ServiceClient, flavorID string, opts CreateExtraSpecsOptsBuilder) (r CreateExtraSpecsResult) {
+ b, err := opts.ToExtraSpecsCreateMap()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ _, r.Err = client.Post(extraSpecsCreateURL(client, flavorID), b, &r.Body, &gophercloud.RequestOpts{
+ OkCodes: []int{200},
+ })
+ return
+}
+
// IDFromName is a convienience function that returns a flavor's ID given its
// name.
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go
index fb5c335b8ea..4451be38c92 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go
@@ -154,6 +154,26 @@ func ExtractAccesses(r pagination.Page) ([]FlavorAccess, error) {
return s.FlavorAccesses, err
}
+type accessResult struct {
+ gophercloud.Result
+}
+
+// AddAccessResult is the response of an AddAccess operations. Call its
+// Extract method to interpret it as a slice of FlavorAccess.
+type AddAccessResult struct {
+ accessResult
+}
+
+// Extract provides access to the result of an access create or delete.
+// The result will be all accesses that the flavor has.
+func (r accessResult) Extract() ([]FlavorAccess, error) {
+ var s struct {
+ FlavorAccesses []FlavorAccess `json:"flavor_access"`
+ }
+ err := r.ExtractInto(&s)
+ return s.FlavorAccesses, err
+}
+
// FlavorAccess represents an ACL of tenant access to a specific Flavor.
type FlavorAccess struct {
// FlavorID is the unique ID of the flavor.
@@ -162,3 +182,50 @@ type FlavorAccess struct {
// TenantID is the unique ID of the tenant.
TenantID string `json:"tenant_id"`
}
+
+// Extract interprets any extraSpecsResult as ExtraSpecs, if possible.
+func (r extraSpecsResult) Extract() (map[string]string, error) {
+ var s struct {
+ ExtraSpecs map[string]string `json:"extra_specs"`
+ }
+ err := r.ExtractInto(&s)
+ return s.ExtraSpecs, err
+}
+
+// extraSpecsResult contains the result of a call for (potentially) multiple
+// key-value pairs. Call its Extract method to interpret it as a
+// map[string]interface.
+type extraSpecsResult struct {
+ gophercloud.Result
+}
+
+// ListExtraSpecsResult contains the result of a Get operation. Call its Extract
+// method to interpret it as a map[string]interface.
+type ListExtraSpecsResult struct {
+ extraSpecsResult
+}
+
+// CreateExtraSpecResult contains the result of a Create operation. Call its
+// Extract method to interpret it as a map[string]interface.
+type CreateExtraSpecsResult struct {
+ extraSpecsResult
+}
+
+// extraSpecResult contains the result of a call for individual a single
+// key-value pair.
+type extraSpecResult struct {
+ gophercloud.Result
+}
+
+// GetExtraSpecResult contains the result of a Get operation. Call its Extract
+// method to interpret it as a map[string]interface.
+type GetExtraSpecResult struct {
+ extraSpecResult
+}
+
+// Extract interprets any extraSpecResult as an ExtraSpec, if possible.
+func (r extraSpecResult) Extract() (map[string]string, error) {
+ var s map[string]string
+ err := r.ExtractInto(&s)
+ return s, err
+}
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/urls.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/urls.go
index 04d33bf1279..b74f81625d8 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/urls.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/urls.go
@@ -23,3 +23,19 @@ func deleteURL(client *gophercloud.ServiceClient, id string) string {
func accessURL(client *gophercloud.ServiceClient, id string) string {
return client.ServiceURL("flavors", id, "os-flavor-access")
}
+
+func accessActionURL(client *gophercloud.ServiceClient, id string) string {
+ return client.ServiceURL("flavors", id, "action")
+}
+
+func extraSpecsListURL(client *gophercloud.ServiceClient, id string) string {
+ return client.ServiceURL("flavors", id, "os-extra_specs")
+}
+
+func extraSpecsGetURL(client *gophercloud.ServiceClient, id, key string) string {
+ return client.ServiceURL("flavors", id, "os-extra_specs", key)
+}
+
+func extraSpecsCreateURL(client *gophercloud.ServiceClient, id string) string {
+ return client.ServiceURL("flavors", id, "os-extra_specs")
+}
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/requests.go
index 6799d200b7a..fa346c8555f 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/requests.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/requests.go
@@ -49,11 +49,12 @@ type CreateOptsBuilder interface {
// CreateOpts contains all the values needed to create a new router. There are
// no required values.
type CreateOpts struct {
- Name string `json:"name,omitempty"`
- AdminStateUp *bool `json:"admin_state_up,omitempty"`
- Distributed *bool `json:"distributed,omitempty"`
- TenantID string `json:"tenant_id,omitempty"`
- GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
+ Name string `json:"name,omitempty"`
+ AdminStateUp *bool `json:"admin_state_up,omitempty"`
+ Distributed *bool `json:"distributed,omitempty"`
+ TenantID string `json:"tenant_id,omitempty"`
+ GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
+ AvailabilityZoneHints []string `json:"availability_zone_hints,omitempty"`
}
// ToRouterCreateMap builds a create request body from CreateOpts.
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/results.go
index e19c8e74c47..da1b9e4bdfa 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/results.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/results.go
@@ -60,6 +60,10 @@ type Router struct {
// Routes are a collection of static routes that the router will host.
Routes []Route `json:"routes"`
+
+ // Availability zone hints groups network nodes that run services like DHCP, L3, FW, and others.
+ // Used to make network resources highly available.
+ AvailabilityZoneHints []string `json:"availability_zone_hints"`
}
// RouterPage is the page returned by a pager when traversing over a
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/requests.go
index 5b61b247192..040f32183b4 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/requests.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/requests.go
@@ -66,10 +66,11 @@ type CreateOptsBuilder interface {
// CreateOpts represents options used to create a network.
type CreateOpts struct {
- AdminStateUp *bool `json:"admin_state_up,omitempty"`
- Name string `json:"name,omitempty"`
- Shared *bool `json:"shared,omitempty"`
- TenantID string `json:"tenant_id,omitempty"`
+ AdminStateUp *bool `json:"admin_state_up,omitempty"`
+ Name string `json:"name,omitempty"`
+ Shared *bool `json:"shared,omitempty"`
+ TenantID string `json:"tenant_id,omitempty"`
+ AvailabilityZoneHints []string `json:"availability_zone_hints,omitempty"`
}
// ToNetworkCreateMap builds a request body from CreateOpts.
diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/results.go
index ffd0259f1d2..c73f9e1a63f 100644
--- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/results.go
+++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/results.go
@@ -69,6 +69,10 @@ type Network struct {
// Specifies whether the network resource can be accessed by any tenant.
Shared bool `json:"shared"`
+
+ // Availability zone hints groups network nodes that run services like DHCP, L3, FW, and others.
+ // Used to make network resources highly available.
+ AvailabilityZoneHints []string `json:"availability_zone_hints"`
}
// NetworkPage is the page returned by a pager when traversing over a
diff --git a/vendor/github.com/gophercloud/gophercloud/provider_client.go b/vendor/github.com/gophercloud/gophercloud/provider_client.go
index 01b3010739a..72daeb0a3eb 100644
--- a/vendor/github.com/gophercloud/gophercloud/provider_client.go
+++ b/vendor/github.com/gophercloud/gophercloud/provider_client.go
@@ -7,6 +7,7 @@ import (
"io/ioutil"
"net/http"
"strings"
+ "sync"
)
// DefaultUserAgent is the default User-Agent string set in the request header.
@@ -51,6 +52,8 @@ type ProviderClient struct {
IdentityEndpoint string
// TokenID is the ID of the most recently issued valid token.
+ // NOTE: Aside from within a custom ReauthFunc, this field shouldn't be set by an application.
+ // To safely read or write this value, call `Token` or `SetToken`, respectively
TokenID string
// EndpointLocator describes how this provider discovers the endpoints for
@@ -68,16 +71,59 @@ type ProviderClient struct {
// authentication functions for different Identity service versions.
ReauthFunc func() error
- Debug bool
+ mut *sync.RWMutex
+
+ reauthmut *reauthlock
+}
+
+type reauthlock struct {
+ sync.RWMutex
+ reauthing bool
}
// AuthenticatedHeaders returns a map of HTTP headers that are common for all
// authenticated service requests.
-func (client *ProviderClient) AuthenticatedHeaders() map[string]string {
- if client.TokenID == "" {
- return map[string]string{}
+func (client *ProviderClient) AuthenticatedHeaders() (m map[string]string) {
+ if client.reauthmut != nil {
+ client.reauthmut.RLock()
+ if client.reauthmut.reauthing {
+ client.reauthmut.RUnlock()
+ return
+ }
+ client.reauthmut.RUnlock()
}
- return map[string]string{"X-Auth-Token": client.TokenID}
+ t := client.Token()
+ if t == "" {
+ return
+ }
+ return map[string]string{"X-Auth-Token": t}
+}
+
+// UseTokenLock creates a mutex that is used to allow safe concurrent access to the auth token.
+// If the application's ProviderClient is not used concurrently, this doesn't need to be called.
+func (client *ProviderClient) UseTokenLock() {
+ client.mut = new(sync.RWMutex)
+ client.reauthmut = new(reauthlock)
+}
+
+// Token safely reads the value of the auth token from the ProviderClient. Applications should
+// call this method to access the token instead of the TokenID field
+func (client *ProviderClient) Token() string {
+ if client.mut != nil {
+ client.mut.RLock()
+ defer client.mut.RUnlock()
+ }
+ return client.TokenID
+}
+
+// SetToken safely sets the value of the auth token in the ProviderClient. Applications may
+// use this method in a custom ReauthFunc
+func (client *ProviderClient) SetToken(t string) {
+ if client.mut != nil {
+ client.mut.Lock()
+ defer client.mut.Unlock()
+ }
+ client.TokenID = t
}
// RequestOpts customizes the behavior of the provider.Request() method.
@@ -166,6 +212,8 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts)
// Set connection parameter to close the connection immediately when we've got the response
req.Close = true
+ prereqtok := req.Header.Get("X-Auth-Token")
+
// Issue the request.
resp, err := client.HTTPClient.Do(req)
if err != nil {
@@ -189,9 +237,6 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts)
if !ok {
body, _ := ioutil.ReadAll(resp.Body)
resp.Body.Close()
- //pc := make([]uintptr, 1)
- //runtime.Callers(2, pc)
- //f := runtime.FuncForPC(pc[0])
respErr := ErrUnexpectedResponseCode{
URL: url,
Method: method,
@@ -199,7 +244,6 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts)
Actual: resp.StatusCode,
Body: body,
}
- //respErr.Function = "gophercloud.ProviderClient.Request"
errType := options.ErrorContext
switch resp.StatusCode {
@@ -210,7 +254,21 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts)
}
case http.StatusUnauthorized:
if client.ReauthFunc != nil {
- err = client.ReauthFunc()
+ if client.mut != nil {
+ client.mut.Lock()
+ client.reauthmut.Lock()
+ client.reauthmut.reauthing = true
+ client.reauthmut.Unlock()
+ if curtok := client.TokenID; curtok == prereqtok {
+ err = client.ReauthFunc()
+ }
+ client.reauthmut.Lock()
+ client.reauthmut.reauthing = false
+ client.reauthmut.Unlock()
+ client.mut.Unlock()
+ } else {
+ err = client.ReauthFunc()
+ }
if err != nil {
e := &ErrUnableToReauthenticate{}
e.ErrOriginal = respErr