Added support for a server action to create a server image / snapshot
diff --git a/openstack/compute/v2/servers/fixtures.go b/openstack/compute/v2/servers/fixtures.go
index e47bc0e..4339a16 100644
--- a/openstack/compute/v2/servers/fixtures.go
+++ b/openstack/compute/v2/servers/fixtures.go
@@ -651,3 +651,14 @@
}`)
})
}
+
+// HandleCreateServerImageSuccessfully sets up the test server to respond to a TestCreateServerImage request.
+func HandleCreateServerImageSuccessfully(t *testing.T) {
+ th.Mux.HandleFunc("/servers/serverimage/action", func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "POST")
+ th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
+ w.Header().Add("Location", "https://0.0.0.0/images/xxxx-xxxxx-xxxxx-xxxx")
+ w.WriteHeader(http.StatusAccepted)
+ })
+}
+
diff --git a/openstack/compute/v2/servers/requests.go b/openstack/compute/v2/servers/requests.go
index e0950e4..caeb946 100644
--- a/openstack/compute/v2/servers/requests.go
+++ b/openstack/compute/v2/servers/requests.go
@@ -4,6 +4,7 @@
"encoding/base64"
"errors"
"fmt"
+ "strings"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
@@ -14,7 +15,6 @@
type ListOptsBuilder interface {
ToServerListQuery() (string, error)
}
-
// ListOpts allows the filtering and sorting of paginated collections through
// the API. Filtering is achieved by passing in struct field values that map to
// the server attributes you want to see returned. Marker and Limit are used
@@ -701,3 +701,68 @@
}
return pagination.NewPager(client, listAddressesByNetworkURL(client, id, network), createPageFn)
}
+
+type CreateServerImageOpts struct {
+ // Name [required] of the image/snapshot
+ Name string
+ // Metadata [optional] contains key-value pairs (up to 255 bytes each) to attach to the created image.
+ Metadata map[string]string
+}
+
+type CreateServerImageOptsBuilder interface {
+ ToCreateServerImageMap() (map[string]interface{}, error)
+}
+
+// ToServerImageCreateMap formats an ServerImageCreateOpts structure into a request body.
+func (opts CreateServerImageOpts) ToCreateServerImageMap() (map[string]interface{}, error) {
+ var err error
+ img := make(map[string]interface{})
+ if opts.Name == "" {
+ err = fmt.Errorf("Cannot create a server image without a name")
+ }
+ img["name"] = opts.Name
+ if opts.Metadata != nil {
+ img["metadata"] = opts.Metadata
+ }
+ createImage := make(map[string]interface{})
+ createImage["createImage"] = img
+ return createImage, err
+}
+
+// ExtractImageID gets the ID of the newly created server image from the header
+func (res CreateServerImageResult) ExtractImageID() (string, error) {
+ var err error
+ if res.Err != nil {
+ return "", res.Err
+ }
+ // Get the image id from the header
+ rawUrl := res.Header.Get("Location")
+ fmt.Println("RawUrl:", rawUrl)
+ if rawUrl != "" {
+ split := strings.Split(rawUrl, "/")
+ if len(split) > 0 {
+ id := split[len(split)-1]
+ return id, nil
+ }
+ }
+ err = fmt.Errorf("Failed to parse the ID of newly created image")
+ return "", err
+}
+
+// CreateServerImage makes a request against the nova API to schedule an image to be created of the server
+func CreateServerImage(client *gophercloud.ServiceClient, serverId string, opts CreateServerImageOptsBuilder) CreateServerImageResult {
+ var res CreateServerImageResult
+ reqBody, err := opts.ToCreateServerImageMap()
+ if err != nil {
+ res.Err = err
+ return res
+ }
+ response, err := client.Post(actionURL(client, serverId), reqBody, nil, &gophercloud.RequestOpts{
+ OkCodes: []int{202},
+ })
+ res.Err = err
+ if err == nil {
+ res.Header = response.Header
+ }
+ return res
+}
diff --git a/openstack/compute/v2/servers/requests_test.go b/openstack/compute/v2/servers/requests_test.go
index 62b89e0..466bbf7 100644
--- a/openstack/compute/v2/servers/requests_test.go
+++ b/openstack/compute/v2/servers/requests_test.go
@@ -325,3 +325,13 @@
th.AssertNoErr(t, err)
th.CheckEquals(t, 1, pages)
}
+
+func TestCreateServerImage(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+ HandleCreateServerImageSuccessfully(t)
+
+ _, err := CreateServerImage(client.ServiceClient(), "serverimage", CreateServerImageOpts{Name: "test"}).ExtractImageID()
+ th.AssertNoErr(t, err)
+
+}
diff --git a/openstack/compute/v2/servers/results.go b/openstack/compute/v2/servers/results.go
index e2be6ba..26e099a 100644
--- a/openstack/compute/v2/servers/results.go
+++ b/openstack/compute/v2/servers/results.go
@@ -74,6 +74,11 @@
ActionResult
}
+// RescueResult represents the result of a server rescue operation
+type CreateServerImageResult struct {
+ gophercloud.Result
+}
+
// Extract interprets any RescueResult as an AdminPass, if possible.
func (r RescueResult) Extract() (string, error) {
if r.Err != nil {