diff --git a/clients/instance/ibm-pi-volume-group.go b/clients/instance/ibm-pi-volume-group.go new file mode 100644 index 00000000..164b3ff6 --- /dev/null +++ b/clients/instance/ibm-pi-volume-group.go @@ -0,0 +1,174 @@ +package instance + +import ( + "context" + "fmt" + + "github.com/IBM-Cloud/power-go-client/errors" + "github.com/IBM-Cloud/power-go-client/helpers" + "github.com/IBM-Cloud/power-go-client/ibmpisession" + "github.com/IBM-Cloud/power-go-client/power/client/p_cloud_volume_groups" + "github.com/IBM-Cloud/power-go-client/power/models" +) + +// IBMPIVolumeGroupClient +type IBMPIVolumeGroupClient struct { + IBMPIClient +} + +// NewIBMPIVolumeGroupClient +func NewIBMPIVolumeGroupClient(ctx context.Context, sess *ibmpisession.IBMPISession, cloudInstanceID string) *IBMPIVolumeGroupClient { + return &IBMPIVolumeGroupClient{ + *NewIBMPIClient(ctx, sess, cloudInstanceID), + } +} + +// Get a Volume-Group +func (f *IBMPIVolumeGroupClient) Get(id string) (*models.VolumeGroup, error) { + params := p_cloud_volume_groups.NewPcloudVolumegroupsGetParams(). + WithContext(f.ctx).WithTimeout(helpers.PIGetTimeOut). + WithCloudInstanceID(f.cloudInstanceID).WithVolumeGroupID(id) + resp, err := f.session.Power.PCloudVolumeGroups.PcloudVolumegroupsGet(params, f.session.AuthInfo(f.cloudInstanceID)) + if err != nil { + return nil, fmt.Errorf(errors.GetVolumeGroupOperationFailed, id, f.cloudInstanceID, err) + } + if resp == nil || resp.Payload == nil { + return nil, fmt.Errorf("failed to get volume-group %s", id) + } + return resp.Payload, nil +} + +// GetAll Volume-Group +func (f *IBMPIVolumeGroupClient) GetAll() (*models.VolumeGroups, error) { + params := p_cloud_volume_groups.NewPcloudVolumegroupsGetallParams(). + WithContext(f.ctx).WithTimeout(helpers.PIGetTimeOut). + WithCloudInstanceID(f.cloudInstanceID) + resp, err := f.session.Power.PCloudVolumeGroups.PcloudVolumegroupsGetall(params, f.session.AuthInfo(f.cloudInstanceID)) + if err != nil { + return nil, fmt.Errorf("failed to Get all volume-groups for Cloud Instance %s: %w", f.cloudInstanceID, err) + } + if resp == nil || resp.Payload == nil { + return nil, fmt.Errorf("failed to Get all volume-groups for Cloud Instance %s", f.cloudInstanceID) + } + return resp.Payload, nil +} + +// Get a Volume-Group with Details +func (f *IBMPIVolumeGroupClient) GetDetails(id string) (*models.VolumeGroupDetails, error) { + params := p_cloud_volume_groups.NewPcloudVolumegroupsGetDetailsParams(). + WithContext(f.ctx).WithTimeout(helpers.PIGetTimeOut). + WithCloudInstanceID(f.cloudInstanceID).WithVolumeGroupID(id) + resp, err := f.session.Power.PCloudVolumeGroups.PcloudVolumegroupsGetDetails(params, f.session.AuthInfo(f.cloudInstanceID)) + if err != nil { + return nil, fmt.Errorf(errors.GetVolumeGroupDetailsOperationFailed, id, f.cloudInstanceID, err) + } + if resp == nil || resp.Payload == nil { + return nil, fmt.Errorf("failed to get volume-group %s details", id) + } + return resp.Payload, nil +} + +// GetAll Volume-Group with Details +func (f *IBMPIVolumeGroupClient) GetAllDetails() (*models.VolumeGroupsDetails, error) { + params := p_cloud_volume_groups.NewPcloudVolumegroupsGetallDetailsParams(). + WithContext(f.ctx).WithTimeout(helpers.PIGetTimeOut). + WithCloudInstanceID(f.cloudInstanceID) + resp, err := f.session.Power.PCloudVolumeGroups.PcloudVolumegroupsGetallDetails(params, f.session.AuthInfo(f.cloudInstanceID)) + if err != nil { + return nil, fmt.Errorf("failed to Get all volume-groups details for Cloud Instance %s: %w", f.cloudInstanceID, err) + } + if resp == nil || resp.Payload == nil { + return nil, fmt.Errorf("failed to Get all volume-groups details for Cloud Instance %s", f.cloudInstanceID) + } + return resp.Payload, nil +} + +// Create a Volume Group +func (f *IBMPIVolumeGroupClient) CreateVolumeGroup(body *models.VolumeGroupCreate) (*models.VolumeGroupCreateResponse, error) { + params := p_cloud_volume_groups.NewPcloudVolumegroupsPostParams(). + WithContext(f.ctx).WithTimeout(helpers.PICreateTimeOut). + WithCloudInstanceID(f.cloudInstanceID).WithBody(body) + respOk, respPartial, err := f.session.Power.PCloudVolumeGroups.PcloudVolumegroupsPost(params, f.session.AuthInfo(f.cloudInstanceID)) + if err != nil { + return nil, fmt.Errorf(errors.CreateVolumeGroupOperationFailed, f.cloudInstanceID, err) + } + if respOk != nil && respOk.Payload != nil { + return respOk.Payload, nil + } + if respPartial != nil && respPartial.Payload != nil { + return respPartial.Payload, nil + } + return nil, fmt.Errorf("failed to create volume-group") +} + +// Update a Volume Group +func (f *IBMPIVolumeGroupClient) UpdateVolumeGroup(id string, body *models.VolumeGroupUpdate) error { + params := p_cloud_volume_groups.NewPcloudVolumegroupsPutParams(). + WithContext(f.ctx).WithTimeout(helpers.PIUpdateTimeOut). + WithCloudInstanceID(f.cloudInstanceID).WithVolumeGroupID(id).WithBody(body) + resp, err := f.session.Power.PCloudVolumeGroups.PcloudVolumegroupsPut(params, f.session.AuthInfo(f.cloudInstanceID)) + if err != nil { + return fmt.Errorf(errors.CreateVolumeGroupOperationFailed, f.cloudInstanceID, err) + } + if resp == nil || resp.Payload == nil { + return fmt.Errorf("failed to update volume-group %s", id) + } + return nil +} + +// Delete a Volume Group +func (f *IBMPIVolumeGroupClient) DeleteVolumeGroup(id string) error { + params := p_cloud_volume_groups.NewPcloudVolumegroupsDeleteParams(). + WithContext(f.ctx).WithTimeout(helpers.PIDeleteTimeOut). + WithCloudInstanceID(f.cloudInstanceID).WithVolumeGroupID(id) + _, err := f.session.Power.PCloudVolumeGroups.PcloudVolumegroupsDelete(params, f.session.AuthInfo(f.cloudInstanceID)) + if err != nil { + return fmt.Errorf(errors.DeleteVolumeGroupOperationFailed, id, err) + } + return nil +} + +// Get live details of a Volume Group +func (f *IBMPIVolumeGroupClient) GetVolumeGroupLiveDetails(id string) (*models.VolumeGroupStorageDetails, error) { + params := p_cloud_volume_groups.NewPcloudVolumegroupsStorageDetailsGetParams(). + WithContext(f.ctx).WithTimeout(helpers.PIGetTimeOut). + WithCloudInstanceID(f.cloudInstanceID).WithVolumeGroupID(id) + resp, err := f.session.Power.PCloudVolumeGroups.PcloudVolumegroupsStorageDetailsGet(params, f.session.AuthInfo(f.cloudInstanceID)) + if err != nil { + return nil, fmt.Errorf(errors.GetLiveVolumeGroupDetailsOperationFailed, id, f.cloudInstanceID, err) + } + if resp == nil || resp.Payload == nil { + return nil, fmt.Errorf("failed to get live details of volume-group %s", id) + } + return resp.Payload, nil +} + +// Performs action on Volume Group +func (f *IBMPIVolumeGroupClient) VolumeGroupAction(id string, body *models.VolumeGroupAction) (models.Object, error) { + params := p_cloud_volume_groups.NewPcloudVolumegroupsActionPostParams(). + WithContext(f.ctx).WithTimeout(helpers.PIUpdateTimeOut). + WithCloudInstanceID(f.cloudInstanceID).WithVolumeGroupID(id).WithBody(body) + resp, err := f.session.Power.PCloudVolumeGroups.PcloudVolumegroupsActionPost(params, f.session.AuthInfo(f.cloudInstanceID)) + if err != nil { + return nil, fmt.Errorf(errors.VolumeGroupActionOperationFailed, id, f.cloudInstanceID, err) + } + if resp == nil || resp.Payload == nil { + return nil, fmt.Errorf("failed to perform action on volume-group %s", id) + } + return resp.Payload, nil +} + +// Get remote copy relationships of the volume belonging to volume group +func (f *IBMPIVolumeGroupClient) GetVolumeGroupRemoteCopyRelationships(id string) (*models.VolumeGroupRemoteCopyRelationships, error) { + params := p_cloud_volume_groups.NewPcloudVolumegroupsRemoteCopyRelationshipsGetParams(). + WithContext(f.ctx).WithTimeout(helpers.PIGetTimeOut). + WithCloudInstanceID(f.cloudInstanceID).WithVolumeGroupID(id) + resp, err := f.session.Power.PCloudVolumeGroups.PcloudVolumegroupsRemoteCopyRelationshipsGet(params, f.session.AuthInfo(f.cloudInstanceID)) + if err != nil { + return nil, fmt.Errorf(errors.GetVolumeGroupRemoteCopyRelationshipsOperationFailed, id, f.cloudInstanceID, err) + } + if resp == nil || resp.Payload == nil { + return nil, fmt.Errorf("failed to Get remote copy relationships of the volumes belonging to volume group %s", id) + } + return resp.Payload, nil +} diff --git a/errors/errors.go b/errors/errors.go index 2bf443cd..f9cdfd49 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -86,6 +86,15 @@ const GetPIKeyOperationFailed = "failed to Get PI Key %s with error %w" const CreatePIKeyOperationFailed = "failed to Create PI Key with error %w" const DeletePIKeyOperationFailed = "failed to Delete PI Key %s with error %w" +// start of Volume Groups +const GetVolumeGroupOperationFailed = "failed to Get volume-group %s for the cloud instance %s with error %w" +const GetVolumeGroupDetailsOperationFailed = "failed to Get volume-group %s details for the cloud instance %s with error %w" +const CreateVolumeGroupOperationFailed = "failed to perform the Create volume-group Operation for the cloud instance %s with error %w" +const DeleteVolumeGroupOperationFailed = "failed to perform Delete volume-group Operation for volume-group %s with error %w" +const GetLiveVolumeGroupDetailsOperationFailed = "failed to Get live details of volume-group %s for the cloud instance %s with error %w" +const VolumeGroupActionOperationFailed = "failed to perform action on volume-group %s for the cloud instance %s with error %w" +const GetVolumeGroupRemoteCopyRelationshipsOperationFailed = "failed to Get remote copy relationships of the volumes belonging to volume group %s for the cloud instance %s with error %w" + // ErrorTarget ... type ErrorTarget struct { Name string diff --git a/examples/volume-group/main.go b/examples/volume-group/main.go new file mode 100644 index 00000000..cefa80db --- /dev/null +++ b/examples/volume-group/main.go @@ -0,0 +1,151 @@ +package main + +import ( + "context" + "log" + "time" + + v "github.com/IBM-Cloud/power-go-client/clients/instance" + ps "github.com/IBM-Cloud/power-go-client/ibmpisession" + "github.com/IBM-Cloud/power-go-client/power/models" + "github.com/IBM/go-sdk-core/v5/core" +) + +func main() { + //session Inputs + token := " < IAM TOKEN > " + region := " < REGION > " + zone := " < ZONE > " + accountID := " < ACCOUNT ID > " + url := region + ".power-iaas.test.cloud.ibm.com" + + // volume inputs + piID := " < POWER INSTANCE ID > " + vgname := "< NAME OF THE volume > " + volIDs := []string{" < VOLUME ID > "} + rmVolIDs := []string{" < VOLUME ID > "} + addVolIDs := []string{" < VOLUME ID > "} + + authenticator := &core.BearerTokenAuthenticator{ + BearerToken: token, + } + // authenticator := &core.IamAuthenticator{ + // ApiKey: "< API KEY >", + // // Uncomment for test environment + // URL: "https://iam.test.cloud.ibm.com", + // } + // Create the session + options := &ps.IBMPIOptions{ + Authenticator: authenticator, + UserAccount: accountID, + Zone: zone, + URL: url, + Debug: true, + } + session, err := ps.NewIBMPISession(options) + if err != nil { + log.Fatal(err) + } + powerClient := v.NewIBMPIVolumeGroupClient(context.Background(), session, piID) + if err != nil { + log.Fatal(err) + } + + body := &models.VolumeGroupCreate{ + Name: vgname, + VolumeIDs: volIDs, + } + + createRespOk, err := powerClient.CreateVolumeGroup(body) + if err != nil { + log.Fatal(err) + } + log.Printf("***************[1]****************** %+v\n", *createRespOk) + + vgID := *createRespOk.ID + getResp, err := powerClient.Get(vgID) + if err != nil { + log.Fatal(err) + } + log.Printf("***************[2]****************** %+v\n", *getResp) + + getDetailsResp, err := powerClient.GetDetails(vgID) + if err != nil { + log.Fatal(err) + } + log.Printf("***************[3]****************** %+v\n", *getDetailsResp) + + vgStatusCheck(vgID, powerClient) + + updateBody := &models.VolumeGroupUpdate{ + AddVolumes: addVolIDs, + RemoveVolumes: rmVolIDs, + } + + err = powerClient.UpdateVolumeGroup(vgID, updateBody) + if err != nil { + log.Fatal(err) + } + + vgStatusCheck(vgID, powerClient) + + getAllVG, err := powerClient.GetAll() + if err != nil { + log.Fatal(err) + } + log.Printf("***************[4]****************** %+v\n", *getAllVG) + + getAllVGDetails, err := powerClient.GetAllDetails() + if err != nil { + log.Fatal(err) + } + log.Printf("***************[5]****************** %+v\n", *getAllVGDetails) + + getDetailsResp, err = powerClient.GetDetails(vgID) + if err != nil { + log.Fatal(err) + } + log.Printf("***************[6]****************** %+v\n", *getDetailsResp) + + getLiveDetails, err := powerClient.GetVolumeGroupLiveDetails(vgID) + if err != nil { + log.Fatal(err) + } + log.Printf("***************[7]****************** %+v\n", *getLiveDetails) + + getRCRelationships, err := powerClient.GetVolumeGroupRemoteCopyRelationships(vgID) + if err != nil { + log.Fatal(err) + } + log.Printf("***************[8]****************** %+v\n", *getRCRelationships) + + // removing volumes before deleting + updateBody = &models.VolumeGroupUpdate{ + RemoveVolumes: getDetailsResp.VolumeIDs, + } + err = powerClient.UpdateVolumeGroup(vgID, updateBody) + if err != nil { + log.Fatal(err) + } + + vgStatusCheck(vgID, powerClient) + + err = powerClient.DeleteVolumeGroup(vgID) + if err != nil { + log.Fatal(err) + } +} + +// vgStatusCheck waits for volume-group status to available +func vgStatusCheck(id string, powerClient *v.IBMPIVolumeGroupClient) { + for start := time.Now(); time.Since(start) < time.Second*30; { + time.Sleep(10 * time.Second) + vg, err := powerClient.GetDetails(id) + if err != nil { + log.Fatal(err) + } + if vg.Status == "available" { + break + } + } +}