From 3e5f6e72c2c1298277f400ace3d758b46c97e282 Mon Sep 17 00:00:00 2001 From: innodreamer Date: Fri, 5 Apr 2024 20:00:18 +0900 Subject: [PATCH 1/3] Update go.mod and go.sum - Specify KT Cloud VPC Go SDK version --- go.mod | 9 +++++---- go.sum | 7 +++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 0782028b4..6ddc21622 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/cloud-barista/cb-spider -go 1.21 +go 1.21.6 replace ( github.com/IBM/vpc-go-sdk/0.23.0 => github.com/IBM/vpc-go-sdk v0.23.0 @@ -48,7 +48,7 @@ require ( github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.0.493 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc v1.0.206 github.com/uber/jaeger-client-go v2.30.0+incompatible - golang.org/x/crypto v0.20.0 + golang.org/x/crypto v0.21.0 golang.org/x/oauth2 v0.7.0 google.golang.org/api v0.114.0 google.golang.org/grpc v1.56.3 @@ -88,6 +88,7 @@ require ( github.com/alibabacloud-go/tea-xml v1.1.3 // indirect github.com/aliyun/credentials-go v1.3.2 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect + github.com/cloud-barista/ktcloudvpc-sdk-go v0.0.0-20240403081203-a0af52c7c7cd // indirect github.com/itchyny/timefmt-go v0.1.5 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect @@ -177,8 +178,8 @@ require ( go.opencensus.io v0.24.0 // indirect go.uber.org/atomic v1.10.0 // indirect golang.org/x/net v0.21.0 // indirect - golang.org/x/sys v0.17.0 // indirect - golang.org/x/term v0.17.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect golang.org/x/tools v0.6.0 // indirect diff --git a/go.sum b/go.sum index 258b1224d..cbb0b20be 100644 --- a/go.sum +++ b/go.sum @@ -183,6 +183,8 @@ github.com/cloud-barista/cb-log v0.8.0 h1:ArWCs1EgpoD3ZnBgcC4cAw5ufI/JHmFKfJswlv github.com/cloud-barista/cb-log v0.8.0/go.mod h1:nGgfTFMPwl1MpCO3FBjexUkNdOYA0BNJoyM9Pd0lMms= github.com/cloud-barista/ktcloud-sdk-go v0.2.1-0.20240123114820-8684cfc5deeb h1:JAQQ/wBdkcoGCeim+J84F8hIuxbtn/XTe/iDYRsr+t0= github.com/cloud-barista/ktcloud-sdk-go v0.2.1-0.20240123114820-8684cfc5deeb/go.mod h1:ZIrUxItUvMIGZyX6Re7tUdcS3cwBIzBPcL+Pk/6lt/8= +github.com/cloud-barista/ktcloudvpc-sdk-go v0.0.0-20240403081203-a0af52c7c7cd h1:kqSI4usVl5or7+nSvt4IpEG+iTPRxuBavYzoOBkeJ6s= +github.com/cloud-barista/ktcloudvpc-sdk-go v0.0.0-20240403081203-a0af52c7c7cd/go.mod h1:SDTNI+0ZyoEWhQKHASGwhS1a9kad+mxsXCKSfnpWnSA= github.com/cloud-barista/nhncloud-sdk-go v0.0.0-20240403130402-131df63a24b4 h1:hQUzGiMvk7agfONh0aLr9d9tuFArxeUc6bOjKNufGQo= github.com/cloud-barista/nhncloud-sdk-go v0.0.0-20240403130402-131df63a24b4/go.mod h1:G+VjfmHi5IUt0oe14A5UXmbrGFlMTMQjLonBuvjy8Yc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -782,6 +784,8 @@ golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg= golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -992,6 +996,8 @@ golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1003,6 +1009,7 @@ golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From c481dbded5b1cd423fbe2e7c9453e4225c449ecd Mon Sep 17 00:00:00 2001 From: innodreamer Date: Fri, 5 Apr 2024 20:11:16 +0900 Subject: [PATCH 2/3] Add KT Cloud VPC driver Handlers and Test codes of them --- build_all_driver_lib.sh | 2 +- .../ktcloudvpc-plugin/KTCloudVpcDriver-lib.go | 187 ++ .../ktcloudvpc-plugin/build_driver_lib.sh | 16 + .../drivers/ktcloudvpc/KTCloudVpcDriver.go | 185 ++ .../cloud-driver/drivers/ktcloudvpc/README.md | 112 + .../connect/KTCloudVpc_Connection.go | 128 ++ .../main/REST_API_test/0.create_token.sh | 32 + .../main/REST_API_test/1.export.env | 18 + .../main/REST_API_test/10.list_lb.sh | 14 + .../main/REST_API_test/11.list_lb-vm.sh | 16 + .../main/REST_API_test/12.create_lb.sh | 11 + .../main/REST_API_test/2.get_flavor.sh | 6 + .../main/REST_API_test/2.list_flavors.sh | 6 + .../REST_API_test/2.list_flavors_detail.sh | 6 + .../main/REST_API_test/3.create_image.sh | 16 + .../main/REST_API_test/3.get_created_image.sh | 11 + .../main/REST_API_test/3.get_image.sh | 14 + .../main/REST_API_test/3.list_images.sh | 6 + .../main/REST_API_test/4.creat_keypair.sh | 14 + .../main/REST_API_test/4.get_keypair.sh | 6 + .../main/REST_API_test/4.list_keypairs.sh | 6 + .../main/REST_API_test/5.creat_subnet.sh | 25 + .../main/REST_API_test/5.list_networks.sh | 10 + .../main/REST_API_test/6.create_vm.sh | 31 + .../main/REST_API_test/7.get_volume.sh | 6 + .../REST_API_test/7.list_volumes_detail.sh | 6 + .../REST_API_test/8.list_portforwarding.sh | 6 + .../main/REST_API_test/9.creat_FW_rule.sh | 53 + .../ktcloudvpc/main/Test_DiskHandler.go | 294 +++ .../ktcloudvpc/main/Test_ImageHandler.go | 273 +++ .../ktcloudvpc/main/Test_KeyPairHandler.go | 279 +++ .../ktcloudvpc/main/Test_MyImageHandler.go | 257 +++ .../ktcloudvpc/main/Test_NLBHandler.go | 356 +++ .../ktcloudvpc/main/Test_RegionZoneHandler.go | 259 +++ .../ktcloudvpc/main/Test_SecurityHandler.go | 509 +++++ .../drivers/ktcloudvpc/main/Test_VMHandler.go | 386 ++++ .../ktcloudvpc/main/Test_VMSpecHandler.go | 285 +++ .../ktcloudvpc/main/Test_VPCHandler.go | 328 +++ .../ktcloudvpc/main/conf/config.yaml.sample | 37 + .../drivers/ktcloudvpc/main/goget-ktvpcsdk.sh | 8 + .../drivers/ktcloudvpc/main/test_disk.sh | 3 + .../drivers/ktcloudvpc/main/test_image.sh | 3 + .../drivers/ktcloudvpc/main/test_keypair.sh | 3 + .../drivers/ktcloudvpc/main/test_myimage.sh | 3 + .../drivers/ktcloudvpc/main/test_nlb.sh | 3 + .../ktcloudvpc/main/test_region-zone.sh | 3 + .../drivers/ktcloudvpc/main/test_security.sh | 3 + .../drivers/ktcloudvpc/main/test_vm.sh | 3 + .../drivers/ktcloudvpc/main/test_vmspec.sh | 3 + .../drivers/ktcloudvpc/main/test_vpc.sh | 3 + .../ktcloudvpc/resources/CommonKTCloudFunc.go | 254 +++ .../ktcloudvpc/resources/DiskHandler.go | 674 ++++++ .../ktcloudvpc/resources/ImageHandler.go | 248 +++ .../ktcloudvpc/resources/KeyPairHandler.go | 272 +++ .../ktcloudvpc/resources/MyImageHandler.go | 382 ++++ .../ktcloudvpc/resources/NLBHandler.go | 476 ++++ .../ktcloudvpc/resources/RegionZoneHandler.go | 250 +++ .../ktcloudvpc/resources/SecurityHandler.go | 356 +++ .../drivers/ktcloudvpc/resources/VMHandler.go | 1910 +++++++++++++++++ .../ktcloudvpc/resources/VMSpecHandler.go | 204 ++ .../ktcloudvpc/resources/VPCHandler.go | 658 ++++++ 61 files changed, 9933 insertions(+), 1 deletion(-) create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc-plugin/KTCloudVpcDriver-lib.go create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc-plugin/build_driver_lib.sh create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/KTCloudVpcDriver.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/README.md create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/connect/KTCloudVpc_Connection.go create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/0.create_token.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/1.export.env create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/10.list_lb.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/11.list_lb-vm.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/12.create_lb.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/2.get_flavor.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/2.list_flavors.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/2.list_flavors_detail.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/3.create_image.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/3.get_created_image.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/3.get_image.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/3.list_images.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/4.creat_keypair.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/4.get_keypair.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/4.list_keypairs.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/5.creat_subnet.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/5.list_networks.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/6.create_vm.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/7.get_volume.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/7.list_volumes_detail.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/8.list_portforwarding.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/9.creat_FW_rule.sh create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_DiskHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_ImageHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_KeyPairHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_MyImageHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_NLBHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_RegionZoneHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_SecurityHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_VMHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_VMSpecHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_VPCHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/conf/config.yaml.sample create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/goget-ktvpcsdk.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_disk.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_image.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_keypair.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_myimage.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_nlb.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_region-zone.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_security.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_vm.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_vmspec.sh create mode 100755 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_vpc.sh create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/CommonKTCloudFunc.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/DiskHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/ImageHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/KeyPairHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/MyImageHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/NLBHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/RegionZoneHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/SecurityHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/VMHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/VMSpecHandler.go create mode 100644 cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/VPCHandler.go diff --git a/build_all_driver_lib.sh b/build_all_driver_lib.sh index 188d782ca..3b1a612f8 100755 --- a/build_all_driver_lib.sh +++ b/build_all_driver_lib.sh @@ -2,7 +2,7 @@ source setup.env #DRIVERS=( aws-plugin azure-plugin openstack-plugin gcp-plugin alibaba-plugin cloudit-plugin docker-plugin ncp-plugin ncpvpc-plugin) -DRIVERS=( aws-plugin azure-plugin gcp-plugin alibaba-plugin openstack-plugin cloudit-plugin docker-plugin mock-plugin tencent-plugin ibmcloud-vpc-plugin ncp-plugin ncpvpc-plugin nhncloud-plugin ktcloud-plugin ) +DRIVERS=( aws-plugin azure-plugin gcp-plugin alibaba-plugin openstack-plugin cloudit-plugin docker-plugin mock-plugin tencent-plugin ibmcloud-vpc-plugin ncp-plugin ncpvpc-plugin nhncloud-plugin ktcloud-plugin ktcloudvpc-plugin ) DRIVER_PATH=$CBSPIDER_ROOT/cloud-control-manager/cloud-driver/drivers DRIVERLIB_PATH=$CBSPIDER_ROOT/cloud-driver-libs diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc-plugin/KTCloudVpcDriver-lib.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc-plugin/KTCloudVpcDriver-lib.go new file mode 100644 index 000000000..eb607bcf2 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc-plugin/KTCloudVpcDriver-lib.go @@ -0,0 +1,187 @@ +// 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 Example for PoC Test. +// +// by ETRI, 2022.08. +// by ETRI, 2024.04. + +package main + +import ( + "github.com/sirupsen/logrus" + // "github.com/davecgh/go-spew/spew" + + ktvpcsdk "github.com/cloud-barista/ktcloudvpc-sdk-go" + ostack "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack" + + cblog "github.com/cloud-barista/cb-log" + idrv "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/interfaces" + icon "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/interfaces/connect" + + // ktvpccon "github.com/cloud-barista/ktcloudvpc/ktcloudvpc/connect" + ktvpccon "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/connect" //To be built in a container + + // ktvpcrs "github.com/cloud-barista/ktcloudvpc/ktcloudvpc/resources" + ktvpcrs "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources" //To be built in a container +) + +type KTCloudVpcDriver struct{} + +var cblogger *logrus.Logger + +func init() { + // cblog is a global variable. + cblogger = cblog.GetLogger("CB-SPIDER") +} + +func (KTCloudVpcDriver) GetDriverVersion() string { + return "KTCLOUD VPC DRIVER Version 1.0" +} + +func (KTCloudVpcDriver) GetDriverCapability() idrv.DriverCapabilityInfo { + var drvCapabilityInfo idrv.DriverCapabilityInfo + + drvCapabilityInfo.ImageHandler = true + drvCapabilityInfo.VPCHandler = true + drvCapabilityInfo.SecurityHandler = true + drvCapabilityInfo.KeyPairHandler = true + drvCapabilityInfo.VNicHandler = false + drvCapabilityInfo.PublicIPHandler = false + drvCapabilityInfo.VMHandler = true + drvCapabilityInfo.VMSpecHandler = true + drvCapabilityInfo.NLBHandler = true + drvCapabilityInfo.ClusterHandler = false + drvCapabilityInfo.MyImageHandler = true + drvCapabilityInfo.DiskHandler = true + drvCapabilityInfo.RegionZoneHandler = true + drvCapabilityInfo.PriceInfoHandler = false + + drvCapabilityInfo.SINGLE_VPC = true + + return drvCapabilityInfo +} + +func (driver *KTCloudVpcDriver) ConnectCloud(connInfo idrv.ConnectionInfo) (icon.CloudConnection, error) { + // Initialize Logger + ktvpcrs.InitLog() + + authOpts := ktvpcsdk.AuthOptions{ + IdentityEndpoint: connInfo.CredentialInfo.IdentityEndpoint, + Username: connInfo.CredentialInfo.Username, + Password: connInfo.CredentialInfo.Password, + DomainName: connInfo.CredentialInfo.DomainName, + TenantID: connInfo.CredentialInfo.ProjectID, // Caution : ProjectID to TenantID on SDK + } + providerClient, err := ostack.AuthenticatedClient(authOpts) + if err != nil { + return nil, err + } + + VMClient, err := getVMClient(providerClient, connInfo) + if err != nil { + return nil, err + } + + ImageClient, err := getImageClient(providerClient, connInfo) + if err != nil { + return nil, err + } + + NetworkClient, err := getNetworkClient(providerClient, connInfo) + if err != nil { + return nil, err + } + + VolumeClient, err := getVolumeClient(providerClient, connInfo) + if err != nil { + return nil, err + } + + NLBClient, err := getNLBClient(providerClient, connInfo) + if err != nil { + return nil, err + } + + iConn := ktvpccon.KTCloudVpcConnection{ + RegionInfo: connInfo.RegionInfo, + VMClient: VMClient, + ImageClient: ImageClient, + NetworkClient: NetworkClient, + VolumeClient: VolumeClient, + NLBClient: NLBClient, + } + return &iConn, nil +} + +// Caution!! : Region info in real client info from KT Cloud VPC(D1) : Not 'DX-M1' but 'regionOne'. +func getVMClient(providerClient *ktvpcsdk.ProviderClient, connInfo idrv.ConnectionInfo) (*ktvpcsdk.ServiceClient, error) { + client, err := ostack.NewComputeV2(providerClient, ktvpcsdk.EndpointOpts{ + Type: "compute", + Region: connInfo.RegionInfo.Zone, + }) + if err != nil { + return nil, err + } + // cblogger.Info("\n# Result serviceClient : ") + // spew.Dump(client) + // cblogger.Info("\n\n") + + return client, err +} + +func getImageClient(providerClient *ktvpcsdk.ProviderClient, connInfo idrv.ConnectionInfo) (*ktvpcsdk.ServiceClient, error) { + client, err := ostack.NewImageServiceV2(providerClient, ktvpcsdk.EndpointOpts{ + Region: connInfo.RegionInfo.Zone, + }) + if err != nil { + return nil, err + } + // cblogger.Info("\n# Result serviceClient : ") + // spew.Dump(client) + // cblogger.Info("\n\n") + + return client, err +} + +func getNetworkClient(providerClient *ktvpcsdk.ProviderClient, connInfo idrv.ConnectionInfo) (*ktvpcsdk.ServiceClient, error) { + client, err := ostack.NewNetworkV2(providerClient, ktvpcsdk.EndpointOpts{ + Name: "neutron", + Region: connInfo.RegionInfo.Zone, + }) + if err != nil { + return nil, err + } + // cblogger.Info("\n# Result serviceClient : ") + // spew.Dump(client) + // cblogger.Info("\n\n") + + return client, err +} + +func getVolumeClient(providerClient *ktvpcsdk.ProviderClient, connInfo idrv.ConnectionInfo) (*ktvpcsdk.ServiceClient, error) { + client, err := ostack.NewBlockStorageV2(providerClient, ktvpcsdk.EndpointOpts{ + Region: connInfo.RegionInfo.Zone, + }) + if err != nil { + return nil, err + } + + return client, err +} + +func getNLBClient(providerClient *ktvpcsdk.ProviderClient, connInfo idrv.ConnectionInfo) (*ktvpcsdk.ServiceClient, error) { + client, err := ostack.NewLoadBalancerV1(providerClient, ktvpcsdk.EndpointOpts{ + Region: connInfo.RegionInfo.Zone, + }) + if err != nil { + return nil, err + } + + return client, err +} + +var CloudDriver KTCloudVpcDriver // Caution!! diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc-plugin/build_driver_lib.sh b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc-plugin/build_driver_lib.sh new file mode 100755 index 000000000..89466297b --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc-plugin/build_driver_lib.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source $CBSPIDER_ROOT/setup.env + +DRIVERLIB_PATH=$CBSPIDER_ROOT/cloud-driver-libs +DRIVERFILENAME=ktcloudvpc-driver-v1.0 + +go mod download + +function build() { + rm -rf $DRIVERLIB_PATH/${DRIVERFILENAME}.so + go build -buildmode=plugin -o ${DRIVERFILENAME}.so KTCloudVpcDriver-lib.go || return 1 + chmod +x ${DRIVERFILENAME}.so || return 1 + mv ./${DRIVERFILENAME}.so $DRIVERLIB_PATH || return 1 +} + +build diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/KTCloudVpcDriver.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/KTCloudVpcDriver.go new file mode 100644 index 000000000..489abbe47 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/KTCloudVpcDriver.go @@ -0,0 +1,185 @@ +// 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 Example for PoC Test. +// +// by ETRI, 2022.08. +// by ETRI, 2024.04. + +package ktcloudvpc + +import ( + "github.com/sirupsen/logrus" + // "github.com/davecgh/go-spew/spew" + + ktvpcsdk "github.com/cloud-barista/ktcloudvpc-sdk-go" + ostack "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack" + + cblog "github.com/cloud-barista/cb-log" + idrv "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/interfaces" + icon "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/interfaces/connect" + + // ktvpccon "github.com/cloud-barista/ktcloudvpc/ktcloudvpc/connect" + ktvpccon "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/connect" //To be built in the container1 + + // ktvpcrs "github.com/cloud-barista/ktcloudvpc/ktcloudvpc/resources" + ktvpcrs "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources" //To be built in the container +) + +type KTCloudVpcDriver struct{} + +var cblogger *logrus.Logger + +func init() { + // cblog is a global variable. + cblogger = cblog.GetLogger("CB-SPIDER") +} + +func (KTCloudVpcDriver) GetDriverVersion() string { + return "KTCLOUD VPC DRIVER Version 1.0" +} + +func (KTCloudVpcDriver) GetDriverCapability() idrv.DriverCapabilityInfo { + var drvCapabilityInfo idrv.DriverCapabilityInfo + + drvCapabilityInfo.ImageHandler = true + drvCapabilityInfo.VPCHandler = true + drvCapabilityInfo.SecurityHandler = true + drvCapabilityInfo.KeyPairHandler = true + drvCapabilityInfo.VNicHandler = false + drvCapabilityInfo.PublicIPHandler = false + drvCapabilityInfo.VMHandler = true + drvCapabilityInfo.VMSpecHandler = true + drvCapabilityInfo.NLBHandler = true + drvCapabilityInfo.ClusterHandler = false + drvCapabilityInfo.MyImageHandler = true + drvCapabilityInfo.DiskHandler = true + drvCapabilityInfo.RegionZoneHandler = true + drvCapabilityInfo.PriceInfoHandler = false + + drvCapabilityInfo.SINGLE_VPC = true + + return drvCapabilityInfo +} + +func (driver *KTCloudVpcDriver) ConnectCloud(connInfo idrv.ConnectionInfo) (icon.CloudConnection, error) { + // Initialize Logger + ktvpcrs.InitLog() + + authOpts := ktvpcsdk.AuthOptions{ + IdentityEndpoint: connInfo.CredentialInfo.IdentityEndpoint, + Username: connInfo.CredentialInfo.Username, + Password: connInfo.CredentialInfo.Password, + DomainName: connInfo.CredentialInfo.DomainName, + TenantID: connInfo.CredentialInfo.ProjectID, // Caution : ProjectID to TenantID on SDK + } + providerClient, err := ostack.AuthenticatedClient(authOpts) + if err != nil { + return nil, err + } + + VMClient, err := getVMClient(providerClient, connInfo) + if err != nil { + return nil, err + } + + ImageClient, err := getImageClient(providerClient, connInfo) + if err != nil { + return nil, err + } + + NetworkClient, err := getNetworkClient(providerClient, connInfo) + if err != nil { + return nil, err + } + + VolumeClient, err := getVolumeClient(providerClient, connInfo) + if err != nil { + return nil, err + } + + NLBClient, err := getNLBClient(providerClient, connInfo) + if err != nil { + return nil, err + } + + iConn := ktvpccon.KTCloudVpcConnection{ + RegionInfo: connInfo.RegionInfo, + VMClient: VMClient, + ImageClient: ImageClient, + NetworkClient: NetworkClient, + VolumeClient: VolumeClient, + NLBClient: NLBClient, + } + return &iConn, nil +} + +// Caution!! : Region info in real client info from KT Cloud VPC(D1) : Not 'DX-M1' but 'regionOne'. +func getVMClient(providerClient *ktvpcsdk.ProviderClient, connInfo idrv.ConnectionInfo) (*ktvpcsdk.ServiceClient, error) { + client, err := ostack.NewComputeV2(providerClient, ktvpcsdk.EndpointOpts{ + Type: "compute", + Region: connInfo.RegionInfo.Zone, + }) + if err != nil { + return nil, err + } + // cblogger.Info("\n# Result serviceClient : ") + // spew.Dump(client) + // cblogger.Info("\n\n") + + return client, err +} + +func getImageClient(providerClient *ktvpcsdk.ProviderClient, connInfo idrv.ConnectionInfo) (*ktvpcsdk.ServiceClient, error) { + client, err := ostack.NewImageServiceV2(providerClient, ktvpcsdk.EndpointOpts{ + Region: connInfo.RegionInfo.Zone, + }) + if err != nil { + return nil, err + } + // cblogger.Info("\n# Result serviceClient : ") + // spew.Dump(client) + // cblogger.Info("\n\n") + + return client, err +} + +func getNetworkClient(providerClient *ktvpcsdk.ProviderClient, connInfo idrv.ConnectionInfo) (*ktvpcsdk.ServiceClient, error) { + client, err := ostack.NewNetworkV2(providerClient, ktvpcsdk.EndpointOpts{ + Name: "neutron", + Region: connInfo.RegionInfo.Zone, + }) + if err != nil { + return nil, err + } + // cblogger.Info("\n# Result serviceClient : ") + // spew.Dump(client) + // cblogger.Info("\n\n") + + return client, err +} + +func getVolumeClient(providerClient *ktvpcsdk.ProviderClient, connInfo idrv.ConnectionInfo) (*ktvpcsdk.ServiceClient, error) { + client, err := ostack.NewBlockStorageV2(providerClient, ktvpcsdk.EndpointOpts{ + Region: connInfo.RegionInfo.Zone, + }) + if err != nil { + return nil, err + } + + return client, err +} + +func getNLBClient(providerClient *ktvpcsdk.ProviderClient, connInfo idrv.ConnectionInfo) (*ktvpcsdk.ServiceClient, error) { + client, err := ostack.NewLoadBalancerV1(providerClient, ktvpcsdk.EndpointOpts{ + Region: connInfo.RegionInfo.Zone, + }) + if err != nil { + return nil, err + } + + return client, err +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/README.md b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/README.md new file mode 100644 index 000000000..2f89b6086 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/README.md @@ -0,0 +1,112 @@ +### KT Cloud VPC(D1 platform) Connection driver Build 및 CB-Spider에 적용 방법 + +#### # 연동 Driver 관련 기본적인 사항은 아래 link 참고 + + - [Cloud Driver Developer Guide](https://github.com/cloud-barista/cb-spider/wiki/Cloud-Driver-Developer-Guide) +


+ +#### # CB-Spider에 KT Cloud VPC 연동 driver 적용 방법 + +​ O 위에서와 같이 CB-Spider 코드가 clone된 상태에서 CB-Spider setup 파일 적용 +``` +$CBSPIDER_ROOT/ source setup.env +``` + +​ O Dynamic plugin mode로 'CB-Spider' 및 driver build 실행 + +``` +cd $CBSPIDER_ROOT + +make dyna +``` + - CB-Spider build 과정이 완료되면, $CBSPIDER_ROOT/bin/ 아래에 binary 파일로 'cb-spider-dyna' 가 생김 + - 각 driver는 $CBSPIDER_ROOT/cloud-driver-libs/ 아래에 binary 파일로 'ktcloudvpc-driver-v1.0.so' 와 같이 생성됨. + +


+ +​ O CB-Spider server 구동(Dynamic plugin 방식, 1024 포트로 REST API server가 구동됨) + +``` +cd $CBSPIDER_ROOT/bin + +./start-dyna.sh +``` + + - CB-Spider server가 구동된 후, KT Cloud VPC driver 등록 과정을 거치고 사용 + +


+ +#### # CB-Spider에 KT Cloud VPC 연동 driver 테스트 방법 + +​ O 아래의 KT Cloud VPC connection config script 파일에 KT Cloud VPC Credential 정보 기입 후 실행
+ +``` +$CBSPIDER_ROOT/api-runtime/rest-runtime/test/connect-config/15.ktcloudvpc-conn-config.sh +``` +


+ +#### # CB-Spider REST API 이용 KT Cloud VPC driver 모든 기능 테스트 + +​ O KT Cloud VPC 각 자원 생성, 자원정보 조회, VM instance Start 및 Terminate 테스트 등 실행 가능 + +- Curl command를 이용하여 CB-Spider REST API를 호출하는 테스트 script 이용 +``` +$CBSPIDER_ROOT/api-runtime/rest-runtime/test/full-test/14.ktcloudvpc-test.sh +$CBSPIDER_ROOT/api-runtime/rest-runtime/test/full-test/ktcloudvpc-full_test.sh +``` +


+ +#### # KT Cloud VPC 연동 driver 자체 test 파일을 이용한 기능 테스트 + +​ O CB-Spider 환경 파일 적용 +``` +$CBSPIDER_ROOT/ source setup.env +``` + +​ O 아래의 config 파일에 KT Cloud VPC Credential 정보 기입 +``` +$CBSPIDER_ROOT/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/conf/config.yaml +``` + +​ O 아래의 위치에 있는 ~.sh 파일을 실행해서 KT Cloud VPC driver 각 handler 세부 기능 테스트 +``` +$CBSPIDER_ROOT/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/ +``` +


+ +#### # KT Cloud VPC 연동 driver를 이용해 생성한 VM에 로그인하는 방법 + +​ O Cloud-Barista KT Cloud VPC driver를 이용해 생성된 VM에 로그인하는 방법 + + - Linux 계열 guest OS의 경우, 사용자가 keyPair 생성시 생성되는 private key를 local에 저장해놓고, 그 private key를 이용해 'cb-user' 계정으로 SSH를 이용해 로그인함. + + - Private key 파일을 이용한 Linux 계열 VM 접속 방법 + +``` +ssh -i /private_key_경로/private_key_파일명(~~.pem) cb-user@VM의_public_ip +``` + +


+ +#### # KTCloud VPC (KT Cloud D1 플랫폼) driver 사용시 참고 및 주의 사항 + +​ O VPC, Subnet 관리시 아래의 사항을 참고 + + - KTCloud VPC에서는 단일(default) VPC를 제공하며, 단일 VPC를 제공하지만 driver를 기준으로는 어떤 이름으로든 생성 가능하고, 삭제도 제공함. + - Default CIDR : 172.25.0.0/12 + - 본 Drvier 기준으로는 이 defualt VPC에 사용자가 지정하는 이름이 붙여짐. + + - KTCloud VPC 서비스에서는 Subnet과 같은 개념으로 'Tier'라는 개념을 사용함. + - VPC는 상기와 같이 단일 VPC를 제공하지만, subnet은 추가, 삭제 등의 제어가 가능함.(AddSubnet, RemoveSubnet 기능 지원함.) + - (주의) Default subnet(tier)인 'DMZ'과 'Private' subnet은 삭제 할 수 없으며, 기본적으로 아래의 CIDR을 사용하고 있으니 subnet 생성시 아래의 대역 외의 CIDR을 지정해야함. + - DMZ subnet : 172.25.0.1/24, Private subnet : 172.25.1.1/24 + + - VPC의 CIDR은 위의 대역이지만, subnet (Tier) 생성시 172.25.X.X 외에도 Custom Tier로서 10.10.X.X, 192.168.X.X 등의 대역을 자유롭게 지정해서 생성할 수 있음.(VM에 그 대역의 private IP가 할당됨.) + + - (참고) Create/Add Subnet시 log에 Error가 발생해도 무시하면됨. KT Cloud D1 Platform의 버그임. + +​ O Security Group 생성시 아래의 사항을 참고 + + - KTCloud VPC에서는 Security Group(S/G) 개념을 지원하지 않지만, 본 드라이버에서 S/G을 생성한 후 VM 생성시 그 S/G을 적용 가능함. + - 사용자가 S/G을 정의하면, 드라이버 내부적으로, VM 생성시 public IP가 생성된 후 그 S/G rule들이 Port forwarding rule, Firewall rule로 전환되어 반영됨. + - KTCloud VPC에서는 outbound rule도 지원하기 때문에 VM에서 outbound 통신이 필요시 반드시 S/G의 outbound 로서 해당 protocol 및 port를 열여줘야함. diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/connect/KTCloudVpc_Connection.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/connect/KTCloudVpc_Connection.go new file mode 100644 index 000000000..7bc302f12 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/connect/KTCloudVpc_Connection.go @@ -0,0 +1,128 @@ +// 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 Example for PoC Test. +// +// by ETRI, 2022.08. + +package connect + +import ( + "fmt" + "github.com/sirupsen/logrus" + + cblog "github.com/cloud-barista/cb-log" + 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" + + ktvpcsdk "github.com/cloud-barista/ktcloudvpc-sdk-go" + + // ktvpcrs "github.com/cloud-barista/ktcloudvpc/ktcloudvpc/resources" + ktvpcrs "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources" //To be built in the container +) + +var cblogger *logrus.Logger + +func init() { + // cblog is a global variable. + cblogger = cblog.GetLogger("CB-SPIDER") +} + +type KTCloudVpcConnection struct { + CredentialInfo idrv.CredentialInfo + RegionInfo idrv.RegionInfo + VMClient *ktvpcsdk.ServiceClient + ImageClient *ktvpcsdk.ServiceClient + NetworkClient *ktvpcsdk.ServiceClient + VolumeClient *ktvpcsdk.ServiceClient + NLBClient *ktvpcsdk.ServiceClient +} + +func (cloudConn *KTCloudVpcConnection) CreateVMHandler() (irs.VMHandler, error) { + cblogger.Info("KT Cloud VPC Driver: called CreateVMHandler()!") + vmHandler := ktvpcrs.KTVpcVMHandler{CredentialInfo: cloudConn.CredentialInfo, RegionInfo: cloudConn.RegionInfo, VMClient: cloudConn.VMClient, ImageClient: cloudConn.ImageClient, NetworkClient: cloudConn.NetworkClient, VolumeClient: cloudConn.VolumeClient} + return &vmHandler, nil +} + +func (cloudConn *KTCloudVpcConnection) CreateImageHandler() (irs.ImageHandler, error) { + cblogger.Info("KT Cloud VPC Driver: called CreateImageHandler()!") + imageHandler := ktvpcrs.KTVpcImageHandler{RegionInfo: cloudConn.RegionInfo, VMClient: cloudConn.VMClient, ImageClient: cloudConn.ImageClient} + return &imageHandler, nil +} + +func (cloudConn *KTCloudVpcConnection) CreateVMSpecHandler() (irs.VMSpecHandler, error) { + cblogger.Info("KT Cloud VPC Driver: called CreateVMSpecHandler()!") + vmSpecHandler := ktvpcrs.KTVpcVMSpecHandler{RegionInfo: cloudConn.RegionInfo, VMClient: cloudConn.VMClient} + return &vmSpecHandler, nil +} + +func (cloudConn *KTCloudVpcConnection) CreateKeyPairHandler() (irs.KeyPairHandler, error) { + cblogger.Info("KT Cloud VPC Driver: called CreateKeyPairHandler()!") + keypairHandler := ktvpcrs.KTVpcKeyPairHandler{CredentialInfo: cloudConn.CredentialInfo, RegionInfo: cloudConn.RegionInfo, VMClient: cloudConn.VMClient} + return &keypairHandler, nil +} + +func (cloudConn KTCloudVpcConnection) CreateSecurityHandler() (irs.SecurityHandler, error) { + cblogger.Info("KT Cloud VPC Driver: called CreateSecurityHandler()!") + securityHandler := ktvpcrs.KTVpcSecurityHandler{RegionInfo: cloudConn.RegionInfo, VMClient: cloudConn.VMClient, NetworkClient: cloudConn.NetworkClient} + return &securityHandler, nil +} + +func (cloudConn *KTCloudVpcConnection) CreateVPCHandler() (irs.VPCHandler, error) { + cblogger.Info("KT Cloud VPC Driver: called CreateVPCHandler()!") + vpcHandler := ktvpcrs.KTVpcVPCHandler{RegionInfo: cloudConn.RegionInfo, NetworkClient: cloudConn.NetworkClient} + return &vpcHandler, nil +} + +func (cloudConn *KTCloudVpcConnection) CreateNLBHandler() (irs.NLBHandler, error) { + cblogger.Info("KT Cloud Driver: called CreateNLBHandler()!") + nlbHandler := ktvpcrs.KTVpcNLBHandler{RegionInfo: cloudConn.RegionInfo, VMClient: cloudConn.VMClient, NetworkClient: cloudConn.NetworkClient, NLBClient: cloudConn.NLBClient} + return &nlbHandler, nil +} + +func (cloudConn *KTCloudVpcConnection) CreateDiskHandler() (irs.DiskHandler, error) { + cblogger.Info("KT Cloud VPC Driver: called CreateDiskHandler()!") + diskHandler := ktvpcrs.KTVpcDiskHandler{RegionInfo: cloudConn.RegionInfo, VMClient: cloudConn.VMClient, VolumeClient: cloudConn.VolumeClient} + return &diskHandler, nil +} + +func (cloudConn *KTCloudVpcConnection) CreateClusterHandler() (irs.ClusterHandler, error) { + cblogger.Info("KT Cloud VPC Driver: called CreateClusterHandler()!") + + return nil, fmt.Errorf("KT Cloud VPC Driver does not support ClusterHandler yet.") +} + +func (cloudConn *KTCloudVpcConnection) CreateMyImageHandler() (irs.MyImageHandler, error) { + cblogger.Info("KT Cloud VPC Driver: called CreateMyImageHandler()!") + myimageHandler := ktvpcrs.KTVpcMyImageHandler{RegionInfo: cloudConn.RegionInfo, VMClient: cloudConn.VMClient, ImageClient: cloudConn.ImageClient, NetworkClient: cloudConn.NetworkClient, VolumeClient: cloudConn.VolumeClient} + return &myimageHandler, nil +} + +func (cloudConn *KTCloudVpcConnection) CreateAnyCallHandler() (irs.AnyCallHandler, error) { + cblogger.Info("KT Cloud VPC Driver: called CreateAnyCallHandler()!") + + return nil, fmt.Errorf("KT Cloud VPC Driver does not support AnyCallHandler yet.") +} + +func (cloudConn *KTCloudVpcConnection) CreateRegionZoneHandler() (irs.RegionZoneHandler, error) { + cblogger.Info("KT Cloud VPC Driver: called CreateRegionZoneHandler()!") + regionZoneHandler := ktvpcrs.KTVpcRegionZoneHandler{RegionInfo: cloudConn.RegionInfo,} + return ®ionZoneHandler, nil +} + +func (cloudConn *KTCloudVpcConnection) CreatePriceInfoHandler() (irs.PriceInfoHandler, error) { + cblogger.Info("KT Cloud VPC Driver: called CreatePriceInfoHandler()!") + + return nil, fmt.Errorf("KT Cloud VPC Driver does not support PriceInfoHandler yet.") +} + +func (cloudConn *KTCloudVpcConnection) IsConnected() (bool, error) { + return true, nil +} + +func (cloudConn *KTCloudVpcConnection) Close() error { + return nil +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/0.create_token.sh b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/0.create_token.sh new file mode 100755 index 000000000..5d7a5a8b3 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/0.create_token.sh @@ -0,0 +1,32 @@ +echo "curl -v -s -X POST https://api.ucloudbiz.olleh.com/d1/identity/auth/tokens" +curl -v -s -X POST 'https://api.ucloudbiz.olleh.com/d1/identity/auth/tokens' --header 'Content-Type: application/json' \ +--data-raw ' +{ + "auth": { + "identity": { + "methods": ["password"], + "password": { + "user": { + "domain": { + "id": "default" + }, + "name": "~~~~~@~~~~~~~~", + "password": "XXXXXXXXXX" + } + } + }, + + "scope": { + "project": { + "domain": { + "id": "default" + }, + "name": "~~~~~@~~~~~~~~" + } + } + } +}' ; echo + +echo -e "\n" + +# String 입력시 양쪽에 [] 기호는 없이 입력해야함. diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/1.export.env b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/1.export.env new file mode 100755 index 000000000..dc51fd7b1 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/1.export.env @@ -0,0 +1,18 @@ +#!/bin/bash +export OS_TOKEN="XXXXXXXXXXXXXXXXXXXX" + +export OS_COMPUTE_API="https://api.ucloudbiz.olleh.com/d1/server" +export OS_IMAGE_API="https://api.ucloudbiz.olleh.com/d1/image" +export OS_NETWORK_API="https://api.ucloudbiz.olleh.com/d1/nc" +export OS_VOLUME_API="https://api.ucloudbiz.olleh.com/d1/volume" + +export PROJECT_ID="~~~~~~~~~~~~~~~~~~~~~~~~~" + +export IMAGE_ID="~~~~~~~~~~~~~~~~~~~~~~~~~" +export CREATED_IMAGE_ID="~~~~~~~~~~~~~~~~~~~~~~~~~" + +export FLAVOR_ID="~~~~~~~~~~~~~~~~~~~~~~~~~" +# 'Flavor' means 'VMSpec'. + +export KEYPAIR_NAME="~~~~~~~~~~~~~~~~~~~~~~~~~" +export VOLUME_ID="~~~~~~~~~~~~~~~~~~~~~~~~~" diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/10.list_lb.sh b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/10.list_lb.sh new file mode 100755 index 000000000..94994724c --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/10.list_lb.sh @@ -0,0 +1,14 @@ +#!/bin/bash +source ./1.export.env_mine + +echo "### OS_LB_API - LB List" +echo "curl -v $OS_LB_API?command=listLoadBalancers&zoneid=DX-M1&response=json" +# echo "curl -v $OS_LB_API?command=listLoadBalancers&zoneid=DX-M1&response=json" + +curl -v -H "X-Auth-Token: $OS_TOKEN" $OS_LB_API?command=listLoadBalancers + +# curl -v -H "X-Auth-Token: $OS_TOKEN" $OS_LB_API?command=listLoadBalancers&zoneid=DX-M1&response=json +# 이것도 동일한 결과 +# => &response=json 않붙여도됨. + +echo -e "\n" diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/11.list_lb-vm.sh b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/11.list_lb-vm.sh new file mode 100755 index 000000000..c2c860ef0 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/REST_API_test/11.list_lb-vm.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ./1.export.env_mine + +echo "### OS_LB_API - LB List" +echo "curl -v $OS_LB_API?command=listLoadBalancerWebServers&loadbalancerid=38288&response=json" + +#curl -v -H "X-Auth-Token: $OS_TOKEN" $OS_LB_API?command=listLoadBalancerWebServers&loadbalancerid=38288&response=json +# curl -v -H "X-Auth-Token: $OS_TOKEN" $OS_LB_API?command=listLoadBalancerWebServers&loadbalancerid=38288 +#echo -e "\n" + +curl -v -H "X-Auth-Token: $OS_TOKEN" $OS_LB_API?command=listLoadBalancerWebServers&loadbalancerid=38288&multi_stack_id=11&response=json + +echo -e "\n" + +# 온라인 고객센터로부터 안내된 예: +# "Image" +func getResourceHandler(handlerType string) (interface{}, error) { + var cloudDriver idrv.CloudDriver + cloudDriver = new(ktvpcdrv.KTCloudVpcDriver) + + config := readConfigFile() + // spew.Dump(config) + + connectionInfo := idrv.ConnectionInfo{ + CredentialInfo: idrv.CredentialInfo{ + IdentityEndpoint: config.KTCloudVPC.IdentityEndpoint, + Username: config.KTCloudVPC.Username, + Password: config.KTCloudVPC.Password, + DomainName: config.KTCloudVPC.DomainName, + ProjectID: config.KTCloudVPC.ProjectID, + }, + RegionInfo: idrv.RegionInfo{ + Region: config.KTCloudVPC.Region, + Zone: config.KTCloudVPC.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() + } + + if err != nil { + return nil, err + } + return resourceHandler, nil +} + +type Config struct { + KTCloudVPC struct { + IdentityEndpoint string `yaml:"identity_endpoint"` + Username string `yaml:"username"` + Password string `yaml:"password"` + DomainName string `yaml:"domain_name"` + ProjectID string `yaml:"project_id"` + Region string `yaml:"region"` + Zone string `yaml:"zone"` + + VMName string `yaml:"vm_name"` + ImageId string `yaml:"image_id"` + VMSpecId string `yaml:"vmspec_id"` + NetworkId string `yaml:"network_id"` + SecurityGroups string `yaml:"security_groups"` + KeypairName string `yaml:"keypair_name"` + + VMId string `yaml:"vm_id"` + DiskID string `yaml:"disk_id"` + ReqDiskName string `yaml:"req_disk_name"` + + Image struct { + Name string `yaml:"name"` + } `yaml:"image_info"` + + KeyPair struct { + Name string `yaml:"name"` + } `yaml:"keypair_info"` + + PublicIP struct { + Name string `yaml:"name"` + } `yaml:"public_info"` + + SecurityGroup struct { + Name string `yaml:"name"` + } `yaml:"security_group_info"` + + VirtualNetwork struct { + Name string `yaml:"name"` + } `yaml:"vnet_info"` + + Subnet struct { + Id string `yaml:"id"` + } `yaml:"subnet_info"` + + Router struct { + Name string `yaml:"name"` + GateWayId string `yaml:"gateway_id"` + AdminStateUp bool `yaml:"adminstatup"` + } `yaml:"router_info"` + } `yaml:"ktcloudvpc"` +} + +func readConfigFile() Config { + // Set Environment Value of Project Root Path + rootPath := os.Getenv("CBSPIDER_ROOT") + configPath := rootPath + "/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/conf/config.yaml" + cblogger.Debugf("Test Environment Config : [%s]", configPath) + + data, err := os.ReadFile(configPath) + if err != nil { + cblogger.Error(err) + } + + var config Config + err = yaml.Unmarshal(data, &config) + if err != nil { + cblogger.Error(err) + } + return config +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_ImageHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_ImageHandler.go new file mode 100644 index 000000000..31c5a273c --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_ImageHandler.go @@ -0,0 +1,273 @@ +// 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, 2022.08. + +package main + +import ( + "os" + "errors" + "fmt" + "github.com/davecgh/go-spew/spew" + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" + + ktvpcdrv "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/drivers/ktcloudvpc" + + 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" +) + +var cblogger *logrus.Logger + +func init() { + // cblog is a global variable. + cblogger = cblog.GetLogger("KT Cloud VPC Resource Test") + cblog.SetLevel("info") +} + +func handleImage() { + cblogger.Debug("Start ImageHandler Resource Test") + + ResourceHandler, err := getResourceHandler("Image") + if err != nil { + panic(err) + } + + handler := ResourceHandler.(irs.ImageHandler) + + for { + fmt.Println("\n============================================================================================") + fmt.Println("[ Image Management Test ]") + fmt.Println("1. Image List") + fmt.Println("2. Image Get") + fmt.Println("3. Image Create (TBD)") + fmt.Println("4. Image Delete (TBD)") + fmt.Println("0. Quit") + fmt.Println("\n Select a number above!! : ") + fmt.Println("============================================================================================") + + var commandNum int + inputCnt, err := fmt.Scan(&commandNum) + if err != nil { + panic(err) + } + + imageReqInfo := irs.ImageReqInfo{ + // IId: irs.IID{NameId: "d3f14f02-15b8-445e-9fb6-4cbd3f3c3387", SystemId: "d3f14f02-15b8-445e-9fb6-4cbd3f3c3387"}, + //KT Cloud VPC : ubuntu-18.04-64bit-221115 + + IId: irs.IID{NameId: "c6814d96-9746-42eb-a7d3-80f31d9cd297", SystemId: "c6814d96-9746-42eb-a7d3-80f31d9cd297"}, + //KT Cloud VPC : ubuntu-18.04-64bit + } + + if inputCnt == 1 { + switch commandNum { + case 0: + return + + case 1: + cblogger.Infof("Image list 조회 테스트") + + result, err := handler.ListImage() + if err != nil { + cblogger.Error(err) + cblogger.Error("Image list 조회 실패 : ", err) + } else { + fmt.Println("\n==================================================================================================================") + cblogger.Info("Image list 조회 결과") + //cblogger.Info(result) + cblogger.Info("출력 결과 수 : ", len(result)) + + fmt.Println("\n") + spew.Dump(result) + + cblogger.Info("출력 결과 수 : ", len(result)) + + //조회및 삭제 테스트를 위해 리스트의 첫번째 정보의 ID를 요청ID로 자동 갱신함. + if result != nil { + imageReqInfo.IId = result[0].IId // 조회 및 삭제를 위해 생성된 ID로 변경 + } + } + + cblogger.Info("\nListImage Test Finished") + + case 2: + cblogger.Infof("[%s] Image 조회 테스트", imageReqInfo.IId) + + result, err := handler.GetImage(imageReqInfo.IId) + if err != nil { + cblogger.Error("[%s] Image 조회 실패 : ", imageReqInfo.IId.SystemId, err) + } else { + fmt.Println("\n==================================================================================================================") + cblogger.Infof("[%s] Image 조회 결과 : \n[%s]", imageReqInfo.IId.SystemId, result) + + fmt.Println("\n") + spew.Dump(result) + } + + cblogger.Info("\nGetImage Test Finished") + + // case 3: + // cblogger.Infof("[%s] Image 생성 테스트", imageReqInfo.IId.NameId) + // result, err := handler.CreateImage(imageReqInfo) + // if err != nil { + // cblogger.Infof(imageReqInfo.IId.NameId, " Image 생성 실패 : ", err) + // } else { + // cblogger.Infof("Image 생성 결과 : ", result) + // imageReqInfo.IId = result.IId // 조회 및 삭제를 위해 생성된 ID로 변경 + // spew.Dump(result) + // } + + // case 4: + // cblogger.Infof("[%s] Image 삭제 테스트", imageReqInfo.IId.NameId) + // result, err := handler.DeleteImage(imageReqInfo.IId) + // if err != nil { + // cblogger.Infof("[%s] Image 삭제 실패 : ", imageReqInfo.IId.NameId, err) + // } else { + // cblogger.Infof("[%s] Image 삭제 결과 : [%s]", imageReqInfo.IId.NameId, result) + // } + } + } + } +} + +func testErr() error { + + return errors.New("") +} + +func main() { + cblogger.Info("KT Cloud VPC Resource Test") + + handleImage() +} + +//handlerType : resources폴더의 xxxHandler.go에서 Handler이전까지의 문자열 +//(예) ImageHandler.go -> "Image" +func getResourceHandler(handlerType string) (interface{}, error) { + var cloudDriver idrv.CloudDriver + cloudDriver = new(ktvpcdrv.KTCloudVpcDriver) + + config := readConfigFile() + // spew.Dump(config) + + connectionInfo := idrv.ConnectionInfo{ + CredentialInfo: idrv.CredentialInfo{ + IdentityEndpoint: config.KTCloudVPC.IdentityEndpoint, + Username: config.KTCloudVPC.Username, + Password: config.KTCloudVPC.Password, + DomainName: config.KTCloudVPC.DomainName, + ProjectID: config.KTCloudVPC.ProjectID, + }, + RegionInfo: idrv.RegionInfo{ + Region: config.KTCloudVPC.Region, + Zone: config.KTCloudVPC.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() + } + + if err != nil { + return nil, err + } + return resourceHandler, nil +} + +type Config struct { + KTCloudVPC struct { + IdentityEndpoint string `yaml:"identity_endpoint"` + Username string `yaml:"username"` + Password string `yaml:"password"` + DomainName string `yaml:"domain_name"` + ProjectID string `yaml:"project_id"` + Region string `yaml:"region"` + Zone string `yaml:"zone"` + + VMName string `yaml:"vm_name"` + ImageId string `yaml:"image_id"` + VMSpecId string `yaml:"vmspec_id"` + NetworkId string `yaml:"network_id"` + SecurityGroups string `yaml:"security_groups"` + KeypairName string `yaml:"keypair_name"` + + VMId string `yaml:"vm_id"` + + Image struct { + Name string `yaml:"name"` + } `yaml:"image_info"` + + KeyPair struct { + Name string `yaml:"name"` + } `yaml:"keypair_info"` + + PublicIP struct { + Name string `yaml:"name"` + } `yaml:"public_info"` + + SecurityGroup struct { + Name string `yaml:"name"` + } `yaml:"security_group_info"` + + VirtualNetwork struct { + Name string `yaml:"name"` + } `yaml:"vnet_info"` + + Subnet struct { + Id string `yaml:"id"` + } `yaml:"subnet_info"` + + Router struct { + Name string `yaml:"name"` + GateWayId string `yaml:"gateway_id"` + AdminStateUp bool `yaml:"adminstatup"` + } `yaml:"router_info"` + } `yaml:"ktcloudvpc"` +} + +func readConfigFile() Config { + // Set Environment Value of Project Root Path + rootPath := os.Getenv("CBSPIDER_ROOT") + configPath := rootPath + "/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/conf/config.yaml" + cblogger.Debugf("Test Environment Config : [%s]", configPath) + + data, err := os.ReadFile(configPath) + if err != nil { + cblogger.Error(err) + } + + var config Config + err = yaml.Unmarshal(data, &config) + if err != nil { + cblogger.Error(err) + } + return config +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_KeyPairHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_KeyPairHandler.go new file mode 100644 index 000000000..78e8e9a6b --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_KeyPairHandler.go @@ -0,0 +1,279 @@ +// 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, 2022.08. + +package main + +import ( + "os" + "errors" + "fmt" + "github.com/davecgh/go-spew/spew" + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" + + ktvpcdrv "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/drivers/ktcloudvpc" + + 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" +) + +var cblogger *logrus.Logger + +func init() { + // cblog is a global variable. + cblogger = cblog.GetLogger("KT Cloud VPC Resource Test") + cblog.SetLevel("info") +} + +func testErr() error { + + return errors.New("") +} + +// Test KeyPair +func handleKeyPair() { + cblogger.Debug("Start KeyPair Resource Test") + + ResourceHandler, err := getResourceHandler("KeyPair") + if err != nil { + panic(err) + } + keyPairHandler := ResourceHandler.(irs.KeyPairHandler) + + for { + fmt.Println("\n============================================================================================") + fmt.Println("[ KeyPair Management Test ]") + fmt.Println("1. List KeyPair") + fmt.Println("2. Get KeyPair") + fmt.Println("3. Create KeyPair") + fmt.Println("4. Delete KeyPair") + fmt.Println("0. Quit") + fmt.Println("\n Select a number above!! : ") + fmt.Println("============================================================================================") + + var commandNum int + config := readConfigFile() + + keyPairName := config.KTCloudVPC.KeypairName + reqKeypairName := config.KTCloudVPC.ReqKeypairName + + inputCnt, err := fmt.Scan(&commandNum) + if err != nil { + panic(err) + } + + if inputCnt == 1 { + switch commandNum { + case 0: + return + + case 1: + result, err := keyPairHandler.ListKey() + if err != nil { + cblogger.Error(err) + cblogger.Error("KeyPair list 조회 실패 : ", err) + } else { + cblogger.Info("KeyPair list 조회 결과") + //cblogger.Info(result) + spew.Dump(result) + + cblogger.Infof("=========== KeyPair list 수 : [%d] ================", len(result)) + } + cblogger.Info("\nListKey Test Finished") + + case 2: + cblogger.Infof("[%s] KeyPair 조회 테스트", keyPairName) + result, err := keyPairHandler.GetKey(irs.IID{NameId: keyPairName}) + if err != nil { + cblogger.Error(err) + cblogger.Error(keyPairName, " KeyPair 조회 실패 : ", err) + } else { + cblogger.Infof("[%s] KeyPair 조회 결과 : \n[%s]", keyPairName, result) + spew.Dump(result) + } + cblogger.Info("\nGetKey Test Finished") + + case 3: + cblogger.Infof("[%s] KeyPair 생성 테스트", reqKeypairName) + keyPairReqInfo := irs.KeyPairReqInfo{ + IId: irs.IID{NameId: reqKeypairName}, + //Name: keyPairName, + } + result, err := keyPairHandler.CreateKey(keyPairReqInfo) + if err != nil { + cblogger.Error(err) + cblogger.Error(reqKeypairName, " KeyPair 생성 실패 : ", err) + } else { + cblogger.Infof("[%s] KeyPair 생성 결과 : \n[%s]", reqKeypairName, result) + spew.Dump(result) + } + cblogger.Info("\nCreateKey Test Finished") + + case 4: + cblogger.Infof("[%s] KeyPair 삭제 테스트", keyPairName) + result, err := keyPairHandler.DeleteKey(irs.IID{NameId: keyPairName}) + if err != nil { + cblogger.Error(err) + cblogger.Error(keyPairName, " KeyPair 삭제 실패 : ", err) + } else { + cblogger.Infof("[%s] KeyPair 삭제 결과 : [%s]", keyPairName, result) + spew.Dump(result) + } + cblogger.Info("\nDeleteKey Test Finished") + } + } + } +} + +func main() { + cblogger.Info("KT Cloud VPC Resource Test") + + handleKeyPair() +} + +//handlerType : resources폴더의 xxxHandler.go에서 Handler이전까지의 문자열 +//(예) ImageHandler.go -> "Image" +func getResourceHandler(handlerType string) (interface{}, error) { + var cloudDriver idrv.CloudDriver + cloudDriver = new(ktvpcdrv.KTCloudVpcDriver) + + config := readConfigFile() + // spew.Dump(config) + + connectionInfo := idrv.ConnectionInfo{ + CredentialInfo: idrv.CredentialInfo{ + IdentityEndpoint: config.KTCloudVPC.IdentityEndpoint, + Username: config.KTCloudVPC.Username, + Password: config.KTCloudVPC.Password, + DomainName: config.KTCloudVPC.DomainName, + ProjectID: config.KTCloudVPC.ProjectID, + }, + RegionInfo: idrv.RegionInfo{ + Region: config.KTCloudVPC.Region, + Zone: config.KTCloudVPC.Zone, + }, + } + + // NOTE Just for test + //cblogger.Info(config.Ncp.NcpAccessKeyID) + //cblogger.Info(config.Ncp.NcpSecretKey) + + 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 "KeyPair": + resourceHandler, err = cloudConnection.CreateKeyPairHandler() + 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() + } + + if err != nil { + return nil, err + } + return resourceHandler, nil +} + +// Region : 사용할 리전명 (ex) ap-northeast-2 +// ImageID : VM 생성에 사용할 AMI ID (ex) ami-047f7b46bd6dd5d84 +// BaseName : 다중 VM 생성 시 사용할 Prefix이름 ("BaseName" + "_" + "숫자" 형식으로 VM을 생성 함.) (ex) mcloud-barista +// VmID : 라이프 사이트클을 테스트할 EC2 인스턴스ID +// InstanceType : VM 생성시 사용할 인스턴스 타입 (ex) t2.micro +// KeyName : VM 생성시 사용할 키페어 이름 (ex) mcloud-barista-keypair +// MinCount : +// MaxCount : +// SubnetId : VM이 생성될 VPC의 SubnetId (ex) subnet-cf9ccf83 +// SecurityGroupID : 생성할 VM에 적용할 보안그룹 ID (ex) sg-0df1c209ea1915e4b +type Config struct { + KTCloudVPC struct { + IdentityEndpoint string `yaml:"identity_endpoint"` + Username string `yaml:"username"` + Password string `yaml:"password"` + DomainName string `yaml:"domain_name"` + ProjectID string `yaml:"project_id"` + Region string `yaml:"region"` + Zone string `yaml:"zone"` + + VMName string `yaml:"vm_name"` + ImageId string `yaml:"image_id"` + VMSpecId string `yaml:"vmspec_id"` + NetworkId string `yaml:"network_id"` + SecurityGroups string `yaml:"security_groups"` + KeypairName string `yaml:"keypair_name"` + ReqKeypairName string `yaml:"req_keypair_name"` + + VMId string `yaml:"vm_id"` + + Image struct { + Name string `yaml:"name"` + } `yaml:"image_info"` + + KeyPair struct { + Name string `yaml:"name"` + } `yaml:"keypair_info"` + + PublicIP struct { + Name string `yaml:"name"` + } `yaml:"public_info"` + + SecurityGroup struct { + Name string `yaml:"name"` + } `yaml:"security_group_info"` + + VirtualNetwork struct { + Name string `yaml:"name"` + } `yaml:"vnet_info"` + + Subnet struct { + Id string `yaml:"id"` + } `yaml:"subnet_info"` + + Router struct { + Name string `yaml:"name"` + GateWayId string `yaml:"gateway_id"` + AdminStateUp bool `yaml:"adminstatup"` + } `yaml:"router_info"` + } `yaml:"ktcloudvpc"` +} + +func readConfigFile() Config { + // Set Environment Value of Project Root Path + rootPath := os.Getenv("CBSPIDER_ROOT") + configPath := rootPath + "/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/conf/config.yaml" + cblogger.Debugf("Test Environment Config : [%s]", configPath) + + data, err := os.ReadFile(configPath) + if err != nil { + cblogger.Error(err) + } + + var config Config + err = yaml.Unmarshal(data, &config) + if err != nil { + cblogger.Error(err) + } + return config +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_MyImageHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_MyImageHandler.go new file mode 100644 index 000000000..cbdb1f002 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_MyImageHandler.go @@ -0,0 +1,257 @@ +// 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.01. + +package main + +import ( + "os" + "errors" + "fmt" + "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" + + ktvpcdrv "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/drivers/ktcloudvpc" +) + +var cblogger *logrus.Logger + +func init() { + // cblog is a global variable. + cblogger = cblog.GetLogger("KT Cloud VPC Resource Test") + cblog.SetLevel("info") +} + +func handleMyImage() { + cblogger.Debug("Start MyImage Resource Test") + + resourceHandler, err := getResourceHandler("MyImage") + if err != nil { + cblogger.Error(err) + return + } + diskHandler := resourceHandler.(irs.MyImageHandler) + //config := readConfigFile() + + for { + fmt.Println("\n============================================================================================") + fmt.Println("[ MyImageHandler Test ]") + cblogger.Info("1. ListMyImage()") + cblogger.Info("2. GetMyImage()") + cblogger.Info("3. SnapshotVM()") + cblogger.Info("4. DeleteMyImage()") + cblogger.Info("5. ChangeMyImageSize()") + cblogger.Info("6. AttachMyImage()") + cblogger.Info("7. DetachMyImage()") + cblogger.Info("0. Exit") + fmt.Println("\n Select a number above!! : ") + fmt.Println("============================================================================================") + + var commandNum int + + myImageIId := irs.IID{ + NameId: "ktvpc-disk-01", + SystemId: "18c1f485-f06c-47f2-8d05-a25b9a4bb0fc", + } + + snapshotReqInfo := irs.MyImageInfo{ + IId: irs.IID{ + NameId: "ktvpc-myimage-03", + }, + SourceVM: irs.IID{ + NameId: "kt-vm-api-29", + SystemId: "d5d679e1-8239-43c1-9b8b-0c8d33767370", + }, + } + + inputCnt, err := fmt.Scan(&commandNum) + if err != nil { + panic(err) + } + + if inputCnt == 1 { + switch commandNum { + case 0: + return + case 1: + cblogger.Info("Start ListMyImage() ...") + if listResult, err := diskHandler.ListMyImage(); err != nil { + cblogger.Error(err) + } else { + spew.Dump(listResult) + cblogger.Info("# 출력 결과 수 : ", len(listResult)) + } + cblogger.Info("Finish ListMyImage()") + case 2: + cblogger.Info("Start GetMyImage() ...") + if diskInfo, err := diskHandler.GetMyImage(myImageIId); err != nil { + cblogger.Error(err) + } else { + spew.Dump(diskInfo) + } + cblogger.Info("Finish GetMyImage()") + case 3: + cblogger.Info("Start SnapshotVM() ...") + if diskInfo, err := diskHandler.SnapshotVM(snapshotReqInfo); err != nil { + cblogger.Error(err) + } else { + spew.Dump(diskInfo) + } + cblogger.Info("Finish SnapshotVM()") + case 4: + cblogger.Info("Start DeleteMyImage() ...") + if delResult, err := diskHandler.DeleteMyImage(myImageIId); err != nil { + cblogger.Error(err) + } else { + spew.Dump(delResult) + } + cblogger.Info("Finish DeleteMyImage()") + } + } + } +} + +func testErr() error { + + return errors.New("") +} + +func main() { + cblogger.Info("KT Cloud VPC Resource Test") + handleMyImage() +} + +//handlerType : resources폴더의 xxxHandler.go에서 Handler이전까지의 문자열 +//(예) ImageHandler.go -> "Image" +func getResourceHandler(handlerType string) (interface{}, error) { + var cloudDriver idrv.CloudDriver + cloudDriver = new(ktvpcdrv.KTCloudVpcDriver) + + config := readConfigFile() + // spew.Dump(config) + + connectionInfo := idrv.ConnectionInfo{ + CredentialInfo: idrv.CredentialInfo{ + IdentityEndpoint: config.KTCloudVPC.IdentityEndpoint, + Username: config.KTCloudVPC.Username, + Password: config.KTCloudVPC.Password, + DomainName: config.KTCloudVPC.DomainName, + ProjectID: config.KTCloudVPC.ProjectID, + }, + RegionInfo: idrv.RegionInfo{ + Region: config.KTCloudVPC.Region, + Zone: config.KTCloudVPC.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 "MyImage": + resourceHandler, err = cloudConnection.CreateMyImageHandler() + } + + if err != nil { + return nil, err + } + return resourceHandler, nil +} + +type Config struct { + KTCloudVPC struct { + IdentityEndpoint string `yaml:"identity_endpoint"` + Username string `yaml:"username"` + Password string `yaml:"password"` + DomainName string `yaml:"domain_name"` + ProjectID string `yaml:"project_id"` + Region string `yaml:"region"` + Zone string `yaml:"zone"` + + VMName string `yaml:"vm_name"` + ImageId string `yaml:"image_id"` + VMSpecId string `yaml:"vmspec_id"` + NetworkId string `yaml:"network_id"` + SecurityGroups string `yaml:"security_groups"` + KeypairName string `yaml:"keypair_name"` + + VMId string `yaml:"vm_id"` + + Image struct { + Name string `yaml:"name"` + } `yaml:"image_info"` + + KeyPair struct { + Name string `yaml:"name"` + } `yaml:"keypair_info"` + + PublicIP struct { + Name string `yaml:"name"` + } `yaml:"public_info"` + + SecurityGroup struct { + Name string `yaml:"name"` + } `yaml:"security_group_info"` + + VirtualNetwork struct { + Name string `yaml:"name"` + } `yaml:"vnet_info"` + + Subnet struct { + Id string `yaml:"id"` + } `yaml:"subnet_info"` + + Router struct { + Name string `yaml:"name"` + GateWayId string `yaml:"gateway_id"` + AdminStateUp bool `yaml:"adminstatup"` + } `yaml:"router_info"` + } `yaml:"ktcloudvpc"` +} + +func readConfigFile() Config { + // Set Environment Value of Project Root Path + rootPath := os.Getenv("CBSPIDER_ROOT") + configPath := rootPath + "/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/conf/config.yaml" + cblogger.Debugf("Test Environment Config : [%s]", configPath) + + data, err := os.ReadFile(configPath) + if err != nil { + cblogger.Error(err) + } + + var config Config + err = yaml.Unmarshal(data, &config) + if err != nil { + cblogger.Error(err) + } + return config +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_NLBHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_NLBHandler.go new file mode 100644 index 000000000..b3ea80244 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_NLBHandler.go @@ -0,0 +1,356 @@ +// 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, 2022.08. + +package main + +import ( + "os" + "fmt" + "github.com/davecgh/go-spew/spew" + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" + + ktvpcdrv "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/drivers/ktcloudvpc" + + cblog "github.com/cloud-barista/cb-log" + 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" +) + +var cblogger *logrus.Logger + +func init() { + // cblog is a global variable. + cblogger = cblog.GetLogger("KT Cloud VPC Resource Test") + cblog.SetLevel("info") +} + +// Test VMSpec +func handleNLB() { + cblogger.Debug("Start NLBHandler Resource Test") + + ResourceHandler, err := getResourceHandler("NLB") + if err != nil { + panic(err) + } + + nlbHandler := ResourceHandler.(irs.NLBHandler) + + for { + fmt.Println("\n============================================================================================") + fmt.Println("[ NLB Resource Test ]") + cblogger.Info("1. ListNLB()") + cblogger.Info("2. GetNLB()") + cblogger.Info("3. CreateNLB()") + cblogger.Info("4. DeleteNLB()") + cblogger.Info("5. ChangeListener()") + cblogger.Info("6. ChangeVMGroupInfo()") + cblogger.Info("7. AddVMs()") + cblogger.Info("8. RemoveVMs()") + cblogger.Info("9. GetVMGroupHealthInfo()") + cblogger.Info("10. ChangeHealthCheckerInfo()") + cblogger.Info("11. Exit") + fmt.Println("============================================================================================") + + config := readConfigFile() + cblogger.Info("# config.KTCloudVPC.Zone : ", config.KTCloudVPC.Zone) + + nlbIId := irs.IID{ + NameId: "lb-dx-01", + SystemId: config.KTCloudVPC.NLBId, + } + + nlbCreateReqInfo := irs.NLBInfo{ + IId: irs.IID{ + NameId: "kt-lb-driver-03", // To Create + }, + VpcIID: irs.IID{ + NameId: "Default Network", + }, + Listener: irs.ListenerInfo{ + Protocol: "TCP", + Port: "80", + }, + VMGroup: irs.VMGroupInfo{ + Protocol: "TCP", + Port: "80", + // VMs: &[]irs.IID{ + // {NameId: "kt-vm-api-05"}, + // }, + }, + HealthChecker: irs.HealthCheckerInfo{ + Protocol: "TCP", + Port: "80", + Interval: 30, + Timeout: 5, + Threshold: 3, + }, + } + + updateListener := irs.ListenerInfo{ + Protocol: "TCP", + Port: "8087", + } + updateVMGroups := irs.VMGroupInfo{ + Protocol: "TCP", + Port: "8080", + } + addVMs := []irs.IID{ + {NameId: "kt-vm-api-05"}, + } + removeVMs := []irs.IID{ + {NameId: "ktvpc-vm-01"}, + } + + updateHealthCheckerInfo := irs.HealthCheckerInfo{ + Protocol: "HTTP", + Port: "8080", + Interval: 7, + Timeout: 5, + Threshold: 4, + } + + var commandNum int + + inputCnt, err := fmt.Scan(&commandNum) + if err != nil { + panic(err) + } + + if inputCnt == 1 { + switch commandNum { + case 1: + cblogger.Info("Start ListNLB() ...") + if list, err := nlbHandler.ListNLB(); err != nil { + cblogger.Error(err) + } else { + spew.Dump(list) + cblogger.Infof("전체 list 개수 : [%d]", len(list)) + } + cblogger.Info("Finish ListNLB()") + case 2: + cblogger.Info("Start GetNLB() ...") + if vm, err := nlbHandler.GetNLB(nlbIId); err != nil { + cblogger.Error(err) + } else { + spew.Dump(vm) + } + cblogger.Info("Finish GetNLB()") + case 3: + cblogger.Info("Start CreateNLB() ...") + if createInfo, err := nlbHandler.CreateNLB(nlbCreateReqInfo); err != nil { + cblogger.Error(err) + } else { + spew.Dump(createInfo) + } + cblogger.Info("Finish CreateNLB()") + case 4: + cblogger.Info("Start DeleteNLB() ...") + if vmStatus, err := nlbHandler.DeleteNLB(nlbIId); err != nil { + cblogger.Error(err) + } else { + spew.Dump(vmStatus) + } + cblogger.Info("Finish DeleteNLB()") + case 5: + cblogger.Info("Start ChangeListener() ...") + if nlbInfo, err := nlbHandler.ChangeListener(nlbIId, updateListener); err != nil { + cblogger.Error(err) + } else { + spew.Dump(nlbInfo) + } + cblogger.Info("Finish ChangeListener()") + case 6: + cblogger.Info("Start ChangeVMGroupInfo() ...") + if info, err := nlbHandler.ChangeVMGroupInfo(nlbIId, updateVMGroups); err != nil { + cblogger.Error(err) + } else { + spew.Dump(info) + } + cblogger.Info("Finish ChangeVMGroupInfo()") + case 7: + cblogger.Info("Start AddVMs() ...") + if info, err := nlbHandler.AddVMs(nlbIId, &addVMs); err != nil { + cblogger.Error(err) + } else { + spew.Dump(info) + } + cblogger.Info("Finish AddVMs()") + case 8: + cblogger.Info("Start RemoveVMs() ...") + if result, err := nlbHandler.RemoveVMs(nlbIId, &removeVMs); err != nil { + cblogger.Error(err) + } else { + spew.Dump(result) + } + cblogger.Info("Finish RemoveVMs()") + case 9: + cblogger.Info("Start GetVMGroupHealthInfo() ...") + if result, err := nlbHandler.GetVMGroupHealthInfo(nlbIId); err != nil { + cblogger.Error(err) + } else { + spew.Dump(result) + } + cblogger.Info("Finish GetVMGroupHealthInfo()") + case 10: + cblogger.Info("Start ChangeHealthCheckerInfo() ...") + if info, err := nlbHandler.ChangeHealthCheckerInfo(nlbIId, updateHealthCheckerInfo); err != nil { + cblogger.Error(err) + } else { + spew.Dump(info) + } + cblogger.Info("Finish ChangeHealthCheckerInfo()") + case 11: + cblogger.Info("Exit") + } + } + } +} + +func main() { + cblogger.Info("KT Cloud VPC Resource Test") + + handleNLB() +} + +//handlerType : resources폴더의 xxxHandler.go에서 Handler이전까지의 문자열 +//(예) ImageHandler.go -> "Image" +func getResourceHandler(handlerType string) (interface{}, error) { + var cloudDriver idrv.CloudDriver + cloudDriver = new(ktvpcdrv.KTCloudVpcDriver) + + config := readConfigFile() + // spew.Dump(config) + + connectionInfo := idrv.ConnectionInfo{ + CredentialInfo: idrv.CredentialInfo{ + IdentityEndpoint: config.KTCloudVPC.IdentityEndpoint, + Username: config.KTCloudVPC.Username, + Password: config.KTCloudVPC.Password, + DomainName: config.KTCloudVPC.DomainName, + ProjectID: config.KTCloudVPC.ProjectID, + }, + RegionInfo: idrv.RegionInfo{ + Region: config.KTCloudVPC.Region, + Zone: config.KTCloudVPC.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 "NLB": + resourceHandler, err = cloudConnection.CreateNLBHandler() + } + + if err != nil { + return nil, err + } + return resourceHandler, nil +} + +// Region : 사용할 리전명 (ex) ap-northeast-2 +// ImageID : VM 생성에 사용할 AMI ID (ex) ami-047f7b46bd6dd5d84 +// BaseName : 다중 VM 생성 시 사용할 Prefix이름 ("BaseName" + "_" + "숫자" 형식으로 VM을 생성 함.) (ex) mcloud-barista +// VmID : 라이프 사이트클을 테스트할 EC2 인스턴스ID +// InstanceType : VM 생성시 사용할 인스턴스 타입 (ex) t2.micro +// KeyName : VM 생성시 사용할 키페어 이름 (ex) mcloud-barista-keypair +// MinCount : +// MaxCount : +// SubnetId : VM이 생성될 VPC의 SubnetId (ex) subnet-cf9ccf83 +// SecurityGroupID : 생성할 VM에 적용할 보안그룹 ID (ex) sg-0df1c209ea1915e4b +type Config struct { + KTCloudVPC struct { + IdentityEndpoint string `yaml:"identity_endpoint"` + Username string `yaml:"username"` + Password string `yaml:"password"` + DomainName string `yaml:"domain_name"` + ProjectID string `yaml:"project_id"` + Region string `yaml:"region"` + Zone string `yaml:"zone"` + + VMName string `yaml:"vm_name"` + ImageId string `yaml:"image_id"` + VMSpecId string `yaml:"vmspec_id"` + NetworkId string `yaml:"network_id"` + NLBId string `yaml:"nlb_id"` + SecurityGroups string `yaml:"security_groups"` + KeypairName string `yaml:"keypair_name"` + + VMId string `yaml:"vm_id"` + + Image struct { + Name string `yaml:"name"` + } `yaml:"image_info"` + + KeyPair struct { + Name string `yaml:"name"` + } `yaml:"keypair_info"` + + PublicIP struct { + Name string `yaml:"name"` + } `yaml:"public_info"` + + SecurityGroup struct { + Name string `yaml:"name"` + } `yaml:"security_group_info"` + + VirtualNetwork struct { + Name string `yaml:"name"` + } `yaml:"vnet_info"` + + Subnet struct { + Id string `yaml:"id"` + } `yaml:"subnet_info"` + + Router struct { + Name string `yaml:"name"` + GateWayId string `yaml:"gateway_id"` + AdminStateUp bool `yaml:"adminstatup"` + } `yaml:"router_info"` + } `yaml:"ktcloudvpc"` +} + +func readConfigFile() Config { + // Set Environment Value of Project Root Path + rootPath := os.Getenv("CBSPIDER_ROOT") + configPath := rootPath + "/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/conf/config.yaml" + cblogger.Debugf("Test Environment Config : [%s]", configPath) + + data, err := os.ReadFile(configPath) + if err != nil { + cblogger.Error(err) + } + + var config Config + err = yaml.Unmarshal(data, &config) + if err != nil { + cblogger.Error(err) + } + return config +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_RegionZoneHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_RegionZoneHandler.go new file mode 100644 index 000000000..8f2c01024 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_RegionZoneHandler.go @@ -0,0 +1,259 @@ +// 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, 2023.10. + +package main + +import ( + "os" + "fmt" + + ktvpcdrv "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/drivers/ktcloudvpc" + + 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" + "github.com/davecgh/go-spew/spew" + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" + + cblog "github.com/cloud-barista/cb-log" +) + +var cblogger *logrus.Logger + +func init() { + // cblog is a global variable. + cblogger = cblog.GetLogger("NHN Cloud Resource Test") + cblog.SetLevel("info") +} + +// Test RegionZone +func handleRegionZone() { + cblogger.Debug("Start RegionZoneHandler Resource Test") + + ResourceHandler, err := getResourceHandler("RegionZone") + if err != nil { + panic(err) + } + handler := ResourceHandler.(irs.RegionZoneHandler) + + for { + fmt.Println("\n============================================================================================") + fmt.Println("[ RegionZone Resource Test ]") + fmt.Println("1. ListRegionZone()") + fmt.Println("2. GetRegionZone()") + fmt.Println("3. ListOrgRegion()") + fmt.Println("4. ListOrgZone()") + fmt.Println("0. Exit") + fmt.Println("\n Select a number above!! : ") + fmt.Println("============================================================================================") + + config := readConfigFile() + reqRegion := config.KTCloudVPC.Region // Region Code Ex) KR, HK, SGN, JPN, DEN, USWN + cblogger.Info("config.KTCloudVPC.Region : ", reqRegion) + + var commandNum int + inputCnt, err := fmt.Scan(&commandNum) + if err != nil { + panic(err) + } + + if inputCnt == 1 { + switch commandNum { + case 1: + fmt.Println("Start ListRegionZone() ...") + result, err := handler.ListRegionZone() + if err != nil { + cblogger.Error("RegionZone list 조회 실패 : ", err) + } else { + fmt.Println("\n==================================================================================================") + cblogger.Debug("RegionZone list 조회 성공!!") + spew.Dump(result) + cblogger.Debug(result) + cblogger.Infof("RegionZone list 개수 : [%d]", len(result)) + } + fmt.Println("\n# ListRegionZone() Test Finished") + + case 2: + fmt.Println("Start ListOrgRegion() ...") + result, err := handler.GetRegionZone(reqRegion) + if err != nil { + cblogger.Error("Region(Org) list 정보 조회 실패 : ", err) + } else { + fmt.Println("\n==================================================================================================") + cblogger.Debug("Region Info 조회 성공!!") + spew.Dump(result) + cblogger.Debug(result) + } + fmt.Println("\n# GetRegionZone() Test Finished") + + case 3: + fmt.Println("Start ListOrgRegion() ...") + result, err := handler.ListOrgRegion() + if err != nil { + cblogger.Error("Region(Org) list 정보 조회 실패 : ", err) + } else { + fmt.Println("\n==================================================================================================") + cblogger.Debug("Region(Org) list 조회 성공!!") + spew.Dump(result) + cblogger.Debug(result) + } + fmt.Println("\n# ListOrgRegion() Test Finished") + + case 4: + fmt.Println("Start ListOrgZone() ...") + result, err := handler.ListOrgZone() + if err != nil { + cblogger.Error("Zone(Org) list 조회 실패 : ", err) + } else { + fmt.Println("\n==================================================================================================") + cblogger.Debug("Zone(Org) list 조회 성공") + spew.Dump(result) + cblogger.Debug(result) + } + fmt.Println("\n# ListOrgZone() Test Finished") + + case 0: + fmt.Println("Exit") + return + } + } + } +} + +func main() { + cblogger.Info("NHN Cloud Resource Test") + + handleRegionZone() +} + +//handlerType : resources폴더의 xxxHandler.go에서 Handler이전까지의 문자열 +//(예) ImageHandler.go -> "Image" +func getResourceHandler(handlerType string) (interface{}, error) { + var cloudDriver idrv.CloudDriver + cloudDriver = new(ktvpcdrv.KTCloudVpcDriver) + + config := readConfigFile() + // spew.Dump(config) + + connectionInfo := idrv.ConnectionInfo{ + CredentialInfo: idrv.CredentialInfo{ + IdentityEndpoint: config.KTCloudVPC.IdentityEndpoint, + Username: config.KTCloudVPC.Username, + Password: config.KTCloudVPC.Password, + DomainName: config.KTCloudVPC.DomainName, + ProjectID: config.KTCloudVPC.ProjectID, + }, + RegionInfo: idrv.RegionInfo{ + Region: config.KTCloudVPC.Region, + Zone: config.KTCloudVPC.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 "NLB": + resourceHandler, err = cloudConnection.CreateNLBHandler() + case "RegionZone": + resourceHandler, err = cloudConnection.CreateRegionZoneHandler() + } + + if err != nil { + return nil, err + } + return resourceHandler, nil +} + +type Config struct { + KTCloudVPC struct { + IdentityEndpoint string `yaml:"identity_endpoint"` + Username string `yaml:"username"` + Password string `yaml:"password"` + DomainName string `yaml:"domain_name"` + ProjectID string `yaml:"project_id"` + Region string `yaml:"region"` + Zone string `yaml:"zone"` + + VMName string `yaml:"vm_name"` + ImageId string `yaml:"image_id"` + VMSpecId string `yaml:"vmspec_id"` + NetworkId string `yaml:"network_id"` + SecurityGroups string `yaml:"security_groups"` + KeypairName string `yaml:"keypair_name"` + + VMId string `yaml:"vm_id"` + + Image struct { + Name string `yaml:"name"` + } `yaml:"image_info"` + + KeyPair struct { + Name string `yaml:"name"` + } `yaml:"keypair_info"` + + PublicIP struct { + Name string `yaml:"name"` + } `yaml:"public_info"` + + SecurityGroup struct { + Name string `yaml:"name"` + } `yaml:"security_group_info"` + + VirtualNetwork struct { + Name string `yaml:"name"` + } `yaml:"vnet_info"` + + Subnet struct { + Id string `yaml:"id"` + } `yaml:"subnet_info"` + + Router struct { + Name string `yaml:"name"` + GateWayId string `yaml:"gateway_id"` + AdminStateUp bool `yaml:"adminstatup"` + } `yaml:"router_info"` + } `yaml:"ktcloudvpc"` +} + +func readConfigFile() Config { + // Set Environment Value of Project Root Path + rootPath := os.Getenv("CBSPIDER_ROOT") + configPath := rootPath + "/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/conf/config.yaml" + cblogger.Debugf("Test Environment Config : [%s]", configPath) + + data, err := os.ReadFile(configPath) + if err != nil { + cblogger.Error(err) + } + + var config Config + err = yaml.Unmarshal(data, &config) + if err != nil { + cblogger.Error(err) + } + return config +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_SecurityHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_SecurityHandler.go new file mode 100644 index 000000000..2ee036367 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_SecurityHandler.go @@ -0,0 +1,509 @@ +// 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, 2022.08. + +package main + +import ( + "os" + "errors" + "fmt" + "github.com/davecgh/go-spew/spew" + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" + + ktvpcdrv "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/drivers/ktcloudvpc" + + 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" +) + +var cblogger *logrus.Logger + +func init() { + // cblog is a global variable. + cblogger = cblog.GetLogger("KT Cloud VPC Resource Test") + cblog.SetLevel("info") +} + +func handleSecurity() { + cblogger.Debug("Start Security Resource Test") + + ResourceHandler, err := getResourceHandler("Security") + if err != nil { + panic(err) + } + + handler := ResourceHandler.(irs.SecurityHandler) + + //config := readConfigFile() + + for { + fmt.Println("\n============================================================================================") + fmt.Println("[ Security Management Test ]") + fmt.Println("1. List Security") + fmt.Println("2. Get Security") + fmt.Println("3. Create Security") + fmt.Println("4. Add Rules") + fmt.Println("5. Remove Rules") + fmt.Println("6. Delete Security") + fmt.Println("0. Quit") + fmt.Println("\n Select a number above!! : ") + fmt.Println("============================================================================================") + + var commandNum int + + securityName := "ktvpc-sg-1" + securityId := "ktvpc-sg-1" + vpcId := "60e5d9da-55cd-47be-a0d9-6cf67c54f15c" + // vpcNameId := "nhn-vpc-01" + + inputCnt, err := fmt.Scan(&commandNum) + if err != nil { + panic(err) + } + + if inputCnt == 1 { + switch commandNum { + case 0: + return + + case 1: + result, err := handler.ListSecurity() + if err != nil { + cblogger.Error(err) + cblogger.Error("SecurityGroup list 조회 실패 : ", err) + } else { + cblogger.Info("SecurityGroup list 조회 결과") + //cblogger.Info(result) + spew.Dump(result) + + cblogger.Infof("=========== S/G list 수 : [%d] ================", len(result)) + if result != nil { + securityId = result[0].IId.SystemId // 조회 및 삭제를 위해 생성된 ID로 변경 + } + } + + cblogger.Info("\nListSecurity Test Finished") + + case 2: + cblogger.Infof("[%s] SecurityGroup 정보 조회 테스트", securityId) + result, err := handler.GetSecurity(irs.IID{SystemId: securityId}) + // result, err := handler.GetSecurity(irs.IID{NameId: securityName}) + if err != nil { + cblogger.Error(err) + cblogger.Error(securityId, " SecurityGroup 조회 실패 : ", err) + } else { + cblogger.Infof("[%s] SecurityGroup 조회 결과 : [%v]", securityId, result) + spew.Dump(result) + } + + cblogger.Info("\nGetSecurity Test Finished") + + case 3: + cblogger.Infof("[%s] Security 생성 테스트", securityName) + + securityReqInfo := irs.SecurityReqInfo{ + IId: irs.IID{NameId: securityName}, + VpcIID: irs.IID{SystemId: vpcId}, + // VpcIID: irs.IID{NameId: vpcNameId}, + SecurityRules: &[]irs.SecurityRuleInfo{ //보안 정책 설정 + // { + // Direction: "inbound", + // IPProtocol: "tcp", + // FromPort: "20", + // ToPort: "22", + // CIDR: "0.0.0.0/0", + // }, + + // { + // Direction: "inbound", + // IPProtocol: "tcp", + // FromPort: "80", + // ToPort: "80", + // CIDR: "0.0.0.0/0", + // }, + // { + // Direction: "inbound", + // IPProtocol: "tcp", + // FromPort: "-1", + // ToPort: "-1", + // CIDR: "192.168.0.0/16", + // }, + + // { + // Direction: "inbound", + // IPProtocol: "udp", + // FromPort: "8080", + // ToPort: "8080", + // CIDR: "0.0.0.0/0", + // }, + // { + // Direction: "inbound", + // IPProtocol: "icmp", + // FromPort: "-1", + // ToPort: "-1", + // CIDR: "0.0.0.0/0", + // }, + // { + // Direction: "outbound", + // IPProtocol: "tcp", + // FromPort: "443", + // ToPort: "443", + // CIDR: "0.0.0.0/0", + // }, + + // { + // Direction: "outbound", + // IPProtocol: "tcp", + // FromPort: "8443", + // ToPort: "9999", + // CIDR: "192.168.0.0/16", + // }, + + + // // All traffic 허용 rule + { + Direction: "inbound", + IPProtocol: "ALL", + FromPort: "-1", + ToPort: "-1", + CIDR: "0.0.0.0/0", + }, + + { + Direction: "outbound", + IPProtocol: "ALL", + FromPort: "-1", + ToPort: "-1", + CIDR: "0.0.0.0/0", + }, + + }, + } + + result, err := handler.CreateSecurity(securityReqInfo) + if err != nil { + cblogger.Infof(securityName, " Security 생성 실패 : ", err) + } else { + cblogger.Infof("[%s] Security 생성 결과 : [%v]", securityName, result) + spew.Dump(result) + } + + case 4: + cblogger.Infof("[%s] Security Rule 추가 테스트", securityName) + + securityRuleReqInfo := &[]irs.SecurityRuleInfo{ + // { + // Direction: "inbound", + // IPProtocol: "tcp", + // FromPort: "20", + // ToPort: "22", + // CIDR: "0.0.0.0/0", + // }, + + // { + // Direction: "inbound", + // IPProtocol: "tcp", + // FromPort: "80", + // ToPort: "80", + // CIDR: "192.168.0.0/16", + // }, + // { + // Direction: "inbound", + // IPProtocol: "tcp", + // FromPort: "-1", + // ToPort: "-1", + // CIDR: "192.168.0.0/16", + // }, + + // { + // Direction: "inbound", + // IPProtocol: "udp", + // FromPort: "8080", + // ToPort: "8080", + // CIDR: "0.0.0.0/0", + // }, + // { + // Direction: "inbound", + // IPProtocol: "icmp", + // FromPort: "-1", + // ToPort: "-1", + // CIDR: "0.0.0.0/0", + // }, + // { + // Direction: "outbound", + // IPProtocol: "tcp", + // FromPort: "443", + // ToPort: "443", + // CIDR: "0.0.0.0/0", + // }, + + // { + // Direction: "outbound", + // IPProtocol: "tcp", + // FromPort: "8443", + // ToPort: "9999", + // CIDR: "192.168.0.0/16", + // }, + + + // // All traffic 허용 rule + { + Direction: "inbound", + IPProtocol: "ALL", + FromPort: "-1", + ToPort: "-1", + CIDR: "0.0.0.0/0", + }, + { + Direction: "outbound", + IPProtocol: "ALL", + FromPort: "-1", + ToPort: "-1", + CIDR: "0.0.0.0/0", + }, + } + + result, err := handler.AddRules(irs.IID{SystemId: securityId}, securityRuleReqInfo) + if err != nil { + cblogger.Infof("[%s] Security Rule Add failed : [%v]", securityName, err) + } else { + cblogger.Infof("[%s] Security Rule 추가 결과 : [%v]", securityName, result) + spew.Dump(result) + } + cblogger.Info("\nAddRules Test Finished") + + case 5: + cblogger.Infof("[%s] Security Rule 제거 테스트", securityName) + + securityRuleReqInfo := &[]irs.SecurityRuleInfo{ + // { + + // Direction: "inbound", + // IPProtocol: "tcp", + // FromPort: "20", + // ToPort: "22", + // CIDR: "0.0.0.0/0", + // }, + // { + // Direction: "inbound", + // IPProtocol: "tcp", + // FromPort: "80", + // ToPort: "80", + // CIDR: "192.168.0.0/16", + // }, + // { + // Direction: "inbound", + // IPProtocol: "tcp", + // FromPort: "-1", + // ToPort: "-1", + // CIDR: "192.168.0.0/16", + // }, + // { + // Direction: "inbound", + // IPProtocol: "udp", + // FromPort: "8080", + // ToPort: "8080", + // CIDR: "0.0.0.0/0", + // }, + // { + // Direction: "inbound", + // IPProtocol: "icmp", + // FromPort: "-1", + // ToPort: "-1", + // CIDR: "0.0.0.0/0", + // }, + // { + // Direction: "outbound", + // IPProtocol: "tcp", + // FromPort: "443", + // ToPort: "443", + // CIDR: "0.0.0.0/0", + // }, + // { + // Direction: "outbound", + // IPProtocol: "tcp", + // FromPort: "8443", + // ToPort: "9999", + // CIDR: "192.168.0.0/16", + // }, + + + // // All traffic 허용 rule + { + Direction: "inbound", + IPProtocol: "ALL", + FromPort: "-1", + ToPort: "-1", + CIDR: "0.0.0.0/0", + }, + { + Direction: "outbound", + IPProtocol: "ALL", + FromPort: "-1", + ToPort: "-1", + CIDR: "0.0.0.0/0", + }, + } + result, err := handler.RemoveRules(irs.IID{SystemId: securityId}, securityRuleReqInfo) + if err != nil { + cblogger.Infof("[%s] Security Rule Remove failed : [%v]", securityName, err) + } else { + cblogger.Infof("[%s] Security Rule 제거 결과 : [%t]", securityName, result) + spew.Dump(result) + } + cblogger.Info("\nRemoveRules Test Finished") + + case 6: + cblogger.Infof("[%s] Security 삭제 테스트", securityId) + result, err := handler.DeleteSecurity(irs.IID{SystemId: securityId}) + if err != nil { + cblogger.Infof(securityId, " Security 삭제 실패 : ", err) + } else { + cblogger.Infof("[%s] Security 삭제 결과 : [%t]", securityId, result) + } + } + } + } +} + +func testErr() error { + + return errors.New("") +} + +func main() { + cblogger.Info("KT Cloud VPC Resource Test") + + handleSecurity() +} + +//handlerType : resources폴더의 xxxHandler.go에서 Handler이전까지의 문자열 +//(예) ImageHandler.go -> "Image" +func getResourceHandler(handlerType string) (interface{}, error) { + var cloudDriver idrv.CloudDriver + cloudDriver = new(ktvpcdrv.KTCloudVpcDriver) + + config := readConfigFile() + // spew.Dump(config) + + connectionInfo := idrv.ConnectionInfo{ + CredentialInfo: idrv.CredentialInfo{ + IdentityEndpoint: config.KTCloudVPC.IdentityEndpoint, + Username: config.KTCloudVPC.Username, + Password: config.KTCloudVPC.Password, + DomainName: config.KTCloudVPC.DomainName, + ProjectID: config.KTCloudVPC.ProjectID, + }, + RegionInfo: idrv.RegionInfo{ + Region: config.KTCloudVPC.Region, + Zone: config.KTCloudVPC.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() + } + + if err != nil { + return nil, err + } + return resourceHandler, nil +} + +type Config struct { + KTCloudVPC struct { + IdentityEndpoint string `yaml:"identity_endpoint"` + Username string `yaml:"username"` + Password string `yaml:"password"` + DomainName string `yaml:"domain_name"` + ProjectID string `yaml:"project_id"` + Region string `yaml:"region"` + Zone string `yaml:"zone"` + + VMName string `yaml:"vm_name"` + ImageId string `yaml:"image_id"` + VMSpecId string `yaml:"vmspec_id"` + NetworkId string `yaml:"network_id"` + SecurityGroups string `yaml:"security_groups"` + KeypairName string `yaml:"keypair_name"` + + VMId string `yaml:"vm_id"` + + Image struct { + Name string `yaml:"name"` + } `yaml:"image_info"` + + KeyPair struct { + Name string `yaml:"name"` + } `yaml:"keypair_info"` + + PublicIP struct { + Name string `yaml:"name"` + } `yaml:"public_info"` + + SecurityGroup struct { + Name string `yaml:"name"` + } `yaml:"security_group_info"` + + VirtualNetwork struct { + Name string `yaml:"name"` + } `yaml:"vnet_info"` + + Subnet struct { + Id string `yaml:"id"` + } `yaml:"subnet_info"` + + Router struct { + Name string `yaml:"name"` + GateWayId string `yaml:"gateway_id"` + AdminStateUp bool `yaml:"adminstatup"` + } `yaml:"router_info"` + } `yaml:"ktcloudvpc"` +} + +func readConfigFile() Config { + // Set Environment Value of Project Root Path + rootPath := os.Getenv("CBSPIDER_ROOT") + configPath := rootPath + "/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/conf/config.yaml" + cblogger.Debugf("Test Environment Config : [%s]", configPath) + + data, err := os.ReadFile(configPath) + if err != nil { + cblogger.Error(err) + } + + var config Config + err = yaml.Unmarshal(data, &config) + if err != nil { + cblogger.Error(err) + } + return config +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_VMHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_VMHandler.go new file mode 100644 index 000000000..dcbce9cf4 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_VMHandler.go @@ -0,0 +1,386 @@ +// 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, 2022.08. + +package main + +import ( + "os" + "errors" + "fmt" + "github.com/davecgh/go-spew/spew" + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" + + ktvpcdrv "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/drivers/ktcloudvpc" + + 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" +) + +var cblogger *logrus.Logger + +func init() { + // cblog is a global variable. + cblogger = cblog.GetLogger("KT Cloud VPC Resource Test") + cblog.SetLevel("info") +} + +func testErr() error { + + return errors.New("") +} + +// Test VM Lifecycle Management (Create/Suspend/Resume/Reboot/Terminate) +func handleVM() { + cblogger.Debug("Start VMHandler Resource Test") + + ResourceHandler, err := getResourceHandler("VM") + if err != nil { + panic(err) + } + + vmHandler := ResourceHandler.(irs.VMHandler) + + for { + fmt.Println("\n============================================================================================") + fmt.Println("[ VM Management Test ]") + fmt.Println("1. Start(Create) VM") + fmt.Println("2. Get VM Info") + fmt.Println("3. Suspend VM") + fmt.Println("4. Resume VM") + fmt.Println("5. Reboot VM") + + fmt.Println("6. Terminate VM") + fmt.Println("7. Get VMStatus") + fmt.Println("8. List VMStatus") + fmt.Println("9. List VM") + fmt.Println("0. Exit") + fmt.Println("\n Select a number above!! : ") + fmt.Println("============================================================================================") + + config := readConfigFile() + cblogger.Info("# config.KTCloudVPC.Zone : ", config.KTCloudVPC.Zone) + + vmID := irs.IID{SystemId: config.KTCloudVPC.VMId} + + var commandNum int + inputCnt, err := fmt.Scan(&commandNum) + if err != nil { + panic(err) + } + + if inputCnt == 1 { + switch commandNum { + case 0: + return + + case 1: + vmReqInfo := irs.VMReqInfo{ + // ImageType: irs.MyImage, + ImageType: irs.PublicImage, + + VMUserPasswd: "cbuser357505**", // No Simple PW!! + + IId: irs.IID{NameId: config.KTCloudVPC.ReqVMName}, + + // MyImage + // ImageIID: irs.IID{NameId: "ubuntu-18.04-64bit-221115", SystemId: "22f5e22d-ebaf-4ffe-a56b-7ea12a9be770"}, // + + // Public Image + ImageIID: irs.IID{NameId: "ubuntu-20.04-64bit", SystemId: "be9a35ed-5988-49d2-b86d-2ca9b375564b"}, + // ImageIID: irs.IID{NameId: "windows-2019-std-64bit", SystemId: "0668b053-2a3c-4751-aef9-b6342d3a19c3"}, + // ImageIID: irs.IID{NameId: "ubuntu-18.04-64bit-221115", SystemId: "d3f14f02-15b8-445e-9fb6-4cbd3f3c3387"}, + // ImageIID: irs.IID{NameId: "ubuntu-18.04-64bit", SystemId: "c6814d96-9746-42eb-a7d3-80f31d9cd297"}, // ubuntu-18.04-64bit + + VMSpecName: config.KTCloudVPC.ReqVMSpec, + + RootDiskType: "HDD", + // RootDiskType: "SSD", + // RootDiskType: "default", + + RootDiskSize: "50", + // RootDiskSize: "default", + + KeyPairIID: irs.IID{NameId: "kt-keypair-02"}, + // KeyPairIID: irs.IID{SystemId: "ktvpc-key-01"}, + + SecurityGroupIIDs: []irs.IID{{SystemId: "ktvpc-sg-2"}}, + + // $$$ Needs KT Cloud VPC VPC 'SystemId' + VpcIID: irs.IID{ + NameId: "", + SystemId: "60e5d9da-55cd-47be-a0d9-6cf67c54f15c", + }, + + // Caution!! Not Tier 'ID' but 'OsNetworkID' (among REST API parameters) to Create VM!! + SubnetIID: irs.IID{ + // NameId: "kt-subnet-ck1f929jcuppgg7kbvig", + SystemId: "99f7fee3-ebe0-42df-87fe-f1e48c8a52d3", + + // NameId: "kt-dx-subnet-1", // 172.25.6.1/24 + // SystemId: "908bb72a-aa50-46d1-ba7d-32d23c0d3eea", // Not 'ID' of Tier but 'OsNetworkID' of Tier to Create VM!! + }, + } + + vmInfo, err := vmHandler.StartVM(vmReqInfo) + if err != nil { + //panic(err) + cblogger.Error(err) + cblogger.Info("VM 생성 실패 : ", err) + } else { + cblogger.Info("VM 생성 완료!!", vmInfo) + spew.Dump(vmInfo) + } + //cblogger.Info(vm) + cblogger.Info("\nCreateVM Test Finished") + + case 2: + vmInfo, err := vmHandler.GetVM(vmID) + if err != nil { + cblogger.Error(err) + cblogger.Errorf("[%s] VM info. 조회 실패 : ", err) + } else { + cblogger.Infof("[%s] VM info. 조회 결과", vmID.SystemId) + cblogger.Info(vmInfo) + spew.Dump(vmInfo) + } + cblogger.Info("\nGetVM Test Finished") + + case 3: + cblogger.Info("Start Suspend the VM ...") + result, err := vmHandler.SuspendVM(vmID) + if err != nil { + cblogger.Error(err) + cblogger.Errorf("[%s] VM Suspend 실패 : [%v]", vmID.SystemId, result) + } else { + cblogger.Infof("[%s] VM Suspend 실행 성공 : [%v]", vmID.SystemId, result) + } + cblogger.Info("\nSuspendVM Test Finished") + + case 4: + cblogger.Info("Start Resume the VM ...") + result, err := vmHandler.ResumeVM(vmID) + if err != nil { + cblogger.Error(err) + cblogger.Errorf("[%s] VM Resume 실패 : [%s]", vmID.SystemId, result) + } else { + cblogger.Infof("[%s] VM Resume 실행 성공 : [%s]", vmID.SystemId, result) + } + cblogger.Info("\nResumeVM Test Finished") + + case 5: + cblogger.Info("Start Reboot the VM ...") + result, err := vmHandler.RebootVM(vmID) + if err != nil { + cblogger.Error(err) + cblogger.Errorf("[%s] VM Reboot 실패 : [%s]", vmID.SystemId, result) + } else { + cblogger.Infof("[%s] VM Reboot 실행 성공 : [%s]", vmID.SystemId, result) + } + cblogger.Info("\nRebootVM Test Finished") + + case 6: + cblogger.Info("Start Terminate VM ...") + result, err := vmHandler.TerminateVM(vmID) + if err != nil { + cblogger.Error(err) + cblogger.Errorf("[%s] Terminate VM 실패 : [%s]", vmID.SystemId, result) + } else { + cblogger.Infof("[%s] Terminate VM 실행 성공 : [%s]", vmID.SystemId, result) + } + cblogger.Info("\nTerminateVM Test Finished") + + case 7: + cblogger.Info("Start Get VM Status...") + vmStatus, err := vmHandler.GetVMStatus(vmID) + if err != nil { + cblogger.Error(err) + cblogger.Errorf("[%s] Get VM Status 실패 : ", vmID.SystemId) + } else { + cblogger.Infof("[%s] Get VM Status 실행 성공 : [%s]", vmID.SystemId, vmStatus) + } + cblogger.Info("\nGet VMStatus Test Finished") + + case 8: + cblogger.Info("Start ListVMStatus ...") + vmStatusInfos, err := vmHandler.ListVMStatus() + if err != nil { + cblogger.Error(err) + cblogger.Error("ListVMStatus 실패 : ") + } else { + cblogger.Info("ListVMStatus 실행 성공") + //cblogger.Info(vmStatusInfos) + spew.Dump(vmStatusInfos) + } + cblogger.Info("\nListVM Status Test Finished") + + case 9: + cblogger.Info("Start ListVM ...") + vmList, err := vmHandler.ListVM() + if err != nil { + cblogger.Error(err) + cblogger.Error("ListVM 실패 : ", err) + } else { + cblogger.Info("ListVM 실행 성공") + cblogger.Info("=========== VM 목록 ================") + // cblogger.Info(vmList) + spew.Dump(vmList) + cblogger.Infof("=========== VM 목록 수 : [%d] ================", len(vmList)) + if len(vmList) > 0 { + vmID = vmList[0].IId + } + } + cblogger.Info("\nListVM Test Finished") + + } + } + } +} + +func main() { + cblogger.Info("KT Cloud VPC Resource Test") + + handleVM() +} + +//handlerType : resources폴더의 xxxHandler.go에서 Handler이전까지의 문자열 +//(예) ImageHandler.go -> "Image" +func getResourceHandler(handlerType string) (interface{}, error) { + var cloudDriver idrv.CloudDriver + cloudDriver = new(ktvpcdrv.KTCloudVpcDriver) + + config := readConfigFile() + // spew.Dump(config) + + connectionInfo := idrv.ConnectionInfo{ + CredentialInfo: idrv.CredentialInfo{ + IdentityEndpoint: config.KTCloudVPC.IdentityEndpoint, + Username: config.KTCloudVPC.Username, + Password: config.KTCloudVPC.Password, + DomainName: config.KTCloudVPC.DomainName, + ProjectID: config.KTCloudVPC.ProjectID, + }, + RegionInfo: idrv.RegionInfo{ + Region: config.KTCloudVPC.Region, + Zone: config.KTCloudVPC.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() + } + + if err != nil { + return nil, err + } + return resourceHandler, nil +} + +// Region : 사용할 리전명 (ex) ap-northeast-2 +// ImageID : VM 생성에 사용할 AMI ID (ex) ami-047f7b46bd6dd5d84 +// BaseName : 다중 VM 생성 시 사용할 Prefix이름 ("BaseName" + "_" + "숫자" 형식으로 VM을 생성 함.) (ex) mcloud-barista +// VMID : 라이프 사이트클을 테스트할 EC2 인스턴스ID +// InstanceType : VM 생성시 사용할 인스턴스 타입 (ex) t2.micro +// KeyName : VM 생성시 사용할 키페어 이름 (ex) mcloud-barista-keypair +// MinCount : +// MaxCount : +// SubnetId : VM이 생성될 VPC의 SubnetId (ex) subnet-cf9ccf83 +// SecurityGroupID : 생성할 VM에 적용할 보안그룹 ID (ex) sg-0df1c209ea1915e4b +type Config struct { + KTCloudVPC struct { + IdentityEndpoint string `yaml:"identity_endpoint"` + Username string `yaml:"username"` + Password string `yaml:"password"` + DomainName string `yaml:"domain_name"` + ProjectID string `yaml:"project_id"` + Region string `yaml:"region"` + Zone string `yaml:"zone"` + + VMName string `yaml:"vm_name"` + ImageId string `yaml:"image_id"` + VMSpecId string `yaml:"vmspec_id"` + NetworkId string `yaml:"network_id"` + SecurityGroups string `yaml:"security_groups"` + KeypairName string `yaml:"keypair_name"` + + VMId string `yaml:"vm_id"` + ReqVMName string `yaml:"req_vm_name"` + ReqVMSpec string `yaml:"req_vm_spec"` + + Image struct { + Name string `yaml:"name"` + } `yaml:"image_info"` + + KeyPair struct { + Name string `yaml:"name"` + } `yaml:"keypair_info"` + + PublicIP struct { + Name string `yaml:"name"` + } `yaml:"public_info"` + + SecurityGroup struct { + Name string `yaml:"name"` + } `yaml:"security_group_info"` + + VirtualNetwork struct { + Name string `yaml:"name"` + } `yaml:"vnet_info"` + + Subnet struct { + Id string `yaml:"id"` + } `yaml:"subnet_info"` + + Router struct { + Name string `yaml:"name"` + GateWayId string `yaml:"gateway_id"` + AdminStateUp bool `yaml:"adminstatup"` + } `yaml:"router_info"` + } `yaml:"ktcloudvpc"` +} + +func readConfigFile() Config { + // Set Environment Value of Project Root Path + rootPath := os.Getenv("CBSPIDER_ROOT") + configPath := rootPath + "/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/conf/config.yaml" + cblogger.Debugf("Test Environment Config : [%s]", configPath) + + data, err := os.ReadFile(configPath) + if err != nil { + cblogger.Error(err) + } + + var config Config + err = yaml.Unmarshal(data, &config) + if err != nil { + cblogger.Error(err) + } + return config +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_VMSpecHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_VMSpecHandler.go new file mode 100644 index 000000000..84d4758ec --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_VMSpecHandler.go @@ -0,0 +1,285 @@ +// 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, 2022.08. + +package main + +import ( + "os" + // "errors" + "fmt" + "github.com/davecgh/go-spew/spew" + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" + + ktvpcdrv "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/drivers/ktcloudvpc" + + 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" +) + +var cblogger *logrus.Logger + +func init() { + // cblog is a global variable. + cblogger = cblog.GetLogger("KT Cloud VPC Resource Test") + cblog.SetLevel("info") +} + +// Test VMSpec +func handleVMSpec() { + cblogger.Debug("Start VMSpecHandler Resource Test") + + ResourceHandler, err := getResourceHandler("VMSpec") + if err != nil { + panic(err) + } + + handler := ResourceHandler.(irs.VMSpecHandler) + + for { + fmt.Println("\n============================================================================================") + fmt.Println("[ VMSpec Resource Test ]") + fmt.Println("1. ListVMSpec()") + fmt.Println("2. GetVMSpec()") + fmt.Println("3. ListOrgVMSpec()") + fmt.Println("4. GetOrgVMSpec()") + fmt.Println("0. Exit") + fmt.Println("\n Select a number above!! : ") + fmt.Println("============================================================================================") + + reqVMSpec := "2x8.itl" //KT Cloud VPC VMSpec + // reqVMSpec := "32x128.itl.v100-2" //KT Cloud VPC VMSpec + + config := readConfigFile() + + cblogger.Info("config.KTCloudVPC.Zone : ", config.KTCloudVPC.Zone) + cblogger.Info("reqVMSpec : ", reqVMSpec) + + var commandNum int + + inputCnt, err := fmt.Scan(&commandNum) + if err != nil { + panic(err) + } + + if inputCnt == 1 { + switch commandNum { + case 1: + fmt.Println("Start ListVMSpec() ...") + + result, err := handler.ListVMSpec() + if err != nil { + cblogger.Error("\nVMSpec list 조회 실패 : ", err) + } else { + fmt.Println("\n==================================================================================================================") + cblogger.Debug("VMSpec list 조회 성공!!") + spew.Dump(result) + //cblogger.Debug(result) + cblogger.Infof("전체 VMSpec list 개수 : [%d]", len(result)) + } + + fmt.Println("\nListVMSpec() Test Finished") + + case 2: + fmt.Println("Start GetVMSpec() ...") + + result, err := handler.GetVMSpec(reqVMSpec) + if err != nil { + cblogger.Error(reqVMSpec, " VMSpec 정보 조회 실패 : ", err) + } else { + fmt.Println("\n==================================================================================================================") + cblogger.Debugf("VMSpec[%s] 정보 조회 성공!!", reqVMSpec) + spew.Dump(result) + cblogger.Debug(result) + //cblogger.Infof(result) + } + + fmt.Println("\nGetVMSpec() Test Finished") + + case 3: + fmt.Println("Start ListOrgVMSpec() ...") + result, err := handler.ListOrgVMSpec() + if err != nil { + cblogger.Error(err) + cblogger.Error("VMSpec Org list 조회 실패 : ", err) + } else { + cblogger.Debug("VMSpec Org list 조회 성공") + spew.Dump(result) + cblogger.Debug(result) + //spew.Dump(result) + //fmt.Println(result) + //fmt.Println("=========================") + //fmt.Println(result) + cblogger.Infof("전체 목록 개수 : [%d]", len(result)) + } + + fmt.Println("\nListOrgVMSpec() Test Finished") + + case 4: + fmt.Println("Start GetOrgVMSpec() ...") + result, err := handler.GetOrgVMSpec(reqVMSpec) + if err != nil { + cblogger.Error(err) + cblogger.Error(reqVMSpec, " VMSpec Org 정보 조회 실패 : ", err) + } else { + cblogger.Debugf("VMSpec[%s] Org 정보 조회 성공", reqVMSpec) + spew.Dump(result) + cblogger.Debug(result) + //fmt.Println(result) + } + + fmt.Println("\nGetOrgVMSpec() Test Finished") + + case 0: + fmt.Println("Exit") + return + } + } + } +} + +func main() { + cblogger.Info("KT Cloud VPC Resource Test") + + handleVMSpec() +} + +//handlerType : resources폴더의 xxxHandler.go에서 Handler이전까지의 문자열 +//(예) ImageHandler.go -> "Image" +func getResourceHandler(handlerType string) (interface{}, error) { + var cloudDriver idrv.CloudDriver + cloudDriver = new(ktvpcdrv.KTCloudVpcDriver) + + config := readConfigFile() + // spew.Dump(config) + + connectionInfo := idrv.ConnectionInfo{ + CredentialInfo: idrv.CredentialInfo{ + IdentityEndpoint: config.KTCloudVPC.IdentityEndpoint, + Username: config.KTCloudVPC.Username, + Password: config.KTCloudVPC.Password, + DomainName: config.KTCloudVPC.DomainName, + ProjectID: config.KTCloudVPC.ProjectID, + }, + RegionInfo: idrv.RegionInfo{ + Region: config.KTCloudVPC.Region, + Zone: config.KTCloudVPC.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() + } + + if err != nil { + return nil, err + } + return resourceHandler, nil +} + +// Region : 사용할 리전명 (ex) ap-northeast-2 +// ImageID : VM 생성에 사용할 AMI ID (ex) ami-047f7b46bd6dd5d84 +// BaseName : 다중 VM 생성 시 사용할 Prefix이름 ("BaseName" + "_" + "숫자" 형식으로 VM을 생성 함.) (ex) mcloud-barista +// VmID : 라이프 사이트클을 테스트할 EC2 인스턴스ID +// InstanceType : VM 생성시 사용할 인스턴스 타입 (ex) t2.micro +// KeyName : VM 생성시 사용할 키페어 이름 (ex) mcloud-barista-keypair +// MinCount : +// MaxCount : +// SubnetId : VM이 생성될 VPC의 SubnetId (ex) subnet-cf9ccf83 +// SecurityGroupID : 생성할 VM에 적용할 보안그룹 ID (ex) sg-0df1c209ea1915e4b +type Config struct { + KTCloudVPC struct { + IdentityEndpoint string `yaml:"identity_endpoint"` + Username string `yaml:"username"` + Password string `yaml:"password"` + DomainName string `yaml:"domain_name"` + ProjectID string `yaml:"project_id"` + Region string `yaml:"region"` + Zone string `yaml:"zone"` + + VMName string `yaml:"vm_name"` + ImageId string `yaml:"image_id"` + VMSpecId string `yaml:"vmspec_id"` + NetworkId string `yaml:"network_id"` + SecurityGroups string `yaml:"security_groups"` + KeypairName string `yaml:"keypair_name"` + + VMId string `yaml:"vm_id"` + + Image struct { + Name string `yaml:"name"` + } `yaml:"image_info"` + + KeyPair struct { + Name string `yaml:"name"` + } `yaml:"keypair_info"` + + PublicIP struct { + Name string `yaml:"name"` + } `yaml:"public_info"` + + SecurityGroup struct { + Name string `yaml:"name"` + } `yaml:"security_group_info"` + + VirtualNetwork struct { + Name string `yaml:"name"` + } `yaml:"vnet_info"` + + Subnet struct { + Id string `yaml:"id"` + } `yaml:"subnet_info"` + + Router struct { + Name string `yaml:"name"` + GateWayId string `yaml:"gateway_id"` + AdminStateUp bool `yaml:"adminstatup"` + } `yaml:"router_info"` + } `yaml:"ktcloudvpc"` +} + +func readConfigFile() Config { + // Set Environment Value of Project Root Path + rootPath := os.Getenv("CBSPIDER_ROOT") + configPath := rootPath + "/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/conf/config.yaml" + cblogger.Debugf("Test Environment Config : [%s]", configPath) + + data, err := os.ReadFile(configPath) + if err != nil { + cblogger.Error(err) + } + + var config Config + err = yaml.Unmarshal(data, &config) + if err != nil { + cblogger.Error(err) + } + return config +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_VPCHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_VPCHandler.go new file mode 100644 index 000000000..dcea847c0 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/Test_VPCHandler.go @@ -0,0 +1,328 @@ +// 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, 2022.08. + +package main + +import ( + "os" + // "errors" + "fmt" + "github.com/davecgh/go-spew/spew" + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" + + ktvpcdrv "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/drivers/ktcloudvpc" + + 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" +) + +var cblogger *logrus.Logger + +func init() { + // cblog is a global variable. + cblogger = cblog.GetLogger("KT Cloud VPC Resource Test") + cblog.SetLevel("info") +} + +// Test VMSpec +func handleVPC() { + cblogger.Debug("Start VPCHandler Resource Test") + + ResourceHandler, err := getResourceHandler("VPC") + if err != nil { + panic(err) + } + + handler := ResourceHandler.(irs.VPCHandler) + + for { + fmt.Println("\n============================================================================================") + fmt.Println("[ VPC Resource Test ]") + fmt.Println("1. CreateVPC()") + fmt.Println("2. ListVPC()") + fmt.Println("3. GetVPC()") + fmt.Println("4. AddSubnet()") + fmt.Println("5. RemoveSubnet()") + fmt.Println("6. DeleteVPC()") + fmt.Println("0. Exit") + fmt.Println("\n Select a number above!! : ") + fmt.Println("============================================================================================") + + config := readConfigFile() + cblogger.Info("# config.KTCloudVPC.Zone : ", config.KTCloudVPC.Zone) + + vpcReqName := "kt-vpc-1" + vpcIId := irs.IID{NameId: vpcReqName, SystemId: "60e5d9da-55cd-47be-a0d9-6cf67c54f15c"} + + // subnetIId := irs.IID{SystemId: "e1a55d19-9412-4cff-bee0-0c446752ce91"} + subnetIId := irs.IID{SystemId: "afaa6ca3-67e8-4a53-95ec-c1a98c79ab55"} // Caution!!) Tier 'OSNetworkID' among REST API parameters + + cblogger.Info("reqVPCName : ", vpcReqName) + + // KT Cloud VPC (D1) 서비스의 VPC CIDR은 다음의 사설 주소 범위로 입력되어야 함. : 172.25.0.0/12 + // 네트워크를 기본설정 선택시, 각각 DMZ : 172.25.0.0/24, Private : 172.25.1.0/24로 제공됨. + + vpcReqInfo := irs.VPCReqInfo{ + IId: vpcIId, + IPv4_CIDR: "172.25.0.0/12", + SubnetInfoList: []irs.SubnetInfo { + // { + // IId: irs.IID{ + // NameId: "ktsubnet1-1", + // }, + // IPv4_CIDR: "172.25.2.0/24", + // }, + { + IId: irs.IID{ + NameId: "ktsubnet1-2", + }, + IPv4_CIDR: "172.25.3.0/24", + }, + }, + } + + subnetReqInfo := irs.SubnetInfo { + IId: irs.IID{ + NameId: "NLB-SUBNET", + }, + IPv4_CIDR: "172.25.100.0/24", + } + + var commandNum int + + inputCnt, err := fmt.Scan(&commandNum) + if err != nil { + panic(err) + } + + if inputCnt == 1 { + switch commandNum { + case 1: + fmt.Println("Start CreateVPC() ...") + + vpcInfo, err := handler.CreateVPC(vpcReqInfo) + if err != nil { + //panic(err) + cblogger.Error(err) + cblogger.Error("VPC 생성 실패 : ", err) + } else { + cblogger.Info("VPC 생성 완료!!", vpcInfo) + spew.Dump(vpcInfo) + cblogger.Debug(vpcInfo) + } + + fmt.Println("\nCreateVPC() Test Finished") + + case 2: + fmt.Println("Start ListVPC() ...") + result, err := handler.ListVPC() + if err != nil { + cblogger.Error(err) + cblogger.Error("VPC list 조회 실패 : ", err) + } else { + cblogger.Info("VPC list 조회 성공!!") + spew.Dump(result) + cblogger.Debug(result) + cblogger.Infof("전체 list 개수 : [%d]", len(result)) + } + + fmt.Println("\nListVMSpec() Test Finished") + + case 3: + fmt.Println("Start GetVPC() ...") + if vpcInfo, err := handler.GetVPC(vpcIId); err != nil { + cblogger.Error(err) + cblogger.Error("VPC 정보 조회 실패 : ", err) + } else { + cblogger.Info("VPC 정보 조회 성공!!") + spew.Dump(vpcInfo) + } + fmt.Println("\nGetVPC() Test Finished") + + case 4: + fmt.Println("Start AddSubnet() ...") + if result, err := handler.AddSubnet(vpcIId, subnetReqInfo); err != nil { + cblogger.Error(err) + cblogger.Error("Subnet 추가 실패 : ", err) + } else { + cblogger.Info("Subnet 추가 성공!!") + spew.Dump(result) + } + fmt.Println("\nAddSubnet() Test Finished") + + case 5: + fmt.Println("Start RemoveSubnet() ...") + if result, err := handler.RemoveSubnet(vpcIId, subnetIId); err != nil { + cblogger.Error(err) + cblogger.Error("Subnet 제거 실패 : ", err) + } else { + cblogger.Info("Subnet 제거 성공!!") + spew.Dump(result) + } + fmt.Println("\nRemoveSubnet() Test Finished") + + case 6: + fmt.Println("Start DeleteVPC() ...") + if result, err := handler.DeleteVPC(vpcIId); err != nil { + cblogger.Error(err) + cblogger.Error("VPC 삭제 실패 : ", err) + } else { + cblogger.Info("VPC 삭제 성공!!") + spew.Dump(result) + } + fmt.Println("\nGetVPC() Test Finished") + + case 0: + fmt.Println("Exit") + return + } + } + } +} + +func main() { + cblogger.Info("KT Cloud VPC Resource Test") + + handleVPC() +} + +//handlerType : resources폴더의 xxxHandler.go에서 Handler이전까지의 문자열 +//(예) ImageHandler.go -> "Image" +func getResourceHandler(handlerType string) (interface{}, error) { + var cloudDriver idrv.CloudDriver + cloudDriver = new(ktvpcdrv.KTCloudVpcDriver) + + config := readConfigFile() + // spew.Dump(config) + + connectionInfo := idrv.ConnectionInfo{ + CredentialInfo: idrv.CredentialInfo{ + IdentityEndpoint: config.KTCloudVPC.IdentityEndpoint, + Username: config.KTCloudVPC.Username, + Password: config.KTCloudVPC.Password, + DomainName: config.KTCloudVPC.DomainName, + ProjectID: config.KTCloudVPC.ProjectID, + }, + RegionInfo: idrv.RegionInfo{ + Region: config.KTCloudVPC.Region, + Zone: config.KTCloudVPC.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() + } + + if err != nil { + return nil, err + } + return resourceHandler, nil +} + +// Region : 사용할 리전명 (ex) ap-northeast-2 +// ImageID : VM 생성에 사용할 AMI ID (ex) ami-047f7b46bd6dd5d84 +// BaseName : 다중 VM 생성 시 사용할 Prefix이름 ("BaseName" + "_" + "숫자" 형식으로 VM을 생성 함.) (ex) mcloud-barista +// VmID : 라이프 사이트클을 테스트할 EC2 인스턴스ID +// InstanceType : VM 생성시 사용할 인스턴스 타입 (ex) t2.micro +// KeyName : VM 생성시 사용할 키페어 이름 (ex) mcloud-barista-keypair +// MinCount : +// MaxCount : +// SubnetId : VM이 생성될 VPC의 SubnetId (ex) subnet-cf9ccf83 +// SecurityGroupID : 생성할 VM에 적용할 보안그룹 ID (ex) sg-0df1c209ea1915e4b +type Config struct { + KTCloudVPC struct { + IdentityEndpoint string `yaml:"identity_endpoint"` + Username string `yaml:"username"` + Password string `yaml:"password"` + DomainName string `yaml:"domain_name"` + ProjectID string `yaml:"project_id"` + Region string `yaml:"region"` + Zone string `yaml:"zone"` + + VMName string `yaml:"vm_name"` + ImageId string `yaml:"image_id"` + VMSpecId string `yaml:"vmspec_id"` + NetworkId string `yaml:"network_id"` + SecurityGroups string `yaml:"security_groups"` + KeypairName string `yaml:"keypair_name"` + + VMId string `yaml:"vm_id"` + + Image struct { + Name string `yaml:"name"` + } `yaml:"image_info"` + + KeyPair struct { + Name string `yaml:"name"` + } `yaml:"keypair_info"` + + PublicIP struct { + Name string `yaml:"name"` + } `yaml:"public_info"` + + SecurityGroup struct { + Name string `yaml:"name"` + } `yaml:"security_group_info"` + + VirtualNetwork struct { + Name string `yaml:"name"` + } `yaml:"vnet_info"` + + Subnet struct { + Id string `yaml:"id"` + } `yaml:"subnet_info"` + + Router struct { + Name string `yaml:"name"` + GateWayId string `yaml:"gateway_id"` + AdminStateUp bool `yaml:"adminstatup"` + } `yaml:"router_info"` + } `yaml:"ktcloudvpc"` +} + +func readConfigFile() Config { + // Set Environment Value of Project Root Path + rootPath := os.Getenv("CBSPIDER_ROOT") + configPath := rootPath + "/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/conf/config.yaml" + cblogger.Debugf("Test Environment Config : [%s]", configPath) + + data, err := os.ReadFile(configPath) + if err != nil { + cblogger.Error(err) + } + + var config Config + err = yaml.Unmarshal(data, &config) + if err != nil { + cblogger.Error(err) + } + return config +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/conf/config.yaml.sample b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/conf/config.yaml.sample new file mode 100644 index 000000000..8f8547784 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/conf/config.yaml.sample @@ -0,0 +1,37 @@ +## Config for KT Cloud VPC connection Driver ## +ktcloudvpc: + identity_endpoint: https://api.ucloudbiz.olleh.com/d1/identity/v3/ + # $$$ Need to append '/v3/' to identity_endpoint URL + + username: ~~~@~~~.com + # KT Cloud Portal User ID + + password: XXXXXXXXXX + # KT Cloud Portal Password + + domain_name: default + + project_id: XXXXXXXXXX + # $$$ For 'V3' verson auth., identity_endpoint, username, password and domain_name are required basically. + # $$$ But, need 'project_id' for the token role + # You can get the prject id on 'Token' > 'Token' menu on KT Cloud Portal + + region: KR1 + zone: DX-M1 + + ########################################################### + # Resource Info for Testing + vm_id: XXXXXXXXXX + + disk_id: XXXXXXXXXX + nlb_id: 38288 + keypair_name: kt-keypair-02 + + req_vm_name: ktvpc-vm-01 + req_vm_spec: 16x32.itl + # 4x16.itl + # 2x8.itl # vCPU: 2, Mem: 8GB + + req_keypair_name: ktvpc-keypair-01 + req_disk_name: ktvpc-disk-01 + \ No newline at end of file diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/goget-ktvpcsdk.sh b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/goget-ktvpcsdk.sh new file mode 100755 index 000000000..d2b8ec9d7 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/goget-ktvpcsdk.sh @@ -0,0 +1,8 @@ + +export GIT_TERMINAL_PROMPT=1 + +export GOPRIVATE="github.com/cloud-barista" + +go get -u github.com/cloud-barista/ktcloudvpc-sdk-go@a0af52c7c7cddae1262b8f0a82d236adcf2f544d + + diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_disk.sh b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_disk.sh new file mode 100755 index 000000000..d29ea52a2 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_disk.sh @@ -0,0 +1,3 @@ +source ../../../../../../cb-spider/setup.env + +go run Test_DiskHandler.go diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_image.sh b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_image.sh new file mode 100755 index 000000000..054667de6 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_image.sh @@ -0,0 +1,3 @@ +source ../../../../../../cb-spider/setup.env + +go run Test_ImageHandler.go diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_keypair.sh b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_keypair.sh new file mode 100755 index 000000000..b462aee96 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_keypair.sh @@ -0,0 +1,3 @@ +source ../../../../../../cb-spider/setup.env + +go run Test_KeyPairHandler.go diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_myimage.sh b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_myimage.sh new file mode 100755 index 000000000..b5db39c27 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_myimage.sh @@ -0,0 +1,3 @@ +source ../../../../../../cb-spider/setup.env + +go run Test_MyImageHandler.go diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_nlb.sh b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_nlb.sh new file mode 100755 index 000000000..7d6910c42 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_nlb.sh @@ -0,0 +1,3 @@ +source ../../../../../../cb-spider/setup.env + +go run Test_NLBHandler.go diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_region-zone.sh b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_region-zone.sh new file mode 100755 index 000000000..c36fdb77e --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_region-zone.sh @@ -0,0 +1,3 @@ +source ../../../../../../cb-spider/setup.env + +go run Test_RegionZoneHandler.go diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_security.sh b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_security.sh new file mode 100755 index 000000000..224d87ec2 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_security.sh @@ -0,0 +1,3 @@ +source ../../../../../../cb-spider/setup.env + +go run Test_SecurityHandler.go diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_vm.sh b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_vm.sh new file mode 100755 index 000000000..ec0fe13ba --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_vm.sh @@ -0,0 +1,3 @@ +source ../../../../../../cb-spider/setup.env + +go run Test_VMHandler.go diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_vmspec.sh b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_vmspec.sh new file mode 100755 index 000000000..31c7ae965 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_vmspec.sh @@ -0,0 +1,3 @@ +source ../../../../../../cb-spider/setup.env + +go run Test_VMSpecHandler.go diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_vpc.sh b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_vpc.sh new file mode 100755 index 000000000..7ce9aeca3 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/main/test_vpc.sh @@ -0,0 +1,3 @@ +source ../../../../../../cb-spider/setup.env + +go run Test_VPCHandler.go \ No newline at end of file diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/CommonKTCloudFunc.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/CommonKTCloudFunc.go new file mode 100644 index 000000000..0ca351cc0 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/CommonKTCloudFunc.go @@ -0,0 +1,254 @@ +// 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 Example for PoC Test. +// +// by ETRI, 2022.08. + +package resources + +import ( + "os" + "os/exec" + "fmt" + "strings" + "sync" + "time" + "net" + "encoding/json" + "github.com/sirupsen/logrus" + + ktvpcsdk "github.com/cloud-barista/ktcloudvpc-sdk-go" + "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/compute/v2/extensions/secgroups" + "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/compute/v2/flavors" + "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/networking/v2/networks" + "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/networking/v2/ports" + "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/networking/v2/subnets" + + cblog "github.com/cloud-barista/cb-log" + call "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/call-log" +) + +var once sync.Once +var cblogger *logrus.Logger +var calllogger *logrus.Logger + +func InitLog() { + once.Do(func() { + // cblog is a global variable. + cblogger = cblog.GetLogger("CB-SPIDER") + calllogger = call.GetLogger("HISCALL") + }) +} + +func loggingError(hiscallInfo call.CLOUDLOGSCHEMA, err error) { + hiscallInfo.ErrorMSG = err.Error() + calllogger.Info(call.String(hiscallInfo)) +} + +func loggingInfo(hiscallInfo call.CLOUDLOGSCHEMA, start time.Time) { + hiscallInfo.ElapsedTime = call.Elapsed(start) + calllogger.Info(call.String(hiscallInfo)) +} + +func getCallLogScheme(zone string, resourceType call.RES_TYPE, resourceName string, apiName string) call.CLOUDLOGSCHEMA { + cblogger.Infof("Calling %s %s", call.KTCLOUDVPC, apiName) + + return call.CLOUDLOGSCHEMA{ + CloudOS: call.KTCLOUDVPC, + RegionZone: zone, + ResourceType: resourceType, + ResourceName: resourceName, + CloudOSAPI: apiName, + } +} + +func logAndReturnError(callLogInfo call.CLOUDLOGSCHEMA, givenErrString string, errMsg error) (error) { + newErr := fmt.Errorf(givenErrString + "[%s]", errMsg) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return newErr +} + +func getFlavorIdWithName(client *ktvpcsdk.ServiceClient, flavorName string) (string, error) { + cblogger.Info("KT Cloud VPC Driver: called GetFlavorIdWithName()") + + allPages, err := flavors.ListDetail(client, nil).AllPages() + if err != nil { + return "", err + } + flavorList, err := flavors.ExtractFlavors(allPages) + if err != nil { + return "", err + } + for _, flavor := range flavorList { + if flavor.Name == flavorName { + return flavor.ID, nil + } + } + return "", fmt.Errorf("Failed to Find the Flavor with the Name [%s]", flavorName) +} + +func getSGWithName(networkClient *ktvpcsdk.ServiceClient, securityName string) (*secgroups.SecurityGroup, error) { + cblogger.Info("KT Cloud VPC Driver: called GetSGWithName()") + + allPages, err := secgroups.List(networkClient).AllPages() + if err != nil { + return nil, err + } + secGroupList, err := secgroups.ExtractSecurityGroups(allPages) + if err != nil { + return nil, err + } + for _, sg := range secGroupList { + if strings.EqualFold(sg.Name, securityName) { + return &sg, nil + } + } + + return nil, fmt.Errorf("Failed to Find the SecurityGroup with the Name [%s]", securityName) +} + +func getNetworkWithName(networkClient *ktvpcsdk.ServiceClient, networkName string) (*networks.Network, error) { + cblogger.Info("KT Cloud VPC Driver: called GetNetworkWithName()") + + allPages, err := networks.List(networkClient, networks.ListOpts{Name: networkName}).AllPages() + if err != nil { + return nil, err + } + netList, err := networks.ExtractNetworks(allPages) + if err != nil { + return nil, err + } + for _, net := range netList { + if strings.EqualFold(net.Name, networkName) { + return &net, nil + } + } + + return nil, fmt.Errorf("Failed to Find KT Cloud Network Info with the name [%s]", networkName) +} + +func getSubnetWithId(networkClient *ktvpcsdk.ServiceClient, subnetId string) (*subnets.Subnet, error) { + cblogger.Info("KT Cloud VPC Driver: called GetSubnetWithId()") + + subnet, err := subnets.Get(networkClient, subnetId).Extract() + if err != nil { + return nil, err + } + return subnet, nil +} + +func getPortWithDeviceId(networkClient *ktvpcsdk.ServiceClient, deviceID string) (*ports.Port, error) { + cblogger.Info("KT Cloud VPC Driver: called GetPortWithDeviceId()") + + allPages, err := ports.List(networkClient, ports.ListOpts{}).AllPages() + if err != nil { + return nil, err + } + portList, err := ports.ExtractPorts(allPages) + if err != nil { + return nil, err + } + for _, port := range portList { + if strings.EqualFold(port.DeviceID, deviceID) { + return &port, nil + } + } + + return nil, fmt.Errorf("Failed to Find Port with the DeviceID [%s]", deviceID) +} + +func checkFolderAndCreate(folderPath string) error { + cblogger.Info("KT Cloud VPC Driver: called CheckFolderAndCreate()") + + // If the Folder doesn't Exist, Create it + if _, err := os.Stat(folderPath); os.IsNotExist(err) { + if err := os.Mkdir(folderPath, 0700); err != nil { + return err + } + } + return nil +} + +func reverse(s string) (result string) { + for _,v := range s { + result = string(v) + result + } + return +} + +func runCommand(cmdName string, cmdArgs []string) (string, error) { + /* + Ref) + var ( + cmdOut []byte + cmdErr error + ) + */ + cblogger.Infof("cmdName : %s", cmdName) + cblogger.Infof("cmdArgs : %s", cmdArgs) + + //if cmdOut, cmdErr = exec.Command(cmdName, cmdArgs...).Output(); cmdErr != nil { + if cmdOut, cmdErr := exec.Command(cmdName, cmdArgs...).CombinedOutput(); cmdErr != nil { + fmt.Fprintln(os.Stderr, "There was an Error running command : ", cmdErr) + //panic("Can't exec the command: " + cmdErr1.Error()) + fmt.Println(fmt.Sprint(cmdErr) + ": " + string(cmdOut)) + os.Exit(1) + + return string(cmdOut), cmdErr + } else { + fmt.Println("cmdOut : ", string(cmdOut)) + + return string(cmdOut), nil + } +} + +// Convert Cloud Object to JSON String type +func convertJsonString(v interface{}) (string, error) { + jsonBytes, err := json.Marshal(v) + if err != nil { + newErr := fmt.Errorf("Failed to Convert Json to String. [%v]", err.Error()) + cblogger.Error(newErr.Error()) + return "", newErr + } + return string(jsonBytes), nil +} + +// Convert time to KTC +func convertTimeToKTC(givenTime time.Time) (time.Time, error) { + loc, err := time.LoadLocation("Asia/Seoul") + if err != nil { + newErr := fmt.Errorf("Failed to Convert the Time to KTC. [%v]", err) + cblogger.Error(newErr.Error()) + return givenTime, newErr + } + return givenTime.In(loc), nil +} + +func ipToCidr32(ipStr string) (string, error) { + ip := net.ParseIP(ipStr) + if ip == nil { + return "", fmt.Errorf("Invalid IP address!!") + } + + // Assuming IPv4 and /24 subnet + mask := net.CIDRMask(32, 32) // for ~/32 subnet + network := ip.Mask(mask) + return fmt.Sprintf("%s/32", network), nil +} + +func ipToCidr24(ipStr string) (string, error) { + ip := net.ParseIP(ipStr) + if ip == nil { + return "", fmt.Errorf("Invalid IP address!!") + } + + // Assuming IPv4 and /24 subnet + mask := net.CIDRMask(24, 32) // for ~/24 subnet + network := ip.Mask(mask) + return fmt.Sprintf("%s/24", network), nil +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/DiskHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/DiskHandler.go new file mode 100644 index 000000000..b4fe6d2b6 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/DiskHandler.go @@ -0,0 +1,674 @@ +// 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 Example for PoC Test. +// +// by ETRI, 2024.01. + +package resources + +import ( + "fmt" + "strconv" + "strings" + "time" + "github.com/davecgh/go-spew/spew" + + ktvpcsdk "github.com/cloud-barista/ktcloudvpc-sdk-go" + volumes2 "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/blockstorage/v2/volumes" + vattach "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/compute/v2/extensions/volumeattach" + "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/compute/v2/servers" + + call "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/call-log" + 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" +) + +const ( + DefaultDataDiskSize string = "100" + DefaultDiskUsagePlanType string = "hourly" +) + +type KTVpcDiskHandler struct { + RegionInfo idrv.RegionInfo + VMClient *ktvpcsdk.ServiceClient + VolumeClient *ktvpcsdk.ServiceClient +} + +func (diskHandler *KTVpcDiskHandler) CreateDisk(diskReqInfo irs.DiskInfo) (irs.DiskInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called CreateDisk()") + callLogInfo := getCallLogScheme(diskHandler.RegionInfo.Region, call.DISK, diskReqInfo.IId.NameId, "CreateDisk()") + + if strings.EqualFold(diskReqInfo.IId.NameId, "") { + newErr := fmt.Errorf("Invalid Disk NameId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } + + if strings.EqualFold(diskHandler.RegionInfo.Zone, "") { + newErr := fmt.Errorf("Invalid Zone Info!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } + + reqDiskType := diskReqInfo.DiskType // 'default', 'HDD' or 'SSD' + reqDiskSize := diskReqInfo.DiskSize // 10~2000(GB) + + if strings.EqualFold(reqDiskType, "") || strings.EqualFold(reqDiskType, "default") { + reqDiskType = "HDD" // In case, Volume Type is not specified. + } else if strings.EqualFold(reqDiskType, "HDD") { + reqDiskType = "HDD" + } else if strings.EqualFold(reqDiskType, "SSD") { + reqDiskType = "SSD" + } else { + newErr := fmt.Errorf("Invalid Disk Type!!") + cblogger.Error(newErr.Error()) + } + + if strings.EqualFold(reqDiskSize, "") || strings.EqualFold(reqDiskSize, "default") { + reqDiskSize = DefaultDataDiskSize // In case, Volume Size is not specified. + } + + reqDiskSizeInt, err := strconv.Atoi(reqDiskSize) + if err != nil { + newErr := fmt.Errorf("Failed to Convert Disk Size to Int. type. [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } + if reqDiskSizeInt < 10 || reqDiskSizeInt > 2000 { // 10~2000(GB) + newErr := fmt.Errorf("Invalid Disk Size. Disk Size Must be between 10 and 2000.") + cblogger.Error(newErr.Error()) + return irs.DiskInfo{}, newErr + } + + start := call.Start() + create0pts := volumes2.CreateOpts{ + AvailabilityZone: diskHandler.RegionInfo.Zone, + Size: reqDiskSizeInt, + Name: diskReqInfo.IId.NameId, + UsagePlanType: DefaultDiskUsagePlanType, + } + // cblogger.Info("\n### Disk create 0pts : ") + // spew.Dump(create0pts) + // cblogger.Info("\n") + + diskResult, err := volumes2.Create(diskHandler.VolumeClient, create0pts).Extract() + if err != nil { + newErr := fmt.Errorf("Failed to Create New Disk Volume. [%v]", err.Error()) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } + loggingInfo(callLogInfo, start) + + // Because there are functions that use 'NameId', Input NameId too + newDiskIID := irs.IID{NameId: diskResult.Name, SystemId: diskResult.ID} + + // Wait for created VM info to be inquired + curStatus, err := diskHandler.waitForDiskCreation(newDiskIID) + if err != nil { + newErr := fmt.Errorf("Failed to Wait to Get Disk Info. [%v]", err.Error()) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } + cblogger.Infof("==> Disk Status of [%s] : [%s]", newDiskIID.NameId, curStatus) + + // Check VM Deploy Status + diskResult, err = volumes2.Get(diskHandler.VolumeClient, diskResult.ID).Extract() + if err != nil { + newErr := fmt.Errorf("Failed to Get the KT Disk Info!! : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } + + newDiskInfo, err := diskHandler.mappingDiskInfo(*diskResult) + if err != nil { + newErr := fmt.Errorf("Failed to Map Disk Info. : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } + return newDiskInfo, nil +} + +func (diskHandler *KTVpcDiskHandler) ListDisk() ([]*irs.DiskInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called ListDisk()") + callLogInfo := getCallLogScheme(diskHandler.RegionInfo.Region, call.DISK, "ListDisk()", "ListDisk()") + + start := call.Start() + listOpts := volumes2.ListOpts{} + allPages, err := volumes2.List(diskHandler.VolumeClient, listOpts).AllPages() + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud Volume list!! : [%v] ", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + ktVolumeList, err := volumes2.ExtractVolumes(allPages) + if err != nil { + newErr := fmt.Errorf("Failed to Extract KT Cloud Volume list!! : [%v] ", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + loggingInfo(callLogInfo, start) + // spew.Dump(ktVolumeList) + + var volumeInfoList []*irs.DiskInfo + for _, volume := range ktVolumeList { + volumeInfo, err := diskHandler.mappingDiskInfo(volume) + if err != nil { + newErr := fmt.Errorf("Failed to Get Disk Info list!! : [%v] ", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + volumeInfoList = append(volumeInfoList, &volumeInfo) + } + return volumeInfoList, nil +} + +func (diskHandler *KTVpcDiskHandler) GetDisk(diskIID irs.IID) (irs.DiskInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called GetDisk()") + callLogInfo := getCallLogScheme(diskHandler.RegionInfo.Region, call.DISK, diskIID.SystemId, "GetDisk()") + + if strings.EqualFold(diskIID.SystemId, "") { + newErr := fmt.Errorf("Invalid Disk SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } + + ktVolumeInfo, err := volumes2.Get(diskHandler.VolumeClient, diskIID.SystemId).Extract() + if err != nil { + newErr := fmt.Errorf("Failed to Get the KT Disk Info!! : [%v] ", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } + cblogger.Info(ktVolumeInfo) + spew.Dump(ktVolumeInfo) + + volumeInfo, err := diskHandler.mappingDiskInfo(*ktVolumeInfo) + if err != nil { + newErr := fmt.Errorf("Failed to Get Disk Info!! : [%v] ", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } + return volumeInfo, nil +} + +func (diskHandler *KTVpcDiskHandler) ChangeDiskSize(diskIID irs.IID, newDiskSize string) (bool, error) { + cblogger.Info("KT Cloud VPC Driver: called ChangeDiskSize()") + + return false, fmt.Errorf("Does not support ChangeDiskSize() yet!!") +} + +func (diskHandler *KTVpcDiskHandler) DeleteDisk(diskIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud VPC Driver: called DeleteDisk()") + callLogInfo := getCallLogScheme(diskHandler.RegionInfo.Region, call.DISK, "DeleteDisk()", "DeleteDisk()") + + if strings.EqualFold(diskIID.SystemId, "") { + newErr := fmt.Errorf("Invalid Disk SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + + // curStatus, err := diskHandler.getDiskStatus(diskIID) + // if err != nil { + // newErr := fmt.Errorf("Failed to Get the Disk Status : [%v] ", err) + // cblogger.Error(newErr.Error()) + // return false, newErr + // } else if strings.EqualFold(string(curStatus), string(irs.DiskAttached)) { + // newErr := fmt.Errorf("Failed to Delete the Disk Volume. The Disk Status is 'Attached'.") + // cblogger.Error(newErr.Error()) + // loggingError(callLogInfo, newErr) + // return false, newErr + // } + + start := call.Start() + delOpts := volumes2.DeleteOpts { + Cascade : true, // Delete all snapshots of this volume as well. + } + delErr := volumes2.Delete(diskHandler.VolumeClient, diskIID.SystemId, delOpts).ExtractErr() + if delErr != nil { + newErr := fmt.Errorf("Failed to Delete the Disk Volume!! : [%v] ", delErr) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + loggingInfo(callLogInfo, start) + + return true, nil +} + +func (diskHandler *KTVpcDiskHandler) AttachDisk(diskIID irs.IID, vmIID irs.IID) (irs.DiskInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called AttachDisk()") + callLogInfo := getCallLogScheme(diskHandler.RegionInfo.Region, call.DISK, diskIID.SystemId, "AttachDisk()") + + if strings.EqualFold(diskIID.SystemId, "") { + newErr := fmt.Errorf("Invalid Disk SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } else if strings.EqualFold(vmIID.SystemId, "") { + newErr := fmt.Errorf("Invalid Disk SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } + + curStatus, err := diskHandler.getDiskStatus(diskIID) + if err != nil { + newErr := fmt.Errorf("Failed to Get the Disk Status : [%v] ", err) + cblogger.Error(newErr.Error()) + return irs.DiskInfo{}, newErr + } else if strings.EqualFold(string(curStatus), string(irs.DiskAttached)) { + newErr := fmt.Errorf("Failed to Attach the Disk Volume. The Disk is already 'Attached'.") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } + + start := call.Start() + createOpts := vattach.CreateOpts{ + VolumeID: diskIID.SystemId, + } + _, createErr := vattach.Create(diskHandler.VMClient, vmIID.SystemId, createOpts).Extract() + if createErr != nil { + newErr := fmt.Errorf("Failed to Attach the Disk Volume!! : [%v] ", createErr) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } + loggingInfo(callLogInfo, start) + + // Wait for Disk Attachment finished + curStatus, waitErr := diskHandler.waitForDiskAttachment(diskIID) + if waitErr != nil { + newErr := fmt.Errorf("Failed to Wait to Get Disk Info. [%v]", waitErr.Error()) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } + cblogger.Infof("==> Disk Status : [%s]", string(curStatus)) + + diskInfo, err := diskHandler.GetDisk(diskIID) + if err != nil { + newErr := fmt.Errorf("Failed to Get Disk Info!! : [%v] ", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.DiskInfo{}, newErr + } + return diskInfo, nil +} + +func (diskHandler *KTVpcDiskHandler) DetachDisk(diskIID irs.IID, vmIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud VPC Driver: called DetachDisk()") + callLogInfo := getCallLogScheme(diskHandler.RegionInfo.Region, call.DISK, diskIID.SystemId, "DetachDisk()") + + if strings.EqualFold(diskIID.SystemId, "") { + newErr := fmt.Errorf("Invalid Disk SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } else if strings.EqualFold(vmIID.SystemId, "") { + newErr := fmt.Errorf("Invalid Disk SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + + curStatus, err := diskHandler.getDiskStatus(diskIID) + if err != nil { + newErr := fmt.Errorf("Failed to Get the Disk Status : [%v] ", err) + cblogger.Error(newErr.Error()) + return false, newErr + } else if !strings.EqualFold(string(curStatus), string(irs.DiskAttached)) { + newErr := fmt.Errorf("Failed to Detach the Disk Volume. The Disk Status is Not 'Attached'.") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + + isBootable, err := diskHandler.isBootableDisk(diskIID) + if err != nil { + newErr := fmt.Errorf("Failed to Get the Bootable Disk Info. : [%v] ", err) + cblogger.Error(newErr.Error()) + return false, newErr + } else if isBootable { + newErr := fmt.Errorf("Failed to Detach the Disk Volume. The Disk is 'Bootable Disk and Attached'.") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + + start := call.Start() + delErr := vattach.Delete(diskHandler.VMClient, vmIID.SystemId, diskIID.SystemId).ExtractErr() + if delErr != nil { + newErr := fmt.Errorf("Failed to Detach the Disk Volume!! : [%v] ", delErr) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + loggingInfo(callLogInfo, start) + + return true, nil +} + +// Waiting for up to 500 seconds during Disk creation until Disk info. can be get +func (diskHandler *KTVpcDiskHandler) waitForDiskCreation(diskIID irs.IID) (irs.DiskStatus, error) { + cblogger.Info("===> Since Disk info. cannot be retrieved immediately after Disk creation, it waits until running.") + + curRetryCnt := 0 + maxRetryCnt := 500 + for { + curStatus, err := diskHandler.getDiskStatus(diskIID) + if err != nil { + newErr := fmt.Errorf("Failed to Get the Disk Status of [%s] : [%v] ", diskIID.NameId, err) + cblogger.Error(newErr.Error()) + return "Failed. ", newErr + } else { + cblogger.Infof("Succeeded in Getting the Disk Status of [%s] : [%s]", diskIID.NameId, string(curStatus)) + } + + cblogger.Infof("===> Disk Status : [%s]", string(curStatus)) + + switch string(curStatus) { + case "Creating": + curRetryCnt++ + cblogger.Infof("The Disk is still 'Creating', so wait for a second more before inquiring the Disk info.") + time.Sleep(time.Second * 2) + if curRetryCnt > maxRetryCnt { + newErr := fmt.Errorf("Despite waiting for a long time(%d sec), the Disk status is %s, so it is forcibly finished.", maxRetryCnt, string(curStatus)) + cblogger.Error(newErr.Error()) + return "Failed. ", newErr + } + default: + cblogger.Infof("===> ### The Disk 'Creation' is finished, stopping the waiting.") + return curStatus, nil + //break + } + } +} + +// Waiting for up to 500 seconds during Disk Attachment +func (diskHandler *KTVpcDiskHandler) waitForDiskAttachment(diskIID irs.IID) (irs.DiskStatus, error) { + curRetryCnt := 0 + maxRetryCnt := 500 + for { + curStatus, err := diskHandler.getDiskStatus(diskIID) + if err != nil { + newErr := fmt.Errorf("Failed to Get the Disk Status of [%s] : [%v] ", diskIID.NameId, err) + cblogger.Error(newErr.Error()) + return "Failed. ", newErr + } else { + cblogger.Infof("Succeeded in Getting the Disk Status of [%s] : [%s]", diskIID.NameId, curStatus) + } + + cblogger.Infof("===> Disk Status : [%s]", string(curStatus)) + + switch string(curStatus) { + case string(irs.DiskCreating), string(irs.DiskAvailable), string(irs.DiskDeleting), string(irs.DiskError), "Unknown" : + curRetryCnt++ + cblogger.Infof("The Disk is still [%s], so wait for a second more during the Disk 'Attachment'.", string(curStatus)) + time.Sleep(time.Second * 2) + if curRetryCnt > maxRetryCnt { + newErr := fmt.Errorf("Despite waiting for a long time(%d sec), the Disk status is '%s', so it is forcibly finished.", maxRetryCnt, string(curStatus)) + cblogger.Error(newErr.Error()) + return "Failed. ", newErr + } + default: + cblogger.Infof("===> ### The Disk 'Attachment' is finished, stopping the waiting.") + return curStatus, nil + //break + } + } +} + +func (diskHandler *KTVpcDiskHandler) getDiskStatus(diskIID irs.IID) (irs.DiskStatus, error) { + cblogger.Info("KT Cloud VPC Driver: called getDiskStatus()") + + if strings.EqualFold(diskIID.SystemId, "") { + newErr := fmt.Errorf("Invalid Disk SystemId!!") + cblogger.Error(newErr.Error()) + return irs.DiskError, newErr + } + + diskResult, err := volumes2.Get(diskHandler.VolumeClient, diskIID.SystemId).Extract() + if err != nil { + newErr := fmt.Errorf("Failed to Get the KT Disk Info!! : [%v]", err) + cblogger.Error(newErr.Error()) + return irs.DiskError, newErr + } + + cblogger.Infof("# diskResult.Status of KT Cloud : [%s]", diskResult.Status) + diskStatus := convertDiskStatus(diskResult.Status) + + return diskStatus, nil +} + +func convertDiskStatus(diskStatus string) irs.DiskStatus { + cblogger.Info("KT Cloud VPC Driver: called convertDiskStatus()") + + var resultStatus irs.DiskStatus + switch strings.ToLower(diskStatus) { + case "creating": + resultStatus = irs.DiskCreating + case "available": + resultStatus = irs.DiskAvailable + case "in-use": + resultStatus = irs.DiskAttached + case "deleting": + resultStatus = irs.DiskDeleting + case "error": + resultStatus = irs.DiskError + case "error_deleting": + resultStatus = irs.DiskError + case "error_backing-up": + resultStatus = irs.DiskError + case "error_restoring": + resultStatus = irs.DiskError + case "error_extending": + resultStatus = irs.DiskError + default: + resultStatus = "Unknown" + } + + return resultStatus +} + +func (diskHandler *KTVpcDiskHandler) isBootableDisk(diskIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud VPC Driver: called isBootableDisk()") + + if strings.EqualFold(diskIID.SystemId, "") { + newErr := fmt.Errorf("Invalid Disk SystemId!!") + cblogger.Error(newErr.Error()) + return false, newErr + } + + diskResult, err := volumes2.Get(diskHandler.VolumeClient, diskIID.SystemId).Extract() + if err != nil { + newErr := fmt.Errorf("Failed to Get the KT Disk Info!! : [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + + isBootable, err := strconv.ParseBool(diskResult.Bootable) + if err != nil { + newErr := fmt.Errorf("Failed to Parse the String value!! : [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + + return isBootable, nil +} + +func (diskHandler *KTVpcDiskHandler) mappingDiskInfo(volume volumes2.Volume) (irs.DiskInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called mappingDiskInfo()") + // cblogger.Info("\n\n### volume : ") + // spew.Dump(volume) + // cblogger.Info("\n") + + // Convert to KTC + convertedTime, err := convertTimeToKTC(volume.CreatedAt) + if err != nil { + newErr := fmt.Errorf("Failed to Get Converted Time. [%v]", err) + return irs.DiskInfo{}, newErr + } + + diskInfo := irs.DiskInfo{ + IId: irs.IID{ + SystemId: volume.ID, + }, + DiskSize: strconv.Itoa(volume.Size), + Status: convertDiskStatus(volume.Status), + CreatedTime: convertedTime, + } + + if strings.EqualFold(volume.Name, "") { // Bootable disk of Not 'u2' VMSpec + diskInfo.IId.NameId = "Auto_Created_Booting_Disk" + } else { + diskInfo.IId.NameId = volume.Name + } + + if strings.Contains(volume.VolumeType, "HDD") { // Ex) volume.VolumeType : "HDD-2000iops" + diskInfo.DiskType = "HDD" + } else if strings.Contains(volume.VolumeType, "SSD") { + diskInfo.DiskType = "SSD" + } + + if volume.Attachments != nil && len(volume.Attachments) > 0 { + for _, attachment := range volume.Attachments { + // ### Because of the abnormal cases of KT Cloud Volume aftger VM Terminateon(Except Not exist VM) + ktVm, err := servers.Get(diskHandler.VMClient, attachment.ServerID).Extract() + if err != nil { + newErr := fmt.Errorf("Failed to Get Volume Info list!! : [%v] ", err) + cblogger.Error(newErr.Error()) + // return irs.DiskInfo{}, newErr + } else if !strings.EqualFold(ktVm.Name, "") { + diskInfo.OwnerVM = irs.IID{ + NameId: ktVm.Name, + SystemId: attachment.ServerID, + } + } + } + } + + keyValueList := []irs.KeyValue{ + {Key: "AvailabilityZone", Value: volume.AvailabilityZone}, + {Key: "IsBootable", Value: volume.Bootable}, + {Key: "IsMultiattached", Value: strconv.FormatBool(volume.Multiattach)}, + {Key: "IsEncrypted", Value: strconv.FormatBool(volume.Encrypted)}, + } + + // Check if 'Image Name' value exists and add it to the key/value list + keyValue := irs.KeyValue{} + if imageName, exists := volume.VolumeImageMetadata["image_name"]; exists { + // fmt.Printf("Image Name: %s\n", imageName) + keyValue = irs.KeyValue{Key: "ImageName", Value: imageName} + } else { + fmt.Println("Image Name not found in volume info.") + } + keyValueList = append(keyValueList, keyValue) + diskInfo.KeyValueList = keyValueList + + return diskInfo, nil +} + +func (diskHandler *KTVpcDiskHandler) getImageNameandIDWithDiskID(diskId string) (irs.IID, error) { + cblogger.Info("KT Cloud VPC Driver: called getImageNameandIDWithDiskID()") + + if strings.EqualFold(diskId, "") { + newErr := fmt.Errorf("Invalid Disk ID!!") + cblogger.Error(newErr.Error()) + return irs.IID{}, newErr + } + + diskResult, err := volumes2.Get(diskHandler.VolumeClient, diskId).Extract() + if err != nil { + newErr := fmt.Errorf("Failed to Get the KT Disk Info!! : [%v]", err) + cblogger.Error(newErr.Error()) + return irs.IID{}, newErr + } + + var imageIID irs.IID + bootable, err := strconv.ParseBool(diskResult.Bootable) + if err != nil { + newErr := fmt.Errorf("Failed to Parse the String to Bool!! : [%v]", err) + return irs.IID{}, newErr + } + if bootable { + // Extract the image name + imageName, ok := diskResult.VolumeImageMetadata["image_name"] + if !ok { + fmt.Println("Image Name not found") + } else { + fmt.Println("Image Name:", imageName) + } + + // Extract the image id + imageId, ok := diskResult.VolumeImageMetadata["image_id"] + if !ok { + fmt.Println("Image ID not found") + } else { + fmt.Println("Image ID:", imageId) + } + + if !strings.EqualFold(imageName, "") && !strings.EqualFold(imageId, "") { + imageIID.NameId = imageName + imageIID.SystemId = imageId + } else { + newErr := fmt.Errorf("Failed to Get the KT Disk Info!! : [%v]", err) + cblogger.Error(newErr.Error()) + return irs.IID{}, newErr + } + } else { + newErr := fmt.Errorf("The Disk Volume is Not Bootable!!") + return irs.IID{}, newErr + } + + return imageIID, nil +} + +func (diskHandler *KTVpcDiskHandler) getKtVolumeList() ([]volumes2.Volume, error) { + cblogger.Info("KT Cloud VPC Driver: called getKtVolumeList()") + callLogInfo := getCallLogScheme(diskHandler.RegionInfo.Region, call.DISK, "getKtVolumeList()", "getKtVolumeList()") + + start := call.Start() + listOpts := volumes2.ListOpts{} + allPages, err := volumes2.List(diskHandler.VolumeClient, listOpts).AllPages() + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud Volume Pages!! : [%v] ", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + ktVolumeList, err := volumes2.ExtractVolumes(allPages) + if err != nil { + newErr := fmt.Errorf("Failed to Extract KT Cloud Volume list!! : [%v] ", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + loggingInfo(callLogInfo, start) + // spew.Dump(ktVolumeList) + + if len(ktVolumeList) < 1 { + newErr := fmt.Errorf("KT Cloud Volume does Not Exist!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + return ktVolumeList, nil +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/ImageHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/ImageHandler.go new file mode 100644 index 000000000..2d8f4165d --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/ImageHandler.go @@ -0,0 +1,248 @@ +// 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 Example for PoC Test. +// +// by ETRI, 2022.08. + +package resources + +import ( + "strings" + "fmt" + // "github.com/davecgh/go-spew/spew" + + ktvpcsdk "github.com/cloud-barista/ktcloudvpc-sdk-go" + + // "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/compute/v2/images" + images "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/imageservice/v2/images" // Caution!! + //Ref) 'Image API' return struct of image : ktcloudvpc-sdk-go/openstack/imageservice/v2/images/results.go + //Ref) 'Compute API' return struct of image : ktcloudvpc-sdk-go/openstack/compute/v2/images/results.go + + call "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/call-log" + 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 KTVpcImageHandler struct { + RegionInfo idrv.RegionInfo + VMClient *ktvpcsdk.ServiceClient + ImageClient *ktvpcsdk.ServiceClient +} + +func (imageHandler *KTVpcImageHandler) ListImage() ([]*irs.ImageInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called ListImage()") + callLogInfo := getCallLogScheme(imageHandler.RegionInfo.Zone, call.VMIMAGE, "ListImage()", "ListImage()") // HisCall logging + + listOpts := images.ListOpts{ + Limit: 300, //default : 20 + Visibility: images.ImageVisibilityPublic, // Note : Public image only + } + start := call.Start() + allPages, err := images.List(imageHandler.ImageClient, listOpts).AllPages() + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud VPC Image List. [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + loggingInfo(callLogInfo, start) + + // # To Check!! + // cblogger.Info("### allPages : ") + // spew.Dump(allPages) + + imageList, err := images.ExtractImages(allPages) + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud VPC Image List. [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + + // # To Check!! + // cblogger.Info("### imageList : ") + // spew.Dump(imageList) + + var imageInfoList []*irs.ImageInfo + for _, vmImage := range imageList { + imageInfo, err := imageHandler.mappingImageInfo(vmImage) + if err != nil { + newErr := fmt.Errorf("Failed to Map KT Cloud VPC Image Info. [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + imageInfoList = append(imageInfoList, imageInfo) + } + return imageInfoList, nil +} + +func (imageHandler *KTVpcImageHandler) GetImage(imageIID irs.IID) (irs.ImageInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called GetImage()") + callLogInfo := getCallLogScheme(imageHandler.RegionInfo.Zone, call.VMIMAGE, imageIID.SystemId, "GetImage()") // HisCall logging + + if strings.EqualFold(imageIID.SystemId, "") { + newErr := fmt.Errorf("Invalid SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.ImageInfo{}, newErr + } + + ktImage, err := imageHandler.getKTImage(imageIID) + if err != nil { + newErr := fmt.Errorf("MyImage(Image Template) having the ID does Not Exist!! [%v]", err) + cblogger.Error(newErr.Error()) + return irs.ImageInfo{}, newErr + } + + if strings.EqualFold(ktImage.ID, "") { + return irs.ImageInfo{}, fmt.Errorf("Failed to Get Any Image Info.") + } + + //Ref) 'Image API' return struct of image :ktcloudvpc-sdk-go/openstack/imageservice/v2/images/results.go + //Ref) 'Compute API' return struct of image : ktcloudvpc-sdk-go/openstack/compute/v2/images/results.go + imageInfo, err := imageHandler.mappingImageInfo(*ktImage) + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return irs.ImageInfo{}, err + } + return *imageInfo, nil +} + +func (imageHandler *KTVpcImageHandler) CreateImage(imageReqInfo irs.ImageReqInfo) (irs.ImageInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called CreateImage()!") + + return irs.ImageInfo{}, fmt.Errorf("Does not support CreateImage() yet!!") +} + +func (imageHandler *KTVpcImageHandler) CheckWindowsImage(imageIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud VP Driver: called CheckWindowsImage()") + + if strings.EqualFold(imageIID.SystemId, "") { + newErr := fmt.Errorf("Invalid Image SystemId!!") + cblogger.Error(newErr.Error()) + return false, newErr + } + + ktImage, err := imageHandler.getKTImage(imageIID) + if err != nil { + newErr := fmt.Errorf("Failed to Find the Image with the ID!! [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + + if strings.EqualFold(ktImage.ID, "") { + return false, fmt.Errorf("Failed to Get Any Image Info.") + } + + isWindowsImage := false + if strings.Contains(strings.ToLower(ktImage.Name), "windows") { + isWindowsImage = true + } + return isWindowsImage, nil +} + +func (imageHandler *KTVpcImageHandler) DeleteImage(imageIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud VPC Driver: called DeleteImage()!") + + return true, fmt.Errorf("Does not support DeleteImage() yet!!") +} + +func (imageHandler *KTVpcImageHandler) mappingImageInfo(image images.Image) (*irs.ImageInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called mappingImageInfo()!") + // spew.Dump(image) + + //Ref) 'Image API' return struct of image :ktcloudvpc-sdk-go/openstack/imageservice/v2/images/results.go + //Ref) 'Compute API' return struct of image : ktcloudvpc-sdk-go/openstack/compute/v2/images/results.go + + if strings.EqualFold(image.ID, "") { + return nil, fmt.Errorf("Failed to Get Any Image Info.") + } + + var imgAvailability string + if strings.EqualFold(string(image.Status), "active") { + imgAvailability = "available" + } else { + imgAvailability = "unavailable" + } + + imageInfo := &irs.ImageInfo { + IId: irs.IID{ + NameId: image.ID, // Caution!! + SystemId: image.ID, + }, + GuestOS: image.Name, // Caution!! + Status: imgAvailability, + } + + keyValueList := []irs.KeyValue{ + {Key: "Zone", Value: imageHandler.RegionInfo.Zone}, + {Key: "DiskFormat:", Value: string(image.DiskFormat)}, + {Key: "ContainerFormat:", Value: string(image.ContainerFormat)}, + {Key: "Visibility:", Value: string(image.Visibility)}, + + } + imageInfo.KeyValueList = keyValueList + return imageInfo, nil +} + + +// # Get 'MyImage' Info from KT Cloud +func (imageHandler *KTVpcImageHandler) getKTImage(imageIID irs.IID) (*images.Image, error) { + cblogger.Info("KT Cloud Driver: called getKTImage()") + callLogInfo := getCallLogScheme(imageHandler.RegionInfo.Zone, call.VMIMAGE, imageIID.SystemId, "isPublicImage()") + + if strings.EqualFold(imageIID.SystemId, "") { + newErr := fmt.Errorf("Invalid Image SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + + start := call.Start() + image, err := images.Get(imageHandler.ImageClient, imageIID.SystemId).Extract() // Not ~.VMClient + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud VPC Image Info. [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + loggingInfo(callLogInfo, start) + + if strings.EqualFold(image.ID, "") { + return nil, fmt.Errorf("Failed to Get Any Image Info.") + } + return image, nil +} + +func (imageHandler *KTVpcImageHandler) isPublicImage(imageIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud Driver: called isPublicImage()") + + if strings.EqualFold(imageIID.SystemId, "") { + newErr := fmt.Errorf("Invalid Image SystemId!!") + cblogger.Error(newErr.Error()) + return false, newErr + } + + ktImage, err := imageHandler.getKTImage(imageIID) + if err != nil { + newErr := fmt.Errorf("Failed to Find the Image with the ID!! [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + + if strings.EqualFold(ktImage.ID, "") { + return false, fmt.Errorf("Failed to Get Any Image Info.") + } + + isPublicImage := false + if (ktImage.Visibility == images.ImageVisibilityPublic) { + isPublicImage = true + } + return isPublicImage, nil +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/KeyPairHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/KeyPairHandler.go new file mode 100644 index 000000000..cc5290190 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/KeyPairHandler.go @@ -0,0 +1,272 @@ +// 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 Example for PoC Test. +// +// by ETRI, 2022.08. + +package resources + +import ( + "fmt" + "strings" + // "github.com/davecgh/go-spew/spew" + + ktvpcsdk "github.com/cloud-barista/ktcloudvpc-sdk-go" + keys "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/compute/v2/extensions/keypairs" + + call "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/call-log" + 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" + keycommon "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/common" +) + +type KTVpcKeyPairHandler struct { + CredentialInfo idrv.CredentialInfo + RegionInfo idrv.RegionInfo + VMClient *ktvpcsdk.ServiceClient +} + +func (keyPairHandler *KTVpcKeyPairHandler) CreateKey(keyPairReqInfo irs.KeyPairReqInfo) (irs.KeyPairInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called CreateKey()") + callLogInfo := getCallLogScheme(keyPairHandler.RegionInfo.Zone, call.VMKEYPAIR, keyPairReqInfo.IId.NameId, "CreateKey()") + + if strings.EqualFold(keyPairReqInfo.IId.NameId, "") { + newErr := fmt.Errorf("Invalid KeyPair Name!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.KeyPairInfo{}, newErr + } + + exist, err := keyPairHandler.keyPairExists(keyPairReqInfo.IId) + if err != nil { + newErr := fmt.Errorf("Failed to Create Key. : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.KeyPairInfo{}, newErr + } + if exist { + keyName := keyPairReqInfo.IId.SystemId + if strings.EqualFold(keyPairReqInfo.IId.SystemId, "") { + keyName = keyPairReqInfo.IId.NameId + } + newErr := fmt.Errorf("Failed to Create Key. The Key name [%s] already exists", keyName) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.KeyPairInfo{}, newErr + } + + create0pts := keys.CreateOpts{ + Name: keyPairReqInfo.IId.NameId, + } + + start := call.Start() + keyPair, err := keys.Create(keyPairHandler.VMClient, create0pts).Extract() + if err != nil { + newErr := fmt.Errorf("Failed to Create Key. : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.KeyPairInfo{}, newErr + } + loggingInfo(callLogInfo, start) + + // # Save the publicKey to DB in other to use on VMHandler(Cloud-init) + publicKey := strings.TrimSpace(keyPair.PublicKey) + " " + LnxUserName // Append VM User Name + + strList:= []string{ + keyPairHandler.CredentialInfo.Username, + keyPairHandler.CredentialInfo.Password, + } + hashString, err := keycommon.GenHash(strList) + if err != nil { + newErr := fmt.Errorf("Failed to Generate Hash String : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.KeyPairInfo{}, newErr + } + + addKeyErr := keycommon.AddKey("KTCLOUDVPC", hashString, keyPairReqInfo.IId.NameId, publicKey) + if addKeyErr != nil { + newErr := fmt.Errorf("Failed to Save the Private Key to DB : [%v]", addKeyErr) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.KeyPairInfo{}, newErr + } + + keyPairInfo := mappingKeypairInfo(*keyPair) + keyPairInfo.PublicKey = keyPair.PublicKey + keyPairInfo.PrivateKey = keyPair.PrivateKey + + return *keyPairInfo, nil +} + +func (keyPairHandler *KTVpcKeyPairHandler) ListKey() ([]*irs.KeyPairInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called ListKey()") + callLogInfo := getCallLogScheme(keyPairHandler.RegionInfo.Zone, call.VMKEYPAIR, "ListKey()", "ListKey()") + + var listOptsBuilder keys.ListOptsBuilder + + start := call.Start() + allPages, err := keys.List(keyPairHandler.VMClient, listOptsBuilder).AllPages() + if err != nil { + newErr := fmt.Errorf("Failed to Get KeyPair Pages from KT Cloud. : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + loggingInfo(callLogInfo, start) + + keys, err := keys.ExtractKeyPairs(allPages) + if err != nil { + newErr := fmt.Errorf("Failed to Get KeyPair list. : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + keyPairList := make([]*irs.KeyPairInfo, len(keys)) + for i, key := range keys { + keyPairList[i] = mappingKeypairInfo(key) + } + return keyPairList, nil +} + +func (keyPairHandler *KTVpcKeyPairHandler) GetKey(keyIID irs.IID) (irs.KeyPairInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called GetKey()") + callLogInfo := getCallLogScheme(keyPairHandler.RegionInfo.Zone, call.VMKEYPAIR, keyIID.NameId, "GetKey()") + + var keyNameId string + if strings.EqualFold(keyIID.SystemId, "") { + keyNameId = keyIID.NameId + } else { + keyNameId = keyIID.SystemId + } + + var keyPair *keys.KeyPair + var getOptsBuilder keys.GetOptsBuilder + + start := call.Start() + keyPair, err := keys.Get(keyPairHandler.VMClient, keyNameId, getOptsBuilder).Extract() + if err != nil { + newErr := fmt.Errorf("Failed to Get the KeyPair info from KT Cloud : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.KeyPairInfo{}, newErr + } + loggingInfo(callLogInfo, start) + + keyPairInfo := mappingKeypairInfo(*keyPair) + return *keyPairInfo, nil +} + +func (keyPairHandler *KTVpcKeyPairHandler) DeleteKey(keyIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud VPC Driver: called DeleteKey()") + callLogInfo := getCallLogScheme(keyPairHandler.RegionInfo.Zone, call.VMKEYPAIR, keyIID.NameId, "DeleteKey()") + + exist, err := keyPairHandler.keyPairExists(keyIID) + if err != nil { + newErr := fmt.Errorf("Failed to Delete the KeyPair. : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + if !exist { + var keyNameId string + if strings.EqualFold(keyIID.SystemId, "") { + keyNameId = keyIID.NameId + } else { + keyNameId = keyIID.SystemId + } + + newErr := fmt.Errorf("Failed to Delete the KeyPair. The Key name [%s] Not found", keyNameId) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + + var delOptsBuilder keys.DeleteOptsBuilder + start := call.Start() + delErr := keys.Delete(keyPairHandler.VMClient, keyIID.NameId, delOptsBuilder).ExtractErr() + if delErr != nil { + newErr := fmt.Errorf("Failed to Delete the KeyPair : [%v]", delErr) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + loggingInfo(callLogInfo, start) + + // # Delete the Key on DB + strList:= []string{ + keyPairHandler.CredentialInfo.Username, + keyPairHandler.CredentialInfo.Password, + } + hashString, err := keycommon.GenHash(strList) + if err != nil { + newErr := fmt.Errorf("Failed to Generate Hash String : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + + // Delete the saved publicKey from DB + delKeyErr := keycommon.DelKey("KTCLOUDVPC", hashString, keyIID.NameId) + if delKeyErr != nil { + newErr := fmt.Errorf("Failed to Delete the KeyPair info form DB : [%v]", delKeyErr) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + cblogger.Infof("Succeeded in Deleting Process of the KeyPair : [%s]\n", keyIID.NameId) + + return true, nil +} + +func mappingKeypairInfo(keypair keys.KeyPair) *irs.KeyPairInfo { + cblogger.Info("KT Cloud VPC Driver: called mappingKeypairInfo()") + + keypairInfo := &irs.KeyPairInfo{ + IId: irs.IID{ + NameId: keypair.Name, + SystemId: keypair.Name, + }, + Fingerprint: keypair.Fingerprint, + PublicKey: "N/A", + PrivateKey: "N/A", + VMUserID: LnxUserName, + } + return keypairInfo +} + +func (keyPairHandler *KTVpcKeyPairHandler) keyPairExists(keyIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud VPC Driver: called keyPairExists()") + + var keyNameId string + if strings.EqualFold(keyIID.SystemId, "") { + keyNameId = keyIID.NameId + } else { + keyNameId = keyIID.SystemId + } + + var listOptsBuilder keys.ListOptsBuilder + allPages, err := keys.List(keyPairHandler.VMClient, listOptsBuilder).AllPages() + if err != nil { + newErr := fmt.Errorf("Failed to Get KeyPair Pages from KT Cloud. : [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + keypairList, err := keys.ExtractKeyPairs(allPages) + if err != nil { + newErr := fmt.Errorf("Failed to Get KeyPair list. : [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + for _, keypair := range keypairList { + if strings.EqualFold(keypair.Name, keyNameId) { + return true, nil + } + } + + return false, nil +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/MyImageHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/MyImageHandler.go new file mode 100644 index 000000000..c858d7dff --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/MyImageHandler.go @@ -0,0 +1,382 @@ +package resources + +import ( + "fmt" + "strings" + "strconv" + "time" + _ "time/tzdata" // To prevent 'unknown time zone Asia/Seoul' error + "github.com/davecgh/go-spew/spew" + + ktvpcsdk "github.com/cloud-barista/ktcloudvpc-sdk-go" + // volumes2 "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/blockstorage/v2/volumes" + "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/blockstorage/extensions/volumeactions" + + images "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/imageservice/v2/images" // imageservice/v2/images : For Visibility parameter + // Not '~/openstack/compute/v2/images' + + call "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/call-log" + 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 KTVpcMyImageHandler struct { + RegionInfo idrv.RegionInfo + VMClient *ktvpcsdk.ServiceClient + ImageClient *ktvpcsdk.ServiceClient + NetworkClient *ktvpcsdk.ServiceClient + VolumeClient *ktvpcsdk.ServiceClient +} + +// To Take a Snapshot Root Volume with VM ID (To Create My Image) +func (myImageHandler *KTVpcMyImageHandler) SnapshotVM(snapshotReqInfo irs.MyImageInfo) (irs.MyImageInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called SnapshotVM()") + callLogInfo := getCallLogScheme(myImageHandler.RegionInfo.Zone, call.MYIMAGE, snapshotReqInfo.SourceVM.SystemId, "SnapshotVM()") + + if strings.EqualFold(snapshotReqInfo.SourceVM.SystemId, "") { + newErr := fmt.Errorf("Invalid VM SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.MyImageInfo{}, newErr + } + + var snapshotName string + if !strings.EqualFold(snapshotReqInfo.IId.NameId, "") { + snapshotName = snapshotReqInfo.IId.NameId + } + + bootableVolumeId, err := myImageHandler.getBootableVolumeID(snapshotReqInfo.SourceVM) + if err != nil { + newErr := fmt.Errorf("Failed to Get Bootable VolumeID of the VM. [%v]", err.Error()) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.MyImageInfo{}, newErr + } + + start := call.Start() + uploadImageOpts := volumeactions.UploadImageOpts { + ImageName: snapshotName, + Force: true, // Even if the volume is connected to the server, whether to create an image. + } + volumeImage, err := volumeactions.UploadImage(myImageHandler.VolumeClient, bootableVolumeId, uploadImageOpts).Extract() + if err != nil { + newErr := fmt.Errorf("Failed to Create Image from the Volume!! : [%v] ", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.MyImageInfo{}, newErr + } + loggingInfo(callLogInfo, start) + cblogger.Infof("\n\n# snapShotImageId : [%s]\n", volumeImage.ImageID) + + cblogger.Info("\n\n### volumeImage : ") + spew.Dump(volumeImage) + cblogger.Info("\n") + + // To Wait for Creating a Snapshot Image + newImageIID := irs.IID{SystemId: volumeImage.ImageID} + curStatus, err := myImageHandler.waitForImageSnapshot(newImageIID) + if err != nil { + newErr := fmt.Errorf("Failed to Wait to Get Image Info. [%v]", err.Error()) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.MyImageInfo{}, newErr + } + cblogger.Infof("==> Image Status of [%s] : [%s]", newImageIID.SystemId, string(curStatus)) + + myImageInfo, err := myImageHandler.GetMyImage(newImageIID) + if err != nil { + newErr := fmt.Errorf("Failed to Wait for Getting New Image Info. [%v]", err.Error()) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.MyImageInfo{}, newErr + } + return myImageInfo, nil +} + +// To Manage My Images +func (myImageHandler *KTVpcMyImageHandler) ListMyImage() ([]*irs.MyImageInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called ListMyImage()") + callLogInfo := getCallLogScheme(myImageHandler.RegionInfo.Region, call.MYIMAGE, "ListMyImage()", "ListMyImage()") + + /* + // ImageVisibilityPublic all users + ImageVisibilityPublic ImageVisibility = "public" + + // ImageVisibilityPrivate users with tenantId == tenantId(owner) + ImageVisibilityPrivate ImageVisibility = "private" + + // ImageVisibilityShared images are visible to: + // - users with tenantId == tenantId(owner) + // - users with tenantId in the member-list of the image + // - users with tenantId in the member-list with member_status == 'accepted' + ImageVisibilityShared ImageVisibility = "shared" + + // ImageVisibilityCommunity images: + // - all users can see and boot it + // - users with tenantId in the member-list of the image with + // member_status == 'accepted' have this image in their default image-list. + ImageVisibilityCommunity ImageVisibility = "community" + */ + + start := call.Start() + listOpts := images.ListOpts{ + Visibility: images.ImageVisibilityShared, // Not 'ImageVisibilityPrivate' + } + allPages, err := images.List(myImageHandler.ImageClient, listOpts).AllPages() + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud VPC Image pages. [%v]", err.Error()) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + ktImageList, err := images.ExtractImages(allPages) + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud VPC Image List. [%v]", err.Error()) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + loggingInfo(callLogInfo, start) + + cblogger.Info("\n\n### ktImageList : ") + spew.Dump(ktImageList) + cblogger.Info("# ktImage count : ", len(ktImageList)) + + // Note) Public image : ktImage.Visibility == "public", MyImage : ktImage.Visibility == "shared" + var imageInfoList []*irs.MyImageInfo + for _, ktImage := range ktImageList { + imageInfo, err := myImageHandler.mappingMyImageInfo(ktImage) + if err != nil { + newErr := fmt.Errorf("Failed to Map the MyImage Info. [%v]", err) + return nil, newErr + } + imageInfoList = append(imageInfoList, imageInfo) + } + return imageInfoList, nil +} + +func (myImageHandler *KTVpcMyImageHandler) GetMyImage(myImageIID irs.IID) (irs.MyImageInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called GetMyImage()") + callLogInfo := getCallLogScheme(myImageHandler.RegionInfo.Region, call.MYIMAGE, myImageIID.SystemId, "GetMyImage()") + + if strings.EqualFold(myImageIID.SystemId, "") { + newErr := fmt.Errorf("Invalid SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.MyImageInfo{}, newErr + } + + start := call.Start() + // ktImage, err := comimages.Get(myImageHandler.VMClient, myImageIID.SystemId).Extract() // VM Client + ktImage, err := images.Get(myImageHandler.ImageClient, myImageIID.SystemId).Extract() // Image Client + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud VPC My Image Info. [%v]", err.Error()) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.MyImageInfo{}, newErr + } + loggingInfo(callLogInfo, start) + + imageInfo, err := myImageHandler.mappingMyImageInfo(*ktImage) + if err != nil { + newErr := fmt.Errorf("Failed to Map the MyImage Info. [%v]", err) + return irs.MyImageInfo{}, newErr + } + return *imageInfo, nil +} + +func (myImageHandler *KTVpcMyImageHandler) CheckWindowsImage(myImageIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud VPC Driver: called CheckWindowsImage()") + + return false, fmt.Errorf("KT Cloud VPC Driver Does not support CheckWindowsImage() yet!!") +} + +func (myImageHandler *KTVpcMyImageHandler) DeleteMyImage(myImageIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud VPC Driver: called DeleteMyImage()") + callLogInfo := getCallLogScheme(myImageHandler.RegionInfo.Region, call.MYIMAGE, myImageIID.SystemId, "DeleteMyImage()") + + if strings.EqualFold(myImageIID.SystemId, "") { + newErr := fmt.Errorf("Invalid SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + + err := images.Delete(myImageHandler.ImageClient, myImageIID.SystemId).ExtractErr() + if err != nil { + newErr := fmt.Errorf("Failed to Delete the Image. [%v]", err.Error()) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + + return true, nil +} + +func (myImageHandler *KTVpcMyImageHandler) getImageStatus(myImageIID irs.IID) (irs.MyImageStatus, error) { + cblogger.Info("KT Cloud VPC Driver: called getImageStatus()") + callLogInfo := getCallLogScheme(myImageHandler.RegionInfo.Region, call.MYIMAGE, myImageIID.SystemId, "getImageStatus()") + + if strings.EqualFold(myImageIID.SystemId, "") { + newErr := fmt.Errorf("Invalid SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return "", newErr + } + + start := call.Start() + // ktImage, err := comimages.Get(myImageHandler.VMClient, myImageIID.SystemId).Extract() // VM Client + ktImage, err := images.Get(myImageHandler.ImageClient, myImageIID.SystemId).Extract() // Image Client + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud VPC My Image Info. [%v]", err.Error()) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return "", newErr + } + loggingInfo(callLogInfo, start) + cblogger.Infof("===> KT Image Status : [%s]", string(ktImage.Status)) + + myImageStatus := convertImageStatus(ktImage.Status) + return myImageStatus, nil +} + +// Waiting for up to 500 seconds during Taking a Snapshot from a VM +func (myImageHandler *KTVpcMyImageHandler) waitForImageSnapshot(myImageIID irs.IID) (irs.MyImageStatus, error) { + cblogger.Info("KT Cloud VPC Driver: called waitForImageSnapshot()") + cblogger.Info("===> Since Snapshot info. cannot be retrieved immediately after taking a snapshot, waits ....") + + if strings.EqualFold(myImageIID.SystemId, "") { + newErr := fmt.Errorf("Invalid SystemId!!") + cblogger.Error(newErr.Error()) + return "", newErr + } + + curRetryCnt := 0 + maxRetryCnt := 500 + for { + curStatus, err := myImageHandler.getImageStatus(myImageIID) + if err != nil { + newErr := fmt.Errorf("Failed to Get the Image Status of [%s] : [%v] ", myImageIID.NameId, err) + cblogger.Error(newErr.Error()) + return "Failed. ", newErr + } else { + cblogger.Infof("Succeeded in Getting the Image Status of [%s] : [%s]", myImageIID.SystemId, string(curStatus)) + } + cblogger.Infof("===> Image Status(Converted) : [%s]", string(curStatus)) + + if strings.EqualFold(string(curStatus), "Unavailable") { + curRetryCnt++ + cblogger.Infof("The Image is still 'Unavailable', so wait for a second more before inquiring the Image info.") + time.Sleep(time.Second * 2) + if curRetryCnt > maxRetryCnt { + newErr := fmt.Errorf("Despite waiting for a long time(%d sec), the Image status is %s, so it is forcibly finished.", maxRetryCnt, string(curStatus)) + cblogger.Error(newErr.Error()) + return "Failed. ", newErr + } + } else { + cblogger.Infof("===> ### The Image Snapshot is finished, stopping the waiting.") + return curStatus, nil + //break + } + } +} + +func (myImageHandler *KTVpcMyImageHandler) mappingMyImageInfo(myImage images.Image) (*irs.MyImageInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called mappingMyImageInfo()!") + // cblogger.Info("\n\n### myImage in mappingMyImageInfo() : ") + // spew.Dump(myImage) + // cblogger.Info("\n") + + // Convert to KTC + convertedTime, err := convertTimeToKTC(myImage.CreatedAt) + if err != nil { + newErr := fmt.Errorf("Failed to Get Converted Time. [%v]", err) + return nil, newErr + } + + myImageInfo := &irs.MyImageInfo { + IId: irs.IID{ + NameId: myImage.Name, + SystemId: myImage.ID, + }, + Status: convertImageStatus(myImage.Status), + CreatedTime: convertedTime, + } + + keyValueList := []irs.KeyValue{ + {Key: "Zone", Value: myImageHandler.RegionInfo.Zone}, + {Key: "Visibility", Value: string(myImage.Visibility)}, + {Key: "ImageSize(GB)", Value: strconv.FormatInt(myImage.SizeBytes/(1024*1024*1024), 10)}, + } + myImageInfo.KeyValueList = keyValueList + return myImageInfo, nil +} + +func convertImageStatus(myImageStatus images.ImageStatus) irs.MyImageStatus { + cblogger.Info("KT Cloud VPC Driver: called convertImageStatus()") + + // Ref) https://github.com/cloud-barista/ktcloudvpc-sdk-go/blob/main/openstack/imageservice/v2/images/types.go + var resultStatus irs.MyImageStatus + switch myImageStatus { + case images.ImageStatusQueued: + resultStatus = irs.MyImageUnavailable + case images.ImageStatusSaving: + resultStatus = irs.MyImageUnavailable + case images.ImageStatusActive: + resultStatus = irs.MyImageAvailable + case images.ImageStatusKilled: + resultStatus = irs.MyImageUnavailable + case images.ImageStatusDeleted: + resultStatus = irs.MyImageUnavailable + case images.ImageStatusPendingDelete: + resultStatus = irs.MyImageUnavailable + default: + resultStatus = "Unknown" + } + + return resultStatus +} + +func (myImageHandler *KTVpcMyImageHandler) getBootableVolumeID(vmIID irs.IID) (string, error) { + cblogger.Info("KT Cloud VPC Driver: called getBootableVolumeID()") + + diskHandler := KTVpcDiskHandler{ + RegionInfo: myImageHandler.RegionInfo, + VMClient: myImageHandler.VMClient, + VolumeClient: myImageHandler.VolumeClient, + } + + nhnVolumeList, err := diskHandler.getKtVolumeList() + if err != nil { + newErr := fmt.Errorf("Failed to Get NHN Cloud Volume Pages!! : [%v] ", err) + cblogger.Error(newErr.Error()) + return "", newErr + } + + var bootableVolumeId string + for _, nhnVolume := range nhnVolumeList { + isBootable, err := strconv.ParseBool(nhnVolume.Bootable) + if err != nil { + newErr := fmt.Errorf("Failed to Parse the String value!! : [%v]", err) + cblogger.Error(newErr.Error()) + return "", newErr + } + + if isBootable && nhnVolume.Attachments != nil && len(nhnVolume.Attachments) > 0 { + for _, attachment := range nhnVolume.Attachments { + if strings.EqualFold(attachment.ServerID, vmIID.SystemId) { + bootableVolumeId = attachment.VolumeID + break + } + } + } + } + + if strings.EqualFold(bootableVolumeId, "") { + newErr := fmt.Errorf("Failed to Find any Bootable Volume : [%v] ", err) + cblogger.Error(newErr.Error()) + return "", newErr + } + + return bootableVolumeId, nil +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/NLBHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/NLBHandler.go new file mode 100644 index 000000000..a4e90355b --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/NLBHandler.go @@ -0,0 +1,476 @@ +// 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 Example for PoC Test. +// +// by ETRI Team, 2024.02. + +package resources + +import ( + "fmt" + "strings" + "strconv" + "time" + // "github.com/davecgh/go-spew/spew" + + call "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/call-log" + 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" + + ktvpcsdk "github.com/cloud-barista/ktcloudvpc-sdk-go" + ktvpclb "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/loadbalancer/v1/loadbalancers" +) + +type KTVpcNLBHandler struct { + RegionInfo idrv.RegionInfo + VMClient *ktvpcsdk.ServiceClient + NetworkClient *ktvpcsdk.ServiceClient + NLBClient *ktvpcsdk.ServiceClient +} + +const ( + DefaultNLBOption string = "roundrobin" // NLBOption : roundrobin / leastconnection / leastresponse / sourceiphash / + DefaultHealthCheckURL string = "abc.kt.com" + NlbSubnetName string = "NLB-SUBNET" // Subnet for NLB +) + +func (nlbHandler *KTVpcNLBHandler) CreateNLB(nlbReqInfo irs.NLBInfo) (createNLB irs.NLBInfo, newErr error) { + cblogger.Info("KT Cloud VPC Driver: called CreateNLB()") + callLogInfo := getCallLogScheme(nlbHandler.RegionInfo.Zone, "NETWORKLOADBALANCE", nlbReqInfo.IId.NameId, "CreateNLB()") + + if strings.EqualFold(nlbReqInfo.IId.NameId, "") { + newErr := fmt.Errorf("Invalid NLB NameId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.NLBInfo{}, newErr + } + + if strings.EqualFold(nlbReqInfo.VpcIID.NameId, "") { + newErr := fmt.Errorf("Invalid VPC NameId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.NLBInfo{}, newErr + } + + if !strings.EqualFold(nlbReqInfo.Listener.Protocol, nlbReqInfo.VMGroup.Protocol) { + newErr := fmt.Errorf("Listener Protocol and VMGroup Protocol should be the Same for KT Cloud NLB!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.NLBInfo{}, newErr + } + + if !strings.EqualFold(nlbReqInfo.Listener.Port, nlbReqInfo.VMGroup.Port) { + newErr := fmt.Errorf("Listener Port and VMGroup Prot should be the Same for this KT Cloud connection driver!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.NLBInfo{}, newErr + } + + vpcHandler := KTVpcVPCHandler{ + RegionInfo: nlbHandler.RegionInfo, + NetworkClient: nlbHandler.NetworkClient, // Required!! + } + OsNetId, getError := vpcHandler.getOsNetworkIdWithTierName(NlbSubnetName) + if getError != nil { + newErr := fmt.Errorf("Failed to Get the OsNetwork ID of the Subnet : [%v]", getError) + cblogger.Error(newErr.Error()) + return irs.NLBInfo{}, newErr + } else { + cblogger.Infof("# OsNetwork ID of NLB-SUBNET : %s", OsNetId) + } + + createOpts := ktvpclb.CreateOpts{ + Name: nlbReqInfo.IId.NameId, // Required + ZoneID: nlbHandler.RegionInfo.Zone, // Required + NlbOption: DefaultNLBOption, // Required + ServiceIP: "", // Required. KT Cloud Virtual IP. $$$ In case of an empty value(""), it is newly created. + ServicePort: nlbReqInfo.Listener.Port, // Required + ServiceType: nlbReqInfo.Listener.Protocol, // Required + HealthCheckType: nlbReqInfo.HealthChecker.Protocol, // Required + HealthCheckURL: DefaultHealthCheckURL, // URL when the HealthCheckType (above) is 'http' or 'https'. + NetworkID: OsNetId, // Required. Caution!!) Not Tier 'ID' but 'OsNetworkID' of the Tier!! + } + + start := call.Start() + resp, err := ktvpclb.Create(nlbHandler.NLBClient, createOpts).Extract() // Not 'NetworkClient' + if err != nil { + newErr := fmt.Errorf("Failed to Create New NLB. [%v]", err.Error()) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.NLBInfo{}, newErr + } + loggingInfo(callLogInfo, start) + cblogger.Infof("# New NLBId : %s", resp.Createnlbresponse.NLBId) + + cblogger.Info("\n### Creating New NLB Now!!") + time.Sleep(time.Second * 15) + + ktNLB, err := nlbHandler.getKTCloudNlbWithName(nlbReqInfo.IId.NameId) + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud NLB info!! [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.NLBInfo{}, newErr + } + nlbIID := irs.IID{SystemId: strconv.Itoa(ktNLB.NlbID)} + + nlbInfo, getErr := nlbHandler.GetNLB(nlbIID) + if getErr != nil { + newErr := fmt.Errorf("Failed to Get New NLB Info : [%v]", getErr) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.NLBInfo{}, newErr + } + return nlbInfo, nil +} + +func (nlbHandler *KTVpcNLBHandler) ListNLB() ([]*irs.NLBInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called ListNLB()") + callLogInfo := getCallLogScheme(nlbHandler.RegionInfo.Zone, "NETWORKLOADBALANCE", "ListNLB()", "ListNLB()") + + if strings.EqualFold(nlbHandler.RegionInfo.Zone, "") { + newErr := fmt.Errorf("Invalid Zone Info!!") + cblogger.Error(newErr.Error()) + return nil, newErr + } + + listOpts := ktvpclb.ListOpts{ + ZoneID: nlbHandler.RegionInfo.Zone, + } + start := call.Start() + firstPage, err := ktvpclb.List(nlbHandler.NLBClient, listOpts).FirstPage() // Not 'NetworkClient', Not 'AllPages()' + if err != nil { + newErr := fmt.Errorf("Failed to Get NLB List from KT Cloud : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + nlbList, err := ktvpclb.ExtractLoadBalancers(firstPage) + if err != nil { + newErr := fmt.Errorf("Failed to Extract NLB List : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + loggingInfo(callLogInfo, start) + + // cblogger.Info("\n\n# nlbList from KT Cloud VPC : ") + // spew.Dump(nlbList) + // cblogger.Info("\n") + + time.Sleep(time.Second * 1) // Before 'return' + // To Prevent the Error : "Unable to execute API command listTags due to ratelimit timeout" + + if len(nlbList) < 1 { + cblogger.Info("# KT Cloud NLB does Not Exist!!") + return []*irs.NLBInfo{}, nil // Not Return Error + } + + var nlbInfoList []*irs.NLBInfo + for _, nlb := range nlbList { + nlbInfo, err := nlbHandler.mappingNlbInfo(&nlb) + if err != nil { + newErr := fmt.Errorf("Failed to Get NLB Info : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + nlbInfoList = append(nlbInfoList, &nlbInfo) + } + return nlbInfoList, nil +} + +func (nlbHandler *KTVpcNLBHandler) GetNLB(nlbIID irs.IID) (irs.NLBInfo, error) { + callLogInfo := getCallLogScheme(nlbHandler.RegionInfo.Zone, "NETWORKLOADBALANCE", nlbIID.SystemId, "GetNLB()") + + if strings.EqualFold(nlbIID.SystemId, "") { + newErr := fmt.Errorf("Invalid NLB ID!!") + cblogger.Error(newErr.Error()) + return irs.NLBInfo{}, newErr + } + + ktNLB, err := nlbHandler.getKTCloudNlb(nlbIID.SystemId) + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud NLB info!! [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.NLBInfo{}, newErr + } + + var nlbInfo irs.NLBInfo + nlbInfo, err = nlbHandler.mappingNlbInfo(ktNLB) + if err != nil { + newErr := fmt.Errorf("Failed to Map NLB Info with the NLB : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.NLBInfo{}, newErr + } + return nlbInfo, nil +} + +func (nlbHandler *KTVpcNLBHandler) DeleteNLB(nlbIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud Driver: called DeleteNLB()") + callLogInfo := getCallLogScheme(nlbHandler.RegionInfo.Region, "NETWORKLOADBALANCE", nlbIID.SystemId, "DeleteNLB()") + + deleteOpts := ktvpclb.DeleteOpts{ + NlbID: nlbIID.SystemId, + } + + start := call.Start() + delErr := ktvpclb.Delete(nlbHandler.NLBClient, deleteOpts).ExtractErr() + if delErr != nil { + newErr := fmt.Errorf("Failed to Delete the KeyPair : [%v]", delErr) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + loggingInfo(callLogInfo, start) + + return true, nil +} + +//------ Frontend Control +func (nlbHandler *KTVpcNLBHandler) ChangeListener(nlbIID irs.IID, listener irs.ListenerInfo) (irs.ListenerInfo, error) { + + return irs.ListenerInfo{}, fmt.Errorf("Does not support yet!!") +} + +//------ Backend Control +func (nlbHandler *KTVpcNLBHandler) ChangeVMGroupInfo(nlbIID irs.IID, vmGroup irs.VMGroupInfo) (irs.VMGroupInfo, error) { + + return irs.VMGroupInfo{}, fmt.Errorf("Does not support yet!!") +} + +func (nlbHandler *KTVpcNLBHandler) AddVMs(nlbIID irs.IID, vmIIDs *[]irs.IID) (irs.VMGroupInfo, error) { + + return irs.VMGroupInfo{}, fmt.Errorf("Does not support yet!!") +} + +func (nlbHandler *KTVpcNLBHandler) RemoveVMs(nlbIID irs.IID, vmIIDs *[]irs.IID) (bool, error) { + + return false, fmt.Errorf("Does not support yet!!") +} + +func (nlbHandler *KTVpcNLBHandler) GetVMGroupHealthInfo(nlbIID irs.IID) (irs.HealthInfo, error) { + cblogger.Info("KT Cloud Driver: called GetVMGroupHealthInfo()") + + return irs.HealthInfo{}, nil +} + +func (nlbHandler *KTVpcNLBHandler) ChangeHealthCheckerInfo(nlbIID irs.IID, healthChecker irs.HealthCheckerInfo) (irs.HealthCheckerInfo, error) { + + return irs.HealthCheckerInfo{}, fmt.Errorf("KT Cloud does not support ChangeHealthCheckerInfo() yet!!") +} + +func (nlbHandler *KTVpcNLBHandler) getListenerInfo(nlb *ktvpclb.LoadBalancer) (irs.ListenerInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called getListenerInfo()") + + nlbId := strconv.Itoa(nlb.NlbID) + InitLog() + callLogInfo := getCallLogScheme(nlbHandler.RegionInfo.Region, "NETWORKLOADBALANCE", nlbId, "getListenerInfo()") + + if strings.EqualFold(nlbId, "") { + newErr := fmt.Errorf("Invalid Load-Balancer ID. The LB does Not Exit!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.ListenerInfo{}, newErr + } + + listenerInfo := irs.ListenerInfo{ + Protocol: nlb.ServiceType, + IP: nlb.ServiceIP, + Port: nlb.ServicePort, + // DNSName: "N/A", + // CspID: "N/A", + } + listenerKVList := []irs.KeyValue{ + // {Key: "NLB_DomainName", Value: *nlb.DomainName}, + } + listenerInfo.KeyValueList = listenerKVList + return listenerInfo, nil +} + +func (nlbHandler *KTVpcNLBHandler) getHealthCheckerInfo(nlb *ktvpclb.LoadBalancer) (irs.HealthCheckerInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called getHealthCheckerInfo()") + + nlbId := strconv.Itoa(nlb.NlbID) + InitLog() + callLogInfo := getCallLogScheme(nlbHandler.RegionInfo.Region, "NETWORKLOADBALANCE", nlbId, "getHealthCheckerInfo()") + + if strings.EqualFold(nlbId, "") { + newErr := fmt.Errorf("Invalid Load-Balancer ID. The LB does Not Exit!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.HealthCheckerInfo{}, newErr + } + + healthCheckerInfo := irs.HealthCheckerInfo{ + Protocol: nlb.HealthCheckType, + Port: nlb.ServicePort, + // CspID: "N/A", + } + return healthCheckerInfo, nil +} + +func (nlbHandler *KTVpcNLBHandler) mappingNlbInfo(nlb *ktvpclb.LoadBalancer) (irs.NLBInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called mappingNlbInfo()") + // cblogger.Info("\n\n### nlb : ") + // spew.Dump(nlb) + + // // # Get ImageInfo frome the Disk Volume + // diskHandler := KTVpcDiskHandler{ + // RegionInfo: vmHandler.RegionInfo, + // VMClient: vmHandler.VMClient, + // VolumeClient: vmHandler.VolumeClient, + // } + + + // vpcId, subnetId, publicIp, _, err := vmHandler.getNetIDsWithPrivateIP(vmInfo.PrivateIP) + // if err != nil { + // newErr := fmt.Errorf("Failed to Get PortForwarding Info. [%v]", err) + // cblogger.Error(newErr.Error()) + // return irs.VMInfo{}, newErr + // } + // vmInfo.VpcIID.SystemId = vpcId + // vmInfo.SubnetIID.SystemId = subnetId // Caution!!) Need modification. Not Tier 'ID' but 'OsNetworkID' to Create VM through REST API!! + // vmInfo.PublicIP = publicIp + + nlbInfo := irs.NLBInfo{ + IId: irs.IID{ + NameId: nlb.Name, + SystemId: strconv.Itoa(nlb.NlbID), + }, + // VpcIID: irs.IID{ + // NameId: "N/A", // Cauton!!) 'NameId: "N/A"' makes an Error on CB-Spider + // SystemId: "N/A", + // }, + Type: "PUBLIC", + Scope: "REGION", + } + + keyValueList := []irs.KeyValue{ + {Key: "NLB_Method", Value: nlb.NlbOption}, + {Key: "NLB_State", Value: nlb.State}, + {Key: "NLB_ServiceIP", Value: nlb.ServiceIP}, + {Key: "NLB_ServicePort", Value: nlb.ServicePort}, + {Key: "ZoneName", Value: nlb.ZoneName}, + } + nlbInfo.KeyValueList = keyValueList + + if !strings.EqualFold(nlb.ServiceIP, "") { + listenerInfo, err := nlbHandler.getListenerInfo(nlb) + if err != nil { + newErr := fmt.Errorf("Failed to Get the Listener Info : [%v]", err.Error()) + cblogger.Error(newErr.Error()) + return irs.NLBInfo{}, newErr + } + nlbInfo.Listener = listenerInfo + } + + if !strings.EqualFold(nlb.HealthCheckType, "") { + healthCheckerInfo, err := nlbHandler.getHealthCheckerInfo(nlb) + if err != nil { + newErr := fmt.Errorf("Failed to Get HealthChecker Info. frome the NLB. [%v]", err.Error()) + cblogger.Error(newErr.Error()) + return irs.NLBInfo{}, newErr + } + nlbInfo.HealthChecker = healthCheckerInfo + } + + // vmGroupInfo, err := nlbHandler.getVMGroupInfo(strconv.Itoa(nlb.NLBId)) + // if err != nil { + // newErr := fmt.Errorf("Failed to Get VM Group Info with the NLB ID : [%v]", err) + // cblogger.Error(newErr.Error()) + // return irs.NLBInfo{}, newErr + // } + // nlbInfo.VMGroup = vmGroupInfo + return nlbInfo, nil +} + +func (nlbHandler *KTVpcNLBHandler) getKTCloudNlb(nlbId string) (*ktvpclb.LoadBalancer, error) { + cblogger.Info("KT Cloud VPC Driver: called getKTCloudNlb()") + InitLog() + callLogInfo := getCallLogScheme(nlbHandler.RegionInfo.Zone, "NETWORKLOADBALANCE", nlbId, "getKTCloudNlb()") + + if strings.EqualFold(nlbId, "") { + newErr := fmt.Errorf("Invalid NLB ID!!") + cblogger.Error(newErr.Error()) + return nil, newErr + } + + listOpts := ktvpclb.ListOpts{ + ZoneID: nlbHandler.RegionInfo.Zone, + NlbID: nlbId, + } + start := call.Start() + firstPage, err := ktvpclb.List(nlbHandler.NLBClient, listOpts).FirstPage() // Not '~.AllPages()' + if err != nil { + cblogger.Errorf("Failed to Get KT Cloud NLB Page : [%v]", err) + return nil, err + } + nlbList, err := ktvpclb.ExtractLoadBalancers(firstPage) + if err != nil { + cblogger.Errorf("Failed to Get KT Cloud NLB list : [%v]", err) + return nil, err + } + loggingInfo(callLogInfo, start) + + time.Sleep(time.Second * 1) // Before 'return' + // To Prevent the Error : "Unable to execute API command listTags due to ratelimit timeout" + + if len(nlbList) < 1 { + newErr := fmt.Errorf("Failed to Find the NLB info with the ID on the zone!!") + cblogger.Error(newErr.Error()) + return nil, newErr + } + // cblogger.Info("\n\n### result.Listnlbsresponse : ") + // spew.Dump(result.Listnlbsresponse) + + return &nlbList[0], nil +} + +func (nlbHandler *KTVpcNLBHandler) getKTCloudNlbWithName(nlbName string) (*ktvpclb.LoadBalancer, error) { + cblogger.Info("KT Cloud VPC Driver: called getKTCloudNlbWithName()") + InitLog() + callLogInfo := getCallLogScheme(nlbHandler.RegionInfo.Zone, "NETWORKLOADBALANCE", nlbName, "getKTCloudNlbWithName()") + + if strings.EqualFold(nlbName, "") { + newErr := fmt.Errorf("Invalid NLB ID!!") + cblogger.Error(newErr.Error()) + return nil, newErr + } + + listOpts := ktvpclb.ListOpts{ + ZoneID: nlbHandler.RegionInfo.Zone, + Name: nlbName, + } + start := call.Start() + firstPage, err := ktvpclb.List(nlbHandler.NLBClient, listOpts).FirstPage() // Not '~.AllPages()' + if err != nil { + cblogger.Errorf("Failed to Get KT Cloud NLB Page : [%v]", err) + return nil, err + } + nlbList, err := ktvpclb.ExtractLoadBalancers(firstPage) + if err != nil { + cblogger.Errorf("Failed to Get KT Cloud NLB list : [%v]", err) + return nil, err + } + loggingInfo(callLogInfo, start) + + time.Sleep(time.Second * 1) // Before 'return' + // To Prevent the Error : "Unable to execute API command listTags due to ratelimit timeout" + + if len(nlbList) < 1 { + newErr := fmt.Errorf("Failed to Find the NLB info with the Name on the zone!!") + cblogger.Error(newErr.Error()) + return nil, newErr + } + // cblogger.Info("\n\n### result.Listnlbsresponse : ") + // spew.Dump(result.Listnlbsresponse) + + return &nlbList[0], nil +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/RegionZoneHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/RegionZoneHandler.go new file mode 100644 index 000000000..527b30a4a --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/RegionZoneHandler.go @@ -0,0 +1,250 @@ +// Proof of Concepts for the Cloud-Barista Multi-Cloud Project. +// * Cloud-Barista: https://github.com/cloud-barista +// +// KT Cloud VPC RegionZone Handler +// +// Created by ETRI, 2023.10. +//================================================================================================== + +package resources + +import ( + "strings" + "errors" + // "github.com/davecgh/go-spew/spew" + + call "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/call-log" + 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 KtVpcZone struct { + ZoneCode string + ZoneName string +} + +type KtVpcRegion struct { + RegionCode string + RegionName string + ZoneList []KtVpcZone +} + +// As Constant Variables +func getSupportedRegionZones() []KtVpcRegion { + regionList := []KtVpcRegion { + { RegionCode: "KR1", + RegionName: "서울", + ZoneList: []KtVpcZone { + { ZoneCode: "DX-M1", + ZoneName: "목동-1", + }, + }, + }, + } + return regionList +} + +type KTVpcRegionZoneHandler struct { + RegionInfo idrv.RegionInfo +} + +func (regionZoneHandler *KTVpcRegionZoneHandler) ListRegionZone() ([]*irs.RegionZoneInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called ListRegionZone()!!") + + callLogInfo := getCallLogScheme(regionZoneHandler.RegionInfo.Zone, call.REGIONZONE, "ListRegionZone()", "ListRegionZone()") + + ktVpcRegionZoneList := getSupportedRegionZones() + if len(ktVpcRegionZoneList) < 1 { + rtnErr := logAndReturnError(callLogInfo, "Failed to Find Any Region Info.", nil) + return nil, rtnErr + } + + var regionZoneInfoList []*irs.RegionZoneInfo + for _, region := range ktVpcRegionZoneList { + cblogger.Info("# KT RegionCode : ", region.RegionCode) + + regionZoneInfo := irs.RegionZoneInfo{ + Name: region.RegionCode, + DisplayName: region.RegionName, + } + + zoneInfoList, err := regionZoneHandler.getZoneInfoList(region.RegionCode) + if err != nil { + rtnErr := logAndReturnError(callLogInfo, "Failed to Get KT Cloud Zone Info : ", err) + return nil, rtnErr + } + if len(zoneInfoList) < 1 { + rtnErr := logAndReturnError(callLogInfo, "Failed to Find Any Zone Info.", nil) + return nil, rtnErr + } + regionZoneInfo.ZoneList = zoneInfoList + regionZoneInfoList = append(regionZoneInfoList, ®ionZoneInfo) + } + return regionZoneInfoList, nil +} + +func (regionZoneHandler KTVpcRegionZoneHandler) GetRegionZone(regionCode string) (irs.RegionZoneInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called GetRegionZone()!!") + + callLogInfo := getCallLogScheme(regionZoneHandler.RegionInfo.Zone, call.REGIONZONE, regionCode, "GetRegionZone()") + + if len(regionCode) < 1 { + rtnErr := logAndReturnError(callLogInfo, "The RegionCode is Empty!!", nil) + return irs.RegionZoneInfo{}, rtnErr + } + + ktVpcRegionZoneList := getSupportedRegionZones() + if len(ktVpcRegionZoneList) < 1 { + rtnErr := logAndReturnError(callLogInfo, "Failed to Find Any Region Info.", nil) + return irs.RegionZoneInfo{}, rtnErr + } + + var regionZoneInfo irs.RegionZoneInfo + for _, region := range ktVpcRegionZoneList { + if strings.EqualFold(regionCode, region.RegionCode) { + regionZoneInfo = irs.RegionZoneInfo { + Name: region.RegionCode, + DisplayName: region.RegionName, + } + } + } + + zoneInfoList, err := regionZoneHandler.getZoneInfoList(regionCode) + if err != nil { + rtnErr := logAndReturnError(callLogInfo, "Failed to Get ZoneInfoList : ", err) + return irs.RegionZoneInfo{}, rtnErr + } + if len(zoneInfoList) < 1 { + rtnErr := logAndReturnError(callLogInfo, "Failed to Find Any Zone Info.", nil) + return irs.RegionZoneInfo{}, rtnErr + } + regionZoneInfo.ZoneList = zoneInfoList + return regionZoneInfo, nil +} + +func (regionZoneHandler *KTVpcRegionZoneHandler) ListOrgRegion() (string, error) { + cblogger.Info("KT Cloud VPC Driver: called ListOrgRegion()!!") + + callLogInfo := getCallLogScheme(regionZoneHandler.RegionInfo.Zone, call.REGIONZONE, "ListOrgRegion()", "ListOrgRegion()") + + type Region struct { + RegionCode string + RegionName string + } + + ktVpcRegionZoneList := getSupportedRegionZones() + if len(ktVpcRegionZoneList) < 1 { + rtnErr := logAndReturnError(callLogInfo, "Failed to Find Any Region Info.", nil) + return "", rtnErr + } + + var regionInfoList []Region + for _, region := range ktVpcRegionZoneList { + cblogger.Info("# KT RegionCode : ", region.RegionCode) + + regionInfo := Region{ + RegionCode: region.RegionCode, + RegionName: region.RegionName, + } + regionInfoList = append(regionInfoList, regionInfo) + } + + // To return the results with a style similar to other CSPs. + type Regions struct { + RegionList []Region + } + + regionList := Regions{ + RegionList: regionInfoList, + } + jsonString, err := convertJsonString(regionList) + if err != nil { + rtnErr := logAndReturnError(callLogInfo, "Failed to Convert to Json String : ", err) + return "", rtnErr + } + return jsonString, nil +} + +func (regionZoneHandler *KTVpcRegionZoneHandler) ListOrgZone() (string, error) { + cblogger.Info("KT Cloud VPC Driver: called ListOrgZone()!!") + + callLogInfo := getCallLogScheme(regionZoneHandler.RegionInfo.Zone, call.REGIONZONE, regionZoneHandler.RegionInfo.Region, "ListOrgZone()") + + if strings.EqualFold(regionZoneHandler.RegionInfo.Region, "") { + err := errors.New("'regionZoneHandler.RegionInfo.Region' invalid") + rtnErr := logAndReturnError(callLogInfo, "Invalid RegionCode!! ", err) + return "", rtnErr + } + + // To return the results with a style similar to other CSPs. + type Zones struct { + ZoneList []KtVpcZone + } + + ktVpcRegionZoneList := getSupportedRegionZones() + if len(ktVpcRegionZoneList) < 1 { + rtnErr := logAndReturnError(callLogInfo, "Failed to Find Any Region Info.", nil) + return "", rtnErr + } + + var ktVpcZoneList []KtVpcZone + for _, region := range ktVpcRegionZoneList { + if strings.EqualFold(regionZoneHandler.RegionInfo.Region, region.RegionCode) { + if len(region.ZoneList) < 1 { + rtnErr := logAndReturnError(callLogInfo, "Failed to Find Any Zone Info in the Region Info.", nil) + return "", rtnErr + } + ktVpcZoneList = region.ZoneList + } + } + + zoneList := Zones{ + ZoneList: ktVpcZoneList, + } + jsonString, err := convertJsonString(zoneList) + if err != nil { + rtnErr := logAndReturnError(callLogInfo, "Failed to Convert to Json String : ", err) + return "", rtnErr + } + return jsonString, nil +} + +func (regionZoneHandler KTVpcRegionZoneHandler) getZoneInfoList(regionCode string) ([]irs.ZoneInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called getZoneInfoList()!!") + + callLogInfo := getCallLogScheme(regionZoneHandler.RegionInfo.Zone, call.REGIONZONE, regionCode, "getZoneInfoList()") + + if strings.EqualFold(regionCode, "") { + rtnErr := logAndReturnError(callLogInfo, "Invalid RegionCode!!", nil) + return nil, rtnErr + } + + ktVpcRegionZoneList := getSupportedRegionZones() + if len(ktVpcRegionZoneList) < 1 { + rtnErr := logAndReturnError(callLogInfo, "Failed to Find Any Region Info.", nil) + return nil, rtnErr + } + + var zoneInfoList []irs.ZoneInfo + for _, region := range ktVpcRegionZoneList { + if strings.EqualFold(regionCode, region.RegionCode) { + cblogger.Info("# KT RegionCode : ", region.RegionCode) + if len(region.ZoneList) < 1 { + rtnErr := logAndReturnError(callLogInfo, "Failed to Find Any Zone Info in the Region Info.", nil) + return nil, rtnErr + } + + for _, zone := range region.ZoneList { + cblogger.Info("# KT ZoneCode : ", zone.ZoneCode) + + zoneInfo := irs.ZoneInfo{ + Name: zone.ZoneCode, + DisplayName: zone.ZoneName, + Status: irs.NotSupported, + } + zoneInfoList = append(zoneInfoList, zoneInfo) + } + } + } + return zoneInfoList, nil +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/SecurityHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/SecurityHandler.go new file mode 100644 index 000000000..09d3901e8 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/SecurityHandler.go @@ -0,0 +1,356 @@ +// Cloud Driver Interface 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 +// +// KT Cloud Security Group Handler +// +// by ETRI, 2022.12. + +package resources + +import ( + "os" + "io" + "strings" + "fmt" + // "crypto/aes" + // "crypto/cipher" + "encoding/base64" + // "github.com/davecgh/go-spew/spew" + "encoding/json" + // "strconv" + + ktvpcsdk "github.com/cloud-barista/ktcloudvpc-sdk-go" + + cblog "github.com/cloud-barista/cb-log" + call "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/call-log" + 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 KTVpcSecurityHandler struct { + RegionInfo idrv.RegionInfo + VMClient *ktvpcsdk.ServiceClient + NetworkClient *ktvpcsdk.ServiceClient +} + +const ( + sgDir string = "/cloud-driver-libs/.securitygroup-kt/" +) + +func init() { + // cblog is a global variable. + cblogger = cblog.GetLogger("KT Cloud SecurityGroup Handler") +} + +type SecurityGroup struct { + IID IId `json:"IId"` + VpcIID VpcIId `json:"VpcIID"` + Direc string `json:"Direction"` + Secu_Rules []Security_Rule `json:"SecurityRules"` +} + +type IId struct { + NameID string `json:"NameId"` + SystemID string `json:"SystemId"` +} + +type VpcIId struct { + NameID string `json:"NameId"` + SystemID string `json:"SystemId"` +} + +type Security_Rule struct { + FromPort string `json:"FromPort"` + ToPort string `json:"ToPort"` + Protocol string `json:"IPProtocol"` + Direc string `json:"Direction"` + Cidr string `json:"CIDR"` +} + +func (securityHandler *KTVpcSecurityHandler) CreateSecurity(securityReqInfo irs.SecurityReqInfo) (irs.SecurityInfo, error) { + cblogger.Info("KT Cloud VPC driver: called CreateSecurity()!") + callLogInfo := getCallLogScheme(securityHandler.RegionInfo.Zone, call.SECURITYGROUP, securityReqInfo.IId.NameId, "CreateSecurity()") + + if strings.EqualFold(securityHandler.RegionInfo.Zone, "") { + newErr := fmt.Errorf("Invalid Region Info!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.SecurityInfo{}, newErr + } + + sgPath := os.Getenv("CBSPIDER_ROOT") + sgDir + sgFilePath := sgPath + securityHandler.RegionInfo.Zone + "/" + + // Check if the KeyPair Folder Exists, and Create it + if err := checkFolderAndCreate(sgPath); err != nil { + cblogger.Errorf("Failed to Create the SecurityGroup Path : [%v]", err) + return irs.SecurityInfo{}, err + } + + // Check if the KeyPair Folder Exists, and Create it + if err := checkFolderAndCreate(sgFilePath); err != nil { + cblogger.Errorf("Failed to Create the SecurityGroup File Path : [%v]", err) + return irs.SecurityInfo{}, err + } + + // Check SecurityGroup Exists + sgList, err := securityHandler.ListSecurity() + if err != nil { + newErr := fmt.Errorf("Failed to Get S/G list. [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.SecurityInfo{}, newErr + } + for _, sg := range sgList { + if sg.IId.NameId == securityReqInfo.IId.NameId { + newErr := fmt.Errorf("Security Group with the Name [%s] Already Exists", securityReqInfo.IId.NameId) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.SecurityInfo{}, newErr + } + } + + hashFileName := base64.StdEncoding.EncodeToString([]byte(securityReqInfo.IId.NameId)) + cblogger.Infof("# S/G NameId : "+ securityReqInfo.IId.NameId) + cblogger.Infof("# Hashed FileName : "+ hashFileName + ".json") + + file, _ := json.MarshalIndent(securityReqInfo, "", " ") + + writeErr := os.WriteFile(sgFilePath + hashFileName + ".json", file, 0644) + if writeErr != nil { + cblogger.Error("Failed to write the file: "+ sgFilePath + hashFileName + ".json", writeErr) + return irs.SecurityInfo{}, writeErr + } + + cblogger.Infof("Succeeded in writing the S/G file: "+ sgFilePath + hashFileName + ".json") + + // Because it's managed as a file, there's no SystemId created. + securityReqInfo.IId.SystemId = securityReqInfo.IId.NameId + + // Return the created SecurityGroup info. + securityInfo, err := securityHandler.GetSecurity(irs.IID{SystemId: securityReqInfo.IId.SystemId}) + if err != nil { + return irs.SecurityInfo{}, err + } + + return securityInfo, nil +} + +func (securityHandler *KTVpcSecurityHandler) GetSecurity(securityIID irs.IID) (irs.SecurityInfo, error) { + cblogger.Info("KT Cloud VPC driver: called GetSecurity()!!") + callLogInfo := getCallLogScheme(securityHandler.RegionInfo.Zone, call.SECURITYGROUP, securityIID.SystemId, "GetSecurity()") + + var sg SecurityGroup + securityIID.NameId = securityIID.SystemId + hashFileName := base64.StdEncoding.EncodeToString([]byte(securityIID.NameId)) + + cblogger.Infof("# securityIID.NameId : "+ securityIID.NameId) + cblogger.Infof("# hashFileName : "+ hashFileName + ".json") + + if strings.EqualFold(securityHandler.RegionInfo.Zone, "") { + newErr := fmt.Errorf("Invalid Region Info!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.SecurityInfo{}, newErr + } + + sgPath := os.Getenv("CBSPIDER_ROOT") + sgDir + sgFilePath := sgPath + securityHandler.RegionInfo.Zone + "/" + + // Check if the KeyPair Folder Exists, and Create it + if err := checkFolderAndCreate(sgPath); err != nil { + cblogger.Errorf("Failed to Create the SecurityGroup Path : [%v]", err) + return irs.SecurityInfo{}, err + } + + // Check if the KeyPair Folder Exists, and Create it + if err := checkFolderAndCreate(sgFilePath); err != nil { + cblogger.Errorf("Failed to Create the SecurityGroup File Path : [%v]", err) + return irs.SecurityInfo{}, err + } + + sgFileName := sgFilePath + hashFileName + ".json" + jsonFile, err := os.Open(sgFileName) + if err != nil { + cblogger.Error("Failed to Find the S/G file : "+ sgFileName +" ", err) + return irs.SecurityInfo{}, err + } + cblogger.Infof("Succeeded in Finding and Opening the S/G file: "+ sgFileName) + + defer jsonFile.Close() + byteValue, readErr := io.ReadAll(jsonFile) + if readErr != nil { + cblogger.Error("Failed to Read the S/G file : "+ sgFileName, readErr) + } + json.Unmarshal(byteValue, &sg) + + // spew.Dump(sg) + + // Caution : ~~~ := mappingSecurityInfo( ) => ~~~ := securityHandler.mappingSecurityInfo( ) + securityGroupInfo, securityInfoError := securityHandler.mappingSecurityInfo(sg) + if securityInfoError != nil { + cblogger.Error(securityInfoError) + return irs.SecurityInfo{}, securityInfoError + } + return securityGroupInfo, nil +} + +func (securityHandler *KTVpcSecurityHandler) ListSecurity() ([]*irs.SecurityInfo, error) { + cblogger.Info("KT Cloud VPC driver: called ListSecurity()!!") + callLogInfo := getCallLogScheme(securityHandler.RegionInfo.Zone, call.SECURITYGROUP, "ListSecurity()", "ListSecurity()") + + var securityIID irs.IID + var securityGroupList []*irs.SecurityInfo + // var sg SecurityGroup + + if strings.EqualFold(securityHandler.RegionInfo.Zone, "") { + newErr := fmt.Errorf("Invalid Region Info!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + + sgPath := os.Getenv("CBSPIDER_ROOT") + sgDir + sgFilePath := sgPath + securityHandler.RegionInfo.Zone + "/" + + // Check if the KeyPair Folder Exists, and Create it + if err := checkFolderAndCreate(sgPath); err != nil { + cblogger.Errorf("Failed to Create the SecurityGroup Path : [%v]", err) + return nil, err + } + + // Check if the KeyPair Folder Exists, and Create it + if err := checkFolderAndCreate(sgFilePath); err != nil { + cblogger.Errorf("Failed to Create the SecurityGroup File Path : [%v]", err) + return nil, err + } + + // File list on the local directory + dirFiles, readRrr := os.ReadDir(sgFilePath) + if readRrr != nil { + return nil, readRrr + } + + for _, file := range dirFiles { + fileName := strings.TrimSuffix(file.Name(), ".json") // 접미사 제거 + decString, baseErr := base64.StdEncoding.DecodeString(fileName) + if baseErr != nil { + cblogger.Errorf("Failed to Decode the Filename : %s", fileName) + return nil, baseErr + } + sgFileName := string(decString) + + // sgFileName := filePath + file.Name() + + securityIID.SystemId = sgFileName + cblogger.Infof("# S/G Group Name : " + securityIID.SystemId) + + sgInfo, err := securityHandler.GetSecurity(irs.IID{SystemId: securityIID.SystemId}) + if err != nil { + cblogger.Errorf("Failed to Find the SecurityGroup : %s", securityIID.SystemId) + return nil, err + } + securityGroupList = append(securityGroupList, &sgInfo) + } + + return securityGroupList, nil +} + +func (securityHandler *KTVpcSecurityHandler) DeleteSecurity(securityIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud VPC driver: called DeleteSecurity()!") + callLogInfo := getCallLogScheme(securityHandler.RegionInfo.Zone, call.SECURITYGROUP, securityIID.SystemId, "DeleteSecurity()") + + securityIID.NameId = securityIID.SystemId + + if strings.EqualFold(securityHandler.RegionInfo.Zone, "") { + newErr := fmt.Errorf("Invalid Region Info!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + + sgPath := os.Getenv("CBSPIDER_ROOT") + sgDir + sgFilePath := sgPath + securityHandler.RegionInfo.Zone + "/" + + // Check if the KeyPair Folder Exists, and Create it + if err := checkFolderAndCreate(sgPath); err != nil { + cblogger.Errorf("Failed to Create the SecurityGroup Path : [%v]", err) + return false, err + } + + // Check if the KeyPair Folder Exists, and Create it + if err := checkFolderAndCreate(sgFilePath); err != nil { + cblogger.Errorf("Failed to Create the SecurityGroup File Path : [%v]", err) + return false, err + } + + hashFileName := base64.StdEncoding.EncodeToString([]byte(securityIID.NameId)) + sgFileName := sgFilePath + hashFileName + ".json" + cblogger.Infof("S/G file to Delete : [%s]", sgFileName) + + //To check whether the security group exists. + _, getErr := securityHandler.GetSecurity(irs.IID{SystemId: securityIID.SystemId}) + if getErr != nil { + cblogger.Errorf("Failed to Find the SecurityGroup : %s", securityIID.SystemId) + return false, getErr + } + + // To Remove the S/G file on the Local machine. + cmdName := "rm" + cmdArgs := []string{sgFileName} + + if cmdOut, cmdErr := runCommand(cmdName, cmdArgs); cmdErr != nil { + cblogger.Errorf("Failed to run the command to remove the S/G file.") + return false, cmdErr + } else { + cblogger.Infof("Succeeded in Deleting the S/G File!!") + cblogger.Infof("cmdOut : " + cmdOut) + } + cblogger.Infof("Succeeded in Deleting the SecurityGroup : " + securityIID.SystemId) + + return true, nil +} + +func (securityHandler *KTVpcSecurityHandler) AddRules(sgIID irs.IID, securityRules *[]irs.SecurityRuleInfo) (irs.SecurityInfo, error) { + cblogger.Info("KT Cloud VPC driver: called AddRules()!") + return irs.SecurityInfo{}, fmt.Errorf("Does not support AddRules() yet!!") +} + +func (securityHandler *KTVpcSecurityHandler) RemoveRules(sgIID irs.IID, securityRules *[]irs.SecurityRuleInfo) (bool, error) { + cblogger.Info("KT Cloud VPC sriver: called RemoveRules()!") + return false, fmt.Errorf("Does not support RemoveRules() yet!!") +} + +func (securityHandler *KTVpcSecurityHandler) mappingSecurityInfo(secuGroup SecurityGroup) (irs.SecurityInfo, error) { + cblogger.Info("KT Cloud VPC driver: called mappingSecurityInfo()!") + + var securityRuleList []irs.SecurityRuleInfo + var securityRuleInfo irs.SecurityRuleInfo + + for i := 0; i < len(secuGroup.Secu_Rules); i++ { + securityRuleInfo.FromPort = secuGroup.Secu_Rules[i].FromPort + securityRuleInfo.ToPort = secuGroup.Secu_Rules[i].ToPort + securityRuleInfo.IPProtocol = secuGroup.Secu_Rules[i].Protocol // For KT Cloud VPC S/G, TCP/UDP/ICMP is available + securityRuleInfo.Direction = secuGroup.Secu_Rules[i].Direc // For KT Cloud VPC S/G, supports inbound/outbound rule. + securityRuleInfo.CIDR = secuGroup.Secu_Rules[i].Cidr + + securityRuleList = append(securityRuleList, securityRuleInfo) + } + + securityInfo := irs.SecurityInfo{ + IId: irs.IID{NameId: secuGroup.IID.NameID, SystemId: secuGroup.IID.NameID}, + // Since it is managed as a file, the systemID is the same as the name ID. + VpcIID: irs.IID{NameId: secuGroup.VpcIID.NameID, SystemId: secuGroup.VpcIID.SystemID}, + SecurityRules: &securityRuleList, + + // KeyValueList: []irs.KeyValue{ + // {Key: "IpAddress", Value: KtCloudFirewallRule.IpAddress}, + // {Key: "IpAddressID", Value: KtCloudFirewallRule.IpAddressId}, + // {Key: "State", Value: KtCloudFirewallRule.State}, + // }, + } + return securityInfo, nil +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/VMHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/VMHandler.go new file mode 100644 index 000000000..652b0b45d --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/VMHandler.go @@ -0,0 +1,1910 @@ +// 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 Example for PoC Test. +// +// by ETRI, 2022.12. +// Updated by ETRI 2024.01. + +package resources + +import ( + "errors" + "fmt" + "os" + "strconv" + "strings" + "time" + _ "time/tzdata" // To prevent 'unknown time zone Asia/Seoul' error + // "encoding/json" + // "github.com/davecgh/go-spew/spew" + + ktvpcsdk "github.com/cloud-barista/ktcloudvpc-sdk-go" + volumes2 "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/blockstorage/v2/volumes" + volumeboot "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/compute/v2/extensions/bootfromvolume" + ips "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/compute/v2/extensions/floatingips" + keys "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/compute/v2/extensions/keypairs" + startstop "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/compute/v2/extensions/startstop" + // flavors "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/compute/v2/flavors" + servers "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/compute/v2/servers" + + images "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/imageservice/v2/images" // Caution!! + //Ref) 'Image API' return struct of image : ktcloudvpc-sdk-go/openstack/imageservice/v2/images/results.go + // "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/compute/v2/images" + //Ref) 'Compute API' return struct of image : ktcloudvpc-sdk-go/openstack/compute/v2/images/results.go + + job "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/job" + portforward "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/networking/v2/extensions/layer3/portforwarding" + rules "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/networking/v2/extensions/fwaas_v2/rules" + + call "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/call-log" + 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" + keycommon "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/common" +) + +const ( + LnxUserName string = "cb-user" + WinUserName string = "Administrator" + + UbuntuCloudInitFilePath string = "/cloud-driver-libs/.cloud-init-ktcloudvpc/cloud-init-ubuntu" + CentosCloudInitFilePath string = "/cloud-driver-libs/.cloud-init-ktcloudvpc/cloud-init-centos" + WinCloudInitFilePath string = "/cloud-driver-libs/.cloud-init-ktcloudvpc/cloud-init-windows" + + DefaultUsagePlan string = "hourly" + DefaultDiskSize string = "50" +) + +type KTVpcVMHandler struct { + CredentialInfo idrv.CredentialInfo + RegionInfo idrv.RegionInfo + VMClient *ktvpcsdk.ServiceClient + ImageClient *ktvpcsdk.ServiceClient + NetworkClient *ktvpcsdk.ServiceClient + VolumeClient *ktvpcsdk.ServiceClient +} + +type NetworkInfo struct { + VpcID string + SubnetID string + PublicIP string + PublicIPID string +} + +func (vmHandler *KTVpcVMHandler) StartVM(vmReqInfo irs.VMReqInfo) (irs.VMInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called StartVM()") + callLogInfo := getCallLogScheme(vmHandler.RegionInfo.Zone, call.VM, vmReqInfo.IId.NameId, "StartVM()") + + if strings.EqualFold(vmReqInfo.IId.NameId,"") { + newErr := fmt.Errorf("Invalid VM Name!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMInfo{}, newErr + } + + // Check VM Name Duplication + vmExist, err := vmHandler.vmExists(vmReqInfo.IId) + if err != nil { + newErr := fmt.Errorf("Failed to Create VM. : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMInfo{}, newErr + } + if vmExist { + newErr := fmt.Errorf("Failed to Create VM. The Name [%s] already exists", vmReqInfo.IId.NameId) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMInfo{}, newErr + } + + // Check Flavor Info. (Change Name to ID) + vmSpecId, err := getFlavorIdWithName(vmHandler.VMClient, vmReqInfo.VMSpecName) + if err != nil { + newErr := fmt.Errorf("Failed to Get VMSpec ID with the name : %v", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMInfo{}, newErr + } + cblogger.Infof("# vmSpec ID : [%s]", vmSpecId) + + // Check Image Info. + // imageExist, imageErr := vmHandler.imageExists(vmReqInfo.ImageIID) + // if imageErr != nil { + // newErr := fmt.Errorf("Failed to Create VM. : [%v]", imageErr) + // cblogger.Error(newErr.Error()) + // loggingError(callLogInfo, newErr) + // return irs.VMInfo{}, newErr + // } + // if !imageExist { + // newErr := fmt.Errorf("Failed to Create VM. The Image System ID [%s] does Not Exist", vmReqInfo.ImageIID.SystemId) + // cblogger.Error(newErr.Error()) + // loggingError(callLogInfo, newErr) + // return irs.VMInfo{}, newErr + // } + + createOpts := keys.CreateOptsExt{ + KeyName: vmReqInfo.KeyPairIID.NameId, // Set KeyPair Name + } + + // Preparing VM Creation Options + vmCreateOpts := servers.CreateOpts{ + Name: vmReqInfo.IId.NameId, + KeyName: vmReqInfo.KeyPairIID.NameId, + FlavorRef: vmSpecId, + AvailabilityZone: vmHandler.RegionInfo.Zone, // Caution : D1 flatform supports only 'zone'. + Networks: []servers.Network{ + {UUID: vmReqInfo.SubnetIID.SystemId}, // Caution : Network 'Tier'의 id 값 + }, + UsagePlanType: DefaultUsagePlan, + } + + // // Get KeyPair Info (To get PublicKey info for cloud-init) + // var getOptsBuilder keys.GetOptsBuilder + // keyPair, err := keys.Get(vmHandler.VMClient, vmReqInfo.KeyPairIID.NameId, getOptsBuilder).Extract() + // if err != nil { + // newErr := fmt.Errorf("Failed to Get KeyPair Info. with the name : %v", err) + // cblogger.Error(newErr.Error()) + // loggingError(callLogInfo, newErr) + // return irs.VMInfo{}, newErr + // } + // cblogger.Info("\n ### PublicKey : ") + // spew.Dump(keyPair.PublicKey) + + // # Preparing for UserData String for Linux and Windows Platform + var initUserData *string + var keyPairId string + if !strings.EqualFold(vmReqInfo.KeyPairIID.SystemId, "") { + keyPairId = vmReqInfo.KeyPairIID.SystemId + } else { + keyPairId = vmReqInfo.KeyPairIID.NameId + } + if vmReqInfo.ImageType == irs.PublicImage || vmReqInfo.ImageType == "" || vmReqInfo.ImageType == "default" { + // isPublicImage() in ImageHandler + imageHandler := KTVpcImageHandler{ + RegionInfo: vmHandler.RegionInfo, + VMClient: vmHandler.VMClient, + ImageClient: vmHandler.ImageClient, + } + isPublicImage, err := imageHandler.isPublicImage(vmReqInfo.ImageIID) + if err != nil { + newErr := fmt.Errorf("Failed to Check Whether the Image is Public Image : [%v]", err) + cblogger.Error(newErr.Error()) + return irs.VMInfo{}, newErr + } + if !isPublicImage { + newErr := fmt.Errorf("'PublicImage' type is selected, but Specified image is Not a PublicImage in the region!!") + cblogger.Error(newErr.Error()) + return irs.VMInfo{}, newErr + } + + // CheckWindowsImage() in ImageHandler + isPublicWindowsImage, err := imageHandler.CheckWindowsImage(vmReqInfo.ImageIID) + if err != nil { + newErr := fmt.Errorf("Failed to Check Whether the Image is MS Windows Image : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMInfo{}, newErr + } + if isPublicWindowsImage { + var createErr error + initUserData, createErr = vmHandler.createWinInitUserData(vmReqInfo.VMUserPasswd) + if createErr != nil { + newErr := fmt.Errorf("Failed to Create Cloud-Init Script with the Password : [%v]", createErr) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMInfo{}, newErr + } + } else { + var createErr error + initUserData, createErr = vmHandler.createLinuxInitUserData(keyPairId) + if createErr != nil { + newErr := fmt.Errorf("Failed to Create Cloud-Init Script with the KeyPairId : [%v]", createErr) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMInfo{}, newErr + } + } + } else { // In case of MyImage + var createErr error + initUserData, createErr = vmHandler.createLinuxInitUserData(keyPairId) + if createErr != nil { + newErr := fmt.Errorf("Failed to Create Cloud-Init Script with the KeyPairId : [%v]", createErr) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMInfo{}, newErr + } + } + + vmCreateOpts.UserData = []byte(*initUserData) // Apply cloud-init script + createOpts.CreateOptsBuilder = vmCreateOpts + + cblogger.Infof("# Image ID : [%s]", vmReqInfo.ImageIID.SystemId) + + // Set VM Booting Source Type + // Note) In case of 'MyImage', SourceType is 'SourceImage', too. Not 'volumeboot.SourceSnapshot' + bootSourceType := volumeboot.SourceImage + if vmReqInfo.ImageType == irs.PublicImage || vmReqInfo.ImageType == "" || vmReqInfo.ImageType == "default" { + bootSourceType = volumeboot.SourceImage // volumeboot.SourceType => "image" + } else if vmReqInfo.ImageType == irs.MyImage { + bootSourceType = volumeboot.SourceImage // volumeboot.SourceType => "image". Not "snapshot" + // bootSourceType = volumeboot.SourceSnapshot // volumeboot.SourceType => "snapshot" + } + + // When Root Volume Size is not specified. + reqDiskSize := vmReqInfo.RootDiskSize + if strings.EqualFold(reqDiskSize, "") || strings.EqualFold(reqDiskSize, "default") { + reqDiskSize = DefaultDiskSize + } + + blockDeviceSet := []volumeboot.BlockDevice{ + { + DestinationType: volumeboot.DestinationVolume, // DestinationType is the type that gets created. Possible values are "volume" and "local". volumeboot.DestinationType => "volume" + BootIndex: 0, // BootIndex is the boot index. It defaults to 0. Set as the Root Volume. + SourceType: bootSourceType, // volumeboot.SourceImage + VolumeSize: reqDiskSize, // VolumeSize is the size of the volume to create (in gigabytes). This can be omitted for existing volumes. + UUID: vmReqInfo.ImageIID.SystemId, + }, + } + + bootOpts := volumeboot.CreateOptsExt{ + CreateOptsBuilder: createOpts, + BlockDevice: blockDeviceSet, + } + // cblogger.Info("\n ### Boot Options : ") + // spew.Dump(bootOpts) + + vm, err := volumeboot.Create(vmHandler.VMClient, bootOpts).Extract() + if err != nil { + newErr := fmt.Errorf("Failed to Create VM!! [%v]", err) + cblogger.Error(err.Error()) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMInfo{}, newErr + } + cblogger.Infof("\n ### New VM ID : [%s]", vm.ID) + + // Because there are some functions that use NameID, so input NameId too + newVMIID := irs.IID{NameId: vmReqInfo.IId.NameId, SystemId: vm.ID} + + // Wait for created VM info to be inquired + curStatus, errStatus := vmHandler.waitToGetVMInfo(newVMIID) + if errStatus != nil { + cblogger.Error(errStatus.Error()) + loggingError(callLogInfo, errStatus) + return irs.VMInfo{}, errStatus + } + cblogger.Infof("==> VM status of [%s] : [%s]", newVMIID.NameId, curStatus) + + // Check VM Deploy Status + vmResult, err := servers.Get(vmHandler.VMClient, vm.ID).Extract() + if err != nil { + newErr := fmt.Errorf("Failed to Start VM. Failed to Get VMInfo, err : %v", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMInfo{}, newErr + } + + if strings.ToLower(vmResult.Status) == "active" { + var privateIP string + for _, subnet := range vmResult.Addresses { + // Get PrivateIP Info + for _, addr := range subnet.([]interface{}) { + addrMap := addr.(map[string]interface{}) + if addrMap["OS-EXT-IPS:type"] == "fixed" { + privateIP = addrMap["addr"].(string) + } + } + } + cblogger.Infof("\n# privateIP : [%s]\n", privateIP) + + // # Create a Public IP + var publicIP string + var publicIPId string + if ok, ip, ipId, err := vmHandler.createPublicIP(); !ok { + newErr := fmt.Errorf("Failed to Create a PublicIP : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMInfo{}, newErr + } else { + publicIP = ip + publicIPId = ipId + } + cblogger.Infof("\n# publicIP : [%s]\n", publicIP) + cblogger.Infof("\n# publicIPId : [%s]\n", publicIPId) + + var sgSystemIDs []string + for _, sgIID := range vmReqInfo.SecurityGroupIIDs { + cblogger.Infof("S/G ID : [%s]", sgIID) + sgSystemIDs = append(sgSystemIDs, sgIID.SystemId) + } + cblogger.Infof("The SystemIds of the Security Group IIDs : [%s]", sgSystemIDs) + + if ok, err := vmHandler.createPortForwardingFirewallRules(vmReqInfo.VpcIID, sgSystemIDs, privateIP, publicIPId); !ok { + newErr := fmt.Errorf("Failed to Create PortForwarding and Firewall Rules : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMInfo{}, newErr + } + + // Get vm info + vmResult, err = servers.Get(vmHandler.VMClient, vm.ID).Extract() + if err != nil { + newErr := fmt.Errorf("Failed to Get New VM Info from KT Cloud VPC. %s", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMInfo{}, newErr + } + + vmInfo, err := vmHandler.mappingVMInfo(*vmResult) + if err != nil { + newErr := fmt.Errorf("Failed to Map New VM Info. %s", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMInfo{}, newErr + } + return vmInfo, nil + } + return irs.VMInfo{}, nil +} + +func (vmHandler *KTVpcVMHandler) GetVM(vmIID irs.IID) (irs.VMInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called GetVM()") + callLogInfo := getCallLogScheme(vmHandler.RegionInfo.Zone, call.VM, vmIID.SystemId, "GetVM()") + + if strings.EqualFold(vmIID.SystemId, "") { + newErr := fmt.Errorf("Invalid VM SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMInfo{}, newErr + } + + start := call.Start() + vmResult, err := servers.Get(vmHandler.VMClient, vmIID.SystemId).Extract() + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return irs.VMInfo{}, err + } + loggingInfo(callLogInfo, start) + + vmInfo, err := vmHandler.mappingVMInfo(*vmResult) + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return irs.VMInfo{}, err + } + return vmInfo, nil +} + +func (vmHandler *KTVpcVMHandler) SuspendVM(vmIID irs.IID) (irs.VMStatus, error) { + cblogger.Info("KT Cloud VPC Driver: called SuspendVM()") + callLogInfo := getCallLogScheme(vmHandler.RegionInfo.Zone, call.VM, vmIID.SystemId, "SuspendVM()") + + if strings.EqualFold(vmIID.SystemId, "") { + newErr := fmt.Errorf("Invalid VM SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.Failed, newErr + } + + var resultStatus string + cblogger.Info("Start Get VM Status...") + vmStatus, err := vmHandler.GetVMStatus(vmIID) + if err != nil { + cblogger.Errorf("[%s] Failed to Get the VM Status of VM : ", vmIID.SystemId) + cblogger.Error(err) + loggingError(callLogInfo, err) + return irs.VMStatus("Failed to Get the VM Status of VM. "), err + } else { + cblogger.Infof("Succeeded in Getting the VM Status of [%s] : [%s]", vmIID.SystemId, vmStatus) + } + + if strings.EqualFold(string(vmStatus), "Suspended") { + resultStatus = "The VM has already been Suspended." + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + + } else if strings.EqualFold(string(vmStatus), "Rebooting") { + resultStatus = "The VM is in the process of Rebooting." + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + + } else if strings.EqualFold(string(vmStatus), "Deleted") { + resultStatus = "The VM has been Deleted." + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + + } else if strings.EqualFold(string(vmStatus), "Creating") { + resultStatus = "The VM is in the process of Creating." + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + + } else if strings.EqualFold(string(vmStatus), "Terminating") { + resultStatus = "The VM is in the process of Terminating." + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + + } else { + start := call.Start() + err := startstop.Stop(vmHandler.VMClient, vmIID.SystemId).Err + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return irs.Failed, err + } + loggingInfo(callLogInfo, start) + } + + // Return of the progress status (KT VPC is not provided with information about in progress) + return irs.Suspending, nil +} + +func (vmHandler *KTVpcVMHandler) ResumeVM(vmIID irs.IID) (irs.VMStatus, error) { + cblogger.Info("KT Cloud VPC Driver: called ResumeVM()") + callLogInfo := getCallLogScheme(vmHandler.RegionInfo.Zone, call.VM, vmIID.NameId, "ResumeVM()") + + if strings.EqualFold(vmIID.SystemId, "") { + newErr := fmt.Errorf("Invalid VM SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.Failed, newErr + } + + cblogger.Info("Start Get VM Status...") + var resultStatus string + vmStatus, err := vmHandler.GetVMStatus(vmIID) + if err != nil { + cblogger.Errorf("Failed to Get the VM Status of : [%s]", vmIID.SystemId) + cblogger.Error(err) + loggingError(callLogInfo, err) + return irs.VMStatus("Failed. "), err + } else { + cblogger.Infof("Succeeded in Getting the VM Status of [%s] : [%s]", vmIID.SystemId, vmStatus) + } + + if strings.EqualFold(string(vmStatus), "Running") { + resultStatus = "The VM is Running. Cannot be Resumed!!" + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + } else if strings.EqualFold(string(vmStatus), "Rebooting") { + resultStatus = "The VM is in the process of Rebooting. Cannot be Resumed" + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + } else if strings.EqualFold(string(vmStatus), "Terminating") { + resultStatus = "The VM is already in the process of Terminating. Cannot be Resumed" + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + } else if strings.EqualFold(string(vmStatus), "Deleted") { + resultStatus = "The VM has been Deleted. Cannot be Resumed" + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + } else if strings.EqualFold(string(vmStatus), "Creating") { + resultStatus = "The VM is in the process of Creating. Cannot be Resumed" + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + } else { + start := call.Start() + err := startstop.Start(vmHandler.VMClient, vmIID.SystemId).Err + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return irs.Failed, err + } + loggingInfo(callLogInfo, start) + + // Return of the progress status (KT VPC is not provided with information about in progress) + return irs.Resuming, nil + } +} + +func (vmHandler *KTVpcVMHandler) RebootVM(vmIID irs.IID) (irs.VMStatus, error) { + cblogger.Info("KT Cloud VPC Driver: called RebootVM()") + callLogInfo := getCallLogScheme(vmHandler.RegionInfo.Zone, call.VM, vmIID.SystemId, "RebootVM()") + + if strings.EqualFold(vmIID.SystemId, "") { + newErr := fmt.Errorf("Invalid VM SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.Failed, newErr + } + + cblogger.Info("Start Get VM Status...") + vmStatus, err := vmHandler.GetVMStatus(vmIID) + if err != nil { + cblogger.Errorf("[%s] Failed to Get the VM Status.", vmIID) + cblogger.Error(err) + loggingError(callLogInfo, err) + return irs.VMStatus("Failed to Get the VM Status."), err + } else { + cblogger.Infof("Succeeded in Getting the VM Status of [%s] : [%s]", vmIID, vmStatus) + } + + var resultStatus string + if strings.EqualFold(string(vmStatus), "Suspended") { + resultStatus = "The VM had been Suspended." + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + } else if strings.EqualFold(string(vmStatus), "Rebooting") { + resultStatus = "The VM is already in the process of Rebooting." + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + } else if strings.EqualFold(string(vmStatus), "Deleted") { + resultStatus = "The VM has been Deleted." + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + } else if strings.EqualFold(string(vmStatus), "Booting") { + resultStatus = "The VM is in the process of Booting." + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + } else if strings.EqualFold(string(vmStatus), "Creating") { + resultStatus = "The VM is in the process of Creating." + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + } else if strings.EqualFold(string(vmStatus), "Terminating") { + resultStatus = "The VM is in the process of Terminating." + + cblogger.Error(resultStatus) + return irs.VMStatus("Failed. " + resultStatus), err + } else { + start := call.Start() + rebootOpts := servers.RebootOpts{ + Type: servers.SoftReboot, + } + + err := servers.Reboot(vmHandler.VMClient, vmIID.SystemId, rebootOpts).ExtractErr() + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return irs.Failed, err + } + loggingInfo(callLogInfo, start) + + // Return of the progress status (KT VPC is not provided with information about in progress) + return irs.Rebooting, nil + } +} + +func (vmHandler *KTVpcVMHandler) TerminateVM(vmIID irs.IID) (irs.VMStatus, error) { + cblogger.Info("KT Cloud VPC Driver: called TerminateVM()") + callLogInfo := getCallLogScheme(vmHandler.RegionInfo.Zone, call.VM, vmIID.SystemId, "TerminateVM()") + + if strings.EqualFold(vmIID.SystemId, "") { + newErr := fmt.Errorf("Invalid VM SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.Failed, newErr + } + + vm, err := vmHandler.GetVM(vmIID) + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return irs.Failed, err + } + + if !strings.EqualFold(vm.PublicIP, "") { + // Delete Firewall Rules + if !strings.EqualFold(vm.PublicIP, "") { + _, dellFwErr := vmHandler.removeFirewallRule(vm.PublicIP) + if dellFwErr != nil { + cblogger.Error(dellFwErr.Error()) + loggingError(callLogInfo, dellFwErr) + return irs.Failed, dellFwErr + } + } + + // Delete Port Forwarding Rules + if !strings.EqualFold(vm.PrivateIP, "") { + _, dellPfErr := vmHandler.removePortForwarding(vm.PrivateIP) + if dellPfErr != nil { + cblogger.Error(dellPfErr.Error()) + loggingError(callLogInfo, dellPfErr) + return irs.Failed, dellPfErr + } + } + + // Delete PublicIP connected VM + if !strings.EqualFold(vm.PublicIP, "") { + _, dellIpErr := vmHandler.removePublicIP(vm.PublicIP) + if dellIpErr != nil { + cblogger.Error(dellIpErr.Error()) + loggingError(callLogInfo, dellIpErr) + return irs.Failed, dellIpErr + } + } + } else { + cblogger.Info("The VM doesn't have any Pulbic IP!! Waitting for Termination!!") + } + + // Terminate VM + start := call.Start() + err = servers.Delete(vmHandler.VMClient, vm.IId.SystemId).ExtractErr() + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return irs.Failed, err + } + loggingInfo(callLogInfo, start) + + // Return of the progress status (KT VPC is not provided with information about in progress) + return irs.Terminating, nil +} + +func (vmHandler *KTVpcVMHandler) GetVMStatus(vmIID irs.IID) (irs.VMStatus, error) { + cblogger.Info("KT Cloud VPC Driver: called GetVMStatus()") + callLogInfo := getCallLogScheme(vmHandler.RegionInfo.Zone, call.VM, vmIID.SystemId, "GetVMStatus()") + + if strings.EqualFold(vmIID.SystemId, "") { + newErr := fmt.Errorf("Invalid VM SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.Failed, newErr + } + + start := call.Start() + vmResult, err := servers.Get(vmHandler.VMClient, vmIID.SystemId).Extract() + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return "", err + } + loggingInfo(callLogInfo, start) + + cblogger.Infof("# vmResult.Status of KT Cloud VPC : [%s]", vmResult.Status) + vmStatus := getVmStatus(vmResult.Status) + return vmStatus, nil +} + +func (vmHandler *KTVpcVMHandler) ListVMStatus() ([]*irs.VMStatusInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called ListVMStatus()") + callLogInfo := getCallLogScheme(vmHandler.RegionInfo.Zone, call.VM, "ListVMStatus()", "ListVMStatus()") + + start := call.Start() + pager, err := servers.List(vmHandler.VMClient, nil).AllPages() + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return nil, err + } + loggingInfo(callLogInfo, start) + + vms, err := servers.ExtractServers(pager) + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return nil, err + } + + // Add to List + vmStatusList := make([]*irs.VMStatusInfo, len(vms)) + for idx, s := range vms { + vmStatus := getVmStatus(s.Status) + vmStatusInfo := irs.VMStatusInfo{ + IId: irs.IID{ + NameId: s.Name, + SystemId: s.ID, + }, + VmStatus: vmStatus, + } + vmStatusList[idx] = &vmStatusInfo + } + return vmStatusList, nil +} + +func (vmHandler *KTVpcVMHandler) ListVM() ([]*irs.VMInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called ListVM()") + callLogInfo := getCallLogScheme(vmHandler.RegionInfo.Zone, call.VM, "ListVM()", "ListVM()") + + // Get VM list + listOpts := servers.ListOpts{ + Limit: 100, + } + start := call.Start() + pager, err := servers.List(vmHandler.VMClient, listOpts).AllPages() + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return nil, err + } + loggingInfo(callLogInfo, start) + + vmList, err := servers.ExtractServers(pager) + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return nil, err + } + + // Mapping VM info list + var vmInfoList []*irs.VMInfo + for _, vm := range vmList { + vmInfo, err := vmHandler.mappingVMInfo(vm) + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return nil, err + } + vmInfoList = append(vmInfoList, &vmInfo) + } + return vmInfoList, nil +} + +func (vmHandler *KTVpcVMHandler) createPublicIP() (bool, string, string, error) { + cblogger.Info("KT Cloud VPC Driver: called createPublicIP()") + + // Create a Public IP + createIpOpts := ips.CreateOpts{} + publicIpResult, err := ips.Create(vmHandler.NetworkClient, createIpOpts).ExtractJobInfo() + if err != nil { + return false, "", "", err + } + + // Get the Job State Info of PublicIP Creation process. + jobResult, err := job.GetJobResult(vmHandler.NetworkClient, publicIpResult.JopID) + if err != nil { + return false, "", "", err + } + return true, (*jobResult).JobResult.IpAddress, (*jobResult).JobResult.Id, nil +} + +// ### To Apply 'PortForwarding Rules' and 'Firewall Rules' to the PublicIP ID. +func (vmHandler *KTVpcVMHandler) createPortForwardingFirewallRules(vpcIID irs.IID, sgSystemIDs []string, privateIP string, publicIPId string) (bool, error) { + cblogger.Info("KT Cloud cloud driver: called createPortForwardingFirewallRules()!") + securityHandler := KTVpcSecurityHandler{ + RegionInfo: vmHandler.RegionInfo, + } + + vpcHandler := KTVpcVPCHandler{ + RegionInfo: vmHandler.RegionInfo, + NetworkClient: vmHandler.NetworkClient, // Required!! + } + externalNetId, getErr := vpcHandler.getExtSubnetId(vpcIID) + if getErr != nil { + newErr := fmt.Errorf("Failed to Get the VPC Info : [%v]", getErr) + cblogger.Error(newErr.Error()) + return false, newErr + } else { + cblogger.Infof("# ExternalNet ID : %s", externalNetId) + } + + for _, sgSystemID := range sgSystemIDs { + cblogger.Infof("S/G System ID : [%s]", sgSystemID) + + sgInfo, err := securityHandler.GetSecurity(irs.IID{SystemId: sgSystemID}) + if err != nil { + cblogger.Errorf("Failed to Find the SecurityGroup : %s", sgSystemID) + return false, err + } + + var protocols []string + for _, sgRule := range *sgInfo.SecurityRules { + if strings.EqualFold(sgRule.IPProtocol , "tcp") { // case insensitive comparing and returns true. + protocols = []string{"TCP",} + } else if strings.EqualFold(sgRule.IPProtocol , "udp") { + protocols = []string{"UDP",} + } else if strings.EqualFold(sgRule.IPProtocol , "icmp") { + protocols = []string{"ICMP",} + } else if strings.EqualFold(sgRule.IPProtocol , "ALL") { + protocols = []string{"TCP", "UDP", "ICMP"} + } else { + cblogger.Errorf("Failed to Find mapping Protocol matching with the given Protocol [%s].", sgRule.IPProtocol) + return false, errors.New("Failed to Find mapping Protocol matching with the given Protocol." + sgRule.IPProtocol) + } + + for _, protocol := range protocols { + // When the request port number is '-1', all ports are opened. + if (sgRule.FromPort == "-1") && (sgRule.ToPort == "-1") { + sgRule.FromPort = "1" + sgRule.ToPort = "65535" + } + + // It's impossible to input any port number when the protocol is ICMP on KT Cloud firewall. + // Caution!!) KT Cloud does Not support 'ICMP' protocol for PortForwarding Rule. + if protocol == "ICMP" { + sgRule.FromPort = "" + sgRule.ToPort = "" + } + + if strings.EqualFold(sgRule.Direction, "inbound") { + if !(strings.EqualFold(protocol, "ICMP")) { + cblogger.Info("### Start to Create PortForwarding Rules!!") + + // ### Set Port Forwarding Rules + createPfOpts := &portforward.CreateOpts{ + ZoneID: vmHandler.RegionInfo.Zone, + PrivateIpAddr: privateIP, + PublicIpID: publicIPId, + Protocol: protocol, + ExternalPort: sgRule.FromPort, + ExternalStartPort: sgRule.FromPort, + ExternalEndPort: sgRule.ToPort, + InternalPort: sgRule.FromPort, + InternalStartPort: sgRule.FromPort, + InternalEndPort: sgRule.ToPort, + } + pfResult, err := portforward.Create(vmHandler.NetworkClient, createPfOpts).ExtractJobInfo() // Not ~.Extract() + if err != nil { + cblogger.Errorf("Failed to Create the Port Forwarding Rule : [%v]", err) + return false, err + } + cblogger.Infof("\n# pfResult.JopID : [%s]", pfResult.JopID) + cblogger.Info("\n") + + cblogger.Info("### Waiting for PortForwarding Rules to be Created(600sec) !!") + // To prevent - json: cannot unmarshal string into Go struct field AsyncJobResult.nc_queryasyncjobresultresponse.result of type job.JobResult + time.Sleep(time.Second * 3) + waitErr := vmHandler.waitForAsyncJob(pfResult.JopID, 600000000000) + if waitErr != nil { + cblogger.Errorf("Failed to Wait the Job : [%v]", waitErr) + return false, waitErr + } + } + + // Caution!!) KT Cloud VPC 'Firewall Rules' Support Only "inbound" and "outbound" + cblogger.Info("### Start to Create Firewall 'inbound' Rules!!") + // ### Set FireWall Rules (In case of "Inbound" FireWall Rules) + // Converted Protocol Name String + + var convertedProtocol rules.Protocol + if strings.EqualFold(protocol, "tcp") { + convertedProtocol = rules.ProtocolTCP + } else if strings.EqualFold(protocol, "udp") { + convertedProtocol = rules.ProtocolUDP + } else if strings.EqualFold(protocol, "icmp") { + convertedProtocol = rules.ProtocolICMP + } + + destCIDR, err := ipToCidr24(privateIP) // Output format ex) "172.25.1.0/24" + if err != nil { + cblogger.Errorf("Failed to Get Dest Net Band : [%v]", err) + return false, err + } else { + fmt.Println(destCIDR) + } + + // After Port-Forwarding Creation!! + netInfo, err := vmHandler.getNetIDsWithPrivateIP(privateIP) + if err != nil { + newErr := fmt.Errorf("Failed to Get Network IDs [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + + inboundFWOpts := &rules.InboundCreateOpts{} + // ### Since 'ICMP' does not have Port Forwarding rule and 'its ID' + if !(strings.EqualFold(protocol, "ICMP")) { + + portFowardingId, err := vmHandler.getPortForwardingID(privateIP, protocol) // Need 'protocol'. Ex) 'TCP' (Uppercase letter) + if err != nil { + newErr := fmt.Errorf("Failed to Get PortForwarding Info. [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + // fmt.Println(portFowardingId) + + inboundFWOpts = &rules.InboundCreateOpts{ + SourceNetID: externalNetId, // ExternalNet + PortFordingID: portFowardingId, + DestIPAdds: destCIDR, // Destination network band (10.1.1.0/24, etc.) + StartPort: sgRule.FromPort, + EndPort: sgRule.ToPort, + Protocol: convertedProtocol, + DestNetID: netInfo.SubnetID, // Tier ID + Action: rules.ActionAllow, // "allow" + } + } else { // Incase of 'ICMP' + udpPortFowardingId, err := vmHandler.getPortForwardingID(privateIP, "TCP") // Caution!! + if err != nil { + newErr := fmt.Errorf("Failed to Get PortForwarding Info. [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + // fmt.Println(udpPortFowardingId) + + inboundFWOpts = &rules.InboundCreateOpts{ + SourceNetID: externalNetId, // ExternalNet + PortFordingID: udpPortFowardingId, // Caution!! + DestIPAdds: destCIDR, // Destination network band (10.1.1.0/24, etc.) + StartPort: sgRule.FromPort, + EndPort: sgRule.ToPort, + Protocol: convertedProtocol, + DestNetID: netInfo.SubnetID, // Tier ID + Action: rules.ActionAllow, // "allow" + } + } + + fwResult, err := rules.Create(vmHandler.NetworkClient, inboundFWOpts).ExtractJobInfo() // Not ~.Extract() + if err != nil { + cblogger.Errorf("Failed to Create the FireWall 'inbound' Rules : [%v]", err) + return false, err + } + // cblogger.Infof("\n# fwResult.JopID : [%s]", fwResult.JopID) + // cblogger.Info("\n") + + cblogger.Info("### Waiting for FireWall 'inbound' Rules to be Created(600sec) !!") + + // To prevent - json: cannot unmarshal string into Go struct field AsyncJobResult.nc_queryasyncjobresultresponse.result of type job.JobResult + time.Sleep(time.Second * 3) + + jobWaitErr := vmHandler.waitForAsyncJob(fwResult.JopID, 600000000000) + if jobWaitErr != nil { + cblogger.Errorf("Failed to Wait the Job : [%v]", jobWaitErr) + return false, jobWaitErr + } + } + + // ### In case of "Outbound" FireWall Rules + if strings.EqualFold(sgRule.Direction, "outbound") { + cblogger.Info("### Start to Create Firewall 'outbound' Rules!!") + + srcCIDR, err := ipToCidr32(privateIP) // Output format ex) "172.25.1.5/32", ipToCidr24() : Output format ex) "172.25.1.0/24" + if err != nil { + cblogger.Errorf("Failed to Get Dest Net Band : [%v]", err) + return false, err + } else { + fmt.Println(srcCIDR) + } + + // Set FireWall Rules + // Converted Protocol Name String + var convertedProtocol rules.Protocol + if strings.EqualFold(protocol, "tcp") { + convertedProtocol = rules.ProtocolTCP + } else if strings.EqualFold(protocol, "udp") { + convertedProtocol = rules.ProtocolUDP + } else if strings.EqualFold(protocol, "icmp") { + convertedProtocol = rules.ProtocolICMP + } + + // After Port-Forwarding Creation!! + netInfo, err := vmHandler.getNetIDsWithPrivateIP(privateIP) + if err != nil { + newErr := fmt.Errorf("Failed to Get Network IDs [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + + destIPAdds := "0.0.0.0/0" + + outboundFWOpts := &rules.OutboundCreateOpts{ + SourceNetID: netInfo.SubnetID, + SourceIPAdds: srcCIDR, + StartPort: sgRule.FromPort, + EndPort: sgRule.ToPort, + Protocol: convertedProtocol, + DestNetID: externalNetId, // External Net + DestIPAdds: destIPAdds, + SourceNAT: "true", + Action: rules.ActionAllow, // "allow" + } + // cblogger.Info("\n# Outbound FireWall Options : ") + // spew.Dump(outboundFWOpts) + + fwResult, err := rules.OutboundCreate(vmHandler.NetworkClient, outboundFWOpts).ExtractJobInfo() // Not ~.Extract() + if err != nil { + cblogger.Errorf("Failed to Create the FireWall 'outbound' Rules : [%v]", err) + return false, err + } + // cblogger.Infof("\n# fwResult.JopID : [%s]", fwResult.JopID) + // cblogger.Info("\n") + + cblogger.Info("### Waiting for FireWall 'outbound' Rules to be Created(600sec) !!") + jobWaitErr := vmHandler.waitForAsyncJob(fwResult.JopID, 600000000000) + if jobWaitErr != nil { + cblogger.Errorf("Failed to Wait the Job : [%v]", jobWaitErr) + return false, jobWaitErr + } + } + } + } + } + return true, nil +} + +func getVmStatus(vmStatus string) irs.VMStatus { + cblogger.Info("KT Cloud VPC Driver: called getVmStatus()") + + var resultStatus string + switch strings.ToLower(vmStatus) { + case "build": + resultStatus = "Creating" + case "active": + resultStatus = "Running" + case "shutoff": + resultStatus = "Suspended" + case "paused": + resultStatus = "Suspended" + case "reboot": + resultStatus = "Rebooting" + case "hard_reboot": + resultStatus = "Rebooting" + case "deleted": + resultStatus = "Deleted" + case "error": + resultStatus = "Error" + default: + resultStatus = "Unknown" + } + return irs.VMStatus(resultStatus) +} + +func (vmHandler *KTVpcVMHandler) mappingVMInfo(vm servers.Server) (irs.VMInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called mappingVMInfo()") + // cblogger.Info("\n# VM from KT Cloud VPC :") + // spew.Dump(vm) + + convertedTime, err := convertTimeToKTC(vm.Created) + if err != nil { + newErr := fmt.Errorf("Failed to Get Converted Time. [%v]", err) + return irs.VMInfo{}, newErr + } + + vmInfo := irs.VMInfo{ + IId: irs.IID{ + NameId: vm.Name, + SystemId: vm.ID, + }, + Region: irs.RegionInfo{ + // Region: "N/A", + Zone: vmHandler.RegionInfo.Zone, + }, + KeyPairIId: irs.IID{ + NameId: vm.KeyName, + SystemId: vm.KeyName, + }, + VMUserId: LnxUserName, + // VMUserPasswd: "N/A", + } + vmInfo.StartTime = convertedTime + vmInfo.VMSpecName = vm.Flavor["original_name"].(string) + + float64Vcpus := vm.Flavor["vcpus"].(float64) + float64Ram := vm.Flavor["ram"].(float64) + + var vCPU string + var vRAM string + if float64Vcpus != 0 { + vCPU = strconv.FormatFloat(vm.Flavor["vcpus"].(float64), 'f', -1, 64) + } + if float64Ram != 0 { + vRAM = strconv.FormatFloat(vm.Flavor["ram"].(float64), 'f', -1, 64) + } + + // # Get Network Info + for key, subnet := range vm.Addresses { + // VPC Info + vmInfo.SubnetIID.NameId = key + // Get PrivateIP Info + for _, addr := range subnet.([]interface{}) { + addrMap := addr.(map[string]interface{}) + if addrMap["OS-EXT-IPS:type"] == "fixed" { + vmInfo.PrivateIP = addrMap["addr"].(string) + } + } + } + netInfo, err := vmHandler.getNetIDsWithPrivateIP(vmInfo.PrivateIP) + if err != nil { + newErr := fmt.Errorf("Failed to Get PortForwarding Info. [%v]", err) + cblogger.Error(newErr.Error()) + return irs.VMInfo{}, newErr + } + vmInfo.VpcIID.SystemId = netInfo.VpcID + vmInfo.PublicIP = netInfo.PublicIP + + vpcHandler := KTVpcVPCHandler{ + RegionInfo: vmHandler.RegionInfo, + NetworkClient: vmHandler.NetworkClient, // Required!! + } + OsNetId, getError := vpcHandler.getOsNetworkIdWithTierId(netInfo.VpcID, netInfo.SubnetID) + if getError != nil { + newErr := fmt.Errorf("Failed to Get the OsNetwork ID of the Tier : [%v]", getError) + cblogger.Error(newErr.Error()) + return irs.VMInfo{}, newErr + } else { + cblogger.Infof("# OsNetwork ID : %s", OsNetId) + } + vmInfo.SubnetIID.SystemId = OsNetId // Caution!!) Not Tier 'ID' but 'OsNetworkID' to Create VM through REST API!! + + // # Get ImageInfo frome the Disk Volume + diskHandler := KTVpcDiskHandler{ + RegionInfo: vmHandler.RegionInfo, + VMClient: vmHandler.VMClient, + VolumeClient: vmHandler.VolumeClient, + } + + var diskIIDs []irs.IID + var imageIID irs.IID + var getErr error + if len(vm.AttachedVolumes) > 0 { + for _, volume := range vm.AttachedVolumes { + cblogger.Infof("# Volume ID : %s", volume.ID) + + // ktVolume, _ := volumes3.Get(vmHandler.VolumeClient, volume.ID).Extract() + ktVolume, err := volumes2.Get(vmHandler.VolumeClient, volume.ID).Extract() + if err != nil { + newErr := fmt.Errorf("Failed to Get the KT Disk Info!! : [%v] ", err) + cblogger.Error(newErr.Error()) + return irs.VMInfo{}, newErr + } + + if ktVolume.Bootable == "true" { + vmInfo.RootDiskType = ktVolume.VolumeType + vmInfo.RootDiskSize = strconv.Itoa(ktVolume.Size) + vmInfo.RootDeviceName = ktVolume.Attachments[0].Device + + imageIID, getErr = diskHandler.getImageNameandIDWithDiskID(volume.ID) + if getErr != nil { + cblogger.Infof("Failed to Get Image Info from the Disk Info : [%v]", getErr) + // return irs.VMInfo{}, err + } + } else { + diskIIDs = append(diskIIDs, irs.IID{SystemId: volume.ID}) // Data Disk. (Not bootable) + } + } + } + vmInfo.DataDiskIIDs = diskIIDs + + // Set the VM Image Info + imageHandler := KTVpcImageHandler{ + RegionInfo: vmHandler.RegionInfo, + VMClient: vmHandler.VMClient, + ImageClient: vmHandler.ImageClient, + } + if !strings.EqualFold(imageIID.SystemId, "") { + vmInfo.ImageIId.NameId = imageIID.NameId + vmInfo.ImageIId.SystemId = imageIID.SystemId + + isPublicImage, err := imageHandler.isPublicImage(irs.IID{SystemId: imageIID.SystemId}) + if err != nil { + newErr := fmt.Errorf("Failed to Check Whether the Image is Public Image : [%v]", err) + cblogger.Error(newErr.Error()) + // return irs.VMInfo{}, newErr // Caution!! + } + if isPublicImage { + vmInfo.ImageType = irs.PublicImage + } else { + vmInfo.ImageType = irs.MyImage + } + } + + if !strings.EqualFold(imageIID.NameId, "") { + if strings.Contains(strings.ToLower(imageIID.NameId), "windows") { + vmInfo.Platform = irs.WINDOWS + vmInfo.VMUserId = WinUserName + vmInfo.VMUserPasswd = "User Specified Passwd" + vmInfo.SSHAccessPoint = netInfo.PublicIP + ":3389" + } else { + vmInfo.Platform = irs.LINUX_UNIX + vmInfo.VMUserId = LnxUserName + vmInfo.RootDeviceName = "/dev/xvda" + // vmInfo.VMUserPasswd = "N/A" + vmInfo.SSHAccessPoint = netInfo.PublicIP + ":22" + } + } + + // Set KeyValueList + var keyValueList []irs.KeyValue + if vCPU != "" { + keyValue := irs.KeyValue{Key: "vCPU", Value: vCPU} + keyValueList = append(keyValueList, keyValue) + } + if vRAM != "" { + keyValue := irs.KeyValue{Key: "vRAM(GB)", Value: vRAM} + keyValueList = append(keyValueList, keyValue) + } + if vm.Status != "" { + keyValue := irs.KeyValue{Key: "VM_Status", Value: string(getVmStatus(vm.Status))} + keyValueList = append(keyValueList, keyValue) + } + vmInfo.KeyValueList = keyValueList + return vmInfo, nil +} + +// Waiting for up to 500 seconds during VM creation until VM info. can be get +func (vmHandler *KTVpcVMHandler) waitToGetVMInfo(vmIID irs.IID) (irs.VMStatus, error) { + cblogger.Info("KT Cloud VPC Driver: called waitToGetVMInfo()") + + cblogger.Info("======> As VM info. cannot be retrieved immediately after VM creation, it waits until running.") + curRetryCnt := 0 + maxRetryCnt := 500 + + for { + curStatus, errStatus := vmHandler.GetVMStatus(vmIID) + if errStatus != nil { + cblogger.Errorf("Failed to Get the VM Status of : [%s]", vmIID) + cblogger.Error(errStatus.Error()) + return irs.VMStatus("Failed. "), errors.New("Failed to Get the VM Status.") + } else { + cblogger.Infof("Succeeded in Getting the VM Status of [%s] : [%s]", vmIID.SystemId, curStatus) + } + cblogger.Info("===> VM Status : ", curStatus) + + switch string(curStatus) { + case "Creating", "Booting": + curRetryCnt++ + cblogger.Infof("The VM is still 'Creating', so wait for a second more before inquiring the VM info.") + time.Sleep(time.Second * 3) + if curRetryCnt > maxRetryCnt { + cblogger.Errorf("Despite waiting for a long time(%d sec), the VM status is %s, so it is forcibly finishied.", maxRetryCnt, curStatus) + return irs.VMStatus("Failed. "), errors.New("Despite waiting for a long time, the VM status is 'Creating', so it is forcibly finishied.") + } + + default: + cblogger.Infof("===> ### The VM Creation is finished, stopping the waiting.") + return irs.VMStatus(curStatus), nil + //break + } + } +} + +func (vmHandler *KTVpcVMHandler) vmExists(vmIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud VPC Driver: called vmExists()") + + if strings.EqualFold(vmIID.NameId,"") { + newErr := fmt.Errorf("Invalid VM Name!!") + cblogger.Error(newErr.Error()) + return false, newErr + } + + allPagers, err := servers.List(vmHandler.VMClient, servers.ListOpts{Name: vmIID.NameId}).AllPages() + if err != nil { + newErr := fmt.Errorf("Failed to Get VM Pages from KT Cloud. : [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + vmList, err := servers.ExtractServers(allPagers) + if err != nil { + newErr := fmt.Errorf("Failed to Get VM list. : [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + for _, vm := range vmList { + if strings.EqualFold(vm.Name, vmIID.NameId) { + return true, nil + } + } + + return false, nil +} + +func (vmHandler *KTVpcVMHandler) imageExists(imageIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud VPC Driver: called imageExists()") + + if strings.EqualFold(imageIID.SystemId,"") { + newErr := fmt.Errorf("Invalid Image System ID!!") + cblogger.Error(newErr.Error()) + return false, newErr + } + + imageHandler := KTVpcImageHandler{ + RegionInfo: vmHandler.RegionInfo, + VMClient: vmHandler.VMClient, + ImageClient: vmHandler.ImageClient, + } + listOpts := images.ListOpts{ + Limit: 300, //default : 20 + Visibility: images.ImageVisibilityPublic, // Note : Public image only + } + allPages, err := images.List(imageHandler.ImageClient, listOpts).AllPages() + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud VPC Image Pages. [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + imageList, err := images.ExtractImages(allPages) + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud VPC Image List. [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + for _, image := range imageList { + if strings.EqualFold(image.ID, imageIID.SystemId) { + return true, nil + } + } + return false, nil +} + +func (vmHandler *KTVpcVMHandler) listFirewallRule() ([]rules.Rule, error) { + cblogger.Info("KT Cloud VPC Driver: called listFirewallRule()!") + callLogInfo := getCallLogScheme(vmHandler.RegionInfo.Zone, call.VPCSUBNET, "listFirewallRule()", "listFirewallRule()") + + listOpts := rules.ListOpts{} + firstPage, err := rules.List(vmHandler.NetworkClient, listOpts).FirstPage() // Caution!! : First Page Only + if err != nil { + cblogger.Errorf("Failed to Get Firewall Rule from KT Cloud VPC : [%v]", err) + loggingError(callLogInfo, err) + return nil, err + } + + fwRuleList, err := rules.ExtractRules(firstPage) + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud Firewall Rule list. [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + + if len(fwRuleList) < 1 { + newErr := fmt.Errorf("Failed to Get Any Port Forwarding Info.") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + return fwRuleList, nil +} + +func (vmHandler *KTVpcVMHandler) listPortForwarding() ([]portforward.PortForwarding, error) { + cblogger.Info("KT Cloud VPC Driver: called listPortForwarding()!") + callLogInfo := getCallLogScheme(vmHandler.RegionInfo.Zone, call.VPCSUBNET, "listPortForwarding()", "listPortForwarding()") + + listOpts := portforward.ListOpts{} + firstPage, err := portforward.List(vmHandler.NetworkClient, listOpts).FirstPage() // Caution!! : First Page Only + if err != nil { + cblogger.Errorf("Failed to Get Port Forwarding Info from KT Cloud VPC : [%v]", err) + loggingError(callLogInfo, err) + return nil, err + } + + pfRuleList, err := portforward.ExtractPortForwardings(firstPage) + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud Port Forwarding list. [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + + if len(pfRuleList) < 1 { + newErr := fmt.Errorf("Failed to Get Any Port Forwarding Info.") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + return pfRuleList, nil +} + +func (vmHandler *KTVpcVMHandler) getFirewallRuleIDs(publicIpAddr string) ([]int, error) { + cblogger.Info("KT Cloud VPC Driver: called getFirewallRuleIDs()!") + + if strings.EqualFold(publicIpAddr,"") { + newErr := fmt.Errorf("Invalid Public IP Address!!") + cblogger.Error(newErr.Error()) + return nil, newErr + } + + fwRuleList, err := vmHandler.listFirewallRule() + if err != nil { + newErr := fmt.Errorf("Failed to Get Firewall Rule ID. [%v]", err) + cblogger.Error(newErr.Error()) + return nil, newErr + } + + var firewallRuleIds []int + for _, rule := range fwRuleList { + for _, acl := range rule.Acls { + for _, addrs := range acl.DstAddrs { + // cblogger.Infof("addrs.IP : [%s]", addrs.IP) + // cblogger.Infof("publicIpAddr : [%s]", publicIpAddr) + if strings.Contains(addrs.IP, publicIpAddr) { + firewallRuleIds = append(firewallRuleIds, acl.ID) // Caution!!) Not acl.Name + } + } + } + } + cblogger.Infof("# Firewall Rule IDs : [%v]", firewallRuleIds) + return firewallRuleIds, nil +} + +/* +type NetworkInfo struct { + VpcID string + SubnetID string + PublicIP string + PublicIPID string +} +*/ + +func (vmHandler *KTVpcVMHandler) getNetIDsWithPrivateIP(privateIpAddr string) (*NetworkInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called getNetIDsWithPrivateIP()!") + + if strings.EqualFold(privateIpAddr,"") { + newErr := fmt.Errorf("Invalid Private IP Address!!") + cblogger.Error(newErr.Error()) + return nil, newErr + } + + pfRuleList, err := vmHandler.listPortForwarding() + if err != nil { + newErr := fmt.Errorf("Failed to Get PortForwarding ID. [%v]", err) + cblogger.Error(newErr.Error()) + return nil, newErr + } + + netInfo := NetworkInfo{} + for _, rule := range pfRuleList { + if strings.EqualFold(rule.PrivateIP, privateIpAddr) { + // cblogger.Infof("\n# PortForwardingName : [%s]", rule.PortForwardingName) + netInfo.VpcID = rule.VpcID + netInfo.SubnetID = rule.SubnetID // Tier 'ID' + netInfo.PublicIP = rule.PublicIP + netInfo.PublicIPID = rule.PublicIpID + break + } + } + return &netInfo, nil +} + +func (vmHandler *KTVpcVMHandler) getPortForwardingIDs(privateIpAddr string) ([]string, error) { + cblogger.Info("KT Cloud VPC Driver: called getPortForwardingIDs()!") + + if strings.EqualFold(privateIpAddr,"") { + newErr := fmt.Errorf("Invalid Private IP Address!!") + cblogger.Error(newErr.Error()) + return nil, newErr + } + + pfRuleList, err := vmHandler.listPortForwarding() + if err != nil { + newErr := fmt.Errorf("Failed to Get PortForwarding ID. [%v]", err) + cblogger.Error(newErr.Error()) + return nil, newErr + } + + var portForwardingIds []string + for _, rule := range pfRuleList { + if strings.EqualFold(rule.PrivateIP, privateIpAddr) { + portForwardingIds = append(portForwardingIds, rule.PortForwardingID) // Caution!! + } + } + return portForwardingIds, nil +} + +func (vmHandler *KTVpcVMHandler) getPortForwardingID(privateIpAddr string, protocol string) (string, error) { + cblogger.Info("KT Cloud VPC Driver: called getPortForwardingID()!") + + if strings.EqualFold(privateIpAddr,"") { + newErr := fmt.Errorf("Invalid Private IP Address!!") + cblogger.Error(newErr.Error()) + return "", newErr + } + + if strings.EqualFold(protocol,"") { + newErr := fmt.Errorf("Invalid Protocol!!") + cblogger.Error(newErr.Error()) + return "", newErr + } + + pfRuleList, err := vmHandler.listPortForwarding() + if err != nil { + newErr := fmt.Errorf("Failed to Get PortForwarding ID. [%v]", err) + cblogger.Error(newErr.Error()) + return "", newErr + } + + var portForwardingId string + for _, rule := range pfRuleList { + if strings.EqualFold(rule.PrivateIP, privateIpAddr) && strings.EqualFold(rule.Protocol, protocol) { + cblogger.Infof("\n# PortForwardingName : [%s]", rule.PortForwardingName) + portForwardingId = rule.PortForwardingID + break + } + } + return portForwardingId, nil +} + +func (vmHandler *KTVpcVMHandler) removeFirewallRule(publicIpAddr string) (bool, error) { + cblogger.Info("KT Cloud VPC Driver: called removeFirewallRule()!") + + if strings.EqualFold(publicIpAddr,"") { + newErr := fmt.Errorf("Invalid Public IP Address!!") + cblogger.Error(newErr.Error()) + return false, newErr + } + + pwRuleIds, err := vmHandler.getFirewallRuleIDs(publicIpAddr) + if err != nil { + newErr := fmt.Errorf("Failed to Get Firewall Rule Info. [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + + // Delete Firewall Rule + for _, ruleIdInt := range pwRuleIds { + cblogger.Info("Deleting a Firewall Rule Now!!") + ruleIdString := strconv.Itoa(ruleIdInt) + resultErr := rules.Delete(vmHandler.NetworkClient, ruleIdString).ExtractErr() //.ExtractDelJobInfo() + if resultErr != nil { + cblogger.Error(resultErr.Error()) + return false, resultErr + } + time.Sleep(time.Second * 3) + // cblogger.Infof("\n# delResult.JopID : [%s]", delResult.JopID) + // cblogger.Info("\n") + + // cblogger.Info("### Waiting for Firewall Rule to be Created(300sec) !!") + // waitErr := vmHandler.waitForAsyncJob(delResult.JopID, 300000000000) + // if waitErr != nil { + // cblogger.Errorf("Failed to Wait the Job : [%v]", waitErr) + // return false, waitErr + // } + } + return true, nil +} + +func (vmHandler *KTVpcVMHandler) removePortForwarding(privateIpAddr string) (bool, error) { + cblogger.Info("KT Cloud VPC Driver: called removePortForwarding()!") + + if strings.EqualFold(privateIpAddr,"") { + newErr := fmt.Errorf("Invalid Private IP Address!!") + cblogger.Error(newErr.Error()) + return false, newErr + } + + pfIds, err := vmHandler.getPortForwardingIDs(privateIpAddr) + if err != nil { + newErr := fmt.Errorf("Failed to Get PortForwarding Info. [%v]", err) + cblogger.Error(newErr.Error()) + return false, newErr + } + + // Delete Port Forwarding Rule + for _, pfId := range pfIds { + cblogger.Info("Deleting a Port Forwarding Rule Now!!") + resultErr := portforward.Delete(vmHandler.NetworkClient, pfId).ExtractErr() //.ExtractDelJobInfo() + if resultErr != nil { + cblogger.Error(resultErr.Error()) + return false, resultErr + } + time.Sleep(time.Second * 3) + // cblogger.Infof("\n# delResult.JopID : [%s]", delResult.JopID) + // cblogger.Info("\n") + + // cblogger.Info("### Waiting for PortForwarding Rule to be Deleted(300sec) !!") + // waitErr := vmHandler.waitForAsyncJob(delResult.JopID, 300000000000) + // if waitErr != nil { + // cblogger.Errorf("Failed to Wait the Job : [%v]", waitErr) + // return false, waitErr + // } + } + return true, nil +} + +func (vmHandler *KTVpcVMHandler) removePublicIP(publicIpAddr string) (bool, error) { + cblogger.Info("KT Cloud VPC Driver: called removePublicIP()!") + + if strings.EqualFold(publicIpAddr,"") { + newErr := fmt.Errorf("Invalid Public IP Address!!") + cblogger.Error(newErr.Error()) + return false, newErr + } + + firstPage, err := ips.List(vmHandler.NetworkClient).FirstPage() // Caution!! : NetworkClient. First Page. + if err != nil { + cblogger.Error(err.Error()) + return false, err + } + publicIPList, err := ips.ExtractFloatingIPs(firstPage) + if err != nil { + cblogger.Error(err.Error()) + return false, err + } + + // Search PublicIP ID + var publicIPId string + for _, p := range publicIPList { + if strings.EqualFold(publicIpAddr, p.IP) { + publicIPId = p.ID + break + } + } + + // Delete Public IP + if !strings.EqualFold(publicIPId, "") { + cblogger.Info("Deleting the Public IP Now!!") + err := ips.Delete(vmHandler.NetworkClient, publicIPId).ExtractErr() // NetworkClient + if err != nil { + cblogger.Error(err.Error()) + return false, err + } + time.Sleep(time.Second * 3) + } + return true, nil +} + +// Blocks until the the asynchronous job has executed or has timed out. +// time.Duration unit => 1 nanosecond. timeOut * 1,000,000,000 => 1 second +func (vmHandler *KTVpcVMHandler) waitForAsyncJob(jobId string, timeOut time.Duration) error { + cblogger.Info("KT Cloud VPC Driver: called waitForAsyncJob()!") + + c := vmHandler.NetworkClient + + done := make(chan struct{}) + defer close(done) + + result := make(chan error, 1) + go func() { + attempts := 0 + for { + attempts += 1 + + cblogger.Infof("Checking the async job status... (attempt: %d)", attempts) + jobResult, err := job.GetJobResult(c, jobId) + if err != nil { + result <- err + return + } + + // # Check status of the job + // 0 - Pending / In progress, Continue job + // 1 - Succeeded + // 2 - Failed + status := (*jobResult).JobState + cblogger.Infof("The job status : %d", status) + switch status { + case 1: + result <- nil + return + case 2: + err := fmt.Errorf("waitForAsyncJob() failed") + result <- err + return + } + + // Wait 3 seconds between requests + time.Sleep(3 * time.Second) + + // Verify whether we shouldn't exit or ... + select { + case <-done: + // Finished, so just exit the goroutine + return + default: + // Keep going + } + } + }() + + cblogger.Infof("Waiting for up to %f seconds for async job : %s", timeOut.Seconds(), jobId) + select { + case err := <-result: + return err + case <-time.After(timeOut): + err := fmt.Errorf("Timeout while waiting to for the async job to finish") + return err + } +} + +func (vmHandler *KTVpcVMHandler) listKTCloudVM() ([]servers.Server, error) { + cblogger.Info("KT Cloud cloud driver: called listKTCloudVM()!") + callLogInfo := getCallLogScheme(vmHandler.RegionInfo.Zone, call.VM, "listKTCloudVM()", "listKTCloudVM()") + + // Get VM list + listOpts := servers.ListOpts{ + Limit: 100, + AvailabilityZone: vmHandler.RegionInfo.Zone, + } + start := call.Start() + pager, err := servers.List(vmHandler.VMClient, listOpts).AllPages() + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return nil, err + } + loggingInfo(callLogInfo, start) + + vmList, err := servers.ExtractServers(pager) + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return nil, err + } + // spew.Dump(vmList) + return vmList, nil +} + +func (vmHandler *KTVpcVMHandler) getKTCloudVM(vmId string) (servers.Server, error) { + cblogger.Info("KT Cloud cloud driver: called getKTCloudVM()!") + callLogInfo := getCallLogScheme(vmHandler.RegionInfo.Zone, call.VM, vmId, "GetVM()") + + if strings.EqualFold(vmId, "") { + newErr := fmt.Errorf("Invalid VM SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return servers.Server{}, newErr + } + + start := call.Start() + vmResult, err := servers.Get(vmHandler.VMClient, vmId).Extract() + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return servers.Server{}, err + } + loggingInfo(callLogInfo, start) + + // spew.Dump(*vmResult) + return *vmResult, nil +} + +func (vmHandler *KTVpcVMHandler) getVmIdWithName(vmNameId string) (string, error) { + cblogger.Info("KT Cloud cloud driver: called getVmIdWithName()!") + + if strings.EqualFold(vmNameId, "") { + newErr := fmt.Errorf("Invalid VM NameId!!") + cblogger.Error(newErr.Error()) + return "", newErr + } + + // Get KT Cloud VM list + ktVMList, err := vmHandler.listKTCloudVM() + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud VM List : [%v]", err) + cblogger.Error(newErr.Error()) + return "", newErr + } + if len(ktVMList) < 1 { + newErr := fmt.Errorf("Failed to Find Any VM form KT Cloud : [%v]", err) + cblogger.Error(newErr.Error()) + return "", newErr + } + + var vmId string + for _, vm := range ktVMList { + if strings.EqualFold(vm.Name, vmNameId) { + vmId = vm.ID + break + } + } + + if vmId == "" { + err := fmt.Errorf("Failed to Find the VM ID with the VM Name %s", vmNameId) + return "", err + } else { + return vmId, nil + } +} + +func (vmHandler *KTVpcVMHandler) getVmNameWithId(vmId string) (string, error) { + cblogger.Info("KT Cloud cloud driver: called getVmNameWithId()!") + + if strings.EqualFold(vmId, "") { + newErr := fmt.Errorf("Invalid VM ID!!") + cblogger.Error(newErr.Error()) + return "", newErr + } + + ktVM, err := vmHandler.getKTCloudVM(vmId) + if err != nil { + newErr := fmt.Errorf("Failed to Get the VM Info from KT Cloud : [%v]", err) + cblogger.Error(newErr.Error()) + return "", newErr + } + vmName := ktVM.Name + if vmName == "" { + err := fmt.Errorf("Failed to Find the VM Name with the VM ID %s", vmId) + return "", err + } else { + return vmName, nil + } +} + +func (vmHandler *KTVpcVMHandler) getPublicIPWithVMId(vmId string) (string, error) { + cblogger.Info("KT Cloud cloud driver: called getPublicIPWithVMId()!") + + if strings.EqualFold(vmId, "") { + newErr := fmt.Errorf("Invalid VM ID!!") + cblogger.Error(newErr.Error()) + return "", newErr + } + + ktVM, err := vmHandler.getKTCloudVM(vmId) + if err != nil { + newErr := fmt.Errorf("Failed to Get the VM Info from KT Cloud : [%v]", err) + cblogger.Error(newErr.Error()) + return "", newErr + } + + // RF) VMHandler mappingVMInfo() + var subnetNameId string + var privateIP string + for key, subnet := range ktVM.Addresses { + // VPC Info + subnetNameId = key + // Get PrivateIP Info + for _, addr := range subnet.([]interface{}) { + addrMap := addr.(map[string]interface{}) + if addrMap["OS-EXT-IPS:type"] == "fixed" { + privateIP = addrMap["addr"].(string) + } + } + } + cblogger.Infof("Subnet NameId and Private IP : [%s], [%s]", subnetNameId, privateIP) + + netInfo, err := vmHandler.getNetIDsWithPrivateIP(privateIP) + if err != nil { + newErr := fmt.Errorf("Failed to Get PortForwarding Info. [%v]", err) + cblogger.Error(newErr.Error()) + return "", newErr + } + + if netInfo.PublicIP == "" { + newErr := fmt.Errorf("Failed to Find the Public IP of the VM ID(%s)", vmId) + return "", newErr + } else { + return netInfo.PublicIP, nil + } +} + +func (vmHandler *KTVpcVMHandler) createLinuxInitUserData(keyPairId string) (*string, error) { + cblogger.Info("KT Cloud driver: called createLinuxInitUserData()!!") + + initFilePath := os.Getenv("CBSPIDER_ROOT") + UbuntuCloudInitFilePath + fileData, readErr := os.ReadFile(initFilePath) + if readErr != nil { + newErr := fmt.Errorf("Failed to Read the file : [%v]", readErr) + cblogger.Error(newErr.Error()) + return nil, newErr + } + cmdString := string(fileData) + + // # Get the publicKey from DB // Caution!! ~.KeyPairIID."SystemId" + strList:= []string{ + vmHandler.CredentialInfo.Username, + vmHandler.CredentialInfo.Password, + } + hashString, err := keycommon.GenHash(strList) + if err != nil { + newErr := fmt.Errorf("Failed to Generate Hash String : [%v]", err) + cblogger.Error(newErr.Error()) + return nil, newErr + } + keyValue, getKeyErr := keycommon.GetKey("KTCLOUDVPC", hashString, keyPairId) + if getKeyErr != nil { + newErr := fmt.Errorf("Failed to Get the Public Key from DB : [%v]", getKeyErr) + cblogger.Error(newErr.Error()) + return nil, newErr + } + + // Set Linux cloud-init script + cmdString = strings.ReplaceAll(cmdString, "{{username}}", LnxUserName) + cmdString = strings.ReplaceAll(cmdString, "{{public_key}}", keyValue.Value) + // cblogger.Info("cmdString : ", cmdString) + return &cmdString, nil +} + +func (vmHandler *KTVpcVMHandler) createWinInitUserData(passWord string) (*string, error) { + cblogger.Info("KT Cloud driver: called createWinInitUserData()!!") + + // Preparing for UserData String + initFilePath := os.Getenv("CBSPIDER_ROOT") + WinCloudInitFilePath + fileData, readErr := os.ReadFile(initFilePath) + if readErr != nil { + newErr := fmt.Errorf("Failed to Read the file : [%v]", readErr) + cblogger.Error(newErr.Error()) + return nil, newErr + } + cmdString := string(fileData) + + // Set Windows cloud-init script + cmdString = strings.ReplaceAll(cmdString, "{{PASSWORD}}", passWord) + // cblogger.Info("cmdString : ", cmdString) + return &cmdString, nil +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/VMSpecHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/VMSpecHandler.go new file mode 100644 index 000000000..b36bc43d4 --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/VMSpecHandler.go @@ -0,0 +1,204 @@ +// 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 Example for PoC Test. +// +// by ETRI 2022.08. + +package resources + +import ( + "fmt" + "strconv" + "strings" + // "github.com/davecgh/go-spew/spew" + + ktvpcsdk "github.com/cloud-barista/ktcloudvpc-sdk-go" + "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/compute/v2/flavors" + + call "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/call-log" + 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 KTVpcVMSpecHandler struct { + RegionInfo idrv.RegionInfo + VMClient *ktvpcsdk.ServiceClient +} + +func (vmSpecHandler *KTVpcVMSpecHandler) ListVMSpec() ([]*irs.VMSpecInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called ListVMSpec()!") + callLogInfo := getCallLogScheme(vmSpecHandler.RegionInfo.Zone, call.VMSPEC, "ListVMSpec()", "ListVMSpec()") + + listOpts := flavors.ListOpts{ + Limit: 300, //default : 20 + } + + start := call.Start() + allPages, err := flavors.ListDetail(vmSpecHandler.VMClient, listOpts).AllPages() + if err != nil { + newErr := fmt.Errorf("Failed to Get Flavor Pages from KT Cloud : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + loggingInfo(callLogInfo, start) + + flavorList, err := flavors.ExtractFlavors(allPages) + if err != nil { + newErr := fmt.Errorf("Failed to Get Flavor list from KT Cloud : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + + // cblogger.Infof("\n # specList : ") + // spew.Dump(specList) + + var vmSpecInfoList []*irs.VMSpecInfo + for _, flavor := range flavorList { + vmSpecInfo := vmSpecHandler.mappingVMSpecInfo(&flavor) + vmSpecInfoList = append(vmSpecInfoList, vmSpecInfo) + } + return vmSpecInfoList, nil +} + +func (vmSpecHandler *KTVpcVMSpecHandler) GetVMSpec(specName string) (irs.VMSpecInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called GetVMSpec()!") + callLogInfo := getCallLogScheme(vmSpecHandler.RegionInfo.Zone, call.VMSPEC, specName, "GetVMSpec()") + + if strings.EqualFold(specName,"") { + newErr := fmt.Errorf("Invalid vmSpec Name!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VMSpecInfo{}, newErr + } + + vmSpecId, err := vmSpecHandler.getVMSpecIdWithName(specName) + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return irs.VMSpecInfo{}, err + } + + start := call.Start() + vmSpec, err := flavors.Get(vmSpecHandler.VMClient, vmSpecId).Extract() + if err != nil { + cblogger.Error(err.Error()) + loggingError(callLogInfo, err) + return irs.VMSpecInfo{}, err + } + loggingInfo(callLogInfo, start) + vmSpecInfo := vmSpecHandler.mappingVMSpecInfo(vmSpec) + return *vmSpecInfo, nil +} + +func (vmSpecHandler *KTVpcVMSpecHandler) ListOrgVMSpec() (string, error) { + cblogger.Info("KT Cloud VPC Driver: called ListOrgVMSpec()!") + callLogInfo := getCallLogScheme(vmSpecHandler.RegionInfo.Zone, call.VMSPEC, "ListOrgVMSpec()", "ListOrgVMSpec()") + + var vmSpecInfoList []*irs.VMSpecInfo + vmSpecInfoList, err := vmSpecHandler.ListVMSpec() + if err != nil { + newErr := fmt.Errorf("Failed to Get VMSpec Info list : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return "", newErr + } + jsonString, jsonErr := convertJsonString(vmSpecInfoList) + if jsonErr != nil { + newErr := fmt.Errorf("Failed to Convert the Json String : [%v]", jsonErr) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return "", newErr + } + return jsonString, jsonErr +} + +func (vmSpecHandler *KTVpcVMSpecHandler) GetOrgVMSpec(specName string) (string, error) { + cblogger.Info("KT Cloud VPC Driver: called GetOrgVMSpec()!") + callLogInfo := getCallLogScheme(vmSpecHandler.RegionInfo.Zone, call.VMSPEC, specName, "GetOrgVMSpec()") + + if strings.EqualFold(specName,"") { + newErr := fmt.Errorf("Invalid vmSpec Name!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return "", newErr + } + + specInfo, err := vmSpecHandler.GetVMSpec(specName) + if err != nil { + newErr := fmt.Errorf("Failed to Get VMSpec Info : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return "", newErr + } + jsonString, jsonErr := convertJsonString(specInfo) + if jsonErr != nil { + newErr := fmt.Errorf("Failed to Convert the Json String : [%v]", jsonErr) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return "", newErr + } + return jsonString, jsonErr +} + +func (vmSpecHandler *KTVpcVMSpecHandler) getVMSpecIdWithName(specName string) (string, error) { + cblogger.Info("KT Cloud VPC Driver: called getVMSpecIdWithName()!") + + allPages, err := flavors.ListDetail(vmSpecHandler.VMClient, flavors.ListOpts{}).AllPages() + if err != nil { + return "", err + } + flavorList, err := flavors.ExtractFlavors(allPages) + if err != nil { + return "", err + } + + var flavorNameList []flavors.Flavor + for _, flavor := range flavorList { + if strings.EqualFold(flavor.Name, specName) { + flavorNameList = append(flavorNameList, flavor) + } + } + if len(flavorNameList) < 1 { + return "", fmt.Errorf("Found multiple vmSpec with the name %s", specName) + } else if len(flavorNameList) == 0 { + return "", fmt.Errorf("Failed to Find vmSpec with the name %s", specName) + } + return flavorNameList[0].ID, nil +} + +func (vmSpecHandler *KTVpcVMSpecHandler) mappingVMSpecInfo(flavor *flavors.Flavor) *irs.VMSpecInfo { + cblogger.Info("KT Cloud VPC Driver: called mappingVMSpecInfo()!") + // spew.Dump(vmSpec) + vmSpecInfo := irs.VMSpecInfo { + Region: vmSpecHandler.RegionInfo.Zone, + Name: flavor.Name, + VCpu: irs.VCpuInfo{Count: strconv.Itoa(flavor.VCPUs), }, + Mem: strconv.Itoa(flavor.RAM), + // Gpu: []irs.GpuInfo{{Count: "N/A", Mfr: "N/A", Model: "N/A", Mem: "N/A"}}, + + KeyValueList: []irs.KeyValue{ + {Key: "Zone", Value: vmSpecHandler.RegionInfo.Zone}, + {Key: "RootDiskSize(GB)", Value: strconv.Itoa(flavor.Disk)}, + {Key: "EphemeralDiskSize(GB)", Value: strconv.Itoa(flavor.Ephemeral)}, + {Key: "SwapDiskSize(MB)", Value: strconv.Itoa(flavor.Swap)}, + {Key: "IsPublic", Value: strconv.FormatBool(flavor.IsPublic)}, + {Key: "VMSpecID", Value: flavor.ID}, + }, + } + + // if strings.EqualFold(strconv.Itoa(vmSpec.Disk), "0") { + // keyValue := irs.KeyValue { + // Key: "Notice", + // Value: "Specify 'RootDiskType' and 'RootDiskSize' when VM Creation to Boot from the Attached Volume!!", + // } + // vmSpecInfo.KeyValueList = append(vmSpecInfo.KeyValueList, keyValue) + // } + + return &vmSpecInfo +} diff --git a/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/VPCHandler.go b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/VPCHandler.go new file mode 100644 index 000000000..3a941a6da --- /dev/null +++ b/cloud-control-manager/cloud-driver/drivers/ktcloudvpc/resources/VPCHandler.go @@ -0,0 +1,658 @@ +// 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 Example for PoC Test. +// +// by ETRI 2022.08. + +package resources + +import ( + // "errors" + "fmt" + "strings" + "time" + // "github.com/davecgh/go-spew/spew" + + ktvpcsdk "github.com/cloud-barista/ktcloudvpc-sdk-go" + external "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/networking/v2/extensions/external" + networks "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/networking/v2/networks" + subnets "github.com/cloud-barista/ktcloudvpc-sdk-go/openstack/networking/v2/subnets" + + call "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/call-log" + 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 KTVpcVPCHandler struct { + RegionInfo idrv.RegionInfo + NetworkClient *ktvpcsdk.ServiceClient +} + +type NetworkWithExt struct { + networks.Network + external.NetworkExternalExt +} + +func (vpcHandler *KTVpcVPCHandler) CreateVPC(vpcReqInfo irs.VPCReqInfo) (irs.VPCInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called CreateVPC()!") + callLogInfo := getCallLogScheme(vpcHandler.RegionInfo.Zone, call.VPCSUBNET, vpcReqInfo.IId.NameId, "CreateVPC()") + + if strings.EqualFold(vpcReqInfo.IId.NameId, "") { + newErr := fmt.Errorf("Invalid VPC NameId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VPCInfo{}, newErr + } + + // KT Cloud (D1) VPC API doc. : https://cloud.kt.com/docs/open-api-guide/d/computing/networking + // KT Cloud (D1) Tier API doc. : https://cloud.kt.com/docs/open-api-guide/d/computing/tier + + start := call.Start() + listOpts := networks.ListOpts{} + firstPage, err := networks.List(vpcHandler.NetworkClient, listOpts).FirstPage() // Caution!! : First Page Only + if err != nil { + cblogger.Errorf("Failed to Create KT Cloud VPC : [%v]", err) + loggingError(callLogInfo, err) + return irs.VPCInfo{}, err + } + loggingInfo(callLogInfo, start) + + vpcList, err := networks.ExtractVPCs(firstPage) + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud VPC Network list. [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VPCInfo{}, newErr + } + if len(vpcList) < 1 { + newErr := fmt.Errorf("Failed to Get Any VPC Network Info.") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VPCInfo{}, newErr + } + if strings.EqualFold(vpcList[0].ID, "") { + cblogger.Error("Failed to Create the Required VPC!!") + return irs.VPCInfo{}, nil + } + + // Create the Requested Subnets + for _, subnetReqInfo := range vpcReqInfo.SubnetInfoList { + _, err := vpcHandler.AddSubnet(irs.IID{SystemId: vpcList[0].ID}, subnetReqInfo) + if err != nil { + newErr := fmt.Errorf("Failed to Create New Subnet : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VPCInfo{}, newErr // Caution!!) D1 Platform Abnormal Error + } + } + + vpcInfo, getErr := vpcHandler.GetVPC(irs.IID{SystemId: vpcList[0].ID}) + if getErr != nil { + newErr := fmt.Errorf("Failed to Get the VPC Info : [%v]", getErr) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VPCInfo{}, newErr + } else { + vpcInfo.IId.NameId = vpcReqInfo.IId.NameId // Caution!! For IID2 NameID validation check for VPC + } + return vpcInfo, nil +} + +func (vpcHandler *KTVpcVPCHandler) GetVPC(vpcIID irs.IID) (irs.VPCInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called GetVPC()!") + callLogInfo := getCallLogScheme(vpcHandler.RegionInfo.Zone, call.VPCSUBNET, vpcIID.SystemId, "GetVPC()") + + if strings.EqualFold(vpcIID.SystemId, "") { + newErr := fmt.Errorf("Invalid VPC SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VPCInfo{}, newErr + } + + start := call.Start() + listOpts := networks.ListOpts{} + firstPage, err := networks.List(vpcHandler.NetworkClient, listOpts).FirstPage() // Caution!! : First Page Only + if err != nil { + cblogger.Errorf("Failed to Get VPC Network info from KT Cloud VPC : [%v]", err) + loggingError(callLogInfo, err) + return irs.VPCInfo{}, err + } + loggingInfo(callLogInfo, start) + + vpcList, err := networks.ExtractVPCs(firstPage) + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud VPC Network list. [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VPCInfo{}, newErr + } + if len(vpcList) < 1 { + newErr := fmt.Errorf("Failed to Get Any VPC Network Info.") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VPCInfo{}, newErr + } + + var vpcInfo *irs.VPCInfo + for _, vpc := range vpcList { + if strings.EqualFold(vpcIID.SystemId, vpc.ID) { + var mapErr error + vpcInfo, mapErr = vpcHandler.mappingVpcInfo(&vpc) + if mapErr != nil { + newErr := fmt.Errorf("Failed to Map the VPC Info : [%v]", mapErr) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VPCInfo{}, newErr + } + break + } + } + return *vpcInfo, nil +} + +func (vpcHandler *KTVpcVPCHandler) ListVPC() ([]*irs.VPCInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called ListVPC()!") + callLogInfo := getCallLogScheme(vpcHandler.RegionInfo.Zone, call.VPCSUBNET, "ListVPC()", "ListVPC()") + + // KT Cloud (D1) VPC API guide : https://cloud.kt.com/docs/open-api-guide/d/computing/networking + // KT Cloud (D1) Tier API guide : https://cloud.kt.com/docs/open-api-guide/d/computing/tier + + listOpts := networks.ListOpts{} + firstPage, err := networks.List(vpcHandler.NetworkClient, listOpts).FirstPage() // Caution!! : First Page Only + if err != nil { + cblogger.Errorf("Failed to Get VPC Network info from KT Cloud VPC : [%v]", err) + loggingError(callLogInfo, err) + return nil, err + } + + vpcList, err := networks.ExtractVPCs(firstPage) + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud VPC Network list. [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + if len(vpcList) < 1 { + newErr := fmt.Errorf("Failed to Get Any VPC Network Info.") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + + var vpcInfoList []*irs.VPCInfo + for _, vpc := range vpcList { + vpcInfo, err := vpcHandler.mappingVpcInfo(&vpc) + if err != nil { + newErr := fmt.Errorf("Failed to Map the VPC Info : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + vpcInfoList = append(vpcInfoList, vpcInfo) + } + return vpcInfoList, nil +} + +func (vpcHandler *KTVpcVPCHandler) DeleteVPC(vpcIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud VPC Driver: called DeleteVPC()!") + callLogInfo := getCallLogScheme(vpcHandler.RegionInfo.Zone, call.VPCSUBNET, vpcIID.SystemId, "DeleteVPC()") + + //To check whether the VPC exists. + cblogger.Infof("vpcIID.SystemId to Delete : [%s]", vpcIID.SystemId) + + vpcInfo, err := vpcHandler.GetVPC(vpcIID) + if err != nil { + cblogger.Errorf("Failed to Find the VPC with the SystemID. : [%s] : [%v]", vpcIID.SystemId, err) + loggingError(callLogInfo, err) + return false, err + } + + // Delete the Subnets belonged in the VPC + for _, subnetInfo := range vpcInfo.SubnetInfoList { + if !strings.EqualFold(subnetInfo.IId.NameId, "Private") && !strings.EqualFold(subnetInfo.IId.NameId, "DMZ") && !strings.EqualFold(subnetInfo.IId.NameId, "external"){ + _, err := vpcHandler.RemoveSubnet(irs.IID{SystemId: vpcIID.SystemId}, irs.IID{SystemId: subnetInfo.IId.SystemId}) + if !strings.Contains(err.Error(), ":true") { // Cauton!! : Abnormal Error when removing a subnet on D1 Platform + newErr := fmt.Errorf("Failed to Delete the Subnet : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + } + } + + result, err := vpcHandler.GetVPC(vpcIID) + if err != nil { + cblogger.Errorf("Failed to Find the VPC with the SystemID. : [%s] : [%v]", vpcIID.SystemId, err) + loggingError(callLogInfo, err) + return false, err + } else { + cblogger.Infof("Succeeded in Deleting the VPC : " + result.IId.SystemId) + } + + return true, nil +} + +func (vpcHandler *KTVpcVPCHandler) GetSubnet(subnetIID irs.IID) (irs.SubnetInfo, error) { + cblogger.Info("KT Cloud VPC Driver: called GetSubnet()!") + callLogInfo := getCallLogScheme(vpcHandler.RegionInfo.Zone, call.VPCSUBNET, subnetIID.SystemId, "GetSubnet()") + + if strings.EqualFold(subnetIID.SystemId, "") { + newErr := fmt.Errorf("Invalid Subnet SystemId!!") + cblogger.Error(newErr.Error()) + return irs.SubnetInfo{}, newErr + } + + subnet, err := subnets.Get(vpcHandler.NetworkClient, subnetIID.SystemId).Extract() + if err != nil { + cblogger.Errorf("Failed to Get Subnet with SystemId [%s] : %v", subnetIID.SystemId, err) + loggingError(callLogInfo, err) + return irs.SubnetInfo{}, nil + } + subnetInfo := vpcHandler.mappingSubnetInfo(*subnet) + return *subnetInfo, nil +} + +func (vpcHandler *KTVpcVPCHandler) AddSubnet(vpcIID irs.IID, subnetReqInfo irs.SubnetInfo) (irs.VPCInfo, error) { + cblogger.Info("KT Cloud VPC driver: called AddSubnet()!!") + callLogInfo := getCallLogScheme(vpcHandler.RegionInfo.Zone, call.VPCSUBNET, subnetReqInfo.IId.NameId, "AddSubnet()") + + if subnetReqInfo.IId.NameId == "" { + newErr := fmt.Errorf("Invalid Sunbet NameId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VPCInfo{}, newErr + } + + // KT Cloud D1 platform API guide - Tier : https://cloud.kt.com/docs/open-api-guide/d/computing/tier + cidrBlock := strings.Split(subnetReqInfo.IPv4_CIDR, ".") + startIP := cidrBlock[0] + "." + cidrBlock[1] + "." + cidrBlock[2] + "." + "11" + endIP := cidrBlock[0] + "." + cidrBlock[1] + "." + cidrBlock[2] + "." + "140" + lbStartIP := cidrBlock[0] + "." + cidrBlock[1] + "." + cidrBlock[2] + "." + "141" + lbEndIP := cidrBlock[0] + "." + cidrBlock[1] + "." + cidrBlock[2] + "." + "200" + bmStartIP := cidrBlock[0] + "." + cidrBlock[1] + "." + cidrBlock[2] + "." + "201" + bmEndIP := cidrBlock[0] + "." + cidrBlock[1] + "." + cidrBlock[2] + "." + "250" + gatewayIP := cidrBlock[0] + "." + cidrBlock[1] + "." + cidrBlock[2] + "." + "1" + + detailTierInfo := subnets.DetailInfo { + CIDR: subnetReqInfo.IPv4_CIDR, + StartIP: startIP, + EndIP: endIP, + LBStartIP: lbStartIP, + LBEndIP: lbEndIP, + BMStartIP: bmStartIP, + BMEndIP: bmEndIP, + Gateway: gatewayIP, + } + + // Create Subnet + createOpts := subnets.CreateOpts{ + Name: subnetReqInfo.IId.NameId, // Mandatory (Required) + Zone: vpcHandler.RegionInfo.Zone, // Mandatory (Required) + Type: "tier", // Mandatory (Required) + UserCustom: "y", // Mandatory (Required) + Detail: detailTierInfo, + } + // cblogger.Info("\n### Subnet createOpts : ") + // spew.Dump(createOpts) + // cblogger.Info("\n") + + cblogger.Info("\n### Adding New Subnet Now!!") + start := call.Start() + _, err := subnets.Create(vpcHandler.NetworkClient, createOpts).Extract() + // subnet, err := subnets.Create(vpcHandler.NetworkClient, createOpts).Extract() + if err != nil { + if !strings.Contains(err.Error(), ":true") { // Cauton!! : Abnormal Error when creating a subnet on D1 Platform + newErr := fmt.Errorf("Failed to Add the Subnet on KTCoud : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VPCInfo{}, newErr + } + } else { + cblogger.Info("\n### Waiting for Adding the Subnet!!") + time.Sleep(time.Second * 15) + + // cblogger.Infof("Succeeded in Adding the Subnet : [%s]", subnet.ID) // To prevent 'panic: runtime error', maded this line as a comment. + } + loggingInfo(callLogInfo, start) + + // subnetInfo := vpcHandler.setterSubnet(*subnet) + // return *subnetInfo, nil + + vpcInfo, err := vpcHandler.GetVPC(irs.IID{SystemId: vpcIID.SystemId}) + if err != nil { + newErr := fmt.Errorf("Failed to Get the VPC Info!! : [%v] ", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return irs.VPCInfo{}, newErr + } + return vpcInfo, nil +} + +func (vpcHandler *KTVpcVPCHandler) RemoveSubnet(vpcIID irs.IID, subnetIID irs.IID) (bool, error) { + cblogger.Info("KT Cloud VPC driver: called RemoveSubnet()!!") + callLogInfo := getCallLogScheme(vpcHandler.RegionInfo.Zone, call.VPCSUBNET, subnetIID.SystemId, "RemoveSubnet()") + + if strings.EqualFold(subnetIID.SystemId, "") { + newErr := fmt.Errorf("Invalid Subnet SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + + err := subnets.Delete(vpcHandler.NetworkClient, subnetIID.SystemId).ExtractErr() + if err != nil { + newErr := fmt.Errorf("Failed to Remove the Subnet from KT Cloud : [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return false, newErr + } + cblogger.Info("\n### Waiting for Deleting the Subnet!!") + time.Sleep(time.Second * 5) + + return true, nil +} + +func (vpcHandler *KTVpcVPCHandler) mappingVpcInfo(nvpc *networks.Network) (*irs.VPCInfo, error) { + cblogger.Info("KT Cloud VPC driver: called mappingVpcInfo()!!") + // cblogger.Info("\n### KTCloud VPC") + // spew.Dump(nvpc) + + if strings.EqualFold(nvpc.ID, "") { + newErr := fmt.Errorf("Invalid VPC Info!!") + cblogger.Error(newErr.Error()) + return nil, newErr + } + + // Mapping VPC info. + vpcInfo := irs.VPCInfo { + IId: irs.IID{ + NameId: nvpc.Name, + SystemId: nvpc.ID, + }, + IPv4_CIDR: "172.25.0.0/12", // VPC CIDR of KT Cloud D1 Platform Default VPC + } + keyValueList := []irs.KeyValue{ + {Key: "VpcID", Value: nvpc.ID}, + {Key: "ZoneId", Value: nvpc.ZoneID}, + // {Key: "CreatedTime", Value: nvpc.CreatedAt.String()}, + } + vpcInfo.KeyValueList = keyValueList + + // Get Subnet info list. + var subnetInfoList []irs.SubnetInfo + for _, subnet := range nvpc.Subnets { + // if !strings.EqualFold(subnet.Name, "Private_Sub") && !strings.EqualFold(subnet.Name, "DMZ_Sub") && !strings.EqualFold(subnet.Name, "external"){ + // # When apply filtering + + subnetInfo := vpcHandler.mappingSubnetInfo(subnet) + subnetInfoList = append(subnetInfoList, *subnetInfo) + // } + } + vpcInfo.SubnetInfoList = subnetInfoList + + return &vpcInfo, nil +} + +func (vpcHandler *KTVpcVPCHandler) mappingSubnetInfo(subnet subnets.Subnet) *irs.SubnetInfo { + cblogger.Info("KT Cloud VPC driver: called mappingSubnetInfo()!!") + + // To remove "_Sub" in the subnet name (Note. "_Sub" is appended to a subnet name in the KT Cloud) + // Removing "_Sub" for CB-Spdier IID manager + subnetName := strings.Split(subnet.Name, "_Sub") + newName := subnetName[0] + + subnetInfo := irs.SubnetInfo{ + IId: irs.IID{ + NameId: newName, + SystemId: subnet.OsNetworkID, // Caution!! Not 'ID' but 'OsNetworkID' to Create VM!! + }, + IPv4_CIDR: subnet.CIDR, + } + + keyValueList := []irs.KeyValue{ + {Key: "Type", Value: subnet.Type}, + {Key: "StartIP", Value: subnet.StartIP}, + {Key: "EndIP", Value: subnet.EndIP}, + {Key: "Gateway", Value: subnet.Gateway}, + {Key: "TierUUID", Value: subnet.ID}, // Tier 'ID' on KT Cloud D platform Consol + {Key: "ZoneId", Value: subnet.ZoneID}, + } + subnetInfo.KeyValueList = keyValueList + return &subnetInfo +} + +func (vpcHandler *KTVpcVPCHandler) getKtCloudVpc(vpcId string) (*networks.Network, error) { + cblogger.Info("KT Cloud VPC Driver: called getKtCloudVpc()!") + callLogInfo := getCallLogScheme(vpcHandler.RegionInfo.Zone, call.VPCSUBNET, vpcId, "getKtCloudVpc()") + + if strings.EqualFold(vpcId, "") { + newErr := fmt.Errorf("Invalid VPC ID!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + + start := call.Start() + listOpts := networks.ListOpts{} + firstPage, err := networks.List(vpcHandler.NetworkClient, listOpts).FirstPage() // Caution!! : First Page Only + if err != nil { + cblogger.Errorf("Failed to Get VPC Network info from KT Cloud VPC : [%v]", err) + loggingError(callLogInfo, err) + return nil, err + } + loggingInfo(callLogInfo, start) + + vpcList, err := networks.ExtractVPCs(firstPage) + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud VPC Network list. [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + if len(vpcList) < 1 { + newErr := fmt.Errorf("Failed to Get Any VPC Network Info.") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return nil, newErr + } + + var ktVpc *networks.Network + for _, vpc := range vpcList { + if strings.EqualFold(vpcId, vpc.ID) { + ktVpc = &vpc + break + } + } + return ktVpc, nil +} + +func (vpcHandler *KTVpcVPCHandler) getExtSubnetId(vpcIID irs.IID) (string, error) { + cblogger.Info("KT Cloud VPC Driver: called getExtSubnetId()!") + callLogInfo := getCallLogScheme(vpcHandler.RegionInfo.Zone, call.VPCSUBNET, vpcIID.SystemId, "getExtSubnetId()") + + if strings.EqualFold(vpcIID.SystemId, "") { + newErr := fmt.Errorf("Invalid VPC SystemId!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return "", newErr + } + + ktVpc, err := vpcHandler.getKtCloudVpc(vpcIID.SystemId) + if err != nil { + cblogger.Errorf("Failed to Get the VPC Info from KT Cloud. : [%v]", err) + loggingError(callLogInfo, err) + return "", err + } + + var extSubnetId string + for _, subnet := range ktVpc.Subnets { + if strings.EqualFold(subnet.Name, "external"){ + extSubnetId = subnet.ID + break + } + } + + if strings.EqualFold(extSubnetId, "") { + newErr := fmt.Errorf("Failed to Find the External Subnet ID!!") + cblogger.Error(newErr.Error()) + return "", newErr + } + + return extSubnetId, nil +} + +func (vpcHandler *KTVpcVPCHandler) getOsNetworkIdWithTierId(vpcId string, tierId string) (string, error) { + cblogger.Info("KT Cloud VPC Driver: called getOsNetworkIdWithTierId()!") + callLogInfo := getCallLogScheme(vpcHandler.RegionInfo.Zone, call.VPCSUBNET, tierId, "getOsNetworkIdWithTierId()") + + if strings.EqualFold(vpcId, "") { + newErr := fmt.Errorf("Invalid VPC ID!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return "", newErr + } + + if strings.EqualFold(tierId, "") { + newErr := fmt.Errorf("Invalid Subnet(Tier) ID!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return "", newErr + } + + ktVpc, err := vpcHandler.getKtCloudVpc(vpcId) + if err != nil { + cblogger.Errorf("Failed to Get the VPC Info from KT Cloud. [%v]", err) + loggingError(callLogInfo, err) + return "", err + } + + var osNetworkId string + for _, subnet := range ktVpc.Subnets { + if strings.EqualFold(subnet.ID, tierId){ + osNetworkId = subnet.OsNetworkID + break + } + } + + if strings.EqualFold(osNetworkId, "") { + newErr := fmt.Errorf("Failed to Find the OsNetwork ID!!") + cblogger.Error(newErr.Error()) + return "", newErr + } + + return osNetworkId, nil +} + +func (vpcHandler *KTVpcVPCHandler) getOsNetworkIdWithTierName(tierName string) (string, error) { + cblogger.Info("KT Cloud VPC Driver: called getOsNetworkIdWithTierName()!") + callLogInfo := getCallLogScheme(vpcHandler.RegionInfo.Zone, call.VPCSUBNET, tierName, "getOsNetworkIdWithTierName()") + + if strings.EqualFold(tierName, "") { + newErr := fmt.Errorf("Invalid Subnet(Tier) Name!!") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return "", newErr + } + cblogger.Infof("# Subnet(Tier) Name to Find OsNetwork ID : %s", tierName) + + start := call.Start() + listOpts := networks.ListOpts{} + firstPage, err := networks.List(vpcHandler.NetworkClient, listOpts).FirstPage() // Caution!! : First Page Only + if err != nil { + cblogger.Errorf("Failed to Get VPC Network info from KT Cloud VPC : [%v]", err) + loggingError(callLogInfo, err) + return "", err + } + loggingInfo(callLogInfo, start) + + vpcList, err := networks.ExtractVPCs(firstPage) + if err != nil { + newErr := fmt.Errorf("Failed to Get KT Cloud VPC Network list. [%v]", err) + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return "", newErr + } + if len(vpcList) < 1 { + newErr := fmt.Errorf("Failed to Get Any VPC Network Info.") + cblogger.Error(newErr.Error()) + loggingError(callLogInfo, newErr) + return "", newErr + } + + var osNetworkId string + for _, vpc := range vpcList { + for _, subnet := range vpc.Subnets { + // To remove "_Sub" in the subnet name (Note. "_Sub" is appended to a subnet name in the KT Cloud) + subnetName := strings.Split(subnet.Name, "_Sub") // Caution!! + + if strings.EqualFold(subnetName[0], tierName){ + osNetworkId = subnet.OsNetworkID + break + } + } + } + + if strings.EqualFold(osNetworkId, "") { + newErr := fmt.Errorf("Failed to Find the OsNetwork ID!!") + cblogger.Error(newErr.Error()) + return "", newErr + } + + return osNetworkId, nil +} + +// func (vpcHandler *KTVpcVPCHandler) getVpcIdWithName(vpcName string) (string, error) { +// cblogger.Info("KT Cloud VPC Driver: called getVpcIdWithName()!") +// callLogInfo := getCallLogScheme(vpcHandler.RegionInfo.Zone, call.VPCSUBNET, vpcName, "getVpcIdWithName()") + +// if strings.EqualFold(vpcName, "") { +// newErr := fmt.Errorf("Invalid VPC ID!!") +// cblogger.Error(newErr.Error()) +// loggingError(callLogInfo, newErr) +// return "", newErr +// } + +// start := call.Start() +// listOpts := networks.ListOpts{} +// firstPage, err := networks.List(vpcHandler.NetworkClient, listOpts).FirstPage() // Caution!! : First Page Only +// if err != nil { +// cblogger.Errorf("Failed to Get VPC Network info from KT Cloud VPC : [%v]", err) +// loggingError(callLogInfo, err) +// return "", err +// } +// loggingInfo(callLogInfo, start) + +// vpcList, err := networks.ExtractVPCs(firstPage) +// if err != nil { +// newErr := fmt.Errorf("Failed to Get KT Cloud VPC Network list. [%v]", err) +// cblogger.Error(newErr.Error()) +// loggingError(callLogInfo, newErr) +// return "", newErr +// } +// if len(vpcList) < 1 { +// newErr := fmt.Errorf("Failed to Get Any VPC Network Info.") +// cblogger.Error(newErr.Error()) +// loggingError(callLogInfo, newErr) +// return "", newErr +// } + +// var vpcId string +// for _, vpc := range vpcList { +// if strings.EqualFold(vpc.Name, vpcName) { +// vpcId = vpc.ID +// break +// } +// } + +// if strings.EqualFold(vpcId, "") { +// newErr := fmt.Errorf("Failed to Find the VPC ID!!") +// cblogger.Error(newErr.Error()) +// return "", newErr +// } + +// return vpcId, nil +// } From 3d7a2b0cf654597e9ad5acd7e4edbd92c023e768 Mon Sep 17 00:00:00 2001 From: innodreamer Date: Fri, 5 Apr 2024 20:31:44 +0900 Subject: [PATCH 3/3] Update go.mod and go.sum --- go.mod | 2 +- go.sum | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 6ddc21622..80a94708c 100644 --- a/go.mod +++ b/go.mod @@ -66,6 +66,7 @@ require ( github.com/alibabacloud-go/tea v1.2.2 github.com/alibabacloud-go/vpc-20160428/v6 v6.4.0 github.com/cloud-barista/ktcloud-sdk-go v0.2.1-0.20240123114820-8684cfc5deeb + github.com/cloud-barista/ktcloudvpc-sdk-go v0.0.0-20240403081203-a0af52c7c7cd github.com/cloud-barista/nhncloud-sdk-go v0.0.0-20240403130402-131df63a24b4 github.com/go-openapi/strfmt v0.21.3 github.com/hashicorp/go-version v1.6.0 @@ -88,7 +89,6 @@ require ( github.com/alibabacloud-go/tea-xml v1.1.3 // indirect github.com/aliyun/credentials-go v1.3.2 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect - github.com/cloud-barista/ktcloudvpc-sdk-go v0.0.0-20240403081203-a0af52c7c7cd // indirect github.com/itchyny/timefmt-go v0.1.5 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect diff --git a/go.sum b/go.sum index cbb0b20be..b4aadfffb 100644 --- a/go.sum +++ b/go.sum @@ -782,8 +782,6 @@ golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg= -golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -994,8 +992,6 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -1007,8 +1003,7 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=