snapshot.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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 openstack
  15. import (
  16. "net/url"
  17. "yunion.io/x/jsonutils"
  18. "yunion.io/x/log"
  19. "yunion.io/x/pkg/errors"
  20. api "yunion.io/x/cloudmux/pkg/apis/compute"
  21. "yunion.io/x/cloudmux/pkg/cloudprovider"
  22. "yunion.io/x/cloudmux/pkg/multicloud"
  23. )
  24. const (
  25. SNAPSHOT_STATUS_CREATING = "creating" //The snapshot is being created.
  26. SNAPSHOT_STATUS_AVAILABLE = "available" //The snapshot is ready to use.
  27. SNAPSHOT_STATUS_BACKING_UP = "backing-up" //The snapshot is being backed up.
  28. SNAPSHOT_STATUS_DELETING = "deleting" //The snapshot is being deleted.
  29. SNAPSHOT_STATUS_ERROR = "error" //A snapshot creation error occurred.
  30. SNAPSHOT_STATUS_DELETED = "deleted" //The snapshot has been deleted.
  31. SNAPSHOT_STATUS_UNMANAGING = "unmanaging" //The snapshot is being unmanaged.
  32. SNAPSHOT_STATUS_RESTORING = "restoring" //The snapshot is being restored to a volume.
  33. SNAPSHOT_STATUS_ERROR_DELETING = "error_deleting" //A snapshot deletion error occurred.
  34. )
  35. type SSnapshot struct {
  36. multicloud.SResourceBase
  37. OpenStackTags
  38. region *SRegion
  39. Id string
  40. VolumeId string
  41. Status string
  42. Progress string `json:"os-extended-snapshot-attributes:progress"`
  43. Name string
  44. UserId string
  45. ProjectId string `json:"os-extended-snapshot-attributes:project_id"`
  46. //CreatedAt time.Time
  47. Size int32
  48. Description string
  49. //UpdatedAt time.Time
  50. }
  51. func (region *SRegion) GetISnapshotById(snapshotId string) (cloudprovider.ICloudSnapshot, error) {
  52. snapshot, err := region.GetSnapshot(snapshotId)
  53. if err != nil {
  54. return nil, err
  55. }
  56. return snapshot, nil
  57. }
  58. func (region *SRegion) GetSnapshot(snapshotId string) (*SSnapshot, error) {
  59. resource := "/snapshots/" + snapshotId
  60. resp, err := region.bsGet(resource)
  61. if err != nil {
  62. return nil, errors.Wrap(err, "bsGet")
  63. }
  64. snapshot := SSnapshot{region: region}
  65. err = resp.Unmarshal(&snapshot, "snapshot")
  66. if err != nil {
  67. return nil, errors.Wrap(err, "resp.Unmarshal")
  68. }
  69. return &snapshot, nil
  70. }
  71. func (snapshot *SSnapshot) GetStatus() string {
  72. switch snapshot.Status {
  73. case SNAPSHOT_STATUS_CREATING:
  74. return api.SNAPSHOT_CREATING
  75. case SNAPSHOT_STATUS_AVAILABLE:
  76. return api.SNAPSHOT_READY
  77. case SNAPSHOT_STATUS_BACKING_UP:
  78. return api.SNAPSHOT_ROLLBACKING
  79. case SNAPSHOT_STATUS_DELETED, SNAPSHOT_STATUS_DELETING:
  80. return api.SNAPSHOT_DELETING
  81. default:
  82. return api.SNAPSHOT_UNKNOWN
  83. }
  84. }
  85. func (snapshot *SSnapshot) IsEmulated() bool {
  86. return false
  87. }
  88. func (snapshot *SSnapshot) Refresh() error {
  89. _snapshot, err := snapshot.region.GetSnapshot(snapshot.Id)
  90. if err != nil {
  91. return err
  92. }
  93. return jsonutils.Update(snapshot, _snapshot)
  94. }
  95. func (region *SRegion) GetSnapshots(diskId string) ([]SSnapshot, error) {
  96. resource := "/snapshots/detail"
  97. query := url.Values{}
  98. query.Set("all_tenants", "true")
  99. if len(diskId) > 0 {
  100. query.Set("volume_id", diskId)
  101. }
  102. snapshots := []SSnapshot{}
  103. for {
  104. resp, err := region.bsList(resource, query)
  105. if err != nil {
  106. return nil, errors.Wrap(err, "bsList")
  107. }
  108. part := struct {
  109. Snapshots []SSnapshot
  110. SnapshotsLinks SNextLinks
  111. }{}
  112. err = resp.Unmarshal(&part)
  113. if err != nil {
  114. return nil, errors.Wrap(err, "resp.Unmarshal")
  115. }
  116. snapshots = append(snapshots, part.Snapshots...)
  117. marker := part.SnapshotsLinks.GetNextMark()
  118. if len(marker) == 0 {
  119. break
  120. }
  121. query.Set("marker", marker)
  122. }
  123. return snapshots, nil
  124. }
  125. func (region *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
  126. snapshots, err := region.GetSnapshots("")
  127. if err != nil {
  128. return nil, err
  129. }
  130. isnapshots := []cloudprovider.ICloudSnapshot{}
  131. for i := range snapshots {
  132. snapshots[i].region = region
  133. isnapshots = append(isnapshots, &snapshots[i])
  134. }
  135. return isnapshots, nil
  136. }
  137. func (snapshot *SSnapshot) GetSizeMb() int32 {
  138. return snapshot.Size * 1024
  139. }
  140. func (snapshot *SSnapshot) GetDiskId() string {
  141. return snapshot.VolumeId
  142. }
  143. func (snapshot *SSnapshot) GetId() string {
  144. return snapshot.Id
  145. }
  146. func (snapshot *SSnapshot) GetGlobalId() string {
  147. return snapshot.Id
  148. }
  149. func (snapshot *SSnapshot) GetName() string {
  150. if len(snapshot.Name) == 0 {
  151. return snapshot.Id
  152. }
  153. return snapshot.Name
  154. }
  155. func (snapshot *SSnapshot) Delete() error {
  156. return snapshot.region.DeleteSnapshot(snapshot.Id)
  157. }
  158. func (snapshot *SSnapshot) GetDiskType() string {
  159. if len(snapshot.VolumeId) > 0 {
  160. disk, err := snapshot.region.GetDisk(snapshot.VolumeId)
  161. if err != nil {
  162. log.Errorf("failed to get snapshot %s disk %s error: %v", snapshot.Name, snapshot.VolumeId, err)
  163. return api.DISK_TYPE_DATA
  164. }
  165. return disk.GetDiskType()
  166. }
  167. return api.DISK_TYPE_DATA
  168. }
  169. func (region *SRegion) DeleteSnapshot(snapshotId string) error {
  170. resource := "/snapshots/" + snapshotId
  171. _, err := region.bsDelete(resource)
  172. return err
  173. }
  174. func (region *SRegion) CreateSnapshot(diskId, name, desc string) (*SSnapshot, error) {
  175. params := map[string]map[string]interface{}{
  176. "snapshot": {
  177. "volume_id": diskId,
  178. "name": name,
  179. "description": desc,
  180. "force": true,
  181. },
  182. }
  183. resp, err := region.bsPost("/snapshots", params)
  184. if err != nil {
  185. return nil, errors.Wrap(err, "bsPost")
  186. }
  187. snapshot := &SSnapshot{region: region}
  188. err = resp.Unmarshal(snapshot, "snapshot")
  189. if err != nil {
  190. return nil, errors.Wrap(err, "resp.Unmarshal")
  191. }
  192. return snapshot, nil
  193. }
  194. func (self *SSnapshot) GetProjectId() string {
  195. return self.ProjectId
  196. }