Skip to content

Commit f47cec5

Browse files
authored
Merge pull request #8 from vngcloud/dev
Release AZ
2 parents ad2fc1c + 0444728 commit f47cec5

10 files changed

Lines changed: 167 additions & 29 deletions

File tree

.github/workflows/build_dev.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
environment:
2020
name: development # Set the environment name
2121
# Only trigger the workflow if the commit message contains '[build]'
22-
if: contains(github.event.head_commit.message, '[build]')
22+
if: contains(github.event.head_commit.message, '[build]' || contains(github.event.head_commit.message, 'Merge branch'))
2323
# Steps represent a sequence of tasks that will be executed as part of the job
2424
steps:
2525
- name: Send alert that a new commit has been created

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/cuongpiger/joat v1.0.17
88
github.com/spf13/pflag v1.0.5
99
github.com/vngcloud/vngcloud-csi-volume-modifier v1.0.2
10-
github.com/vngcloud/vngcloud-go-sdk/v2 v2.11.0
10+
github.com/vngcloud/vngcloud-go-sdk/v2 v2.14.13
1111
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0
1212
go.opentelemetry.io/otel v1.26.0
1313
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
126126
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
127127
github.com/vngcloud/vngcloud-csi-volume-modifier v1.0.2 h1:LBSW1T0W4HxJKtpgSYbL5ZL1XiyOTF2nHIs8uqG5uoo=
128128
github.com/vngcloud/vngcloud-csi-volume-modifier v1.0.2/go.mod h1:wkhxk+x3ILNOk0aUxGivvhdiOXxPOVNXeRDHUx/IR50=
129-
github.com/vngcloud/vngcloud-go-sdk/v2 v2.11.0 h1:+W3rrDyFWfaU7jIvcoy00yO52ZGS6pb7VU10Edz4SyY=
130-
github.com/vngcloud/vngcloud-go-sdk/v2 v2.11.0/go.mod h1:FetWUe2fEuqySEkYgkuDgt/WOAlI/YC02reGqjdJRMU=
129+
github.com/vngcloud/vngcloud-go-sdk/v2 v2.14.13 h1:0aNotvsnTknaD/yafS7lYEL+ki27AIJCKvpO3K2Xi3s=
130+
github.com/vngcloud/vngcloud-go-sdk/v2 v2.14.13/go.mod h1:FetWUe2fEuqySEkYgkuDgt/WOAlI/YC02reGqjdJRMU=
131131
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
132132
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
133133
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 h1:A3SayB3rNyt+1S6qpI9mHPkeHTZbD7XILEqWnYZb2l0=

pkg/cloud/cloud.go

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cloud
33
import (
44
lctx "context"
55
lfmt "fmt"
6+
"strings"
67

78
ljmath "github.com/cuongpiger/joat/math"
89
ljtime "github.com/cuongpiger/joat/timer"
@@ -68,7 +69,6 @@ func (s *cloud) EitherCreateResizeVolume(preq lsdkVolumeV2.ICreateBlockVolumeReq
6869
serr lserr.IError
6970
sdkErr lsdkErrs.IError
7071
)
71-
7272
// Get the volume depend on the volume name
7373
if preq.GetVolumeName() != "" {
7474
llog.InfoS("[INFO] - EitherCreateResizeVolume: Get the volume by name", "volumeName", preq.GetVolumeName())
@@ -110,7 +110,7 @@ func (s *cloud) EitherCreateResizeVolume(preq lsdkVolumeV2.ICreateBlockVolumeReq
110110
return nil, lserr.NewError(sdkErr)
111111
}
112112

113-
llog.InfoS("[INFO] - EitherCreateResizeVolume: Created the volume successfully", "volumeID", vol.Id)
113+
llog.InfoS("[INFO] - EitherCreateResizeVolume: Created the volume successfully", "volumeID", vol.Id, "zoneId", vol.ZoneId)
114114
return &lsentity.Volume{
115115
Volume: vol,
116116
}, nil
@@ -555,3 +555,41 @@ func (s *cloud) GetDefaultVolumeType() (*lsentity.VolumeType, lserr.IError) {
555555

556556
return &lsentity.VolumeType{VolumeType: volType}, nil
557557
}
558+
559+
func (s *cloud) GetVolumeTypeIdByName(zoneId, volumeName string) (string, lserr.IError) {
560+
parts := strings.Split(volumeName, "-")
561+
if len(parts) != 2 {
562+
return volumeName, nil
563+
}
564+
volTypeName := strings.ToUpper(parts[0])
565+
iopsName := strings.TrimPrefix(parts[1], "iops")
566+
567+
req := lsdkVolumeV1.NewGetVolumeTypeZonesRequest(zoneId)
568+
res, sdkErr := s.client.VServerGateway().V1().VolumeService().GetVolumeTypeZones(req)
569+
if sdkErr != nil {
570+
return "", lserr.NewError(sdkErr)
571+
}
572+
573+
for _, vtZone := range res.VolumeTypeZones {
574+
if vtZone == nil || vtZone.Name != volTypeName {
575+
continue
576+
}
577+
578+
listReq := lsdkVolumeV1.NewListVolumeTypeRequest(vtZone.Id)
579+
listRes, sdkErr := s.client.VServerGateway().V1().VolumeService().GetListVolumeTypes(listReq)
580+
if sdkErr != nil {
581+
return "", lserr.NewError(sdkErr)
582+
}
583+
584+
for _, vt := range listRes.VolumeTypes {
585+
if vt != nil && vt.Name == iopsName {
586+
llog.InfoS("[INFO] - GetVolumeTypeIdByName: Found volume type ID",
587+
"volumeTypeId", vt.Id, "zoneId", zoneId, "volumeName", volumeName)
588+
return vt.Id, nil
589+
}
590+
}
591+
break
592+
}
593+
llog.InfoS("[INFO] - GetVolumeTypeIdByName: Volume type ID response", "zoneId", zoneId, "volumeName", volumeName)
594+
return volumeName, nil
595+
}

pkg/cloud/icloud.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ type Cloud interface {
2424
ListSnapshots(pvolID string, ppage int, ppageSize int) (*lsentity.ListSnapshots, lserr.IError)
2525
GetVolumeTypeById(pvolTypeId string) (*lsentity.VolumeType, lserr.IError)
2626
GetDefaultVolumeType() (*lsentity.VolumeType, lserr.IError)
27+
GetVolumeTypeIdByName(zoneId string, volumeName string) (string, lserr.IError)
2728
}

pkg/driver/constants.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ const (
1515
AgentNotReadyNodeTaintKey = "csi.vngcloud.vn/agent-not-ready"
1616

1717
DefaultTimeoutModifyChannel = 10 * ltime.Minute
18-
19-
DriverName = "bs.csi.vngcloud.vn"
20-
ZoneTopologyKey = "topology." + DriverName + "/zone"
18+
WellKnownZoneTopologyKey = "topology.kubernetes.io/zone"
19+
DriverName = "bs.csi.vngcloud.vn"
20+
ZoneTopologyKey = "topology." + DriverName + "/zone"
2121
)
2222

2323
// constants of disk partition suffix

pkg/driver/controller.go

Lines changed: 63 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,20 @@ func (s *controllerService) CreateVolume(pctx lctx.Context, preq *lcsi.CreateVol
8888
return nil, err
8989
}
9090

91+
volName := preq.GetName() // get the name of the volume, always in the format of pvc-<random-uuid>
92+
volCap := preq.GetVolumeCapabilities() // get volume capabilities
93+
multiAttach := isMultiAttach(volCap) // check if the volume is multi-attach, true if multi-attach, false otherwise
94+
zone := lsutil.ConvertVMZoneToPortalZone(pickAvailabilityZone(preq.GetAccessibilityRequirements()))
95+
96+
llog.V(5).InfoS("[INFO] - CreateVolume: zone info", "zone", zone)
97+
9198
// Validate volume size, if volume size is less than the default volume size of cloud provider, set it to the default volume size
92-
volSizeBytes, err := s.getVolSizeBytes(preq)
99+
volumeTypeId, volSizeBytes, err := s.getVolSizeBytes(zone, preq)
93100
if err != nil {
94101
llog.ErrorS(err, "[ERROR] - CreateVolume: Failed to get volume size")
95102
return nil, ErrFailedToValidateVolumeSize(preq.GetName(), err)
96103
}
97104

98-
volName := preq.GetName() // get the name of the volume, always in the format of pvc-<random-uuid>
99-
volCap := preq.GetVolumeCapabilities() // get volume capabilities
100-
multiAttach := isMultiAttach(volCap) // check if the volume is multi-attach, true if multi-attach, false otherwise
101-
102105
// check if a request is already in-flight
103106
if ok := s.inFlight.Insert(volName); !ok {
104107
llog.InfoS("[INFO] - CreateVolume: Operation is already in-flight", "volumeName", volName, "inflightKey", volName)
@@ -118,13 +121,11 @@ func (s *controllerService) CreateVolume(pctx lctx.Context, preq *lcsi.CreateVol
118121
}
119122
}
120123

121-
cvr := NewCreateVolumeRequest().WithDriverOptions(s.driverOptions)
124+
cvr := NewCreateVolumeRequest().WithDriverOptions(s.driverOptions).WithZone(zone).WithVolumeTypeID(volumeTypeId)
122125
parser, _ := ljoat.GetParser()
123126
for pk, pv := range preq.GetParameters() {
124127
llog.InfoS("[INFO] - CreateVolume: Parsing request parameters", "key", pk, "value", pv)
125128
switch lstr.ToLower(pk) {
126-
case VolumeTypeKey:
127-
cvr = cvr.WithVolumeTypeID(pv)
128129
case EncryptedKey:
129130
cvr = cvr.WithEncrypted(pv)
130131
case PVCNameKey:
@@ -237,6 +238,36 @@ func (s *controllerService) CreateVolume(pctx lctx.Context, preq *lcsi.CreateVol
237238
return newCreateVolumeResponse(newVol, cvr, respCtx), nil
238239
}
239240

241+
// pickAvailabilityZone selects 1 zone given topology requirement.
242+
// if not found, empty string is returned.
243+
func pickAvailabilityZone(requirement *lcsi.TopologyRequirement) string {
244+
if requirement == nil {
245+
return ""
246+
}
247+
for _, topology := range requirement.GetPreferred() {
248+
zone, exists := topology.GetSegments()[WellKnownZoneTopologyKey]
249+
if exists {
250+
return zone
251+
}
252+
253+
zone, exists = topology.GetSegments()[ZoneTopologyKey]
254+
if exists {
255+
return zone
256+
}
257+
}
258+
for _, topology := range requirement.GetRequisite() {
259+
zone, exists := topology.GetSegments()[WellKnownZoneTopologyKey]
260+
if exists {
261+
return zone
262+
}
263+
zone, exists = topology.GetSegments()[ZoneTopologyKey]
264+
if exists {
265+
return zone
266+
}
267+
}
268+
return ""
269+
}
270+
240271
func (s *controllerService) DeleteVolume(pctx lctx.Context, preq *lcsi.DeleteVolumeRequest) (*lcsi.DeleteVolumeResponse, error) {
241272
llog.InfoS("[INFO] - DeleteVolume: called", "request", *preq)
242273

@@ -599,13 +630,19 @@ func (s *controllerService) ModifyVolumeProperties(pctx lctx.Context, preq *lvmr
599630
return nil, ErrFailedToGetVolume(volumeID)
600631
}
601632

602-
if volume.VolumeTypeID == options.VolumeType {
633+
volumeTypeId, sdkErr := s.cloud.GetVolumeTypeIdByName(volume.ZoneId, options.VolumeType)
634+
if sdkErr != nil {
635+
llog.ErrorS(sdkErr.GetError(), "[ERROR] - ModifyVolumeProperties: Failed to get the volume type ID by name", sdkErr.GetListParameters()...)
636+
return nil, ErrFailedToGetVolume(volumeID)
637+
}
638+
639+
if volume.VolumeTypeID == options.VolumeType || volumeTypeId == volume.VolumeTypeID {
603640
llog.V(2).Infof("[INFO] - ModifyVolumeProperties: Volume %s already has volume type %s", volumeID, options.VolumeType)
604641
return &lvmrpc.ModifyVolumePropertiesResponse{}, nil
605642
}
606643

607644
llog.InfoS("[INFO] - ModifyVolumeProperties: Modifying volume", "volumeID", volumeID, "newVolumeType", options.VolumeType, "oldVolumeType", volume.VolumeTypeID, "newSize", volume.Size)
608-
ierr := s.cloud.ModifyVolumeType(volumeID, options.VolumeType, int(volume.Size))
645+
ierr := s.cloud.ModifyVolumeType(volumeID, volumeTypeId, int(volume.Size))
609646
if ierr != nil {
610647
llog.ErrorS(ierr.GetError(), "ModifyVolumeProperties: failed to modify volume", "volumeID", volumeID)
611648
return nil, ierr.GetError()
@@ -636,7 +673,7 @@ func (s *controllerService) getClusterID() string {
636673
return s.driverOptions.clusterID
637674
}
638675

639-
func (s *controllerService) getVolSizeBytes(preq *lcsi.CreateVolumeRequest) (volSizeBytes int64, err error) {
676+
func (s *controllerService) getVolSizeBytes(zoneID string, preq *lcsi.CreateVolumeRequest) (volumeTypeId string, volSizeBytes int64, err error) {
640677
// get the volume size that user provided
641678
if preq.GetCapacityRange() != nil {
642679
volSizeBytes = preq.GetCapacityRange().GetRequiredBytes()
@@ -648,25 +685,29 @@ func (s *controllerService) getVolSizeBytes(preq *lcsi.CreateVolumeRequest) (vol
648685
// If the user forget to specify the volume type, get the default volume type
649686
tmpVolType, sdkErr := s.cloud.GetDefaultVolumeType()
650687
if sdkErr != nil {
651-
return 0, sdkErr.GetError()
688+
return "", 0, sdkErr.GetError()
652689
}
653690

654691
volType = tmpVolType.Id
655692
}
693+
volumeTypeId, sdkErr := s.cloud.GetVolumeTypeIdByName(zoneID, volType)
694+
if sdkErr != nil {
695+
return "", 0, sdkErr.GetError()
696+
}
656697

657698
// Get the minimum volume size allowed by the volume type
658-
volTypeEntity, sdkErr := s.cloud.GetVolumeTypeById(volType)
699+
volTypeEntity, sdkErr := s.cloud.GetVolumeTypeById(volumeTypeId)
659700
if sdkErr != nil {
660-
return 0, sdkErr.GetError()
701+
return "", 0, sdkErr.GetError()
661702
}
662703

663704
// Calculate the bytes that cloud provider allowing to create the volume
664705
cvs := lsutil.GiBToBytes(int64(volTypeEntity.MinSize))
665706
if volSizeBytes < cvs {
666-
return 0, ErrVolumeSizeTooSmall(preq.GetName(), volSizeBytes)
707+
return volumeTypeId, 0, ErrVolumeSizeTooSmall(preq.GetName(), volSizeBytes)
667708
}
668709

669-
return volSizeBytes, nil
710+
return volumeTypeId, volSizeBytes, nil
670711
}
671712

672713
func newCreateVolumeResponse(disk *lsentity.Volume, pcvr *CreateVolumeRequest, prespCtx map[string]string) *lcsi.CreateVolumeResponse {
@@ -680,12 +721,18 @@ func newCreateVolumeResponse(disk *lsentity.Volume, pcvr *CreateVolumeRequest, p
680721
},
681722
}
682723
}
724+
segments := map[string]string{WellKnownZoneTopologyKey: lsutil.ConvertPortalZoneToVMZone(disk.ZoneId)}
683725

684726
return &lcsi.CreateVolumeResponse{
685727
Volume: &lcsi.Volume{
686728
VolumeId: disk.Id,
687729
CapacityBytes: int64(disk.Size * 1024 * 1024 * 1024),
688730
VolumeContext: prespCtx,
731+
AccessibleTopology: []*lcsi.Topology{
732+
{
733+
Segments: segments,
734+
},
735+
},
689736
ContentSource: vcs,
690737
},
691738
}

pkg/driver/node.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ import (
55
"encoding/json"
66
"fmt"
77
lcsi "github.com/container-storage-interface/spec/lib/go/csi"
8+
lscloud "github.com/vngcloud/vngcloud-blockstorage-csi-driver/pkg/cloud"
9+
lsinternal "github.com/vngcloud/vngcloud-blockstorage-csi-driver/pkg/driver/internal"
10+
//lsutil "github.com/vngcloud/vngcloud-blockstorage-csi-driver/pkg/util"
811
lsdkClientV2 "github.com/vngcloud/vngcloud-go-sdk/v2/client"
12+
//computev2 "github.com/vngcloud/vngcloud-go-sdk/v2/vngcloud/services/compute/v2"
913
lsdkPortalSvcV1 "github.com/vngcloud/vngcloud-go-sdk/v2/vngcloud/services/portal/v1"
1014
lsdkPortalSvcV2 "github.com/vngcloud/vngcloud-go-sdk/v2/vngcloud/services/portal/v2"
1115
"golang.org/x/sys/unix"
@@ -24,9 +28,6 @@ import (
2428
"strconv"
2529
"strings"
2630
"time"
27-
28-
lscloud "github.com/vngcloud/vngcloud-blockstorage-csi-driver/pkg/cloud"
29-
lsinternal "github.com/vngcloud/vngcloud-blockstorage-csi-driver/pkg/driver/internal"
3031
)
3132

3233
type JSONPatch struct {
@@ -548,6 +549,15 @@ func (s *nodeService) NodeGetInfo(_ lctx.Context, _ *lcsi.NodeGetInfoRequest) (*
548549
mvpn = quota.Limit
549550
klog.InfoS("[INFO] - NodeGetInfo: Setup the VngCloud Manage CSI driver for this node successfully",
550551
"quota", quota, "nodeId", nodeUUID, "zone", zone, "projectId", projectID)
552+
//opt := computev2.NewGetServerByIdRequest(nodeUUID)
553+
//server, sdkErr := cloudClient.VServerGateway().V2().ComputeService().GetServerById(opt)
554+
//if sdkErr != nil {
555+
// klog.ErrorS(sdkErr.GetError(), "[ERROR] - GetServerByID: ", "nodeUUID", nodeUUID)
556+
// return nil, sdkErr.GetError()
557+
//}
558+
//zone = lsutil.ConvertPortalZoneToVMZone(server.ZoneId)
559+
//klog.InfoS("[INFO] - NodeGetInfo: Get the server info successfully",
560+
// "nodeId", nodeUUID, "zone", zone, "projectId", projectID)
551561
} else {
552562
mvpn = s.driverOptions.maxVolumesPerNode
553563
klog.InfoS("[INFO] - NodeGetInfo: Setup the VngCloud Manage CSI driver for this node successfully",
@@ -881,8 +891,9 @@ func checkAllocatable(clientset kubernetes.Interface, nodeName string) error {
881891
if err != nil {
882892
return fmt.Errorf("isAllocatableSet: failed to get CSINode for %s: %w", nodeName, err)
883893
}
884-
894+
klog.InfoS("CSINode drivers: ", "nodeName", nodeName, "driverName", csiNode.Spec)
885895
for _, driver := range csiNode.Spec.Drivers {
896+
klog.InfoS("CSINode driver info", "nodeName", nodeName, "driverName", driver.Name, "count", *driver.Allocatable.Count)
886897
if driver.Name == DriverName {
887898
if driver.Allocatable != nil && driver.Allocatable.Count != nil {
888899
klog.InfoS("CSINode Allocatable value is set", "nodeName", nodeName, "count", *driver.Allocatable.Count)

pkg/driver/volume_dto.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ type CreateVolumeRequest struct {
3636
Ext4ClusterSize string
3737
Ext4BigAlloc bool
3838
ReclaimPolicy string
39+
Zone string
3940

4041
DriverOptions *DriverOptions
4142
}
@@ -50,6 +51,11 @@ func NewCreateVolumeRequest() *CreateVolumeRequest {
5051
}
5152
}
5253

54+
func (s *CreateVolumeRequest) WithZone(zone string) *CreateVolumeRequest {
55+
s.Zone = zone
56+
return s
57+
}
58+
5359
func (s *CreateVolumeRequest) WithClusterID(pclusterID string) *CreateVolumeRequest {
5460
s.ClusterID = pclusterID
5561
return s
@@ -166,6 +172,7 @@ func (s *CreateVolumeRequest) WithReclaimPolicy(ppolicy string) *CreateVolumeReq
166172
func (s *CreateVolumeRequest) ToSdkCreateVolumeRequest() lsdkVolumeV2.ICreateBlockVolumeRequest {
167173
opts := lsdkVolumeV2.NewCreateBlockVolumeRequest(s.VolumeName, s.VolumeTypeID, int64(s.VolumeSize)).
168174
WithPoc(s.IsPoc).
175+
WithZone(s.Zone).
169176
WithMultiAttach(s.IsMultiAttach).
170177
WithEncryptionType(lsdkVolumeV2.EncryptType(s.EncryptedAlgorithm)).
171178
WithTags(s.prepareTag(s.DriverOptions.GetTagKeyLength(), s.DriverOptions.GetTagValueLength())...)

pkg/util/util.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,37 @@ func RoundUpGiB(volumeSizeBytes int64) int64 {
6262
func GiBToBytes(volumeSizeGiB int64) int64 {
6363
return volumeSizeGiB * GiB
6464
}
65+
66+
func ConvertPortalZoneToVMZone(zone string) string {
67+
switch zone {
68+
case "HCM03-1A":
69+
return "AZ01"
70+
case "HCM03-1B":
71+
return "HCM-1B"
72+
case "HCM03-1C":
73+
return "HCM-1C"
74+
case "BKK-01":
75+
return "BKK01"
76+
case "HAN-01":
77+
return "az01"
78+
default:
79+
return zone
80+
}
81+
}
82+
83+
func ConvertVMZoneToPortalZone(zone string) string {
84+
switch zone {
85+
case "AZ01":
86+
return "HCM03-1A"
87+
case "HCM-1B":
88+
return "HCM03-1B"
89+
case "HCM-1C":
90+
return "HCM03-1C"
91+
case "BKK01":
92+
return "BKK-01"
93+
case "az01":
94+
return "HAN-01"
95+
default:
96+
return zone
97+
}
98+
}

0 commit comments

Comments
 (0)