yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/qcloud/snapshot.go (about) 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 15 package qcloud 16 17 import ( 18 "fmt" 19 "strconv" 20 "time" 21 22 "yunion.io/x/jsonutils" 23 "yunion.io/x/log" 24 25 api "yunion.io/x/cloudmux/pkg/apis/compute" 26 "yunion.io/x/cloudmux/pkg/cloudprovider" 27 "yunion.io/x/cloudmux/pkg/multicloud" 28 ) 29 30 type SnapshotStatusType string 31 32 const ( 33 SnapshotStatusAccomplished SnapshotStatusType = "NORMAL" 34 SnapshotStatusProgress SnapshotStatusType = "CREATING" 35 SnapshotStatusFailed SnapshotStatusType = "failed" 36 ) 37 38 type SSnapshot struct { 39 multicloud.SResourceBase 40 QcloudTags 41 region *SRegion 42 43 SnapshotId string // 快照ID。 44 Placement Placement // 快照所在的位置。 45 DiskUsage string // 创建此快照的云硬盘类型。取值范围:SYSTEM_DISK:系统盘 DATA_DISK:数据盘。 46 DiskId string // 创建此快照的云硬盘ID。 47 DiskSize int32 // 创建此快照的云硬盘大小,单位GB。 48 SnapshotState SnapshotStatusType // 快照的状态。取值范围: NORMAL:正常 CREATING:创建中 ROLLBACKING:回滚中 COPYING_FROM_REMOTE:跨地域复制快照拷贝中。 49 SnapshotName string // 快照名称,用户自定义的快照别名。调用ModifySnapshotAttribute可修改此字段。 50 Percent int // 快照创建进度百分比,快照创建成功后此字段恒为100。 51 CreateTime time.Time // 快照的创建时间。 52 DeadlineTime time.Time // 快照到期时间。如果快照为永久保留,此字段为空。 53 Encrypt bool // 是否为加密盘创建的快照。取值范围:true:该快照为加密盘创建的 false:非加密盘创建的快照。 54 IsPermanent bool // 是否为永久快照。取值范围: true:永久快照 false:非永久快照。 55 CopyingToRegions []string // 快照正在跨地域复制的目的地域,默认取值为[]。 56 CopyFromRemote bool // 是否为跨地域复制的快照。取值范围:true:表示为跨地域复制的快照。 false:本地域的快照。 57 } 58 59 func (self *SRegion) GetISnapshotById(snapshotId string) (cloudprovider.ICloudSnapshot, error) { 60 snapshots, total, err := self.GetSnapshots("", "", "", []string{snapshotId}, 0, 1) 61 if err != nil { 62 return nil, err 63 } 64 if total > 1 { 65 return nil, cloudprovider.ErrDuplicateId 66 } 67 if total == 0 { 68 return nil, cloudprovider.ErrNotFound 69 } 70 return &snapshots[0], nil 71 } 72 73 func (self *SSnapshot) GetStatus() string { 74 // NORMAL:正常 75 // CREATING:创建中 76 // ROLLBACKING:回滚中 77 // COPYING_FROM_REMOTE:跨地域复制快照拷贝中。 78 switch self.SnapshotState { 79 case "NORMAL", "COPYING_FROM_REMOTE": 80 return api.SNAPSHOT_READY 81 case "CREATING": 82 return api.SNAPSHOT_CREATING 83 case "ROLLBACKING": 84 return api.SNAPSHOT_ROLLBACKING 85 } 86 return api.SNAPSHOT_UNKNOWN 87 } 88 89 func (self *SSnapshot) IsEmulated() bool { 90 return false 91 } 92 93 func (self *SSnapshot) Refresh() error { 94 snapshots, total, err := self.region.GetSnapshots("", "", "", []string{self.SnapshotId}, 0, 1) 95 if err != nil { 96 return err 97 } 98 if total > 1 { 99 return cloudprovider.ErrDuplicateId 100 } 101 102 if total == 0 { 103 return cloudprovider.ErrNotFound 104 } 105 return jsonutils.Update(self, snapshots[0]) 106 } 107 108 func (self *SRegion) GetSnapshots(instanceId string, diskId string, snapshotName string, snapshotIds []string, offset int, limit int) ([]SSnapshot, int, error) { 109 if limit > 50 || limit <= 0 { 110 limit = 50 111 } 112 params := make(map[string]string) 113 params["Limit"] = fmt.Sprintf("%d", limit) 114 params["Offset"] = fmt.Sprintf("%d", offset) 115 116 filter := 0 117 if len(instanceId) > 0 { 118 } 119 if len(diskId) > 0 { 120 params[fmt.Sprintf("Filters.%d.Name", filter)] = "disk-id" 121 params[fmt.Sprintf("Filters.%d.Values.0", filter)] = diskId 122 filter++ 123 } 124 if len(snapshotName) > 0 { 125 params[fmt.Sprintf("Filters.%d.Name", filter)] = "snapshot-name" 126 params[fmt.Sprintf("Filters.%d.Values", filter)] = snapshotName 127 filter++ 128 } 129 if snapshotIds != nil && len(snapshotIds) > 0 { 130 for index, snapshotId := range snapshotIds { 131 params[fmt.Sprintf("SnapshotIds.%d", index)] = snapshotId 132 } 133 } 134 snapshots := []SSnapshot{} 135 body, err := self.cbsRequest("DescribeSnapshots", params) 136 if err != nil { 137 log.Errorf("GetSnapshots fail %s", err) 138 return nil, 0, err 139 } 140 body.Unmarshal(&snapshots, "SnapshotSet") 141 if err != nil { 142 return nil, 0, err 143 } 144 total, _ := body.Float("TotalCount") 145 for i := 0; i < len(snapshots); i++ { 146 snapshots[i].region = self 147 } 148 return snapshots, int(total), nil 149 } 150 151 func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) { 152 snapshots, total, err := self.GetSnapshots("", "", "", []string{}, 0, 50) 153 if err != nil { 154 return nil, err 155 } 156 for len(snapshots) < total { 157 var parts []SSnapshot 158 parts, total, err = self.GetSnapshots("", "", "", []string{}, len(snapshots), 50) 159 if err != nil { 160 return nil, err 161 } 162 snapshots = append(snapshots, parts...) 163 } 164 ret := make([]cloudprovider.ICloudSnapshot, len(snapshots)) 165 for i := 0; i < len(snapshots); i++ { 166 ret[i] = &snapshots[i] 167 } 168 return ret, nil 169 } 170 171 func (self *SSnapshot) GetRegionId() string { 172 return self.region.GetId() 173 } 174 175 func (self *SSnapshot) GetSizeMb() int32 { 176 return self.DiskSize * 1024 177 } 178 179 func (self *SSnapshot) GetDiskId() string { 180 return self.DiskId 181 } 182 183 func (self *SSnapshot) GetId() string { 184 return self.SnapshotId 185 } 186 187 func (self *SSnapshot) GetGlobalId() string { 188 return fmt.Sprintf("%s", self.SnapshotId) 189 } 190 191 func (self *SSnapshot) GetName() string { 192 return self.SnapshotName 193 } 194 195 func (self *SSnapshot) Delete() error { 196 if self.region == nil { 197 return fmt.Errorf("not init region for snapshot %s", self.SnapshotId) 198 } 199 return self.region.DeleteSnapshot(self.SnapshotId) 200 } 201 202 func (self *SSnapshot) GetDiskType() string { 203 switch self.DiskUsage { 204 case "SYSTEM_DISK": 205 return api.DISK_TYPE_SYS 206 case "DATA_DISK": 207 return api.DISK_TYPE_DATA 208 } 209 return api.DISK_TYPE_DATA 210 } 211 212 func (self *SRegion) DeleteSnapshot(snapshotId string) error { 213 params := map[string]string{"SnapshotIds.0": snapshotId} 214 _, err := self.cbsRequest("DeleteSnapshots", params) 215 return err 216 } 217 218 func (self *SRegion) CreateSnapshot(diskId, name, desc string) (string, error) { 219 params := make(map[string]string) 220 params["DiskId"] = diskId 221 params["SnapshotName"] = name 222 223 body, err := self.cbsRequest("CreateSnapshot", params) 224 if err != nil { 225 log.Errorf("CreateSnapshot fail %s", err) 226 return "", err 227 } 228 return body.GetString("SnapshotId") 229 } 230 231 func (self *SSnapshot) GetProjectId() string { 232 return strconv.Itoa(self.Placement.ProjectId) 233 }