proxmox.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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 SProxmoxHostDriver struct {
  35. SManagedVirtualizationHostDriver
  36. }
  37. func init() {
  38. driver := SProxmoxHostDriver{}
  39. models.RegisterHostDriver(&driver)
  40. }
  41. func (self *SProxmoxHostDriver) GetHostType() string {
  42. return api.HOST_TYPE_PROXMOX
  43. }
  44. func (self *SProxmoxHostDriver) GetHypervisor() string {
  45. return api.HYPERVISOR_PROXMOX
  46. }
  47. func (self *SProxmoxHostDriver) GetProvider() string {
  48. return api.CLOUD_PROVIDER_PROXMOX
  49. }
  50. func (self *SProxmoxHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb int) error {
  51. return nil
  52. }
  53. func (driver *SProxmoxHostDriver) GetStoragecacheQuota(host *models.SHost) int {
  54. return -1
  55. }
  56. func (self *SProxmoxHostDriver) CheckAndSetCacheImage(ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, storageCache *models.SStoragecache, task taskman.ITask) error {
  57. input := api.CacheImageInput{}
  58. task.GetParams().Unmarshal(&input)
  59. opts := &cloudprovider.SImageCreateOption{}
  60. task.GetParams().Unmarshal(&opts)
  61. if len(input.ImageId) == 0 {
  62. return fmt.Errorf("no image_id params")
  63. }
  64. if input.Format != "iso" {
  65. return fmt.Errorf("invalid image format %s", input.Format)
  66. }
  67. imageSize := int64(0)
  68. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  69. lockman.LockRawObject(ctx, models.CachedimageManager.Keyword(), fmt.Sprintf("%s-%s", storageCache.Id, input.ImageId))
  70. defer lockman.ReleaseRawObject(ctx, models.CachedimageManager.Keyword(), fmt.Sprintf("%s-%s", storageCache.Id, input.ImageId))
  71. log.Debugf("XXX Hold lockman key %p cachedimages %s-%s", ctx, storageCache.Id, input.ImageId)
  72. image, err := models.CachedimageManager.GetCachedimageById(ctx, userCred, input.ImageId, false)
  73. if err != nil {
  74. return nil, errors.Wrapf(err, "CachedimageManager.FetchById(%s)", input.ImageId)
  75. }
  76. if len(image.ExternalId) > 0 {
  77. storages, err := image.GetStorages()
  78. if err != nil {
  79. return nil, err
  80. }
  81. find := false
  82. for i := range storages {
  83. iStorage, _ := storages[i].GetIStorage(ctx)
  84. if gotypes.IsNil(iStorage) {
  85. continue
  86. }
  87. iCache := iStorage.GetIStoragecache()
  88. if gotypes.IsNil(iCache) {
  89. continue
  90. }
  91. iImage, err := iCache.GetIImageById(image.ExternalId)
  92. if err == nil {
  93. imageSize = iImage.GetSizeByte()
  94. find = true
  95. break
  96. }
  97. }
  98. if !find {
  99. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", image.ExternalId)
  100. }
  101. opts.ExternalId = image.ExternalId
  102. } else {
  103. var guest *models.SGuest
  104. if len(input.ServerId) > 0 {
  105. server, _ := models.GuestManager.FetchById(input.ServerId)
  106. if server != nil {
  107. guest = server.(*models.SGuest)
  108. }
  109. }
  110. callback := func(progress float32) {
  111. guestInfo := ""
  112. if guest != nil {
  113. guest.SetProgress(progress)
  114. guestInfo = fmt.Sprintf(" for server %s ", guest.Name)
  115. }
  116. log.Infof("Upload image %s from storagecache %s%s status: %.2f%%", opts.ImageName, storageCache.Name, guestInfo, progress)
  117. }
  118. storages, err := host.GetStorages()
  119. if err != nil {
  120. return nil, errors.Wrapf(err, "GetStorages")
  121. }
  122. opts.ExternalId, err = func() (string, error) {
  123. s := auth.GetAdminSession(ctx, options.Options.Region)
  124. info, err := modules.Images.Get(s, input.ImageId, nil)
  125. if err != nil {
  126. return "", errors.Wrapf(err, "Images.Get(%s)", input.ImageId)
  127. }
  128. opts.Description, _ = info.GetString("description")
  129. opts.Checksum, _ = info.GetString("checksum")
  130. minDiskMb, _ := info.Int("min_disk")
  131. opts.MinDiskMb = int(minDiskMb)
  132. minRamMb, _ := info.Int("min_ram")
  133. opts.MinRamMb = int(minRamMb)
  134. opts.TmpPath = options.Options.TempPath
  135. opts.GetReader = func(imageId, format string) (io.Reader, int64, error) {
  136. _, reader, sizeByte, err := modules.Images.Download(s, imageId, format, false)
  137. return reader, sizeByte, err
  138. }
  139. for i := range storages {
  140. cache := storages[i].GetStoragecache()
  141. iCache, _ := cache.GetIStorageCache(ctx)
  142. if gotypes.IsNil(iCache) {
  143. continue
  144. }
  145. ret, err := iCache.UploadImage(ctx, opts, callback)
  146. if err != nil {
  147. if errors.Cause(err) == cloudprovider.ErrNotSupported {
  148. continue
  149. }
  150. return "", errors.Wrapf(err, "UploadImage")
  151. }
  152. region, err := host.GetRegion()
  153. if err != nil {
  154. return ret, nil
  155. }
  156. obj, err := models.CachedimageManager.FetchById(input.ImageId)
  157. if err != nil {
  158. return ret, errors.Wrapf(err, "CachedimageManager.FetchById")
  159. }
  160. cachedImage := obj.(*models.SCachedimage)
  161. db.Update(cachedImage, func() error {
  162. cachedImage.ExternalId = ret
  163. return nil
  164. })
  165. cache.SyncCloudImages(ctx, userCred, iCache, region, true)
  166. return ret, nil
  167. }
  168. return "", fmt.Errorf("no valid storagecache for upload image")
  169. }()
  170. if err != nil {
  171. return nil, err
  172. }
  173. log.Infof("upload image %s id: %s", opts.ImageName, image.ExternalId)
  174. }
  175. ret := jsonutils.NewDict()
  176. ret.Add(jsonutils.NewString(opts.ExternalId), "image_id")
  177. ret.Add(jsonutils.NewInt(imageSize), "size")
  178. return ret, nil
  179. })
  180. return nil
  181. }