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