mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-10-31 02:38:07 +08:00
Merge pull request #14747 from ioito/hotfix/qx-incloudsphere-image
fix(region): incloudsphere image
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user