| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package hostdrivers
- import (
- "context"
- "fmt"
- "io"
- "yunion.io/x/cloudmux/pkg/cloudprovider"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/gotypes"
- api "yunion.io/x/onecloud/pkg/apis/compute"
- "yunion.io/x/onecloud/pkg/cloudcommon/db"
- "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
- "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
- "yunion.io/x/onecloud/pkg/compute/models"
- "yunion.io/x/onecloud/pkg/compute/options"
- "yunion.io/x/onecloud/pkg/mcclient"
- "yunion.io/x/onecloud/pkg/mcclient/auth"
- modules "yunion.io/x/onecloud/pkg/mcclient/modules/image"
- )
- type SUisHostDriver struct {
- SManagedVirtualizationHostDriver
- }
- func init() {
- driver := SUisHostDriver{}
- models.RegisterHostDriver(&driver)
- }
- func (self *SUisHostDriver) GetHostType() string {
- return api.HOST_TYPE_UIS
- }
- func (self *SUisHostDriver) GetHypervisor() string {
- return api.HYPERVISOR_UIS
- }
- func (self *SUisHostDriver) GetProvider() string {
- return api.CLOUD_PROVIDER_UIS
- }
- func (self *SUisHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb int) error {
- return nil
- }
- func (self *SUisHostDriver) CheckAndSetCacheImage(ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, storageCache *models.SStoragecache, task taskman.ITask) error {
- input := api.CacheImageInput{}
- task.GetParams().Unmarshal(&input)
- opts := &cloudprovider.SImageCreateOption{}
- task.GetParams().Unmarshal(&opts)
- if len(input.ImageId) == 0 {
- return fmt.Errorf("no image_id params")
- }
- if input.Format != "iso" {
- return fmt.Errorf("invalid image format %s", input.Format)
- }
- imageSize := int64(0)
- taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
- lockman.LockRawObject(ctx, models.CachedimageManager.Keyword(), fmt.Sprintf("%s-%s", storageCache.Id, input.ImageId))
- defer lockman.ReleaseRawObject(ctx, models.CachedimageManager.Keyword(), fmt.Sprintf("%s-%s", storageCache.Id, input.ImageId))
- log.Debugf("XXX Hold lockman key %p cachedimages %s-%s", ctx, storageCache.Id, input.ImageId)
- image, err := models.CachedimageManager.GetCachedimageById(ctx, userCred, input.ImageId, false)
- if err != nil {
- return nil, errors.Wrapf(err, "CachedimageManager.FetchById(%s)", input.ImageId)
- }
- if len(image.ExternalId) > 0 {
- storages, err := image.GetStorages()
- if err != nil {
- return nil, err
- }
- find := false
- for i := range storages {
- iStorage, _ := storages[i].GetIStorage(ctx)
- if gotypes.IsNil(iStorage) {
- continue
- }
- iCache := iStorage.GetIStoragecache()
- if gotypes.IsNil(iCache) {
- continue
- }
- iImage, err := iCache.GetIImageById(image.ExternalId)
- if err == nil {
- imageSize = iImage.GetSizeByte()
- find = true
- break
- }
- }
- if !find {
- return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", image.ExternalId)
- }
- opts.ExternalId = image.ExternalId
- } else {
- var guest *models.SGuest
- if len(input.ServerId) > 0 {
- server, _ := models.GuestManager.FetchById(input.ServerId)
- if server != nil {
- guest = server.(*models.SGuest)
- }
- }
- callback := func(progress float32) {
- guestInfo := ""
- if guest != nil {
- guest.SetProgress(progress)
- guestInfo = fmt.Sprintf(" for server %s ", guest.Name)
- }
- log.Infof("Upload image %s from storagecache %s%s status: %.2f%%", opts.ImageName, storageCache.Name, guestInfo, progress)
- }
- storages, err := host.GetStorages()
- if err != nil {
- return nil, errors.Wrapf(err, "GetStorages")
- }
- opts.ExternalId, err = func() (string, error) {
- s := auth.GetAdminSession(ctx, options.Options.Region)
- info, err := modules.Images.Get(s, input.ImageId, nil)
- if err != nil {
- return "", errors.Wrapf(err, "Images.Get(%s)", input.ImageId)
- }
- opts.Description, _ = info.GetString("description")
- opts.Checksum, _ = info.GetString("checksum")
- minDiskMb, _ := info.Int("min_disk")
- opts.MinDiskMb = int(minDiskMb)
- minRamMb, _ := info.Int("min_ram")
- opts.MinRamMb = int(minRamMb)
- opts.TmpPath = options.Options.TempPath
- opts.GetReader = func(imageId, format string) (io.Reader, int64, error) {
- _, reader, sizeByte, err := modules.Images.Download(s, imageId, format, false)
- return reader, sizeByte, err
- }
- for i := range storages {
- cache := storages[i].GetStoragecache()
- iCache, _ := cache.GetIStorageCache(ctx)
- if gotypes.IsNil(iCache) {
- continue
- }
- ret, err := iCache.UploadImage(ctx, opts, callback)
- if err != nil {
- if errors.Cause(err) == cloudprovider.ErrNotSupported {
- continue
- }
- return "", errors.Wrapf(err, "UploadImage")
- }
- region, err := host.GetRegion()
- if err != nil {
- return ret, nil
- }
- obj, err := models.CachedimageManager.FetchById(input.ImageId)
- if err != nil {
- return ret, errors.Wrapf(err, "CachedimageManager.FetchById")
- }
- cachedImage := obj.(*models.SCachedimage)
- db.Update(cachedImage, func() error {
- cachedImage.ExternalId = ret
- return nil
- })
- cache.SyncCloudImages(ctx, userCred, iCache, region, true)
- return ret, nil
- }
- return "", fmt.Errorf("no valid storagecache for upload image")
- }()
- if err != nil {
- return nil, err
- }
- log.Infof("upload image %s id: %s", opts.ImageName, image.ExternalId)
- }
- ret := jsonutils.NewDict()
- ret.Add(jsonutils.NewString(opts.ExternalId), "image_id")
- ret.Add(jsonutils.NewInt(imageSize), "size")
- return ret, nil
- })
- return nil
- }
|