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  }