From bb95ec5fd33e3b36fec9a3e8b26819bcde0c2e23 Mon Sep 17 00:00:00 2001 From: innodreamer Date: Thu, 11 Jul 2024 21:08:55 +0900 Subject: [PATCH 1/3] Create TagHandler (Init commit) --- .../drivers/ncp/connect/NcpCloudConnection.go | 5 +- .../drivers/ncp/main/Test_TagHandler.go | 243 ++++++++++++++++++ .../drivers/ncp/resources/TagHandler.go | 216 ++++++++++++++++ 3 files changed, 463 insertions(+), 1 deletion(-) create mode 100644 cloud-control-manager/cloud-driver/drivers/ncp/main/Test_TagHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ncp/resources/TagHandler.go diff --git a/cloud-control-manager/cloud-driver/drivers/ncp/connect/NcpCloudConnection.go b/cloud-control-manager/cloud-driver/drivers/ncp/connect/NcpCloudConnection.go index d13bc3698..3541f4176 100644 --- a/cloud-control-manager/cloud-driver/drivers/ncp/connect/NcpCloudConnection.go +++ b/cloud-control-manager/cloud-driver/drivers/ncp/connect/NcpCloudConnection.go @@ -135,7 +135,10 @@ func (cloudConn *NcpCloudConnection) CreatePriceInfoHandler() (irs.PriceInfoHand } func (cloudConn *NcpCloudConnection) CreateTagHandler() (irs.TagHandler, error) { - return nil, fmt.Errorf("NCP Cloud Driver does not support CreateTagHandler() yet.") + cblogger.Info("NCP Cloud Driver: called CreateTagHandler()!") + + tagHandler := ncprs.NcpTagHandler{cloudConn.CredentialInfo, cloudConn.RegionInfo, cloudConn.VmClient} + return &tagHandler, nil } func (cloudConn *NcpCloudConnection) IsConnected() (bool, error) { diff --git a/cloud-control-manager/cloud-driver/drivers/ncp/main/Test_TagHandler.go b/cloud-control-manager/cloud-driver/drivers/ncp/main/Test_TagHandler.go new file mode 100644 index 000000000..d4db1674a --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ncp/main/Test_TagHandler.go @@ -0,0 +1,243 @@ +// Proof of Concepts of CB-Spider. +// The CB-Spider is a sub-Framework of the Cloud-Barista Multi-Cloud Project. +// The CB-Spider Mission is to connect all the clouds with a single interface. +// +// * Cloud-Barista: https://github.com/cloud-barista +// +// This is a Cloud Driver Tester Example. +// +// by ETRI, 2024.07. + +package main + +import ( + "os" + "errors" + "fmt" + // "bufio" + // "strings" + "github.com/davecgh/go-spew/spew" + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" + + idrv "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/interfaces" + irs "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/interfaces/resources" + cblog "github.com/cloud-barista/cb-log" + + // ncpdrv "github.com/cloud-barista/ncp/ncp" // For local test + ncpdrv "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/drivers/ncp" +) + +var cblogger *logrus.Logger + +func init() { + // cblog is a global variable. + cblogger = cblog.GetLogger("NCP Resource Test") + cblog.SetLevel("info") +} + +func handleTag() { + cblogger.Debug("Start Disk Resource Test") + + resourceHandler, err := getResourceHandler("Tag") + if err != nil { + cblogger.Error(err) + return + } + tagHandler := resourceHandler.(irs.TagHandler) + //config := readConfigFile() + + for { + fmt.Println("\n============================================================================================") + fmt.Println("[ TagHandler Test ]") + cblogger.Info("1. ListTag()") + cblogger.Info("2. GetTag()") + cblogger.Info("3. AddTag()") + cblogger.Info("4. RemoveTag()") + cblogger.Info("5. FindTag()") + cblogger.Info("0. Exit") + fmt.Println("\n Select a number above!! : ") + fmt.Println("============================================================================================") + + var commandNum int + + rsType := irs.RSType(irs.VM) + + rsIId := irs.IID{ + NameId: "MyVM-1", + SystemId: "25453063", + } + + tagKV := irs.KeyValue{ + Key: "VPCNameTest", + Value: "NCP-myVPC-000001", + } + + tagKey := "VPCNameTest" + + keyword := "VPC" + + inputCnt, err := fmt.Scan(&commandNum) + if err != nil { + panic(err) + } + + if inputCnt == 1 { + switch commandNum { + case 0: + return + case 1: + cblogger.Info("Start ListTag() ...") + if tagList, err := tagHandler.ListTag(rsType, rsIId); err != nil { + cblogger.Error(err) + } else { + spew.Dump(tagList) + } + cblogger.Info("Finish ListTag()") + case 2: + cblogger.Info("Start GetTag() ...") + if tagKeyValue, err := tagHandler.GetTag(rsType, rsIId, tagKey); err != nil { + cblogger.Error(err) + } else { + spew.Dump(tagKeyValue) + } + cblogger.Info("Finish GetTag()") + case 3: + cblogger.Info("Start AddTag() ...") + if tagKeyValue, err := tagHandler.AddTag(rsType, rsIId, tagKV); err != nil { + cblogger.Error(err) + } else { + spew.Dump(tagKeyValue) + } + cblogger.Info("Finish AddTag()") + case 4: + cblogger.Info("Start RemoveTag() ...") + if tagKeyValue, err := tagHandler.RemoveTag(rsType, rsIId, tagKey); err != nil { + cblogger.Error(err) + } else { + spew.Dump(tagKeyValue) + } + cblogger.Info("Finish RemoveTag()") + case 5: + cblogger.Info("Start FindTag() ...") + if tagKeyValue, err := tagHandler.FindTag(rsType, keyword); err != nil { + cblogger.Error(err) + } else { + spew.Dump(tagKeyValue) + } + cblogger.Info("Finish FindTag()") + } + } + } +} + +func testErr() error { + + return errors.New("") +} + +func main() { + cblogger.Info("NCP Resource Test") + handleTag() +} + +//handlerType : resources폴더의 xxxHandler.go에서 Handler이전까지의 문자열 +//(예) ImageHandler.go -> "Image" +func getResourceHandler(handlerType string) (interface{}, error) { + var cloudDriver idrv.CloudDriver + cloudDriver = new(ncpdrv.NcpDriver) + + config := readConfigFile() + connectionInfo := idrv.ConnectionInfo{ + CredentialInfo: idrv.CredentialInfo{ + ClientId: config.Ncp.NcpAccessKeyID, + ClientSecret: config.Ncp.NcpSecretKey, + }, + RegionInfo: idrv.RegionInfo{ + Region: config.Ncp.Region, + Zone: config.Ncp.Zone, + }, + } + + cloudConnection, errCon := cloudDriver.ConnectCloud(connectionInfo) + if errCon != nil { + return nil, errCon + } + + var resourceHandler interface{} + var err error + + switch handlerType { + case "Image": + resourceHandler, err = cloudConnection.CreateImageHandler() + case "Security": + resourceHandler, err = cloudConnection.CreateSecurityHandler() + case "VNetwork": + resourceHandler, err = cloudConnection.CreateVPCHandler() + case "VM": + resourceHandler, err = cloudConnection.CreateVMHandler() + case "VMSpec": + resourceHandler, err = cloudConnection.CreateVMSpecHandler() + case "VPC": + resourceHandler, err = cloudConnection.CreateVPCHandler() + case "Disk": + resourceHandler, err = cloudConnection.CreateDiskHandler() + case "Tag": + resourceHandler, err = cloudConnection.CreateTagHandler() + } + + if err != nil { + return nil, err + } + return resourceHandler, nil +} + +type Config struct { + Ncp struct { + NcpAccessKeyID string `yaml:"ncp_access_key_id"` + NcpSecretKey string `yaml:"ncp_secret_key"` + Region string `yaml:"region"` + Zone string `yaml:"zone"` + + ImageID string `yaml:"image_id"` + + VmID string `yaml:"ncp_instance_id"` + BaseName string `yaml:"base_name"` + InstanceType string `yaml:"instance_type"` + KeyName string `yaml:"key_name"` + MinCount int64 `yaml:"min_count"` + MaxCount int64 `yaml:"max_count"` + + SubnetID string `yaml:"subnet_id"` + SecurityGroupID string `yaml:"security_group_id"` + + PublicIP string `yaml:"public_ip"` + } `yaml:"ncp"` +} + +func readConfigFile() Config { + // # Set Environment Value of Project Root Path + // goPath := os.Getenv("GOPATH") + // rootPath := goPath + "/src/github.com/cloud-barista/ncp/ncp/main" + // cblogger.Debugf("Test Config file : [%]", rootPath+"/config/config.yaml") + rootPath := os.Getenv("CBSPIDER_ROOT") + configPath := rootPath + "/cloud-control-manager/cloud-driver/drivers/ncp/main/config/config.yaml" + cblogger.Debugf("Test Config file : [%s]", configPath) + + data, err := os.ReadFile(configPath) + if err != nil { + panic(err) + } + + var config Config + err = yaml.Unmarshal(data, &config) + if err != nil { + panic(err) + } + cblogger.Info("ConfigFile Loaded ...") + + // Just for test + cblogger.Debug(config.Ncp.NcpAccessKeyID, " ", config.Ncp.Region) + + return config +} diff --git a/cloud-control-manager/cloud-driver/drivers/ncp/resources/TagHandler.go b/cloud-control-manager/cloud-driver/drivers/ncp/resources/TagHandler.go new file mode 100644 index 000000000..3bb8f0c7c --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ncp/resources/TagHandler.go @@ -0,0 +1,216 @@ +package resources + +import ( + "fmt" + "strings" + + ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go-v2/ncloud" + server "github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/server" + + idrv "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/interfaces" + irs "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/interfaces/resources" +) + +type NcpTagHandler struct { + CredentialInfo idrv.CredentialInfo + RegionInfo idrv.RegionInfo + VMClient *server.APIClient +} + +func (tagHandler *NcpTagHandler) AddTag(resType irs.RSType, resIID irs.IID, tag irs.KeyValue) (irs.KeyValue, error) { + cblogger.Info("NCP Classic Cloud driver: called AddTag()!!") + + if resType != irs.VM { + newErr := fmt.Errorf("Only 'VM' type are supported as a resource type to add a Tag on NCP Classic!!") + cblogger.Error(newErr.Error()) + return irs.KeyValue{}, newErr + } + + if strings.EqualFold(resIID.SystemId, "") { + newErr := fmt.Errorf("Invalid Resource SystemId") + cblogger.Error(newErr.Error()) + return irs.KeyValue{}, newErr + } + + _, err := tagHandler.createVMTag(&resIID.SystemId, tag) + if err != nil { + newErr := fmt.Errorf("Failed to Add New Tag : [%v]", err) + cblogger.Error(newErr.Error()) + return irs.KeyValue{}, newErr + } + + tagKV, err := tagHandler.GetTag(resType, resIID, tag.Key) + if err != nil { + newErr := fmt.Errorf("Failed to Get the Tag Info : [%v]", err) + cblogger.Error(newErr.Error()) + return irs.KeyValue{}, newErr + } + return tagKV, nil +} + +func (tagHandler *NcpTagHandler) ListTag(resType irs.RSType, resIID irs.IID) ([]irs.KeyValue, error) { + cblogger.Info("NCP Classic Cloud driver: called ListTag()!!") + + return nil, fmt.Errorf("NCP Cloud Driver does not support ListTag yet.") +} + +func (tagHandler *NcpTagHandler) GetTag(resType irs.RSType, resIID irs.IID, key string) (irs.KeyValue, error) { + cblogger.Info("NCP Classic Cloud driver: called GetTag()!") + + if resType != irs.VM { + newErr := fmt.Errorf("Only 'VM' type are supported as a resource type to add a Tag on NCP Classic!!") + cblogger.Error(newErr.Error()) + return irs.KeyValue{}, newErr + } + + if strings.EqualFold(resIID.SystemId, "") { + newErr := fmt.Errorf("Invalid Resource SystemId") + cblogger.Error(newErr.Error()) + return irs.KeyValue{}, newErr + } + + tagValue, err := tagHandler.getVMTagValue(&resIID.SystemId, key) + if err != nil { + newErr := fmt.Errorf("Failed to Get the Tag Value with the Key : [%v]", err) + cblogger.Error(newErr.Error()) + return irs.KeyValue{}, newErr + } + + tagKV := irs.KeyValue{ + Key: key, + Value: tagValue, + } + return tagKV, nil +} + +func (tagHandler *NcpTagHandler) RemoveTag(resType irs.RSType, resIID irs.IID, key string) (bool, error) { + cblogger.Info("NCP Classic Cloud driver: called RemoveTag()!") + + if resType != irs.VM { + newErr := fmt.Errorf("Only 'VM' type are supported as a resource type to add a Tag on NCP Classic!!") + cblogger.Error(newErr.Error()) + return false, newErr + } + + _, err := tagHandler.GetTag(resType, resIID, key) + if err != nil { + newErr := fmt.Errorf("The Tag with the Key does not exist [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + + _, delErr := tagHandler.deleteVMTag(&resIID.SystemId, key) + if delErr != nil { + newErr := fmt.Errorf("Failed to Remove the Tag with the Key : [%v]", delErr) + cblogger.Error(newErr.Error()) + return false, newErr + } + + return true, nil +} + +func (tagHandler *NcpTagHandler) FindTag(resType irs.RSType, keyword string) ([]*irs.TagInfo, error) { + cblogger.Info("NCP Classic Cloud driver: called FindTag()!") + + if resType != irs.VM { + newErr := fmt.Errorf("Only 'VM' type are supported as a resource type to add a Tag on NCP Classic!!") + cblogger.Error(newErr.Error()) + return nil, newErr + } + + return nil, fmt.Errorf("NCP Cloud Driver does not support FindTag yet.") +} + +func (tagHandler *NcpTagHandler) createVMTag(vmID *string, tag irs.KeyValue) (bool, error) { + cblogger.Info("NCP Classic Cloud driver: called createVMTag()!") + + var instanceNos []*string + var instanceTags []*server.InstanceTagParameter + + instanceNos = append(instanceNos, vmID) + + instanceTags = []*server.InstanceTagParameter { + { + TagKey: ncloud.String(tag.Key), + TagValue: ncloud.String(tag.Value), + }, + } + tagReq := server.CreateInstanceTagsRequest{ + InstanceNoList: instanceNos, + InstanceTagList: instanceTags, + } + tagResult, err := tagHandler.VMClient.V2Api.CreateInstanceTags(&tagReq) + if err != nil { + newErr := fmt.Errorf("Failed to Create the Tag on the VM : [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } else { + cblogger.Infof("Tag Creation Result : [%s]", *tagResult.ReturnMessage) + } + + return true, nil +} + +func (tagHandler *NcpTagHandler) getVMTagValue(vmID *string, key string) (string, error) { + cblogger.Info("NCP Classic Cloud driver: called getVMTagValue()!") + + var instanceNos []*string + var tagValue string + instanceNos = append(instanceNos, vmID) + + tagReq := server.GetInstanceTagListRequest{InstanceNoList: instanceNos} + tagListResult, err := tagHandler.VMClient.V2Api.GetInstanceTagList(&tagReq) + if err != nil { + newErr := fmt.Errorf("Failed to Get VM Tag List from the VM : [%v]", err) + cblogger.Error(newErr.Error()) + return "", newErr + } + if len(tagListResult.InstanceTagList) < 1 { + newErr := fmt.Errorf("Failed to Find Any Tag with the VM SystemID!!") + cblogger.Error(newErr.Error()) + return "", newErr + } else { + cblogger.Infof("Tag Info Listing Result : [%s]", *tagListResult.ReturnMessage) + } + + for _, curTag := range tagListResult.InstanceTagList { + if strings.EqualFold(ncloud.StringValue(curTag.TagKey), key) { + tagValue = ncloud.StringValue(curTag.TagValue) + } + } + if len(tagValue) < 1 { + newErr := fmt.Errorf("Failed to Get the Tag Value with the Key!!") + cblogger.Error(newErr.Error()) + return "", newErr + } + return tagValue, nil +} + +func (tagHandler *NcpTagHandler) deleteVMTag(vmID *string, key string) (bool, error) { + cblogger.Info("NCP Classic Cloud driver: called deleteVMTag()!") + + var instanceNos []*string + var instanceTags []*server.InstanceTagParameter + + instanceNos = append(instanceNos, vmID) + + instanceTags = []*server.InstanceTagParameter { + { + TagKey: ncloud.String(key), + }, + } + tagReq := server.DeleteInstanceTagsRequest { + InstanceNoList: instanceNos, + InstanceTagList: instanceTags, + } + tagResult, err := tagHandler.VMClient.V2Api.DeleteInstanceTags(&tagReq) + if err != nil { + newErr := fmt.Errorf("Failed to Delete the Tag with the Key on the VM : [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } else { + cblogger.Infof("Tag Deletion Result : [%s]", *tagResult.ReturnMessage) + } + + return true, nil +} From 90371bb6de5fab802e5ae80d5ba645d7a4eda720 Mon Sep 17 00:00:00 2001 From: innodreamer Date: Thu, 11 Jul 2024 21:10:00 +0900 Subject: [PATCH 2/3] Update README.md - Add Notice of Tagging --- .../cloud-driver/drivers/ncp/README.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/cloud-control-manager/cloud-driver/drivers/ncp/README.md b/cloud-control-manager/cloud-driver/drivers/ncp/README.md index 4b2015998..16cc222d8 100644 --- a/cloud-control-manager/cloud-driver/drivers/ncp/README.md +++ b/cloud-control-manager/cloud-driver/drivers/ncp/README.md @@ -88,20 +88,25 @@ $CBSPIDER_ROOT/cloud-control-manager/cloud-driver/drivers/ncp/main/ - 사용자가 keyPair 생성시 생성되는 private key를 local에 저장해놓고, 그 private key를 이용해 'cb-user' 계정으로 SSH를 이용해 로그인하는 방법을 제공함. - - Private ket 파일을 이용한 VM 접속 방법 + - Private key 파일을 이용한 Linux 계열 VM 접속 방법 (on CLI) ``` ssh -i /private_key_경로/private_key_파일명(~~.pem) cb-user@VM의_public_ip ``` +​ O Cloud-Barista NCP driver를 이용해 생성된 VM에 로그인하는 방법(Windows 계열 guest OS 경우) -​ (참고) NCP CSP에서 제공하는 VM 접속 방법 + - 'Administrator' 계정으로 VM 생성시 사용자가 지정한 password로 로그인함. - - VM 생성 후, NCP console에서 사용자가 생성한 private key를 이용해 해당 VM의 root 비밀번호를 알아내어 SSH를 이용해 root 계정과 비밀번호로 로그인함. +
-​ O Cloud-Barista NCP driver를 이용해 생성된 VM에 로그인하는 방법(Windows 계열 guest OS 경우) +​ (참고-1) NCP CSP에서 기본적으로 제공하는 VM 접속 방법 + + - VM 생성 후, 사용자가 생성한 private key를 이용해 NCP console에서 해당 VM의 root 비밀번호를 알아내어 SSH를 이용해 root 계정과 비밀번호로 로그인함. - - 'Administrator' 계정으로 VM 생성시 지정한 사용자가 password 로그인함. +​ (참고-2) NCP CSP 콘솔에서 key pair 목록 확인 방법 + + - Sever 메뉴 > Sever > 상단의 '서버 관리 및 설정 변경' > '인증키 관리' 선택


@@ -134,4 +139,7 @@ ssh -i /private_key_경로/private_key_파일명(~~.pem) cb-user@VM의_public_ip - 단, NCP driver나 CB-Spider API를 이용해 NCP VM 반납시에는 VM 반납 후 자동으로 public IP까지 반납됨. + + O NCP Classic은 클라우드 자원들중 VM 기준으로만 tag 생성이 가능함. + ​ O NCP 정책상, VM이 생성된 후 한번 정지시킨 상태에서 연속으로 최대 90일, 12개월 누적 180일을 초과하여 정지할 수 없으며, 해당 기간을 초과할 경우 반납(Terminate)하도록 안내하고 있음. From 9c2b2e7c7e8616d9539d2b498951c55c8d7fcf2f Mon Sep 17 00:00:00 2001 From: innodreamer Date: Thu, 11 Jul 2024 21:11:17 +0900 Subject: [PATCH 3/3] Change cblogger.Error to cblogger.Debug --- .../cloud-driver/drivers/ncp/resources/VMHandler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloud-control-manager/cloud-driver/drivers/ncp/resources/VMHandler.go b/cloud-control-manager/cloud-driver/drivers/ncp/resources/VMHandler.go index 89aa7019d..433dd0524 100644 --- a/cloud-control-manager/cloud-driver/drivers/ncp/resources/VMHandler.go +++ b/cloud-control-manager/cloud-driver/drivers/ncp/resources/VMHandler.go @@ -82,7 +82,7 @@ func (vmHandler *NcpVMHandler) StartVM(vmReqInfo irs.VMReqInfo) (irs.VMInfo, err // Check whether the VM name exists. Search by instanceName converted to lowercase vmId, err := vmHandler.GetVmIdByName(instanceName) if err != nil { - cblogger.Error("The VM with the name is not exists : " + instanceName) + cblogger.Debug("The VM with the name does not exists : " + instanceName) // return irs.VMInfo{}, err //Caution!! } if vmId != "" {