uis.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package hostdrivers
  15. import (
  16. "context"
  17. "fmt"
  18. "io"
  19. "yunion.io/x/cloudmux/pkg/cloudprovider"
  20. "yunion.io/x/jsonutils"
  21. "yunion.io/x/log"
  22. "yunion.io/x/pkg/errors"
  23. "yunion.io/x/pkg/gotypes"
  24. api "yunion.io/x/onecloud/pkg/apis/compute"
  25. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  26. "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
  27. "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
  28. "yunion.io/x/onecloud/pkg/compute/models"
  29. "yunion.io/x/onecloud/pkg/compute/options"
  30. "yunion.io/x/onecloud/pkg/mcclient"
  31. "yunion.io/x/onecloud/pkg/mcclient/auth"
  32. modules "yunion.io/x/onecloud/pkg/mcclient/modules/image"
  33. )
  34. type SUisHostDriver struct {
  35. SManagedVirtualizationHostDriver
  36. }
  37. func init() {
  38. driver := SUisHostDriver{}
  39. models.RegisterHostDriver(&driver)
  40. }
  41. func (self *SUisHostDriver) GetHostType() string {
  42. return api.HOST_TYPE_UIS
  43. }
  44. func (self *SUisHostDriver) GetHypervisor() string {
  45. return api.HYPERVISOR_UIS
  46. }
  47. func (self *SUisHostDriver) GetProvider() string {
  48. return api.CLOUD_PROVIDER_UIS
  49. }
  50. func (self *SUisHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb int) error {
  51. return nil
  52. }
  53. func (self *SUisHostDriver) CheckAndSetCacheImage(ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, storageCache *models.SStoragecache, task taskman.ITask) error {
  54. input := api.CacheImageInput{}
  55. task.GetParams().Unmarshal(&input)
  56. opts := &cloudprovider.SImageCreateOption{}
  57. task.GetParams().Unmarshal(&opts)
  58. if len(input.ImageId) == 0 {
  59. return fmt.Errorf("no image_id params")
  60. }
  61. if input.Format != "iso" {
  62. return fmt.Errorf("invalid image format %s", input.Format)
  63. }
  64. imageSize := int64(0)
  65. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  66. lockman.LockRawObject(ctx, models.CachedimageManager.Keyword(), fmt.Sprintf("%s-%s", storageCache.Id, input.ImageId))
  67. defer lockman.ReleaseRawObject(ctx, models.CachedimageManager.Keyword(), fmt.Sprintf("%s-%s", storageCache.Id, input.ImageId))
  68. log.Debugf("XXX Hold lockman key %p cachedimages %s-%s", ctx, storageCache.Id, input.ImageId)
  69. image, err := models.CachedimageManager.GetCachedimageById(ctx, userCred, input.ImageId, false)
  70. if err != nil {
  71. return nil, errors.Wrapf(err, "CachedimageManager.FetchById(%s)", input.ImageId)
  72. }
  73. if len(image.ExternalId) > 0 {
  74. storages, err := image.GetStorages()
  75. if err != nil {
  76. return nil, err
  77. }
  78. find := false
  79. for i := range storages {
  80. iStorage, _ := storages[i].GetIStorage(ctx)
  81. if gotypes.IsNil(iStorage) {
  82. continue
  83. }
  84. iCache := iStorage.GetIStoragecache()
  85. if gotypes.IsNil(iCache) {
  86. continue
  87. }
  88. iImage, err := iCache.GetIImageById(image.ExternalId)
  89. if err == nil {
  90. imageSize = iImage.GetSizeByte()
  91. find = true
  92. break
  93. }
  94. }
  95. if !find {
  96. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", image.ExternalId)
  97. }
  98. opts.ExternalId = image.ExternalId
  99. } else {
  100. var guest *models.SGuest
  101. if len(input.ServerId) > 0 {
  102. server, _ := models.GuestManager.FetchById(input.ServerId)
  103. if server != nil {
  104. guest = server.(*models.SGuest)
  105. }
  106. }
  107. callback := func(progress float32) {
  108. guestInfo := ""
  109. if guest != nil {
  110. guest.SetProgress(progress)
  111. guestInfo = fmt.Sprintf(" for server %s ", guest.Name)
  112. }
  113. log.Infof("Upload image %s from storagecache %s%s status: %.2f%%", opts.ImageName, storageCache.Name, guestInfo, progress)
  114. }
  115. storages, err := host.GetStorages()
  116. if err != nil {
  117. return nil, errors.Wrapf(err, "GetStorages")
  118. }
  119. opts.ExternalId, err = func() (string, error) {
  120. s := auth.GetAdminSession(ctx, options.Options.Region)
  121. info, err := modules.Images.Get(s, input.ImageId, nil)
  122. if err != nil {
  123. return "", errors.Wrapf(err, "Images.Get(%s)", input.ImageId)
  124. }
  125. opts.Description, _ = info.GetString("description")
  126. opts.Checksum, _ = info.GetString("checksum")
  127. minDiskMb, _ := info.Int("min_disk")
  128. opts.MinDiskMb = int(minDiskMb)
  129. minRamMb, _ := info.Int("min_ram")
  130. opts.MinRamMb = int(minRamMb)
  131. opts.TmpPath = options.Options.TempPath
  132. opts.GetReader = func(imageId, format string) (io.Reader, int64, error) {
  133. _, reader, sizeByte, err := modules.Images.Download(s, imageId, format, false)
  134. return reader, sizeByte, err
  135. }
  136. for i := range storages {
  137. cache := storages[i].GetStoragecache()
  138. iCache, _ := cache.GetIStorageCache(ctx)
  139. if gotypes.IsNil(iCache) {
  140. continue
  141. }
  142. ret, err := iCache.UploadImage(ctx, opts, callback)
  143. if err != nil {
  144. if errors.Cause(err) == cloudprovider.ErrNotSupported {
  145. continue
  146. }
  147. return "", errors.Wrapf(err, "UploadImage")
  148. }
  149. region, err := host.GetRegion()
  150. if err != nil {
  151. return ret, nil
  152. }
  153. obj, err := models.CachedimageManager.FetchById(input.ImageId)
  154. if err != nil {
  155. return ret, errors.Wrapf(err, "CachedimageManager.FetchById")
  156. }
  157. cachedImage := obj.(*models.SCachedimage)
  158. db.Update(cachedImage, func() error {
  159. cachedImage.ExternalId = ret
  160. return nil
  161. })
  162. cache.SyncCloudImages(ctx, userCred, iCache, region, true)
  163. return ret, nil
  164. }
  165. return "", fmt.Errorf("no valid storagecache for upload image")
  166. }()
  167. if err != nil {
  168. return nil, err
  169. }
  170. log.Infof("upload image %s id: %s", opts.ImageName, image.ExternalId)
  171. }
  172. ret := jsonutils.NewDict()
  173. ret.Add(jsonutils.NewString(opts.ExternalId), "image_id")
  174. ret.Add(jsonutils.NewInt(imageSize), "size")
  175. return ret, nil
  176. })
  177. return nil
  178. }