Skip to content

Commit

Permalink
[feat] api attach/detach volume
Browse files Browse the repository at this point in the history
  • Loading branch information
cuongpiger committed May 27, 2024
1 parent b3df3e7 commit 260a541
Show file tree
Hide file tree
Showing 12 changed files with 267 additions and 21 deletions.
51 changes: 51 additions & 0 deletions test/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,54 @@ func TestCreateServerWithAutoRenew(t *ltesting.T) {
t.Log("Result: ", server)
t.Log("PASS")
}

func TestAttachVolumeFailure(t *ltesting.T) {
vngcloud := validSdkConfig()
opt := lscomputeSvcV2.NewAttachBlockVolumeRequest("this-is-fake-server-id", "vol-a9484a51-243b-4217-81d4-9f55a7ad426d")
sdkerr := vngcloud.VServerGateway().V2().ComputeService().AttachBlockVolume(opt)

if sdkerr == nil {
t.Fatalf("Expect error but got nil")
}

t.Log("Result: ", sdkerr)
t.Log("PASS")
}

func TestAttachVolumeSuccess(t *ltesting.T) {
vngcloud := validSdkConfig()
opt := lscomputeSvcV2.NewAttachBlockVolumeRequest("ins-6f6b7238-1d57-4c4b-a683-225454a2e168", "vol-a9484a51-243b-4217-81d4-9f55a7ad426d")
sdkerr := vngcloud.VServerGateway().V2().ComputeService().AttachBlockVolume(opt)

if sdkerr != nil {
t.Fatalf("Expect nil but got %v", sdkerr)
}

t.Log("PASS")
}

func TestDetachVolumeSuccess(t *ltesting.T) {
vngcloud := validSdkConfig()
opt := lscomputeSvcV2.NewDetachBlockVolumeRequest("undefined", "vol-a9484a51-243b-4217-81d4-9f55a7ad426d")
sdkerr := vngcloud.VServerGateway().V2().ComputeService().DetachBlockVolume(opt)

if sdkerr != nil {
t.Fatalf("Expect error but got nil")
}

t.Log("Result: ", sdkerr)
t.Log("PASS")
}

func TestDetachVolumeFailure(t *ltesting.T) {
vngcloud := validSdkConfig()
opt := lscomputeSvcV2.NewDetachBlockVolumeRequest("ins-6f6b7238-1d57-4c4b-a683-225454a2e168", "this-is-fake-volume-id")
sdkerr := vngcloud.VServerGateway().V2().ComputeService().DetachBlockVolume(opt)

if sdkerr == nil {
t.Fatalf("Expect error but got nil")
}

t.Log("Result: ", sdkerr)
t.Log("PASS")
}
13 changes: 9 additions & 4 deletions vngcloud/sdk_error/error_codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,14 @@ const (
// vServer volume

const (
EcVServerVolumeTypeNotFound = ErrorCode("VngCloudVServerVolumeTypeNotFound")
EcVServerVolumeNameNotValid = ErrorCode("VngCloudVServerVolumeNameNotValid")
EcVServerVolumeSizeOutOfRange = ErrorCode("VngCloudVServerVolumeSizeOutOfRange")
EcVServerVolumeNotFound = ErrorCode("VngCloudVServerVolumeNotFound")
EcVServerVolumeTypeNotFound = ErrorCode("VngCloudVServerVolumeTypeNotFound")
EcVServerVolumeNameNotValid = ErrorCode("VngCloudVServerVolumeNameNotValid")
EcVServerVolumeSizeOutOfRange = ErrorCode("VngCloudVServerVolumeSizeOutOfRange")
EcVServerVolumeNotFound = ErrorCode("VngCloudVServerVolumeNotFound")
EcVServerVolumeAvailable = ErrorCode("VngCloudVServerVolumeAvailable")
EcVServerVolumeAlreadyAttached = ErrorCode("VngCloudVServerVolumeAlreadyAttached")
EcVServerVolumeAlreadyAttachedThisServer = ErrorCode("VngCloudVServerVolumeAlreadyAttachedThisServer")
EcVServerVolumeInProcess = ErrorCode("VngCloudVServerVolumeInProcess")
)

// Billing
Expand All @@ -69,6 +73,7 @@ const (
EcVServerServerExceedQuota = ErrorCode("VngCloudVServerServerExceedQuota")
EcVServerServerDeleteDeletingServer = ErrorCode("VngCloudVServerServerDeleteDeletingServer")
EcVServerServerDeleteBillingServer = ErrorCode("VngCloudVServerServerDeleteBillingServer")
EcVServerServerVolumeAttachQuotaExceeded = ErrorCode("VngCloudVServerServerVolumeAttachQuotaExceeded")
EcVServerCreateBillingPaymentMethodNotAllowed = ErrorCode("VngCloudVServerCreateBillingPaymentMethodNotAllowed")
)

Expand Down
28 changes: 22 additions & 6 deletions vngcloud/sdk_error/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package sdk_error
import lstr "strings"

const (
patternServerNotFound = "cannot get server with id" // "Cannot get volume type with id vtype-6790f903-38d2-454d-919e-5b49184b5927"
patternServerCreating = "cannot delete server with status creating" // "Server is creating"
patternServerExceedQuota = "exceeded vm quota" // "The number of servers exceeds the quota"
patternServerDeleting = "cannot delete server with status deleting" // "Server is deleting"
patternServerBilling = "cannot delete server with status creating-billing"
patternBillingPaymentMethodNotAllowed = "payment method is not allowed for the user"
patternServerNotFound = "cannot get server with id" // "Cannot get volume type with id vtype-6790f903-38d2-454d-919e-5b49184b5927"
patternServerCreating = "cannot delete server with status creating" // "Server is creating"
patternServerExceedQuota = "exceeded vm quota" // "The number of servers exceeds the quota"
patternServerDeleting = "cannot delete server with status deleting" // "Server is deleting"
patternServerBilling = "cannot delete server with status creating-billing"
patternBillingPaymentMethodNotAllowed = "payment method is not allowed for the user"
patternServerAttachVolumeQuotaExceeded = "exceeded volume_per_server quota"
)

func WithErrorServerNotFound(perrResp IErrorRespone) func(sdkError ISdkError) {
Expand Down Expand Up @@ -100,3 +101,18 @@ func WithErrorServerCreateBillingPaymentMethodNotAllowed(perrResp IErrorRespone)
}
}
}

func WithErrorServerAttachVolumeQuotaExceeded(perrResp IErrorRespone) func(sdkError ISdkError) {
return func(sdkError ISdkError) {
if perrResp == nil {
return
}

errMsg := perrResp.GetMessage()
if lstr.Contains(lstr.ToLower(lstr.TrimSpace(errMsg)), patternServerAttachVolumeQuotaExceeded) {
sdkError.WithErrorCode(EcVServerServerVolumeAttachQuotaExceeded).
WithMessage(errMsg).
WithErrors(perrResp.GetError())
}
}
}
72 changes: 68 additions & 4 deletions vngcloud/sdk_error/volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ import (
)

const (
patternVolumeTypeNotFound = "cannot get volume type with id" // "Cannot get volume type with id vtype-6790f903-38d2-454d-919e-5b49184b5927"
patternVolumeNameNotValid = "only letters (a-z, a-z, 0-9, '.', '@', '_', '-', space) are allowed. your input data length must be between 5 and 50" // "Volume name is not valid"
patternVolumeSizeOutOfRange = "field volume_size must from"
patternVolumeNotFound = `volume with id [^.]+ is not found`
patternVolumeTypeNotFound = "cannot get volume type with id" // "Cannot get volume type with id vtype-6790f903-38d2-454d-919e-5b49184b5927"
patternVolumeNameNotValid = "only letters (a-z, a-z, 0-9, '.', '@', '_', '-', space) are allowed. your input data length must be between 5 and 50" // "Volume name is not valid"
patternVolumeSizeOutOfRange = "field volume_size must from"
patternVolumeNotFound = `volume with id [^.]+ is not found`
patternVolumeAvailable = "this volume is available"
patternVolumeAlreadyAttached = "already attached to instance"
patternVolumeAlreadyAttachedThisServer = "this volume has been attached"
patternVolumeInProcess = "is in-process"
)

var (
Expand Down Expand Up @@ -75,3 +79,63 @@ func WithErrorVolumeNotFound(perrResp IErrorRespone) func(sdkError ISdkError) {
}
}
}

func WithErrorVolumeAvailable(perrResp IErrorRespone) func(sdkError ISdkError) {
return func(sdkError ISdkError) {
if perrResp == nil {
return
}

errMsg := perrResp.GetMessage()
if lstr.Contains(lstr.ToLower(lstr.TrimSpace(errMsg)), patternVolumeAvailable) {
sdkError.WithErrorCode(EcVServerVolumeAvailable).
WithMessage(errMsg).
WithErrors(perrResp.GetError())
}
}
}

func WithErrorVolumeAlreadyAttached(perrResp IErrorRespone) func(sdkError ISdkError) {
return func(sdkError ISdkError) {
if perrResp == nil {
return
}

errMsg := perrResp.GetMessage()
if lstr.Contains(lstr.ToLower(lstr.TrimSpace(errMsg)), patternVolumeAlreadyAttached) {
sdkError.WithErrorCode(EcVServerVolumeAlreadyAttached).
WithMessage(errMsg).
WithErrors(perrResp.GetError())
}
}
}

func WithErrorVolumeAlreadyAttachedThisServer(perrResp IErrorRespone) func(sdkError ISdkError) {
return func(sdkError ISdkError) {
if perrResp == nil {
return
}

errMsg := perrResp.GetMessage()
if lstr.Contains(lstr.ToLower(lstr.TrimSpace(errMsg)), patternVolumeAlreadyAttachedThisServer) {
sdkError.WithErrorCode(EcVServerVolumeAlreadyAttachedThisServer).
WithMessage(errMsg).
WithErrors(perrResp.GetError())
}
}
}

func WithErrorVolumeInProcess(perrResp IErrorRespone) func(sdkError ISdkError) {
return func(sdkError ISdkError) {
if perrResp == nil {
return
}

errMsg := perrResp.GetMessage()
if lstr.Contains(lstr.ToLower(lstr.TrimSpace(errMsg)), patternVolumeInProcess) {
sdkError.WithErrorCode(EcVServerVolumeInProcess).
WithMessage(errMsg).
WithErrors(perrResp.GetError())
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package v2
package common

type ServerCommon struct {
ServerId string
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package v2
package common

type BlockVolumeCommon struct {
BlockVolumeId string
Expand Down
2 changes: 2 additions & 0 deletions vngcloud/services/compute/icompute.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ type IComputeServiceV2 interface {
GetServerById(popts lscomputeSvcV2.IGetServerByIdRequest) (*lsentity.Server, lserr.ISdkError)
DeleteServerById(popts lscomputeSvcV2.IDeleteServerByIdRequest) lserr.ISdkError
UpdateServerSecgroupsByServerId(popts lscomputeSvcV2.IUpdateServerSecgroupsByServerIdRequest) (*lsentity.Server, lserr.ISdkError)
AttachBlockVolume(popts lscomputeSvcV2.IAttachBlockVolumeRequest) lserr.ISdkError
DetachBlockVolume(popts lscomputeSvcV2.IDetachBlockVolumeRequest) lserr.ISdkError
}
10 changes: 10 additions & 0 deletions vngcloud/services/compute/v2/irequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,13 @@ type IUpdateServerSecgroupsByServerIdRequest interface {
ToRequestBody() interface{}
GetListSecgroupsIds() []string
}

type IAttachBlockVolumeRequest interface {
GetServerId() string
GetBlockVolumeId() string
}

type IDetachBlockVolumeRequest interface {
GetServerId() string
GetBlockVolumeId() string
}
45 changes: 45 additions & 0 deletions vngcloud/services/compute/v2/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,48 @@ func (s *ComputeServiceV2) UpdateServerSecgroupsByServerId(popts IUpdateServerSe

return resp.ToEntityServer(), nil
}

func (s *ComputeServiceV2) AttachBlockVolume(popts IAttachBlockVolumeRequest) lserr.ISdkError {
url := attachBlockVolumeUrl(s.VServerClient, popts)
errResp := lserr.NewErrorResponse(lserr.NormalErrorType)
req := lsclient.NewRequest().
WithOkCodes(202).
WithJsonBody(map[string]interface{}{}).
WithJsonError(errResp)

if _, sdkErr := s.VServerClient.Put(url, req); sdkErr != nil {
return lserr.SdkErrorHandler(sdkErr, errResp,
lserr.WithErrorVolumeNotFound(errResp),
lserr.WithErrorServerNotFound(errResp),
lserr.WithErrorVolumeAvailable(errResp),
lserr.WithErrorVolumeInProcess(errResp),
lserr.WithErrorVolumeAlreadyAttached(errResp),
lserr.WithErrorVolumeAlreadyAttachedThisServer(errResp),
lserr.WithErrorServerAttachVolumeQuotaExceeded(errResp)).
WithKVparameters("projectId", s.getProjectId(),
"volumeId", popts.GetBlockVolumeId(),
"serverId", popts.GetServerId())
}

return nil
}

func (s *ComputeServiceV2) DetachBlockVolume(popts IDetachBlockVolumeRequest) lserr.ISdkError {
url := detachBlockVolumeUrl(s.VServerClient, popts)
errResp := lserr.NewErrorResponse(lserr.NormalErrorType)
req := lsclient.NewRequest().
WithOkCodes(202).
WithJsonBody(map[string]interface{}{}).
WithJsonError(errResp)

if _, sdkErr := s.VServerClient.Put(url, req); sdkErr != nil {
return lserr.SdkErrorHandler(sdkErr, errResp,
lserr.WithErrorVolumeNotFound(errResp),
lserr.WithErrorVolumeAvailable(errResp)).
WithKVparameters("projectId", s.getProjectId(),
"volumeId", popts.GetBlockVolumeId(),
"serverId", popts.GetServerId())
}

return nil
}
32 changes: 29 additions & 3 deletions vngcloud/services/compute/v2/server_request.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package v2

import lscommon "github.com/vngcloud/vngcloud-go-sdk/v2/vngcloud/services/common"

func NewCreateServerRequest(pname, pimageId, pflavorId, pnetworkId, psubnetId, prootDiskType string, prootDiskSize int) ICreateServerRequest {
opt := new(CreateServerRequest)
opt.Name = pname
Expand Down Expand Up @@ -32,6 +34,20 @@ func NewUpdateServerSecgroupsRequest(pserverId string, psecgroups ...string) IUp
return opt
}

func NewAttachBlockVolumeRequest(pserverId, pvolumeId string) IAttachBlockVolumeRequest {
opt := new(AttachBlockVolumeRequest)
opt.ServerId = pserverId
opt.BlockVolumeId = pvolumeId
return opt
}

func NewDetachBlockVolumeRequest(pserverId, pvolumeId string) IDetachBlockVolumeRequest {
opt := new(DetachBlockVolumeRequest)
opt.ServerId = pserverId
opt.BlockVolumeId = pvolumeId
return opt
}

const (
DataDiskEncryptionAesXtsType DataDiskEncryptionType = "aes-xts-plain64_256"
)
Expand Down Expand Up @@ -70,6 +86,16 @@ type CreateServerRequest struct {
AutoRenew bool `json:"isEnableAutoRenew,omitempty"`
}

type AttachBlockVolumeRequest struct {
lscommon.BlockVolumeCommon
lscommon.ServerCommon
}

type DetachBlockVolumeRequest struct {
lscommon.BlockVolumeCommon
lscommon.ServerCommon
}

type DataDiskEncryptionType string

type ServerTag struct {
Expand Down Expand Up @@ -138,12 +164,12 @@ func (s *CreateServerRequest) WithProduct(pproduct string) ICreateServerRequest
}

type GetServerByIdRequest struct {
ServerCommon
lscommon.ServerCommon
}

type DeleteServerByIdRequest struct {
DeleteAllVolume bool `json:"deleteAllVolume"`
ServerCommon
lscommon.ServerCommon
}

func (s *DeleteServerByIdRequest) WithDeleteAllVolume(pok bool) IDeleteServerByIdRequest {
Expand All @@ -158,7 +184,7 @@ func (s *DeleteServerByIdRequest) ToRequestBody() interface{} {
type UpdateServerSecgroupsByServerIdRequest struct {
Secgroups []string `json:"securityGroup"`

ServerCommon
lscommon.ServerCommon
}

func (s *UpdateServerSecgroupsByServerIdRequest) ToRequestBody() interface{} {
Expand Down
21 changes: 21 additions & 0 deletions vngcloud/services/compute/v2/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,24 @@ func updateServerSecgroupsByServerIdUrl(psc lsclient.IServiceClient, popts IUpda
popts.GetServerId(),
"update-sec-group")
}

func attachBlockVolumeUrl(psc lsclient.IServiceClient, popts IAttachBlockVolumeRequest) string {
return psc.ServiceURL(
psc.GetProjectId(),
"volumes",
popts.GetBlockVolumeId(),
"servers",
popts.GetServerId(),
"attach")
}

func detachBlockVolumeUrl(psc lsclient.IServiceClient, popts IDetachBlockVolumeRequest) string {
return psc.ServiceURL(
psc.GetProjectId(),
"volumes",
popts.GetBlockVolumeId(),
"servers",
popts.GetServerId(),
"detach",
)
}
Loading

0 comments on commit 260a541

Please sign in to comment.