Skip to content

Commit

Permalink
[manila]: add reset and force delete actions to a snapshot
Browse files Browse the repository at this point in the history
  • Loading branch information
kayrus committed Aug 2, 2023
1 parent b94e2f7 commit bf9a309
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 7 deletions.
15 changes: 8 additions & 7 deletions acceptance/openstack/sharedfilesystems/v2/replicas_test.go
Expand Up @@ -13,8 +13,9 @@ import (
th "github.com/gophercloud/gophercloud/testhelper"
)

// 2.56 is required for a /v2/replicas/XXX URL support
// otherwise we need to set "X-OpenStack-Manila-API-Experimental: true"
const replicasMicroversion = "2.60"
const replicasPathMicroversion = "2.56"

func TestReplicaCreate(t *testing.T) {
clients.RequireManilaReplicas(t)
Expand All @@ -23,7 +24,7 @@ func TestReplicaCreate(t *testing.T) {
if err != nil {
t.Fatalf("Unable to create a shared file system client: %v", err)
}
client.Microversion = replicasMicroversion
client.Microversion = replicasPathMicroversion

share, err := CreateShare(t, client)
if err != nil {
Expand Down Expand Up @@ -60,7 +61,7 @@ func TestReplicaPromote(t *testing.T) {
if err != nil {
t.Fatalf("Unable to create a shared file system client: %v", err)
}
client.Microversion = replicasMicroversion
client.Microversion = replicasPathMicroversion

share, err := CreateShare(t, client)
if err != nil {
Expand Down Expand Up @@ -136,7 +137,7 @@ func TestReplicaExportLocations(t *testing.T) {
if err != nil {
t.Fatalf("Unable to create a shared file system client: %v", err)
}
client.Microversion = replicasMicroversion
client.Microversion = replicasPathMicroversion

share, err := CreateShare(t, client)
if err != nil {
Expand Down Expand Up @@ -203,7 +204,7 @@ func TestReplicaListDetail(t *testing.T) {
if err != nil {
t.Fatalf("Unable to create a shared file system client: %v", err)
}
client.Microversion = replicasMicroversion
client.Microversion = replicasPathMicroversion

share, err := CreateShare(t, client)
if err != nil {
Expand Down Expand Up @@ -236,7 +237,7 @@ func TestReplicaResetStatus(t *testing.T) {
if err != nil {
t.Fatalf("Unable to create a shared file system client: %v", err)
}
client.Microversion = replicasMicroversion
client.Microversion = replicasPathMicroversion

share, err := CreateShare(t, client)
if err != nil {
Expand Down Expand Up @@ -278,7 +279,7 @@ func TestReplicaForceDelete(t *testing.T) {
if err != nil {
t.Fatalf("Unable to create a shared file system client: %v", err)
}
client.Microversion = replicasMicroversion
client.Microversion = replicasPathMicroversion

share, err := CreateShare(t, client)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions acceptance/openstack/sharedfilesystems/v2/snapshots.go
Expand Up @@ -54,6 +54,9 @@ func ListSnapshots(t *testing.T, client *gophercloud.ServiceClient) ([]snapshots
func DeleteSnapshot(t *testing.T, client *gophercloud.ServiceClient, snapshot *snapshots.Snapshot) {
err := snapshots.Delete(client, snapshot.ID).ExtractErr()
if err != nil {
if _, ok := err.(gophercloud.ErrDefault404); ok {
return
}
t.Errorf("Unable to delete snapshot %s: %v", snapshot.ID, err)
}

Expand Down
75 changes: 75 additions & 0 deletions acceptance/openstack/sharedfilesystems/v2/snapshots_test.go
Expand Up @@ -12,6 +12,10 @@ import (
th "github.com/gophercloud/gophercloud/testhelper"
)

// 2.7 is required for a /v2/snapshots/XXX/action URL support
// otherwise we need to set "X-OpenStack-Manila-API-Experimental: true"
const snapshotsPathMicroversion = "2.7"

func TestSnapshotCreate(t *testing.T) {
client, err := clients.NewSharedFileSystemV2Client()
if err != nil {
Expand Down Expand Up @@ -119,3 +123,74 @@ func TestSnapshotListDetail(t *testing.T) {
tools.PrintResource(t, &ss[i])
}
}

func TestSnapshotResetStatus(t *testing.T) {
client, err := clients.NewSharedFileSystemV2Client()
if err != nil {
t.Fatalf("Unable to create a shared file system client: %v", err)
}
client.Microversion = snapshotsPathMicroversion

share, err := CreateShare(t, client)
if err != nil {
t.Fatalf("Unable to create a share: %v", err)
}

defer DeleteShare(t, client, share)

snapshot, err := CreateSnapshot(t, client, share.ID)
if err != nil {
t.Fatalf("Unable to create a snapshot: %v", err)
}

defer DeleteSnapshot(t, client, snapshot)

resetStatusOpts := &snapshots.ResetStatusOpts{
Status: "error",
}
err = snapshots.ResetStatus(client, snapshot.ID, resetStatusOpts).ExtractErr()
if err != nil {
t.Fatalf("Unable to reset a snapshot status: %v", err)
}

err = waitForSnapshotStatus(t, client, snapshot.ID, "error")
if err != nil {
t.Fatalf("Snapshot status error: %v", err)
}

t.Logf("Snapshot %s status successfuly reset", snapshot.ID)
}

func TestSnapshotForceDelete(t *testing.T) {
client, err := clients.NewSharedFileSystemV2Client()
if err != nil {
t.Fatalf("Unable to create a shared file system client: %v", err)
}
client.Microversion = snapshotsPathMicroversion

share, err := CreateShare(t, client)
if err != nil {
t.Fatalf("Unable to create a share: %v", err)
}

defer DeleteShare(t, client, share)

snapshot, err := CreateSnapshot(t, client, share.ID)
if err != nil {
t.Fatalf("Unable to create a snapshot: %v", err)
}

defer DeleteSnapshot(t, client, snapshot)

err = snapshots.ForceDelete(client, snapshot.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to force delete a snapshot: %v", err)
}

err = waitForSnapshotStatus(t, client, snapshot.ID, "deleted")
if err != nil {
t.Fatalf("Snapshot status error: %v", err)
}

t.Logf("Snapshot %s was successfuly deleted", snapshot.ID)
}
51 changes: 51 additions & 0 deletions openstack/sharedfilesystems/v2/snapshots/requests.go
Expand Up @@ -163,3 +163,54 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}

// ResetStatusOptsBuilder allows extensions to add additional parameters to the
// ResetStatus request.
type ResetStatusOptsBuilder interface {
ToSnapshotResetStatusMap() (map[string]interface{}, error)
}

// ResetStatusOpts contains options for resetting a Snapshot status.
// For more information about these parameters, please, refer to the shared file systems API v2,
// Snapshot Actions, ResetStatus share documentation.
type ResetStatusOpts struct {
// Status is a snapshot status to reset to. Can be "available", "error",
// "creating", "deleting", "manage_starting", "manage_error",
// "unmanage_starting", "unmanage_error" or "error_deleting".
Status string `json:"status"`
}

// ToSnapshotResetStatusMap assembles a request body based on the contents of a
// ResetStatusOpts.
func (opts ResetStatusOpts) ToSnapshotResetStatusMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "reset_status")
}

// ResetStatus will reset the existing snapshot status. ResetStatusResult contains only the error.
// To extract it, call the ExtractErr method on the ResetStatusResult.
func ResetStatus(client *gophercloud.ServiceClient, id string, opts ResetStatusOptsBuilder) (r ResetStatusResult) {
b, err := opts.ToSnapshotResetStatusMap()
if err != nil {
r.Err = err
return
}

resp, err := client.Post(resetStatusURL(client, id), b, nil, &gophercloud.RequestOpts{
OkCodes: []int{202},
})
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}

// ForceDelete will delete the existing snapshot in any state. ForceDeleteResult contains only the error.
// To extract it, call the ExtractErr method on the ForceDeleteResult.
func ForceDelete(client *gophercloud.ServiceClient, id string) (r ForceDeleteResult) {
b := map[string]interface{}{
"force_delete": nil,
}
resp, err := client.Post(forceDeleteURL(client, id), b, nil, &gophercloud.RequestOpts{
OkCodes: []int{202},
})
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}
10 changes: 10 additions & 0 deletions openstack/sharedfilesystems/v2/snapshots/results.go
Expand Up @@ -173,3 +173,13 @@ type GetResult struct {
type UpdateResult struct {
commonResult
}

// ResetStatusResult contains the response error from an ResetStatus request.
type ResetStatusResult struct {
gophercloud.ErrResult
}

// ForceDeleteResult contains the response error from an ForceDelete request.
type ForceDeleteResult struct {
gophercloud.ErrResult
}
36 changes: 36 additions & 0 deletions openstack/sharedfilesystems/v2/snapshots/testing/fixtures.go
Expand Up @@ -204,3 +204,39 @@ func MockListDetailResponse(t *testing.T) {
}
})
}

var resetStatusRequest = `{
"reset_status": {
"status": "error"
}
}`

// MockResetStatusResponse creates a mock reset status snapshot response
func MockResetStatusResponse(t *testing.T) {
th.Mux.HandleFunc(snapshotEndpoint+"/"+snapshotID+"/action", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "POST")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
th.TestHeader(t, r, "Content-Type", "application/json")
th.TestHeader(t, r, "Accept", "application/json")
th.TestJSONRequest(t, r, resetStatusRequest)
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusAccepted)
})
}

var forceDeleteRequest = `{
"force_delete": null
}`

// MockForceDeleteResponse creates a mock force delete snapshot response
func MockForceDeleteResponse(t *testing.T) {
th.Mux.HandleFunc(snapshotEndpoint+"/"+snapshotID+"/action", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "POST")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
th.TestHeader(t, r, "Content-Type", "application/json")
th.TestHeader(t, r, "Accept", "application/json")
th.TestJSONRequest(t, r, forceDeleteRequest)
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusAccepted)
})
}
24 changes: 24 additions & 0 deletions openstack/sharedfilesystems/v2/snapshots/testing/request_test.go
Expand Up @@ -125,3 +125,27 @@ func TestListDetail(t *testing.T) {
},
})
}

func TestResetStatusSuccess(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()

MockResetStatusResponse(t)

c := client.ServiceClient()

err := snapshots.ResetStatus(c, snapshotID, &snapshots.ResetStatusOpts{Status: "error"}).ExtractErr()
th.AssertNoErr(t, err)
}

func TestForceDeleteSuccess(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()

MockForceDeleteResponse(t)

c := client.ServiceClient()

err := snapshots.ForceDelete(c, snapshotID).ExtractErr()
th.AssertNoErr(t, err)
}
8 changes: 8 additions & 0 deletions openstack/sharedfilesystems/v2/snapshots/urls.go
Expand Up @@ -21,3 +21,11 @@ func getURL(c *gophercloud.ServiceClient, id string) string {
func updateURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL("snapshots", id)
}

func resetStatusURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL("snapshots", id, "action")
}

func forceDeleteURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL("snapshots", id, "action")
}

0 comments on commit bf9a309

Please sign in to comment.