Skip to content

Commit

Permalink
[KT Cloud] Enhance Supported VM Image Info
Browse files Browse the repository at this point in the history
  • Loading branch information
innodreamer committed Feb 7, 2025
1 parent d8f2351 commit c4c653b
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
// KT Cloud Image Handler
//
// by ETRI, 2021.05.
// Updated by ETRI, 2025.02.

package resources

import (
"errors"
"fmt"
"strings"

//"github.com/davecgh/go-spew/spew"
"regexp"
// "github.com/davecgh/go-spew/spew"

ktsdk "github.com/cloud-barista/ktcloud-sdk-go"

Expand All @@ -36,55 +37,37 @@ func init() {
}

// <Note> 'Image' in KT Cloud API manual means an image created for Volume or Snapshot of VM stopped state.

func (imageHandler *KtCloudImageHandler) GetImage(imageIID irs.IID) (irs.ImageInfo, error) {
cblogger.Info("KT Cloud cloud driver: called GetImage()!!")
// cblogger.Infof("KT Cloud image ID(Templateid) : [%s]", imageIID.SystemId)
// cblogger.Info("imageHandler.RegionInfo.Zone : ", zoneId)

if strings.EqualFold(imageIID.SystemId, "") {
newErr := fmt.Errorf("Invalid Image SystemId!!")
cblogger.Error(newErr.Error())
return irs.ImageInfo{}, newErr
}

var resultImageInfo irs.ImageInfo
zoneId := imageHandler.RegionInfo.Zone

cblogger.Infof("KT Cloud image ID(Templateid) : [%s]", imageIID.SystemId)
cblogger.Info("imageHandler.RegionInfo.Zone : ", zoneId)

// Caution!! : KT Cloud searches by 'zoneId' when searching Image info/VMSpc info.
result, err := imageHandler.Client.ListAvailableProductTypes(zoneId)
// Note!!) Use ListImage() to search within the organized image list information
imageListResult, err := imageHandler.ListImage()
if err != nil {
cblogger.Error("Failed to Get List of Available Product Types: %s", err)
return irs.ImageInfo{}, err
}

if len(result.Listavailableproducttypesresponse.ProductTypes) < 1 {
return irs.ImageInfo{}, errors.New("Failed to Get Any Product Types!!")
newErr := fmt.Errorf("Failed to Get the VMSpec info list!! : [%v]", err)
cblogger.Error(newErr.Error())
return irs.ImageInfo{}, newErr
}

var foundImgId string
for _, productType := range result.Listavailableproducttypesresponse.ProductTypes {
// cblogger.Info("# Search criteria of Image Template ID : ", imageIID.SystemId)
if strings.EqualFold(productType.TemplateId, imageIID.SystemId) {
foundImgId = productType.TemplateId
resultImageInfo = mappingImageInfo(productType)
break
for _, image := range imageListResult {
if strings.EqualFold(image.Name, imageIID.SystemId) {
return *image, nil
}
}
if strings.EqualFold(foundImgId, "") {
return irs.ImageInfo{}, fmt.Errorf("Failed to Find Any Image(Template) info with the ID.")
}
return resultImageInfo, nil
return irs.ImageInfo{}, errors.New("Failed to find the VM Image info : '" + imageIID.SystemId)
}

func (imageHandler *KtCloudImageHandler) ListImage() ([]*irs.ImageInfo, error) {
cblogger.Info("KT Cloud cloud driver: called ListImage()!")

var vmImageList []*irs.ImageInfo
zoneId := imageHandler.RegionInfo.Zone

result, err := imageHandler.Client.ListAvailableProductTypes(zoneId)
result, err := imageHandler.Client.ListAvailableProductTypes(imageHandler.RegionInfo.Zone)
if err != nil {
cblogger.Error("Failed to Get List of Available Product Types: %s", err)
return []*irs.ImageInfo{}, err
Expand All @@ -94,35 +77,79 @@ func (imageHandler *KtCloudImageHandler) ListImage() ([]*irs.ImageInfo, error) {
if len(result.Listavailableproducttypesresponse.ProductTypes) < 1 {
return []*irs.ImageInfo{}, errors.New("Failed to Find Product Types!!")
}

// ### In order to remove the list of identical duplicates over and over again
tempID := ""
var vmImageInfoMap = make(map[string]*irs.ImageInfo) // Map to track unique VMSpec Info.
for _, productType := range result.Listavailableproducttypesresponse.ProductTypes {
// if (tempID == "") || (productType.Templateid != tempID) {
if productType.TemplateId != tempID {
imageInfo := mappingImageInfo(productType)
vmImageList = append(vmImageList, &imageInfo)

tempID = productType.TemplateId
// cblogger.Infof("\nImage Template Id : " + tempID)
// ### Caution!!) If the diskofferingid value exists, additional data disks are created.(=> So Not include to image list for 'Correct RootDiskSize')
if strings.EqualFold(productType.DiskOfferingId, "") {
imageInfo := mappingImageInfo(&productType)
if _, exists := vmImageInfoMap[imageInfo.Name]; exists {
// break
} else {
vmImageInfoMap[imageInfo.Name] = &imageInfo
}
}
}
cblogger.Info("# Supported Image Product Count : ", len(vmImageList))
return vmImageList, nil

// Convert the map to a list
var vmImageInfoList []*irs.ImageInfo
for _, imageInfo := range vmImageInfoMap {
vmImageInfoList = append(vmImageInfoList, imageInfo)
}
// cblogger.Info("# Supported Image Product Count : ", len(vmImageInfoList))
return vmImageInfoList, nil
}

func mappingImageInfo(ktServerProductType ktsdk.ProductTypes) irs.ImageInfo {
cblogger.Info("KT Cloud Cloud Driver: called mappingImageInfo()!")
func mappingImageInfo(productType *ktsdk.ProductTypes) irs.ImageInfo {
// cblogger.Info("KT Cloud Cloud Driver: called mappingImageInfo()!")
// cblogger.Info("\n\n### productType : ")
// spew.Dump(productType)
// cblogger.Info("\n")

var osPlatform irs.OSPlatform
if productType.TemplateDesc != "" {
if strings.Contains(productType.TemplateDesc, "WIN ") {
osPlatform = irs.Windows
} else {
osPlatform = irs.Linux_UNIX
}
} else {
osPlatform = irs.PlatformNA
}

var imageStatus irs.ImageStatus
if productType.ProductState != "" {
if strings.EqualFold(productType.ProductState, "available") {
imageStatus = irs.ImageAvailable
} else {
imageStatus = irs.ImageUnavailable
}
} else {
imageStatus = irs.ImageNA
}

diskSize := getImageDiskSize(productType.DiskOfferingDesc)

imageInfo := irs.ImageInfo{
// NOTE!! : TemplateId -> Image Name (TemplateId as Image Name)
IId: irs.IID{ktServerProductType.TemplateId, ktServerProductType.TemplateId},
GuestOS: ktServerProductType.TemplateDesc,
Status: ktServerProductType.ProductState,
IId: irs.IID{NameId: productType.TemplateId, SystemId: productType.TemplateId},
GuestOS: productType.TemplateDesc,
Status: productType.ProductState,

Name: productType.TemplateId,
OSArchitecture: irs.ArchitectureNA,
OSPlatform: osPlatform,
OSDistribution: productType.TemplateDesc,
OSDiskType: "NA",
OSDiskSizeInGB: diskSize,
ImageStatus: imageStatus,
}

// Since KT Cloud has different supported images for each zone, zone information is also presented.
keyValueList := []irs.KeyValue{
{Key: "Zone", Value: ktServerProductType.ZoneDesc},
{Key: "ProductType", Value: productType.Product},
{Key: "Zone", Value: productType.ZoneDesc},
}
imageInfo.KeyValueList = keyValueList
return imageInfo
Expand Down Expand Up @@ -199,3 +226,18 @@ func (imageHandler *KtCloudImageHandler) getKTProductType(imageIID irs.IID) (*kt
}
return nil, nil
}

func getImageDiskSize(sizeGB string) (string) {
// sizeGB Ex : "100GB"
re := regexp.MustCompile(`(\d+)GB`)
matches := re.FindStringSubmatch(sizeGB) // Find the match

var diskSize string
if len(matches) > 1 {
diskSize = matches[1] // Extract only the numeric part
}
if strings.EqualFold(diskSize, "") {
diskSize = "-1"
}
return diskSize // diskSize Ex : "100"
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ package resources
import (
"strings"
"fmt"
// "strconv"
// "github.com/davecgh/go-spew/spew"

ktvpcsdk "github.com/cloud-barista/ktcloudvpc-sdk-go"
Expand Down Expand Up @@ -50,8 +51,6 @@ func (imageHandler *KTVpcImageHandler) ListImage() ([]*irs.ImageInfo, error) {
return nil, newErr
}
loggingInfo(callLogInfo, start)

// # To Check!!
// cblogger.Info("### allPages : ")
// spew.Dump(allPages)

Expand All @@ -62,14 +61,12 @@ func (imageHandler *KTVpcImageHandler) ListImage() ([]*irs.ImageInfo, 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)
for _, image := range imageList {
imageInfo, err := imageHandler.mappingImageInfo(&image)
if err != nil {
newErr := fmt.Errorf("Failed to Map KT Cloud VPC Image Info. [%v]", err)
cblogger.Error(newErr.Error())
Expand Down Expand Up @@ -105,7 +102,7 @@ func (imageHandler *KTVpcImageHandler) GetImage(imageIID irs.IID) (irs.ImageInfo

//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)
imageInfo, err := imageHandler.mappingImageInfo(ktImage)
if err != nil {
cblogger.Error(err.Error())
loggingError(callLogInfo, err)
Expand Down Expand Up @@ -153,9 +150,11 @@ func (imageHandler *KTVpcImageHandler) DeleteImage(imageIID irs.IID) (bool, erro
return true, fmt.Errorf("Does not support DeleteImage() yet!!")
}

func (imageHandler *KTVpcImageHandler) mappingImageInfo(image images.Image) (*irs.ImageInfo, error) {
func (imageHandler *KTVpcImageHandler) mappingImageInfo(image *images.Image) (*irs.ImageInfo, error) {
cblogger.Info("KT Cloud VPC Driver: called mappingImageInfo()!")
// cblogger.Info("\n\n### image : ")
// spew.Dump(image)
// cblogger.Info("\n")

//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
Expand All @@ -171,20 +170,54 @@ func (imageHandler *KTVpcImageHandler) mappingImageInfo(image images.Image) (*ir
imgAvailability = "unavailable"
}

var osPlatform irs.OSPlatform
if image.Name != "" {
if strings.Contains(image.Name, "Windows") || strings.Contains(image.Name, "windows") || strings.Contains(image.Name, "win") {
osPlatform = irs.Windows
} else {
osPlatform = irs.Linux_UNIX
}
} else {
osPlatform = irs.PlatformNA
}

var imageStatus irs.ImageStatus
if image.Status != "" {
if strings.EqualFold(string(image.Status), "active") {
imageStatus = irs.ImageAvailable
} else {
imageStatus = irs.ImageUnavailable
}
} else {
imageStatus = irs.ImageNA
}

// # Note) image.SizeBytes is not Root Disk Size
// valueInGB := float64(image.SizeBytes) / (1024 * 1024 * 1024)
// diskSizeInGB := strconv.FormatFloat(valueInGB, 'f', 0, 64)

imageInfo := &irs.ImageInfo {
IId: irs.IID{
NameId: image.ID, // Caution!!
SystemId: image.ID,
},
GuestOS: image.Name, // Caution!!
Status: imgAvailability,

Name: image.ID,
OSArchitecture: "NA",
OSPlatform: osPlatform,
OSDistribution: image.Name,
OSDiskType: "NA",
OSDiskSizeInGB: "NA",
ImageStatus: imageStatus,
}

keyValueList := []irs.KeyValue{
{Key: "Zone", Value: imageHandler.RegionInfo.Zone},
{Key: "DiskFormat:", Value: string(image.DiskFormat)},
{Key: "Zone", Value: imageHandler.RegionInfo.Zone},
{Key: "DiskFormat:", Value: string(image.DiskFormat)},
{Key: "ContainerFormat:", Value: string(image.ContainerFormat)},
{Key: "Visibility:", Value: string(image.Visibility)},
{Key: "Visibility:", Value: string(image.Visibility)},

}
imageInfo.KeyValueList = keyValueList
Expand Down

0 comments on commit c4c653b

Please sign in to comment.