Skip to content

Commit

Permalink
[Feat.] CBR update and refactoring (#714)
Browse files Browse the repository at this point in the history
  • Loading branch information
anton-sidelnikov authored Sep 17, 2024
1 parent f87feed commit 6be3493
Show file tree
Hide file tree
Showing 35 changed files with 615 additions and 41 deletions.
91 changes: 87 additions & 4 deletions acceptance/openstack/cbr/v3/backups_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

func TestBackupLifecycle(t *testing.T) {
if os.Getenv("RUN_CBR") == "" {
t.Skip("unstable test")
t.Skip("too long to run in ci")
}
client, err := clients.NewCbrV3Client()
th.AssertNoErr(t, err)
Expand Down Expand Up @@ -51,9 +51,6 @@ func TestBackupLifecycle(t *testing.T) {
}

func TestBackupListing(t *testing.T) {
if os.Getenv("RUN_CBR") == "" {
t.Skip("unstable test")
}
client, err := clients.NewCbrV3Client()
th.AssertNoErr(t, err)

Expand Down Expand Up @@ -136,3 +133,89 @@ func TestBackupListing(t *testing.T) {
th.AssertNoErr(t, errBack)
th.AssertNoErr(t, waitForBackupDelete(client, 600, allBackups[0].ID))
}

func TestBackupSharingLifecycle(t *testing.T) {
if os.Getenv("RUN_CBR") == "" {
t.Skip("too long to run in ci")
}
destProjectID := os.Getenv("OS_PROJECT_ID_2")
if destProjectID == "" {
t.Skip("OS_PROJECT_ID_2 are mandatory for this test!")
}
client, err := clients.NewCbrV3Client()
th.AssertNoErr(t, err)

vault, aOpts, optsVault, checkp := CreateCBR(t, client)
th.AssertEquals(t, vault.ID, checkp.Vault.ID)
th.AssertEquals(t, optsVault.Parameters.Description, checkp.ExtraInfo.Description)
th.AssertEquals(t, optsVault.Parameters.Name, checkp.ExtraInfo.Name)
th.AssertEquals(t, aOpts.Resources[0].Type, checkp.Vault.Resources[0].Type)

checkpointGet, err := checkpoint.Get(client, checkp.ID)
th.AssertNoErr(t, err)
th.AssertEquals(t, "available", checkpointGet.Status)
th.AssertEquals(t, vault.ID, checkpointGet.Vault.ID)
th.AssertEquals(t, aOpts.Resources[0].Type, checkp.Vault.Resources[0].Type)

allBackups, err := backups.List(client, backups.ListOpts{VaultID: vault.ID})
th.AssertNoErr(t, err)
t.Cleanup(func() {
err = backups.Delete(client, allBackups[0].ID)
th.AssertNoErr(t, err)
th.AssertNoErr(t, waitForBackupDelete(client, 600, allBackups[0].ID))
})

member, err := backups.AddSharingMember(client, allBackups[0].ID, backups.MembersOpts{
Members: []string{destProjectID},
})
th.AssertNoErr(t, err)
th.AssertEquals(t, member[0].DestProjectId, destProjectID)

members, err := backups.ListSharingMembers(client, allBackups[0].ID, backups.ListMemberOpts{})
th.AssertNoErr(t, err)
th.AssertEquals(t, 1, len(members))

t.Cleanup(func() {
err = backups.DeleteSharingMember(client, allBackups[0].ID, destProjectID)
th.AssertNoErr(t, err)
})

newCloud := os.Getenv("OS_CLOUD_2")
if newCloud != "" {
err = os.Setenv("OS_CLOUD", newCloud)
th.AssertNoErr(t, err)
_, err := clients.EnvOS.Cloud(newCloud)
th.AssertNoErr(t, err)
newClient, err := clients.NewCbrV3Client()
th.AssertNoErr(t, err)

// Create Vault for further accept member
vault2Opts := vaults.CreateOpts{
Billing: &vaults.BillingCreate{
ConsistentLevel: "crash_consistent",
ObjectType: "disk",
ProtectType: "backup",
Size: 100,
},
Description: "gophertelemocloud testing vault",
Name: tools.RandomString("cbr-test-", 5),
Resources: []vaults.ResourceCreate{},
}
vault2, err := vaults.Create(client, vault2Opts)
th.AssertNoErr(t, err)
t.Cleanup(func() {
th.AssertNoErr(t, vaults.Delete(client, vault2.ID))
})

_, err = backups.UpdateSharingMember(newClient, destProjectID, backups.UpdateOpts{
BackupID: allBackups[0].ID,
Status: "accepted",
VaultId: vault2.ID,
})
th.AssertNoErr(t, err)

newShare, err := backups.GetSharingMember(client, allBackups[0].ID, destProjectID)
th.AssertNoErr(t, err)
th.AssertEquals(t, "accepted", newShare.Status)
}
}
66 changes: 66 additions & 0 deletions acceptance/openstack/cbr/v3/policies_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package v3

import (
"os"
"testing"

"github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients"
Expand Down Expand Up @@ -66,3 +67,68 @@ func TestPolicyLifecycle(t *testing.T) {
th.CheckEquals(t, updateOpts.Name, current.Name)

}

func TestPolicyReplicationLifecycle(t *testing.T) {
destProjectID := os.Getenv("OS_PROJECT_ID_2")
destRegionName := os.Getenv("OS_REGION_NAME_2")
if destProjectID == "" || destRegionName == "" {
t.Skip("OS_PROJECT_ID_2 and OS_REGION_NAME_2 are mandatory for this test!")
}
client, err := clients.NewCbrV3Client()
th.AssertNoErr(t, err)
iTrue := true
policy, err := policies.Create(client, policies.CreateOpts{
Name: "test-policy",
OperationDefinition: &policies.PolicyODCreate{
DailyBackups: 1,
WeekBackups: 2,
YearBackups: 3,
MonthBackups: 4,
MaxBackups: 10,
Timezone: "UTC+03:00",
DestinationProjectId: destProjectID,
DestinationRegion: destRegionName,
},
Trigger: &policies.Trigger{
Properties: policies.TriggerProperties{
Pattern: []string{"FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU;BYHOUR=14;BYMINUTE=00"},
},
},
Enabled: &iTrue,
OperationType: "replication",
})
th.AssertNoErr(t, err)

t.Cleanup(func() {
err = policies.Delete(client, policy.ID)
th.AssertNoErr(t, err)
})

allPolicies, err := policies.List(client, policies.ListOpts{})
th.AssertNoErr(t, err)
found := false
for _, p := range allPolicies {
if p.ID == policy.ID {
found = true
break
}
}
th.CheckEquals(t, true, found)

iFalse := false
updateOpts := policies.UpdateOpts{
Enabled: &iFalse,
Name: "name2",
}

updated, err := policies.Update(client, policy.ID, updateOpts)
th.AssertNoErr(t, err)
th.CheckEquals(t, *updateOpts.Enabled, updated.Enabled)
th.CheckEquals(t, updateOpts.Name, updated.Name)

current, err := policies.Get(client, policy.ID)
th.AssertNoErr(t, err)
th.CheckEquals(t, *updateOpts.Enabled, current.Enabled)
th.CheckEquals(t, updateOpts.Name, current.Name)

}
68 changes: 68 additions & 0 deletions acceptance/openstack/cbr/v3/vaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,71 @@ func TestVaultPolicy(t *testing.T) {
th.AssertEquals(t, vault.ID, unbind.VaultID)
th.AssertEquals(t, policy.ID, unbind.PolicyID)
}

func TestVaultMigrateResources(t *testing.T) {
client, err := clients.NewCbrV3Client()
th.AssertNoErr(t, err)

opts := vaults.CreateOpts{
Billing: &vaults.BillingCreate{
ConsistentLevel: "crash_consistent",
ObjectType: "disk",
ProtectType: "backup",
Size: 100,
},
Description: "gophertelemocloud testing vault",
Name: tools.RandomString("cbr-test-", 5),
Resources: []vaults.ResourceCreate{},
}
vault, err := vaults.Create(client, opts)
th.AssertNoErr(t, err)

t.Cleanup(func() {
th.AssertNoErr(t, vaults.Delete(client, vault.ID))
})

optsM := vaults.CreateOpts{
Billing: &vaults.BillingCreate{
ConsistentLevel: "crash_consistent",
ObjectType: "disk",
ProtectType: "backup",
Size: 100,
},
Description: "gophertelemocloud testing vault",
Name: tools.RandomString("cbr-test-migrate", 5),
Resources: []vaults.ResourceCreate{},
}
vaultM, err := vaults.Create(client, optsM)
th.AssertNoErr(t, err)

t.Cleanup(func() {
th.AssertNoErr(t, vaults.Delete(client, vaultM.ID))
})

resourceType := "OS::Cinder::Volume"
volume := openstack.CreateVolume(t)
t.Cleanup(func() {
openstack.DeleteVolume(t, volume.ID)
})

aOpts := vaults.AssociateResourcesOpts{
Resources: []vaults.ResourceCreate{
{
ID: volume.ID,
Type: resourceType,
Name: "cbr-vault-test-volume",
},
},
}
associated, err := vaults.AssociateResources(client, vault.ID, aOpts)
th.AssertNoErr(t, err)
th.AssertEquals(t, 1, len(associated))
th.AssertEquals(t, volume.ID, associated[0])

migrate, err := vaults.MigrateResources(client, vault.ID, vaults.MigrateOpts{
DestinationVaultId: vaultM.ID,
ResourceIds: associated,
})
th.AssertNoErr(t, err)
th.AssertEquals(t, 1, len(migrate))
}
49 changes: 49 additions & 0 deletions openstack/cbr/v3/backups/AddSharingMember.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package backups

import (
"github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/build"
"github.com/opentelekomcloud/gophertelekomcloud/internal/extract"
)

type MembersOpts struct {
// Project IDs of the backup share members to be added
Members []string `json:"members" required:"true"`
}

func AddSharingMember(client *golangsdk.ServiceClient, backupID string, opts MembersOpts) ([]Members, error) {
b, err := build.RequestBody(opts, "")
if err != nil {
return nil, err
}

// POST /v3/{project_id}/backups/{backup_id}/members
raw, err := client.Post(client.ServiceURL("backups", backupID, "members"), b, nil, &golangsdk.RequestOpts{
OkCodes: []int{200},
})
if err != nil {
return nil, err
}
var res []Members
err = extract.IntoSlicePtr(raw.Body, &res, "members")
return res, err
}

type Members struct {
// Backup sharing status
Status string `json:"status"`
// Backup sharing time
CreatedAt string `json:"created_at"`
// Update time
UpdatedAt string `json:"updated_at"`
// Backup ID
BackupId string `json:"backup_id"`
// ID of the image created by using the accepted shared backup
ImageId string `json:"image_id"`
// ID of the project with which the backup is shared
DestProjectId string `json:"dest_project_id"`
// Replication record ID
VaultId string `json:"vault_id"`
// ID of the shared record
ID string `json:"id"`
}
File renamed without changes.
8 changes: 8 additions & 0 deletions openstack/cbr/v3/backups/DeleteSharingMember.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package backups

import "github.com/opentelekomcloud/gophertelekomcloud"

func DeleteSharingMember(client *golangsdk.ServiceClient, id, memberID string) (err error) {
_, err = client.Delete(client.ServiceURL("backups", id, "members", memberID), nil)
return
}
File renamed without changes.
17 changes: 17 additions & 0 deletions openstack/cbr/v3/backups/GetMember.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package backups

import (
"github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/extract"
)

func GetSharingMember(client *golangsdk.ServiceClient, id, memberID string) (*Member, error) {
raw, err := client.Get(client.ServiceURL("backups", id, "members", memberID), nil, nil)
if err != nil {
return nil, err
}

var res Member
err = extract.IntoStructPtr(raw.Body, &res, "member")
return &res, err
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,27 @@ import (
// the API. Filtering is achieved by passing in struct field values that map to
// the flavor attributes you want to see returned.
type ListOpts struct {
ID string
CheckpointID string `q:"checkpoint_id"`
ImageType string `q:"image_type"`
Limit string `q:"limit"`
Marker string `q:"marker"`
Name string `q:"name"`
Offset string `q:"offset"`
ParentID string `q:"parent_id"`
ResourceAZ string `q:"resource_az"`
ResourceID string `q:"resource_id"`
ResourceName string `q:"resource_name"`
ResourceType string `q:"resource_type"`
Sort string `q:"sort"`
Status string `q:"status"`
VaultID string `q:"vault_id"`
ID string
CheckpointID string `q:"checkpoint_id"`
DedicatedCloud bool `q:"dec"`
EndTime string `q:"end_time"`
ImageType string `q:"image_type"`
Limit string `q:"limit"`
Marker string `q:"marker"`
MemberStatus string `q:"member_status"`
Name string `q:"name"`
Offset string `q:"offset"`
OwningType string `q:"own_type"`
ParentID string `q:"parent_id"`
ResourceAZ string `q:"resource_az"`
ResourceID string `q:"resource_id"`
ResourceName string `q:"resource_name"`
ResourceType string `q:"resource_type"`
Sort string `q:"sort"`
StartTime string `q:"start_time"`
Status string `q:"status"`
UsedPercent string `q:"used_percent"`
VaultID string `q:"vault_id"`
}

func List(client *golangsdk.ServiceClient, opts ListOpts) ([]Backup, error) {
Expand Down
Loading

0 comments on commit 6be3493

Please sign in to comment.