disk.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. // Copyright 2023 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 volcengine
  15. import (
  16. "context"
  17. "fmt"
  18. "time"
  19. "yunion.io/x/jsonutils"
  20. "yunion.io/x/pkg/errors"
  21. "yunion.io/x/pkg/utils"
  22. billing_api "yunion.io/x/cloudmux/pkg/apis/billing"
  23. api "yunion.io/x/cloudmux/pkg/apis/compute"
  24. "yunion.io/x/cloudmux/pkg/cloudprovider"
  25. "yunion.io/x/cloudmux/pkg/multicloud"
  26. )
  27. type SDisk struct {
  28. storage *SStorage
  29. multicloud.SDisk
  30. VolcEngineTags
  31. ZoneId string
  32. VolumeId string
  33. VolumeName string
  34. VolumeType string
  35. Description string
  36. InstanceId string
  37. ImageId string
  38. Size int
  39. Status string
  40. Kind string
  41. CreatedAt time.Time
  42. UpdatedAt time.Time
  43. BillingType string
  44. PayType string
  45. TradeStatus int
  46. ExpiredTime time.Time
  47. ProjectName string
  48. DeleteWithInstance bool
  49. }
  50. func (disk *SDisk) GetId() string {
  51. return disk.VolumeId
  52. }
  53. func (disk *SDisk) Delete(ctx context.Context) error {
  54. return disk.storage.zone.region.DeleteDisk(disk.VolumeId)
  55. }
  56. func (disk *SDisk) Resize(ctx context.Context, sizeMb int64) error {
  57. return disk.storage.zone.region.ResizeDisk(disk.VolumeId, sizeMb/1024)
  58. }
  59. func (disk *SDisk) GetName() string {
  60. if len(disk.VolumeName) > 0 {
  61. return disk.VolumeName
  62. }
  63. return disk.VolumeId
  64. }
  65. func (disk *SDisk) GetGlobalId() string {
  66. return disk.VolumeId
  67. }
  68. func (disk *SDisk) GetIStorage() (cloudprovider.ICloudStorage, error) {
  69. return disk.storage, nil
  70. }
  71. func (disk *SDisk) GetStatus() string {
  72. switch disk.Status {
  73. case "creating":
  74. return api.DISK_ALLOCATING
  75. default:
  76. return api.DISK_READY
  77. }
  78. }
  79. func (disk *SDisk) Refresh() error {
  80. _disk, err := disk.storage.zone.region.GetDisk(disk.VolumeId)
  81. if err != nil {
  82. return err
  83. }
  84. return jsonutils.Update(disk, _disk)
  85. }
  86. func (disk *SDisk) GetDiskFormat() string {
  87. return "vhd"
  88. }
  89. func (disk *SDisk) GetDiskSizeMB() int {
  90. return disk.Size * 1024
  91. }
  92. func (disk *SDisk) GetIsAutoDelete() bool {
  93. return disk.DeleteWithInstance
  94. }
  95. func (disk *SDisk) GetTemplateId() string {
  96. return disk.ImageId
  97. }
  98. func (disk *SDisk) GetDiskType() string {
  99. switch disk.Kind {
  100. case "system":
  101. return api.DISK_TYPE_SYS
  102. case "data":
  103. return api.DISK_TYPE_DATA
  104. default:
  105. return api.DISK_TYPE_DATA
  106. }
  107. }
  108. func (disk *SDisk) GetFsFormat() string {
  109. return ""
  110. }
  111. func (disk *SDisk) GetIsNonPersistent() bool {
  112. return false
  113. }
  114. func (disk *SDisk) GetDriver() string {
  115. return "scsi"
  116. }
  117. func (disk *SDisk) GetCacheMode() string {
  118. return "none"
  119. }
  120. func (disk *SDisk) GetMountpoint() string {
  121. return ""
  122. }
  123. func (disk *SDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
  124. snapshots, err := disk.storage.zone.region.GetSnapshots(disk.VolumeId, "", nil)
  125. if err != nil {
  126. return nil, err
  127. }
  128. ret := []cloudprovider.ICloudSnapshot{}
  129. for i := range snapshots {
  130. snapshots[i].region = disk.storage.zone.region
  131. ret = append(ret, &snapshots[i])
  132. }
  133. return ret, nil
  134. }
  135. func (disk *SDisk) Reset(ctx context.Context, snapshotId string) (string, error) {
  136. return "", cloudprovider.ErrNotSupported
  137. }
  138. func (disk *SDisk) GetBillingType() string {
  139. if disk.PayType != "post" {
  140. return billing_api.BILLING_TYPE_PREPAID
  141. }
  142. return billing_api.BILLING_TYPE_POSTPAID
  143. }
  144. func (disk *SDisk) GetCreatedAt() time.Time {
  145. return disk.CreatedAt
  146. }
  147. func (disk *SDisk) GetExpiredAt() time.Time {
  148. return convertExpiredAt(disk.ExpiredTime)
  149. }
  150. func (disk *SDisk) GetAccessPath() string {
  151. return ""
  152. }
  153. func (disk *SDisk) Rebuild(ctx context.Context) error {
  154. return errors.Wrapf(cloudprovider.ErrNotImplemented, "Rebuild")
  155. }
  156. func (disk *SDisk) GetProjectId() string {
  157. return disk.ProjectName
  158. }
  159. func (disk *SDisk) CreateISnapshot(ctx context.Context, name, desc string) (cloudprovider.ICloudSnapshot, error) {
  160. snapshot, err := disk.storage.zone.region.CreateSnapshot(disk.VolumeId, name, desc)
  161. if err != nil {
  162. return nil, err
  163. }
  164. return snapshot, nil
  165. }
  166. // region
  167. func (region *SRegion) GetDisks(instanceId string, zoneId string, category string, diskIds []string) ([]SDisk, error) {
  168. params := make(map[string]string)
  169. params["PageSize"] = "100"
  170. pageNum := 1
  171. params["PageNumber"] = fmt.Sprintf("%d", pageNum)
  172. if len(instanceId) > 0 {
  173. params["InstanceId"] = instanceId
  174. }
  175. if len(zoneId) > 0 {
  176. params["ZoneId"] = zoneId
  177. }
  178. if len(category) > 0 {
  179. params["VolumeType"] = category
  180. }
  181. for index, id := range diskIds {
  182. key := fmt.Sprintf("VolumeIds.%d", index+1)
  183. params[key] = id
  184. }
  185. ret := []SDisk{}
  186. for {
  187. resp, err := region.storageRequest("DescribeVolumes", params)
  188. if err != nil {
  189. return nil, errors.Wrap(err, "GetDisks fail")
  190. }
  191. part := struct {
  192. Volumes []SDisk
  193. TotalCount int
  194. }{}
  195. err = resp.Unmarshal(&part)
  196. if err != nil {
  197. return nil, err
  198. }
  199. ret = append(ret, part.Volumes...)
  200. if len(ret) >= part.TotalCount || len(part.Volumes) == 0 {
  201. break
  202. }
  203. pageNum++
  204. params["PageNumber"] = fmt.Sprintf("%d", pageNum)
  205. }
  206. return ret, nil
  207. }
  208. func (region *SRegion) CreateDisk(zoneId string, category string, opts *cloudprovider.DiskCreateConfig) (string, error) {
  209. params := make(map[string]string)
  210. params["ZoneId"] = zoneId
  211. params["VolumeName"] = opts.Name
  212. if len(opts.Desc) > 0 {
  213. params["Description"] = opts.Desc
  214. }
  215. params["VolumeType"] = category
  216. // only data disk is supported
  217. params["Kind"] = "data"
  218. params["Size"] = fmt.Sprintf("%d", opts.SizeGb)
  219. params["ClientToken"] = utils.GenRequestId(20)
  220. body, err := region.storageRequest("CreateVolume", params)
  221. if err != nil {
  222. return "", err
  223. }
  224. return body.GetString("VolumeId")
  225. }
  226. func (region *SRegion) GetDisk(diskId string) (*SDisk, error) {
  227. disks, err := region.GetDisks("", "", "", []string{diskId})
  228. if err != nil {
  229. return nil, errors.Wrapf(err, "%s not found", diskId)
  230. }
  231. for _, disk := range disks {
  232. if disk.VolumeId == diskId {
  233. return &disk, nil
  234. }
  235. }
  236. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s not found", diskId)
  237. }
  238. func (region *SRegion) DeleteDisk(diskId string) error {
  239. params := make(map[string]string)
  240. params["VolumeId"] = diskId
  241. _, err := region.storageRequest("DeleteVolume", params)
  242. return err
  243. }
  244. func (region *SRegion) ResizeDisk(diskId string, sizeGb int64) error {
  245. params := make(map[string]string)
  246. params["VolumeId"] = diskId
  247. params["NewSize"] = fmt.Sprintf("%d", sizeGb)
  248. _, err := region.storageRequest("ExtendVolume", params)
  249. if err != nil {
  250. return errors.Wrapf(err, "Resizing disk (%s) to %d GiB failed", diskId, sizeGb)
  251. }
  252. return nil
  253. }