yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aws/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 aws 16 17 import ( 18 "fmt" 19 "strings" 20 21 "github.com/aws/aws-sdk-go/service/ec2" 22 23 "yunion.io/x/jsonutils" 24 "yunion.io/x/log" 25 "yunion.io/x/pkg/errors" 26 27 api "yunion.io/x/cloudmux/pkg/apis/compute" 28 "yunion.io/x/cloudmux/pkg/cloudprovider" 29 "yunion.io/x/cloudmux/pkg/multicloud" 30 ) 31 32 type SnapshotStatusType string 33 34 const ( 35 SnapshotStatusAccomplished SnapshotStatusType = "completed" 36 SnapshotStatusProgress SnapshotStatusType = "pending" 37 SnapshotStatusFailed SnapshotStatusType = "error" 38 ) 39 40 type SSnapshot struct { 41 multicloud.SResourceBase 42 AwsTags 43 region *SRegion 44 45 Progress string 46 SnapshotId string 47 SnapshotName string 48 SourceDiskId string 49 SourceDiskSize int32 50 SourceDiskType string 51 Status SnapshotStatusType 52 Usage string 53 //TagSpec TagSpec 54 } 55 56 func (self *SSnapshot) GetDiskType() string { 57 // todo: self.SourceDiskType 58 return "" 59 } 60 61 func (self *SSnapshot) GetId() string { 62 return self.SnapshotId 63 } 64 65 func (self *SSnapshot) GetName() string { 66 if len(self.SnapshotName) == 0 { 67 return self.SnapshotId 68 } 69 70 return self.SnapshotName 71 } 72 73 func (self *SSnapshot) GetGlobalId() string { 74 return fmt.Sprintf("%s", self.SnapshotId) 75 } 76 77 func (self *SSnapshot) GetStatus() string { 78 // todo: implement me 79 if self.Status == SnapshotStatusAccomplished { 80 return api.SNAPSHOT_READY 81 } else if self.Status == SnapshotStatusProgress { 82 return api.SNAPSHOT_CREATING 83 } else { // if self.Status == SnapshotStatusFailed 84 return api.SNAPSHOT_FAILED 85 } 86 } 87 88 func (self *SSnapshot) Refresh() error { 89 if snapshots, total, err := self.region.GetSnapshots("", "", "", []string{self.SnapshotId}, 0, 1); err != nil { 90 return err 91 } else if total != 1 { 92 return errors.Wrap(cloudprovider.ErrNotFound, "GetSnapshots") 93 } else if err := jsonutils.Update(self, snapshots[0]); err != nil { 94 return err 95 } 96 return nil 97 } 98 99 func (self *SSnapshot) IsEmulated() bool { 100 return false 101 } 102 103 func (self *SSnapshot) GetSizeMb() int32 { 104 return self.SourceDiskSize * 1024 105 } 106 107 func (self *SSnapshot) GetDiskId() string { 108 return self.SourceDiskId 109 } 110 111 func (self *SSnapshot) Delete() error { 112 return self.region.DeleteSnapshot(self.SnapshotId) 113 } 114 115 func (self *SRegion) GetSnapshots(instanceId string, diskId string, snapshotName string, snapshotIds []string, offset int, limit int) ([]SSnapshot, int, error) { 116 params := &ec2.DescribeSnapshotsInput{} 117 filters := make([]*ec2.Filter, 0) 118 // todo: not support search by instancesId. use Tag? 119 // if len(instanceId) > o { 120 // filters = AppendSingleValueFilter(filters, ) 121 // } 122 // owner by self 123 owner := "self" 124 params.SetOwnerIds([]*string{&owner}) 125 if len(diskId) > 0 { 126 filters = AppendSingleValueFilter(filters, "volume-id", diskId) 127 } 128 129 if len(snapshotName) > 0 { 130 filters = AppendSingleValueFilter(filters, "tag:Name", snapshotName) 131 } 132 133 if len(filters) > 0 { 134 params.SetFilters(filters) 135 } 136 137 if len(snapshotIds) > 0 { 138 params.SetSnapshotIds(ConvertedList(snapshotIds)) 139 } 140 141 ec2Client, err := self.getEc2Client() 142 if err != nil { 143 return nil, 0, errors.Wrap(err, "getEc2Client") 144 } 145 ret, err := ec2Client.DescribeSnapshots(params) 146 err = parseNotFoundError(err) 147 if err != nil { 148 if strings.Contains(err.Error(), "InvalidSnapshot.NotFound") { 149 return nil, 0, errors.Wrap(cloudprovider.ErrNotFound, "parseNotFoundError") 150 } 151 152 return nil, 0, err 153 } 154 155 snapshots := []SSnapshot{} 156 for _, item := range ret.Snapshots { 157 if err := FillZero(item); err != nil { 158 return nil, 0, err 159 } 160 161 tagspec := TagSpec{ResourceType: "snapshot"} 162 tagspec.LoadingEc2Tags(item.Tags) 163 164 snapshot := SSnapshot{} 165 snapshot.SnapshotId = *item.SnapshotId 166 snapshot.Status = SnapshotStatusType(*item.State) 167 snapshot.region = self 168 snapshot.Progress = *item.Progress 169 snapshot.SnapshotName = *item.SnapshotId 170 snapshot.SourceDiskId = *item.VolumeId 171 snapshot.SourceDiskSize = int32(*item.VolumeSize) 172 // snapshot.SourceDiskType 173 snapshot.SnapshotName = tagspec.GetNameTag() 174 jsonutils.Update(&snapshot.AwsTags.TagSet, item.Tags) 175 snapshots = append(snapshots, snapshot) 176 } 177 178 return snapshots, len(snapshots), nil 179 } 180 181 func (self *SRegion) GetISnapshotById(snapshotId string) (cloudprovider.ICloudSnapshot, error) { 182 if snapshots, total, err := self.GetSnapshots("", "", "", []string{snapshotId}, 0, 1); err != nil { 183 return nil, errors.Wrap(err, "GetSnapshots") 184 } else if total != 1 { 185 return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetSnapshots") 186 } else { 187 return &snapshots[0], nil 188 } 189 } 190 191 func (self *SRegion) CreateSnapshot(diskId, name, desc string) (string, error) { 192 params := &ec2.CreateSnapshotInput{} 193 if len(diskId) <= 0 { 194 return "", fmt.Errorf("disk id should not be empty") 195 } else { 196 params.SetVolumeId(diskId) 197 } 198 199 if len(name) <= 0 { 200 return "", fmt.Errorf("name length should great than 0") 201 } else { 202 tagspec := TagSpec{ResourceType: "snapshot"} 203 tagspec.SetNameTag(name) 204 ec2Tag, _ := tagspec.GetTagSpecifications() 205 params.SetTagSpecifications([]*ec2.TagSpecification{ec2Tag}) 206 } 207 208 params.SetDescription(desc) 209 log.Debugf("CreateSnapshots with params %s", params) 210 ec2Client, err := self.getEc2Client() 211 if err != nil { 212 return "", errors.Wrap(err, "getEc2Client") 213 } 214 215 ret, err := ec2Client.CreateSnapshot(params) 216 if err != nil { 217 return "", errors.Wrap(err, "CreateSnapshot") 218 } 219 return StrVal(ret.SnapshotId), nil 220 } 221 222 func (self *SRegion) DeleteSnapshot(snapshotId string) error { 223 ec2Client, err := self.getEc2Client() 224 if err != nil { 225 return errors.Wrap(err, "getEc2Client") 226 } 227 params := &ec2.DeleteSnapshotInput{} 228 params.SetSnapshotId(snapshotId) 229 _, err = ec2Client.DeleteSnapshot(params) 230 return errors.Wrap(err, "DeleteSnapshot") 231 } 232 233 func (self *SSnapshot) GetProjectId() string { 234 return "" 235 }