Merge pull request #14747 from ioito/hotfix/qx-incloudsphere-image

fix(region): incloudsphere image
This commit is contained in:
Zexi Li
2022-08-02 09:43:58 +08:00
committed by GitHub
8 changed files with 235 additions and 100 deletions
+52 -7
View File
@@ -202,6 +202,32 @@ func (self *SHost) GetVersion() string {
}
func (self *SHost) CreateVM(opts *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) {
storages, err := self.zone.region.GetImageStorages(self.zone.Id)
if err != nil {
return nil, errors.Wrapf(err, "GetImageStorages")
}
var image *SImage = nil
storageCache := &SStoragecache{zone: self.zone}
for i := range storages {
images, err := self.zone.region.GetImageList(storages[i].Id)
if err != nil {
return nil, err
}
for j := range images {
images[j].cache = storageCache
if images[j].GetGlobalId() == opts.ExternalImageId {
image = &images[j]
break
}
}
}
if image == nil {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, opts.ExternalImageId)
}
format := "RAW"
if strings.HasSuffix(opts.ExternalImageId, "qcow2") {
format = "QCOW2"
}
disks := []Disks{}
disks = append(disks, Disks{
BusModel: "IDE",
@@ -210,9 +236,17 @@ func (self *SHost) CreateVM(opts *cloudprovider.SManagedVMCreateConfig) (cloudpr
Volume: Volume{
Bootable: true,
DataStoreId: opts.SysDisk.StorageExternalId,
Format: "RAW",
Size: float64(opts.SysDisk.SizeGB),
Format: format,
Size: float64(image.GetSizeByte() / 1024 / 1024 / 1024),
VolumePolicy: "THIN",
VvSourceDto: VvSourceDto{
FilePath: fmt.Sprintf("%s/%s", image.Path, image.Name),
SourceType: "IMAGE_STORAGE",
FtpServerHost: FtpServerHost{
Id: image.ServerID,
Ip: image.FTPServer,
},
},
},
})
for i := range opts.DataDisks {
@@ -229,9 +263,20 @@ func (self *SHost) CreateVM(opts *cloudprovider.SManagedVMCreateConfig) (cloudpr
},
})
}
imageInfo := strings.Split(opts.ExternalImageId, "/")
if len(imageInfo) != 3 {
return nil, fmt.Errorf("invalid image id %s", opts.ExternalImageId)
imageTree, err := self.zone.region.GetImageTrees()
if err != nil {
return nil, errors.Wrapf(err, "GetImageTrees")
}
guestLabel, guestosType := "CentOS 7.9(2009) 64bit", "CentOS"
for i := range imageTree {
images := imageTree[i].ToList()
for j := range images {
if images[j].IsEquals(image.Name) {
guestLabel = images[j].Model
guestosType = images[j].OsDist
break
}
}
}
body := map[string]interface{}{
"boot": "HD",
@@ -254,8 +299,8 @@ func (self *SHost) CreateVM(opts *cloudprovider.SManagedVMCreateConfig) (cloudpr
"enableReplicate": false,
"graphicsCardMemory": 16384,
"graphicsCardModel": "VGA",
"guestosLabel": imageInfo[2],
"guestosType": imageInfo[1],
"guestosLabel": guestLabel,
"guestosType": guestosType,
"hostBinded": false,
"hostId": self.Id,
"maxCpuNum": 128,
+42 -28
View File
@@ -30,19 +30,20 @@ type SImage struct {
multicloud.InCloudSphereTags
cache *SStoragecache
OsType string
OsDist string
Model string
SocketLimit int
SupportCpuHotPlug bool
SupportMemHotPlug bool
SupportDiskHotPlug bool
SupportUefiBootMode bool
}
func (self *SRegion) GetImages() ([]SImage, error) {
ret := []SImage{}
return ret, self.list("/vms/guestos", nil, &ret)
Name string `json:"name"`
FileSize int64 `json:"fileSize"`
RealSize int64 `json:"realSize"`
SourceType string `json:"sourceType"`
Format string `json:"format"`
FileType string `json:"fileType"`
Size int64 `json:"size"`
Date string `json:"date"`
Path string `json:"path"`
FTPServer string `json:"ftpServer"`
DataStoreID string `json:"dataStoreId"`
DataStoreName string `json:"dataStoreName"`
ServerID string `json:"serverId"`
Md5 string `json:"md5"`
}
func (self *SImage) GetMinRamSizeMb() int {
@@ -50,23 +51,19 @@ func (self *SImage) GetMinRamSizeMb() int {
}
func (self *SImage) GetId() string {
return self.Model
return fmt.Sprintf("%s/%s/%s", self.cache.zone.Id, self.Path, self.Name)
}
func (self *SImage) GetName() string {
return self.Model
}
func (self *SImage) IsEmulated() bool {
return true
return self.Name
}
func (self *SImage) Delete(ctx context.Context) error {
return cloudprovider.ErrNotSupported
return cloudprovider.ErrNotImplemented
}
func (self *SImage) GetGlobalId() string {
return fmt.Sprintf("%s/%s/%s", self.OsType, self.OsDist, self.Model)
return self.GetId()
}
func (self *SImage) GetIStoragecache() cloudprovider.ICloudStoragecache {
@@ -86,11 +83,11 @@ func (self *SImage) GetImageType() cloudprovider.TImageType {
}
func (self *SImage) GetSizeByte() int64 {
return 20 * 1024 * 1024 * 1024
return self.FileSize
}
func (self *SImage) GetOsType() cloudprovider.TOsType {
if strings.Contains(strings.ToLower(self.OsType), "windows") {
if strings.Contains(strings.ToLower(self.Name), "windows") {
return cloudprovider.OsTypeWindows
}
return cloudprovider.OsTypeLinux
@@ -101,7 +98,7 @@ func (self *SImage) GetOsDist() string {
}
func (self *SImage) getNormalizedImageInfo() imagetools.ImageInfo {
return imagetools.NormalizeImageInfo(self.Model, "", "", "", "")
return imagetools.NormalizeImageInfo(self.Name, "", "", "", "")
}
func (self *SImage) GetOsVersion() string {
@@ -120,13 +117,30 @@ func (self *SImage) GetMinOsDiskSizeGb() int {
}
func (self *SImage) GetImageFormat() string {
return "vhd"
return self.Format
}
func (self *SImage) UEFI() bool {
return false
}
type SImageInfo struct {
OsType string
OsDist string
Model string
SocketLimit int
SupportCpuHotPlug bool
SupportMemHotPlug bool
SupportDiskHotPlug bool
SupportUefiBootMode bool
}
func (self *SImageInfo) IsEquals(name string) bool {
model := imagetools.NormalizeImageInfo(self.Model, "", "", "", "")
image := imagetools.NormalizeImageInfo(name, "", "", "", "")
return model.OsDistro == image.OsDistro && model.OsVersion == image.OsVersion
}
type SImageTree struct {
Id string
Name string
@@ -136,13 +150,13 @@ type SImageTree struct {
Children []struct {
Id string
Name string
Object SImage
Object SImageInfo
}
}
}
func (self *SImageTree) ToList() []SImage {
ret := []SImage{}
func (self *SImageTree) ToList() []SImageInfo {
ret := []SImageInfo{}
for i := range self.Children {
for j := range self.Children[i].Children {
self.Children[i].Children[j].Object.OsType = self.Name
+50 -38
View File
@@ -46,45 +46,57 @@ type Floppy struct {
VfdType string `json:"vfdType"`
}
type FtpServerHost struct {
Id string `json:"id"`
Ip string `json:"ip"`
}
type VvSourceDto struct {
SourceType string `json:"sourceType"`
FilePath string `json:"filePath"`
Name string `json:"name"`
FtpServerHost FtpServerHost `json:"ftpServerHost"`
}
type Volume struct {
Id string `json:"id"`
UUID string `json:"uuid"`
Size float64 `json:"size"`
RealSize float64 `json:"realSize"`
Name string `json:"name"`
FileName string `json:"fileName"`
Offset int `json:"offset"`
Shared bool `json:"shared"`
DeleteModel string `json:"deleteModel"`
VolumePolicy string `json:"volumePolicy"`
Format string `json:"format"`
BlockDeviceId string `json:"blockDeviceId"`
DiskType string `json:"diskType"`
DataStoreId string `json:"dataStoreId"`
DataStoreName string `json:"dataStoreName"`
DataStoreSize float64 `json:"dataStoreSize"`
FreeStorage float64 `json:"freeStorage"`
DataStoreType string `json:"dataStoreType"`
DataStoreReplicate int `json:"dataStoreReplicate"`
VMName string `json:"vmName"`
VMStatus string `json:"vmStatus"`
Type string `json:"type"`
Description string `json:"description"`
Bootable bool `json:"bootable"`
VolumeStatus string `json:"volumeStatus"`
MountedHostIds string `json:"mountedHostIds"`
Md5 string `json:"md5"`
DataSize int `json:"dataSize"`
OpenStackId string `json:"openStackId"`
VvSourceDto string `json:"vvSourceDto"`
FormatDisk bool `json:"formatDisk"`
ToBeConverted bool `json:"toBeConverted"`
RelatedVms string `json:"relatedVms"`
XactiveDataStoreId string `json:"xactiveDataStoreId"`
ClusterSize int `json:"clusterSize"`
ScsiId string `json:"scsiId"`
SecondaryUUID string `json:"secondaryUuid"`
SecondaryVolumes []struct{} `json:"secondaryVolumes"`
Id string `json:"id"`
UUID string `json:"uuid"`
Size float64 `json:"size"`
RealSize float64 `json:"realSize"`
Name string `json:"name"`
FileName string `json:"fileName"`
Offset int `json:"offset"`
Shared bool `json:"shared"`
DeleteModel string `json:"deleteModel"`
VolumePolicy string `json:"volumePolicy"`
Format string `json:"format"`
BlockDeviceId string `json:"blockDeviceId"`
DiskType string `json:"diskType"`
DataStoreId string `json:"dataStoreId"`
DataStoreName string `json:"dataStoreName"`
DataStoreSize float64 `json:"dataStoreSize"`
FreeStorage float64 `json:"freeStorage"`
DataStoreType string `json:"dataStoreType"`
DataStoreReplicate int `json:"dataStoreReplicate"`
VMName string `json:"vmName"`
VMStatus string `json:"vmStatus"`
Type string `json:"type"`
Description string `json:"description"`
Bootable bool `json:"bootable"`
VolumeStatus string `json:"volumeStatus"`
MountedHostIds string `json:"mountedHostIds"`
Md5 string `json:"md5"`
DataSize int `json:"dataSize"`
OpenStackId string `json:"openStackId"`
VvSourceDto VvSourceDto `json:"vvSourceDto"`
FormatDisk bool `json:"formatDisk"`
ToBeConverted bool `json:"toBeConverted"`
RelatedVms string `json:"relatedVms"`
XactiveDataStoreId string `json:"xactiveDataStoreId"`
ClusterSize int `json:"clusterSize"`
ScsiId string `json:"scsiId"`
SecondaryUUID string `json:"secondaryUuid"`
SecondaryVolumes []struct{} `json:"secondaryVolumes"`
}
type Disks struct {
+18 -9
View File
@@ -161,19 +161,28 @@ func (self *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
return host, nil
}
func (self *SRegion) getStorageCache() *SStoragecache {
return &SStoragecache{region: self}
}
func (self *SRegion) GetIStoragecaches() ([]cloudprovider.ICloudStoragecache, error) {
cache := self.getStorageCache()
return []cloudprovider.ICloudStoragecache{cache}, nil
zones, err := self.GetZones()
if err != nil {
return nil, err
}
ret := []cloudprovider.ICloudStoragecache{}
for i := range zones {
cache := &SStoragecache{zone: &zones[i]}
ret = append(ret, cache)
}
return ret, nil
}
func (self *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) {
cache := self.getStorageCache()
if cache.GetGlobalId() == id {
return cache, nil
caches, err := self.GetIStoragecaches()
if err != nil {
return nil, err
}
for i := range caches {
if caches[i].GetGlobalId() == id {
return caches[i], nil
}
}
return nil, cloudprovider.ErrNotFound
}
+29 -2
View File
@@ -20,9 +20,9 @@ import (
)
func init() {
type ImageListOptions struct {
type ImageTreeOptions struct {
}
shellutils.R(&ImageListOptions{}, "image-list", "list images", func(cli *incloudsphere.SRegion, args *ImageListOptions) error {
shellutils.R(&ImageTreeOptions{}, "image-tree", "list images", func(cli *incloudsphere.SRegion, args *ImageTreeOptions) error {
trees, err := cli.GetImageTrees()
if err != nil {
return err
@@ -32,4 +32,31 @@ func init() {
}
return nil
})
type ImageStorageListOptions struct {
DS_ID string
}
shellutils.R(&ImageStorageListOptions{}, "image-storage-list", "list image storages", func(cli *incloudsphere.SRegion, args *ImageStorageListOptions) error {
storages, err := cli.GetImageStorages(args.DS_ID)
if err != nil {
return err
}
printList(storages, 0, 0, 0, []string{})
return nil
})
type ImageListOptions struct {
STORAGE_ID string
}
shellutils.R(&ImageListOptions{}, "image-list", "list images", func(cli *incloudsphere.SRegion, args *ImageListOptions) error {
images, err := cli.GetImageList(args.STORAGE_ID)
if err != nil {
return err
}
printList(images, 0, 0, 0, []string{})
return nil
})
}
+2
View File
@@ -22,6 +22,7 @@ import (
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
@@ -121,6 +122,7 @@ func (self SphereError) Error() string {
func (ce *SphereError) ParseErrorFromJsonResponse(statusCode int, body jsonutils.JSONObject) error {
if body != nil {
body.Unmarshal(ce)
log.Errorf("error: %v", body.PrettyString())
}
if ce.Code == 0 && statusCode > 0 {
ce.Code = statusCode
+2 -1
View File
@@ -152,7 +152,8 @@ func (self *SStorage) GetIDiskById(id string) (cloudprovider.ICloudDisk, error)
}
func (self *SStorage) GetIStoragecache() cloudprovider.ICloudStoragecache {
return self.zone.region.getStorageCache()
cache := &SStoragecache{zone: self.zone}
return cache
}
func (self *SStorage) GetMediumType() string {
+40 -15
View File
@@ -16,8 +16,11 @@ package incloudsphere
import (
"context"
"fmt"
"net/url"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/mcclient"
@@ -27,19 +30,20 @@ import (
type SStoragecache struct {
multicloud.SResourceBase
multicloud.InCloudSphereTags
region *SRegion
zone *SZone
}
func (self *SStoragecache) GetGlobalId() string {
return self.region.GetGlobalId()
return self.zone.GetGlobalId()
}
func (self *SStoragecache) GetId() string {
return self.region.GetId()
return self.zone.GetId()
}
func (self *SStoragecache) GetName() string {
return self.region.GetName()
return self.zone.GetName()
}
func (self *SStoragecache) GetStatus() string {
@@ -47,20 +51,22 @@ func (self *SStoragecache) GetStatus() string {
}
func (self *SStoragecache) GetICloudImages() ([]cloudprovider.ICloudImage, error) {
trees, err := self.region.GetImageTrees()
if err != nil {
return nil, err
}
ret := []cloudprovider.ICloudImage{}
gMap := map[string]bool{}
for i := range trees {
images := trees[i].ToList()
iss, err := self.zone.region.GetImageStorages(self.zone.Id)
if err != nil {
return nil, errors.Wrapf(err, "GetImageStorages")
}
for i := range iss {
images, err := self.zone.region.GetImageList(iss[i].Id)
if err != nil {
return nil, err
}
for j := range images {
if _, ok := gMap[images[j].GetGlobalId()]; !ok {
images[j].cache = self
ret = append(ret, &images[j])
gMap[images[j].GetGlobalId()] = true
if images[i].GetImageFormat() == "iso" {
continue
}
images[j].cache = self
ret = append(ret, &images[j])
}
}
return ret, nil
@@ -98,3 +104,22 @@ func (self *SStoragecache) DownloadImage(userCred mcclient.TokenCredential, imag
func (self *SStoragecache) UploadImage(ctx context.Context, userCred mcclient.TokenCredential, image *cloudprovider.SImageCreateOption, callback func(float32)) (string, error) {
return "", cloudprovider.ErrNotSupported
}
type SImageStorage struct {
Id string
Name string
}
func (self *SRegion) GetImageStorages(dsId string) ([]SImageStorage, error) {
params := url.Values{}
params.Set("type", "imagestorage")
res := fmt.Sprintf("/datacenters/%s/storages", dsId)
ret := []SImageStorage{}
return ret, self.get(res, params, &ret)
}
func (self *SRegion) GetImageList(storageId string) ([]SImage, error) {
res := fmt.Sprintf("/storages/%s/files", storageId)
ret := []SImage{}
return ret, self.list(res, url.Values{}, &ret)
}