From a93b44d00f6868e7117215da244e0f05f0e95fb5 Mon Sep 17 00:00:00 2001 From: Connor Doria <128822122+doriac11@users.noreply.github.com> Date: Tue, 22 Oct 2024 12:53:21 -0400 Subject: [PATCH] RCG Actions (#136) - Update RPO - Update Volume Access Mode - Update Name - Update to Inconsistent - Update to Consistent - Update to Activate - Update to Terminate --- inttests/replication_test.go | 75 ++++++++++++++++++++++++++++++- replication.go | 85 ++++++++++++++++++++++++++++++++++++ types/v1/replication.go | 33 ++++++++++++++ 3 files changed, 192 insertions(+), 1 deletion(-) diff --git a/inttests/replication_test.go b/inttests/replication_test.go index 5be1a68..a16fd1a 100644 --- a/inttests/replication_test.go +++ b/inttests/replication_test.go @@ -499,6 +499,67 @@ func TestExecuteResumeOnReplicationGroup(t *testing.T) { assert.Nil(t, err) } +// Test TestSetRPOOnReplicationGroup +func TestSetRPOOnReplicationGroup(t *testing.T) { + // Set the RCG context + TestGetReplicationConsistencyGroups(t) + // Update the RPO + err := rep.rcg.SetRPOOnReplicationGroup(siotypes.SetRPOReplicationConsistencyGroup{RpoInSeconds: "60"}) + assert.Nil(t, err) +} + +// Test TestSetTargetVolumeAccessModeOnReplicationGroup +func TestSetTargetVolumeAccessModeOnReplicationGroup(t *testing.T) { + // Set the RCG context + TestGetReplicationConsistencyGroups(t) + err := rep.rcg.SetTargetVolumeAccessModeOnReplicationGroup(siotypes.SetTargetVolumeAccessModeOnReplicationGroup{TargetVolumeAccessMode: "ReadOnly"}) + assert.Nil(t, err) +} + +// Test TestSetNewNameOnReplicationGroup +func TestSetNewNameOnReplicationGroup(t *testing.T) { + // Set the RCG context + TestGetReplicationConsistencyGroups(t) + err := rep.rcg.SetNewNameOnReplicationGroup(siotypes.SetNewNameOnReplicationGroup{NewName: "UpdatedNameRCG"}) + assert.Nil(t, err) + // Sleep for 10 to make sure the name is updated, then update it back to the original name + time.Sleep(10 * time.Second) + err = rep.rcg.SetNewNameOnReplicationGroup(siotypes.SetNewNameOnReplicationGroup{NewName: "inttestrcg"}) + assert.Nil(t, err) +} + +// Test TestExecuteInconsistentOnReplicationGroup +func TestExecuteInconsistentOnReplicationGroup(t *testing.T) { + // Set the RCG context + TestGetReplicationConsistencyGroups(t) + err := rep.rcg.ExecuteInconsistentOnReplicationGroup() + assert.Nil(t, err) +} + +// Test TestExecuteConsistentOnReplicationGroup +func TestExecuteConsistentOnReplicationGroup(t *testing.T) { + // Set the RCG context + TestGetReplicationConsistencyGroups(t) + err := rep.rcg.ExecuteConsistentOnReplicationGroup() + assert.Nil(t, err) +} + +// Test TestExecuteTerminateOnReplicationGroup +func TestExecuteTerminateOnReplicationGroup(t *testing.T) { + // Set the RCG context + TestGetReplicationConsistencyGroups(t) + err := rep.rcg.ExecuteTerminateOnReplicationGroup() + assert.Nil(t, err) +} + +// Test TestExecuteActivateOnReplicationGroup +func TestExecuteActivateOnReplicationGroup(t *testing.T) { + // Set the RCG context + TestGetReplicationConsistencyGroups(t) + err := rep.rcg.ExecuteActivateOnReplicationGroup() + assert.Nil(t, err) +} + // Test ResizeReplicationPair func TestResizeReplicationPair(t *testing.T) { if C2 == nil { @@ -600,12 +661,24 @@ func TestFreezeReplcationGroup(t *testing.T) { time.Sleep(2 * time.Second) } +// Test TestUnfreezeReplcationGroup +func TestUnfreezeReplcationGroup(t *testing.T) { + if C2 == nil { + t.Skip("no client connection to replication target system") + } + TestGetReplicationConsistencyGroups(t) + assert.NotNil(t, rep.rcg) + + err := rep.rcg.UnfreezeReplicationConsistencyGroup() + assert.Nil(t, err) +} + // Test RemoveReplicatonConsistencyGroup func TestRemoveReplicationConsistencyGroup(t *testing.T) { if C2 == nil { t.Skip("no client connection to replication target system") } - + TestGetReplicationConsistencyGroups(t) assert.NotNil(t, rep.rcg) err := rep.rcg.RemoveReplicationConsistencyGroup(false) diff --git a/replication.go b/replication.go index 968caf3..699edde 100644 --- a/replication.go +++ b/replication.go @@ -167,6 +167,17 @@ func (rcg *ReplicationConsistencyGroup) FreezeReplicationConsistencyGroup(id str return err } +// UnfreezeReplicationConsistencyGroup sets the ReplicationConsistencyGroup into a Unfreeze state +func (rcg *ReplicationConsistencyGroup) UnfreezeReplicationConsistencyGroup() error { + defer TimeSpent("UnfreezeReplicationConsistencyGroup", time.Now()) + + params := types.EmptyPayload{} + path := "/api/instances/ReplicationConsistencyGroup::" + rcg.ReplicationConsistencyGroup.ID + "/action/unfreezeApplyReplicationConsistencyGroup" + + err := rcg.client.getJSONWithRetry(http.MethodPost, path, params, nil) + return err +} + // CreateReplicationPair creates a ReplicationPair on the desired ReplicaitonConsistencyGroup func (c *Client) CreateReplicationPair(rp *types.QueryReplicationPair) (*types.ReplicationPair, error) { defer TimeSpent("CreateReplicationPair", time.Now()) @@ -369,6 +380,80 @@ func (rcg *ReplicationConsistencyGroup) ExecuteSyncOnReplicationGroup() (*types. return resp, err } +// SetRPOOnReplicationGroup on the ConsistencyGroup. +func (rcg *ReplicationConsistencyGroup) SetRPOOnReplicationGroup(param types.SetRPOReplicationConsistencyGroup) error { + defer TimeSpent("SetRPOOnReplicationGroup", time.Now()) + + uri := "/api/instances/ReplicationConsistencyGroup::" + rcg.ReplicationConsistencyGroup.ID + "/action/ModifyReplicationConsistencyGroupRpo" + + err := rcg.client.getJSONWithRetry(http.MethodPost, uri, param, nil) + return err +} + +// SetTargetVolumeAccessModeOnReplicationGroup on the ConsistencyGroup. +func (rcg *ReplicationConsistencyGroup) SetTargetVolumeAccessModeOnReplicationGroup(param types.SetTargetVolumeAccessModeOnReplicationGroup) error { + defer TimeSpent("SetTargetVolumeAccessModeOnReplicationGroup", time.Now()) + + uri := "/api/instances/ReplicationConsistencyGroup::" + rcg.ReplicationConsistencyGroup.ID + "/action/modifyReplicationConsistencyGroupTargetVolumeAccessMode" + + err := rcg.client.getJSONWithRetry(http.MethodPost, uri, param, nil) + return err +} + +// SetNewNameOnReplicationGroup on the ConsistencyGroup. +func (rcg *ReplicationConsistencyGroup) SetNewNameOnReplicationGroup(param types.SetNewNameOnReplicationGroup) error { + defer TimeSpent("SetNewNameOnReplicationGroup", time.Now()) + + uri := "/api/instances/ReplicationConsistencyGroup::" + rcg.ReplicationConsistencyGroup.ID + "/action/renameReplicationConsistencyGroup" + + err := rcg.client.getJSONWithRetry(http.MethodPost, uri, param, nil) + return err +} + +// ExecuteConsistentOnReplicationGroup on the ConsistencyGroup. +func (rcg *ReplicationConsistencyGroup) ExecuteConsistentOnReplicationGroup() error { + defer TimeSpent("ExecuteConsistentOnReplicationGroup", time.Now()) + + uri := "/api/instances/ReplicationConsistencyGroup::" + rcg.ReplicationConsistencyGroup.ID + "/action/setReplicationConsistencyGroupConsistent" + param := types.EmptyPayload{} + + err := rcg.client.getJSONWithRetry(http.MethodPost, uri, param, nil) + return err +} + +// ExecuteInconsistentOnReplicationGroup on the ConsistencyGroup. +func (rcg *ReplicationConsistencyGroup) ExecuteInconsistentOnReplicationGroup() error { + defer TimeSpent("ExecuteInconsistentOnReplicationGroup", time.Now()) + + uri := "/api/instances/ReplicationConsistencyGroup::" + rcg.ReplicationConsistencyGroup.ID + "/action/setReplicationConsistencyGroupInconsistent" + param := types.EmptyPayload{} + + err := rcg.client.getJSONWithRetry(http.MethodPost, uri, param, nil) + return err +} + +// ExecuteActivateOnReplicationGroup on the ConsistencyGroup. +func (rcg *ReplicationConsistencyGroup) ExecuteActivateOnReplicationGroup() error { + defer TimeSpent("ExecuteActivateOnReplicationGroup", time.Now()) + + uri := "/api/instances/ReplicationConsistencyGroup::" + rcg.ReplicationConsistencyGroup.ID + "/action/activateReplicationConsistencyGroup" + param := types.EmptyPayload{} + + err := rcg.client.getJSONWithRetry(http.MethodPost, uri, param, nil) + return err +} + +// ExecuteTerminateOnReplicationGroup on the ConsistencyGroup. +func (rcg *ReplicationConsistencyGroup) ExecuteTerminateOnReplicationGroup() error { + defer TimeSpent("ExecuteTerminateOnReplicationGroup", time.Now()) + + uri := "/api/instances/ReplicationConsistencyGroup::" + rcg.ReplicationConsistencyGroup.ID + "/action/terminateReplicationConsistencyGroup" + param := types.EmptyPayload{} + + err := rcg.client.getJSONWithRetry(http.MethodPost, uri, param, nil) + return err +} + // GetSyncStateOnReplicationGroup returns the sync status of the ReplicaitonConsistencyGroup. func (rcg *ReplicationConsistencyGroup) GetSyncStateOnReplicationGroup(syncKey string) error { defer TimeSpent("ExecuteSyncOnReplicationGroup", time.Now()) diff --git a/types/v1/replication.go b/types/v1/replication.go index 883782b..8a11f40 100644 --- a/types/v1/replication.go +++ b/types/v1/replication.go @@ -1,3 +1,21 @@ +/* + * + * Copyright © 2020-2024 Dell Inc. or its subsidiaries. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + package goscaleio // PauseMode states in which the ConsistencyGroup can be set to when Paused. @@ -14,6 +32,21 @@ type PauseReplicationConsistencyGroup struct { PauseMode string `json:"pauseMode"` } +// SetRPOReplicationConsistencyGroup defines struct for SetRPOReplicationConsistencyGroup. +type SetRPOReplicationConsistencyGroup struct { + RpoInSeconds string `json:"rpoInSeconds"` +} + +// SetTargetVolumeAccessModeOnReplicationGroup defines struct for SetTargetVolumeAccessModeOnReplicationGroup. +type SetTargetVolumeAccessModeOnReplicationGroup struct { + TargetVolumeAccessMode string `json:"targetVolumeAccessMode"` +} + +// SetNewNameOnReplicationGroup defines struct for SetNewNameOnReplicationGroup. +type SetNewNameOnReplicationGroup struct { + NewName string `json:"newName"` +} + // SynchronizationResponse defines struct for SynchronizationResponse. type SynchronizationResponse struct { SyncNowKey string `json:"syncNowKey"`