mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
aliyun snapshot sync, create, delete; disk reset
This commit is contained in:
@@ -35,7 +35,9 @@ type ICloudRegion interface {
|
||||
GetIZones() ([]ICloudZone, error)
|
||||
GetIVpcs() ([]ICloudVpc, error)
|
||||
GetIEips() ([]ICloudEIP, error)
|
||||
GetISnapshots() ([]ICloudSnapshot, error)
|
||||
|
||||
GetISnapshotById(snapshotId string) (ICloudSnapshot, error)
|
||||
GetIZoneById(id string) (ICloudZone, error)
|
||||
GetIVpcById(id string) (ICloudVpc, error)
|
||||
GetIHostById(id string) (ICloudHost, error)
|
||||
@@ -242,11 +244,16 @@ type ICloudDisk interface {
|
||||
GetISnapshots() ([]ICloudSnapshot, error)
|
||||
|
||||
Resize(newSize int64) error
|
||||
Reset(snapshotId string) error
|
||||
}
|
||||
|
||||
type ICloudSnapshot interface {
|
||||
ICloudResource
|
||||
GetManagerId() string
|
||||
GetSize() int32
|
||||
GetDiskId() string
|
||||
Delete() error
|
||||
GetRegionId() string
|
||||
}
|
||||
|
||||
type ICloudVpc interface {
|
||||
|
||||
@@ -654,3 +654,26 @@ func (self *SAliyunGuestDriver) RequestStartOnHost(ctx context.Context, guest *m
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}*/
|
||||
|
||||
func (self *SAliyunGuestDriver) RequestDiskSnapshot(ctx context.Context, guest *models.SGuest, task taskman.ITask, snapshotId, diskId string) error {
|
||||
iDisk, _ := models.DiskManager.FetchById(diskId)
|
||||
disk := iDisk.(*models.SDisk)
|
||||
providerDisk, err := disk.GetIDisk()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
iSnapshot, _ := models.SnapshotManager.FetchById(snapshotId)
|
||||
snapshot := iSnapshot.(*models.SSnapshot)
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
cloudSnapshot, err := providerDisk.CreateISnapshot(snapshot.Name, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res := jsonutils.NewDict()
|
||||
res.Set("snapshot_id", jsonutils.NewString(cloudSnapshot.GetId()))
|
||||
res.Set("manager_id", jsonutils.NewString(cloudSnapshot.GetManagerId()))
|
||||
res.Set("cloudregion_id", jsonutils.NewString(cloudSnapshot.GetRegionId()))
|
||||
return res, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -47,15 +47,6 @@ func (self *SKVMGuestDriver) DoGuestCreateDisksTask(ctx context.Context, guest *
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) StartGuestDiskSnapshotTask(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, params *jsonutils.JSONDict) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "GuestDiskSnapshotTask", guest, userCred, params, "", "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) RequestDiskSnapshot(ctx context.Context, guest *models.SGuest, task taskman.ITask, snapshotId, diskId string) error {
|
||||
url := fmt.Sprintf("/servers/%s/snapshot", guest.Id)
|
||||
body := jsonutils.NewDict()
|
||||
|
||||
@@ -203,3 +203,12 @@ func (self *SVirtualizedGuestDriver) StartGuestSaveImage(ctx context.Context, us
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) StartGuestDiskSnapshotTask(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, params *jsonutils.JSONDict) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "GuestDiskSnapshotTask", guest, userCred, params, "", "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
)
|
||||
|
||||
type SAliyunHostDriver struct {
|
||||
@@ -37,7 +37,6 @@ func (self *SAliyunHostDriver) CheckAndSetCacheImage(ctx context.Context, host *
|
||||
osType, _ := params.GetString("os_type")
|
||||
osDist, _ := params.GetString("os_distribution")
|
||||
|
||||
|
||||
isForce := jsonutils.QueryBoolean(params, "is_force", false)
|
||||
userCred := task.GetUserCred()
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
@@ -189,3 +188,19 @@ func (self *SAliyunHostDriver) RequestResizeDiskOnHost(host *models.SHost, stora
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAliyunHostDriver) RequestResetDisk(ctx context.Context, host *models.SHost, disk *models.SDisk, params *jsonutils.JSONDict, task taskman.ITask) error {
|
||||
iDisk, err := disk.GetIDisk()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
snapshotId, err := params.GetString("snapshot_id")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
err := iDisk.Reset(snapshotId)
|
||||
return nil, err
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1245,11 +1245,11 @@ func (manager *SDiskManager) AutoDiskSnapshot(ctx context.Context, userCred mccl
|
||||
continue
|
||||
}
|
||||
if !utils.IsInStringArray(guests[0].Status, []string{VM_RUNNING, VM_READY}) {
|
||||
log.Errorln("Guest(%s) in status(%s) cannot do snapshot action", guests[0].Id, guests[0].Status)
|
||||
log.Errorf("Guest(%s) in status(%s) cannot do snapshot action", guests[0].Id, guests[0].Status)
|
||||
continue
|
||||
}
|
||||
// name
|
||||
name := disk.Name + time.Now().Format("2006-01-02#15:04:05")
|
||||
name := guests[0].Name + time.Now().Format("2006-01-02#15:04:05")
|
||||
snap, err := SnapshotManager.CreateSnapshot(ctx, userCred, AUTO, disk.Id, guests[0].Id, "", name)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
|
||||
@@ -13,12 +13,12 @@ import (
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -82,6 +82,7 @@ const (
|
||||
|
||||
VM_START_SNAPSHOT = "snapshot_start"
|
||||
VM_SNAPSHOT = "snapshot"
|
||||
VM_SNAPSHOT_DELETE = "snapshot_delete"
|
||||
VM_SNAPSHOT_STREAM = "block_stream"
|
||||
VM_SNAPSHOT_SUCC = "snapshot_succ"
|
||||
VM_SNAPSHOT_FAILED = "snapshot_failed"
|
||||
@@ -3866,39 +3867,50 @@ func (self *SGuest) PerformDiskSnapshot(ctx context.Context, userCred mcclient.T
|
||||
}
|
||||
diskId, err := data.GetString("disk_id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, httperrors.NewBadRequestError(err.Error())
|
||||
}
|
||||
name, err := data.GetString("name")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, httperrors.NewBadRequestError(err.Error())
|
||||
}
|
||||
// if self.GetHypervisor() == HYPERVISOR_ALIYUN && strings.HasPrefix(name, "auto") {
|
||||
// }
|
||||
if self.GetGuestDisk(diskId) == nil {
|
||||
return nil, httperrors.NewNotFoundError("Guest disk %s not found", diskId)
|
||||
}
|
||||
snapshots := SnapshotManager.GetDiskSnapshotsByCreate(diskId, MANUAL)
|
||||
if snapshots != nil {
|
||||
if len(snapshots) >= options.Options.DefaultMaxManualSnapshotCount {
|
||||
return nil, httperrors.NewBadRequestError("Disk %s snapshot full, cannot take any more", diskId)
|
||||
}
|
||||
for _, snapshot := range snapshots {
|
||||
if snapshot.Name == name {
|
||||
return nil, httperrors.NewBadRequestError("Name Conflict")
|
||||
if self.GetHypervisor() == HYPERVISOR_KVM {
|
||||
snapshots := SnapshotManager.GetDiskSnapshotsByCreate(diskId, MANUAL)
|
||||
if snapshots != nil {
|
||||
if len(snapshots) >= options.Options.DefaultMaxManualSnapshotCount {
|
||||
return nil, httperrors.NewBadRequestError("Disk %s snapshot full, cannot take any more", diskId)
|
||||
}
|
||||
for _, snapshot := range snapshots {
|
||||
if snapshot.Name == name {
|
||||
return nil, httperrors.NewBadRequestError("Name Conflict")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pendingUsage := &SQuota{Snapshot: 1}
|
||||
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, self.ProjectId, pendingUsage)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewBadRequestError("Check set pending quota error %s", err)
|
||||
}
|
||||
snapshot, err := SnapshotManager.CreateSnapshot(ctx, userCred, MANUAL, diskId, self.Id, "", name)
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, self.ProjectId, nil, pendingUsage)
|
||||
if err != nil {
|
||||
pendingUsage := &SQuota{Snapshot: 1}
|
||||
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, self.ProjectId, pendingUsage)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewBadRequestError("Check set pending quota error %s", err)
|
||||
}
|
||||
snapshot, err := SnapshotManager.CreateSnapshot(ctx, userCred, MANUAL, diskId, self.Id, "", name)
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, self.ProjectId, nil, pendingUsage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = self.StartDiskSnapshot(ctx, userCred, diskId, snapshot.Id)
|
||||
return nil, err
|
||||
} else {
|
||||
snapshot, err := SnapshotManager.CreateSnapshot(ctx, userCred, MANUAL, diskId, self.Id, "", name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = self.StartDiskSnapshot(ctx, userCred, diskId, snapshot.Id)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = self.StartDiskSnapshot(ctx, userCred, diskId, snapshot.Id)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (self *SGuest) StartDiskSnapshot(ctx context.Context, userCred mcclient.TokenCredential, diskId, snapshotId string) error {
|
||||
|
||||
+145
-12
@@ -7,10 +7,13 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
@@ -21,9 +24,11 @@ const (
|
||||
MANUAL = "manual"
|
||||
AUTO = "auto"
|
||||
|
||||
SNAPSHOT_CREATING = "creating"
|
||||
SNAPSHOT_FAILED = "create_failed"
|
||||
SNAPSHOT_READY = "ready"
|
||||
SNAPSHOT_DELETING = "deleting"
|
||||
SNAPSHOT_UNKNOWN = "unknown"
|
||||
)
|
||||
|
||||
type SSnapshotManager struct {
|
||||
@@ -32,13 +37,17 @@ type SSnapshotManager struct {
|
||||
|
||||
type SSnapshot struct {
|
||||
db.SVirtualResourceBase
|
||||
DiskId string `width:"36" charset:"ascii" nullable:"false" create:"required" key_index:"true" list:"user"`
|
||||
SManagedResourceBase
|
||||
|
||||
DiskId string `width:"36" charset:"ascii" nullable:"true" create:"required" key_index:"true" list:"user"`
|
||||
StorageId string `width:"36" charset:"ascii" nullable:"true" list:"admin"`
|
||||
CreatedBy string `width:"36" charset:"ascii" nullable:"false" default:"manual" list:"admin"`
|
||||
Location string `charset:"ascii" nullable:"false" list:"admin"`
|
||||
Location string `charset:"ascii" nullable:"true" list:"admin"`
|
||||
Size int `nullable:"false" list:"user"` // MB
|
||||
OutOfChain bool `nullable:"false" default:"false" index:"true" list:"admin"`
|
||||
FakeDeleted bool `nullable:"false" default:"false" index:"true"`
|
||||
|
||||
CloudregionId string `width:"36" charset:"ascii" nullable:"true" list:"user"`
|
||||
}
|
||||
|
||||
var SnapshotManager *SSnapshotManager
|
||||
@@ -180,6 +189,7 @@ func (self *SSnapshotManager) CreateSnapshot(ctx context.Context, userCred mccli
|
||||
snapshot.Location = location
|
||||
snapshot.CreatedBy = createdBy
|
||||
snapshot.Name = name
|
||||
snapshot.Status = SNAPSHOT_CREATING
|
||||
err = SnapshotManager.TableSpec().Insert(snapshot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -211,21 +221,29 @@ func (self *SSnapshot) ValidateDeleteCondition(ctx context.Context) error {
|
||||
func (self *SSnapshot) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
if self.Status == SNAPSHOT_DELETING {
|
||||
return fmt.Errorf("Cannot delete snapshot in status %s", self.Status)
|
||||
} else if self.Status == VM_SNAPSHOT_FAILED {
|
||||
}
|
||||
if self.Status == SNAPSHOT_UNKNOWN {
|
||||
return self.RealDelete(ctx, userCred)
|
||||
}
|
||||
if self.CreatedBy == MANUAL {
|
||||
if !self.FakeDeleted {
|
||||
return self.FakeDelete()
|
||||
} else {
|
||||
_, err := SnapshotManager.GetConvertSnapshot(self)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot delete snapshot: %s, disk need at least one of snapshot as backing file", err.Error())
|
||||
if len(self.ExternalId) == 0 {
|
||||
if utils.IsInStringArray(self.Status, []string{SNAPSHOT_FAILED}) {
|
||||
return self.RealDelete(ctx, userCred)
|
||||
}
|
||||
if self.CreatedBy == MANUAL {
|
||||
if !self.FakeDeleted {
|
||||
return self.FakeDelete()
|
||||
} else {
|
||||
_, err := SnapshotManager.GetConvertSnapshot(self)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot delete snapshot: %s, disk need at least one of snapshot as backing file", err.Error())
|
||||
}
|
||||
return self.StartSnapshotDeleteTask(ctx, userCred, false, "")
|
||||
}
|
||||
return self.StartSnapshotDeleteTask(ctx, userCred, false, "")
|
||||
} else {
|
||||
return fmt.Errorf("Cannot delete snapshot created by %s", self.CreatedBy)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("Cannot delete snapshot created by %s", self.CreatedBy)
|
||||
return self.StartSnapshotDeleteTask(ctx, userCred, false, "")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,3 +342,118 @@ func totalSnapshotCount(projectId string) int {
|
||||
count := q.Equals("tenant_id", projectId).Equals("fake_deleted", false).Count()
|
||||
return count
|
||||
}
|
||||
|
||||
// Only sync snapshot status
|
||||
func (self *SSnapshot) SyncWithCloudSnapshot(userCred mcclient.TokenCredential, ext cloudprovider.ICloudSnapshot) error {
|
||||
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
|
||||
self.Status = ext.GetStatus()
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("SyncWithCloudSnapshot fail %s", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (manager *SSnapshotManager) newFromCloudSnapshot(userCred mcclient.TokenCredential, extSnapshot cloudprovider.ICloudSnapshot, region *SCloudregion) (*SSnapshot, error) {
|
||||
snapshot := SSnapshot{}
|
||||
snapshot.SetModelManager(manager)
|
||||
|
||||
snapshot.Name = extSnapshot.GetName()
|
||||
snapshot.Status = extSnapshot.GetStatus()
|
||||
snapshot.ExternalId = extSnapshot.GetGlobalId()
|
||||
if len(extSnapshot.GetDiskId()) > 0 {
|
||||
disk, err := DiskManager.FetchByExternalId(extSnapshot.GetDiskId())
|
||||
if err != nil {
|
||||
log.Errorf("snapshot %s missing disk?", snapshot.Name)
|
||||
} else {
|
||||
snapshot.DiskId = disk.GetId()
|
||||
}
|
||||
}
|
||||
|
||||
snapshot.Size = int(extSnapshot.GetSize()) * 1024
|
||||
snapshot.ManagerId = extSnapshot.GetManagerId()
|
||||
snapshot.CloudregionId = region.Id
|
||||
|
||||
snapshot.ProjectId = userCred.GetProjectId()
|
||||
err := manager.TableSpec().Insert(&snapshot)
|
||||
if err != nil {
|
||||
log.Errorf("newFromCloudEip fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
return &snapshot, nil
|
||||
}
|
||||
|
||||
func (manager *SSnapshotManager) getProviderSnapshotsByRegion(region *SCloudregion, provider *SCloudprovider) ([]SSnapshot, error) {
|
||||
if region == nil || provider == nil {
|
||||
return nil, fmt.Errorf("Region is nil or provider is nil")
|
||||
}
|
||||
snapshots := make([]SSnapshot, 0)
|
||||
q := manager.Query().Equals("cloudregion_id", region.Id).Equals("manager_id", provider.Id).NotEquals("status", SNAPSHOT_UNKNOWN)
|
||||
err := db.FetchModelObjects(manager, q, &snapshots)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snapshots, nil
|
||||
}
|
||||
|
||||
func (manager *SSnapshotManager) SyncSnapshots(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, region *SCloudregion, snapshots []cloudprovider.ICloudSnapshot) compare.SyncResult {
|
||||
syncResult := compare.SyncResult{}
|
||||
dbSnapshots, err := manager.getProviderSnapshotsByRegion(region, provider)
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return syncResult
|
||||
}
|
||||
removed := make([]SSnapshot, 0)
|
||||
commondb := make([]SSnapshot, 0)
|
||||
commonext := make([]cloudprovider.ICloudSnapshot, 0)
|
||||
added := make([]cloudprovider.ICloudSnapshot, 0)
|
||||
|
||||
err = compare.CompareSets(dbSnapshots, snapshots, &removed, &commondb, &commonext, &added)
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return syncResult
|
||||
}
|
||||
for i := 0; i < len(removed); i += 1 {
|
||||
err = removed[i].SetStatus(userCred, SNAPSHOT_UNKNOWN, "sync to delete")
|
||||
if err != nil {
|
||||
syncResult.DeleteError(err)
|
||||
} else {
|
||||
syncResult.Delete()
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(commondb); i += 1 {
|
||||
err = commondb[i].SyncWithCloudSnapshot(userCred, commonext[i])
|
||||
if err != nil {
|
||||
syncResult.UpdateError(err)
|
||||
} else {
|
||||
syncResult.Update()
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(added); i += 1 {
|
||||
_, err := manager.newFromCloudSnapshot(userCred, added[i], region)
|
||||
if err != nil {
|
||||
syncResult.AddError(err)
|
||||
} else {
|
||||
syncResult.Add()
|
||||
}
|
||||
}
|
||||
return syncResult
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetRegion() *SCloudregion {
|
||||
return CloudregionManager.FetchRegionById(self.CloudregionId)
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetISnapshotRegion() (cloudprovider.ICloudRegion, error) {
|
||||
provider, err := self.GetDriver()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
region := self.GetRegion()
|
||||
if region == nil {
|
||||
return nil, fmt.Errorf("fail to find region for snapshot")
|
||||
}
|
||||
return provider.GetIRegionById(region.GetExternalId())
|
||||
}
|
||||
|
||||
@@ -108,7 +108,6 @@ func syncCloudProviderInfo(ctx context.Context, provider *models.SCloudprovider,
|
||||
if len(syncRange.Region) > 0 && !utils.IsInStringArray(localRegions[i].Id, syncRange.Region) {
|
||||
continue
|
||||
}
|
||||
|
||||
syncRegionEips(ctx, provider, task, &localRegions[i], remoteRegions[i])
|
||||
|
||||
localZones, remoteZones := syncRegionZones(ctx, provider, task, &localRegions[i], remoteRegions[i])
|
||||
@@ -125,9 +124,29 @@ func syncCloudProviderInfo(ctx context.Context, provider *models.SCloudprovider,
|
||||
syncZoneHosts(ctx, provider, task, &localZones[j], remoteZones[j], syncRange)
|
||||
}
|
||||
}
|
||||
syncRegionSnapshots(ctx, provider, task, &localRegions[i], remoteRegions[i])
|
||||
}
|
||||
}
|
||||
|
||||
func syncRegionSnapshots(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localRegion *models.SCloudregion, remoteRegion cloudprovider.ICloudRegion) {
|
||||
snapshots, err := remoteRegion.GetISnapshots()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("GetISnapshots for region %s failed %s", remoteRegion.GetName(), err)
|
||||
log.Errorf(msg)
|
||||
logSyncFailed(provider, task, msg)
|
||||
return
|
||||
}
|
||||
|
||||
result := models.SnapshotManager.SyncSnapshots(ctx, task.GetUserCred(), provider, localRegion, snapshots)
|
||||
msg := result.Result()
|
||||
log.Infof("SyncSnapshots for region %s result: %s", localRegion.Name, msg)
|
||||
if result.IsError() {
|
||||
logSyncFailed(provider, task, msg)
|
||||
return
|
||||
}
|
||||
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, task.GetUserCred())
|
||||
}
|
||||
|
||||
func syncRegionEips(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localRegion *models.SCloudregion, remoteRegion cloudprovider.ICloudRegion) {
|
||||
eips, err := remoteRegion.GetIEips()
|
||||
if err != nil {
|
||||
@@ -405,7 +424,7 @@ func syncHostVMs(ctx context.Context, provider *models.SCloudprovider, task *Clo
|
||||
for i := 0; i < len(localVMs); i += 1 {
|
||||
syncVMNics(ctx, provider, task, localHost, &localVMs[i], remoteVMs[i])
|
||||
syncVMDisks(ctx, provider, task, localHost, &localVMs[i], remoteVMs[i])
|
||||
syncVMEip(ctx, provider, task, &localVMs[i], remoteVMs[i])
|
||||
syncVMEip(ctx, provider, task, &localVMs[i], remoteVMs[i])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,4 +484,4 @@ func syncVMEip(ctx context.Context, provider *models.SCloudprovider, task *Cloud
|
||||
return
|
||||
}
|
||||
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, task.UserCred)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,11 +45,15 @@ func (self *DiskResetTask) RequestResetDisk(ctx context.Context, disk *models.SD
|
||||
iSnapshot, _ := models.SnapshotManager.FetchById(snapshotId)
|
||||
snapshot := iSnapshot.(*models.SSnapshot)
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("snapshot_id", jsonutils.NewString(snapshot.Id))
|
||||
if snapshot.OutOfChain {
|
||||
params.Set("out_of_chain", jsonutils.JSONTrue)
|
||||
if len(snapshot.ExternalId) == 0 {
|
||||
params.Set("snapshot_id", jsonutils.NewString(snapshot.Id))
|
||||
if snapshot.OutOfChain {
|
||||
params.Set("out_of_chain", jsonutils.JSONTrue)
|
||||
} else {
|
||||
params.Set("out_of_chain", jsonutils.JSONFalse)
|
||||
}
|
||||
} else {
|
||||
params.Set("out_of_chain", jsonutils.JSONFalse)
|
||||
params.Set("snapshot_id", jsonutils.NewString(snapshot.ExternalId))
|
||||
}
|
||||
self.SetStage("OnRequestResetDisk", nil)
|
||||
err = host.GetHostDriver().RequestResetDisk(ctx, host, disk, params, self)
|
||||
@@ -71,11 +75,13 @@ func (self *DiskResetTask) OnRequestResetDisk(ctx context.Context, disk *models.
|
||||
log.Errorln(err)
|
||||
}
|
||||
}
|
||||
err := disk.CleanUpDiskSnapshots(ctx, self.UserCred, snapshot)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
self.SetStageFailed(ctx, fmt.Sprintf("OnRequestResetDisk %s", err.Error()))
|
||||
return
|
||||
if len(snapshot.ExternalId) == 0 {
|
||||
err := disk.CleanUpDiskSnapshots(ctx, self.UserCred, snapshot)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
self.SetStageFailed(ctx, fmt.Sprintf("OnRequestResetDisk %s", err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@ package tasks
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
@@ -49,19 +51,35 @@ func (self *GuestDiskSnapshotTask) DoDiskSnapshot(ctx context.Context, guest *mo
|
||||
|
||||
func (self *GuestDiskSnapshotTask) OnDiskSnapshotComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
res := data.(*jsonutils.JSONDict)
|
||||
location, err := res.GetString("location")
|
||||
if err != nil {
|
||||
log.Infof("OnDiskSnapshotComplete called with data no location")
|
||||
return
|
||||
if guest.Hypervisor == models.HYPERVISOR_KVM {
|
||||
location, err := res.GetString("location")
|
||||
if err != nil {
|
||||
log.Infof("OnDiskSnapshotComplete called with data no location")
|
||||
return
|
||||
}
|
||||
snapshotId, _ := self.Params.GetString("snapshot_id")
|
||||
iSnapshot, _ := models.SnapshotManager.FetchById(snapshotId)
|
||||
snapshot := iSnapshot.(*models.SSnapshot)
|
||||
models.SnapshotManager.TableSpec().Update(snapshot, func() error {
|
||||
snapshot.Location = location
|
||||
snapshot.Status = models.SNAPSHOT_READY
|
||||
return nil
|
||||
})
|
||||
} else {
|
||||
snapshotId, _ := self.Params.GetString("snapshot_id")
|
||||
iSnapshot, _ := models.SnapshotManager.FetchById(snapshotId)
|
||||
snapshot := iSnapshot.(*models.SSnapshot)
|
||||
extSnapshotId, _ := data.GetString("snapshot_id")
|
||||
cloudregionId, _ := data.GetString("cloudregion_id")
|
||||
managerId, _ := data.GetString("manager_id")
|
||||
models.SnapshotManager.TableSpec().Update(snapshot, func() error {
|
||||
snapshot.CloudregionId = cloudregionId
|
||||
snapshot.ExternalId = extSnapshotId
|
||||
snapshot.Status = models.SNAPSHOT_READY
|
||||
snapshot.ManagerId = managerId
|
||||
return nil
|
||||
})
|
||||
}
|
||||
snapshotId, _ := self.Params.GetString("snapshot_id")
|
||||
iSnapshot, _ := models.SnapshotManager.FetchById(snapshotId)
|
||||
snapshot := iSnapshot.(*models.SSnapshot)
|
||||
models.SnapshotManager.TableSpec().Update(snapshot, func() error {
|
||||
snapshot.Location = location
|
||||
snapshot.Status = models.SNAPSHOT_READY
|
||||
return nil
|
||||
})
|
||||
guest.SetStatus(self.UserCred, models.VM_SNAPSHOT_SUCC, "")
|
||||
self.TaskComplete(ctx, guest, nil)
|
||||
}
|
||||
@@ -108,6 +126,16 @@ type SnapshotDeleteTask struct {
|
||||
|
||||
func (self *SnapshotDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
snapshot := obj.(*models.SSnapshot)
|
||||
if len(snapshot.ExternalId) > 0 {
|
||||
err := self.deleteExternalSnapshot(ctx, snapshot)
|
||||
if err != nil {
|
||||
self.SetStageFailed(ctx, err.Error())
|
||||
} else {
|
||||
snapshot.RealDelete(ctx, self.GetUserCred())
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
return
|
||||
}
|
||||
guest, err := snapshot.GetGuest()
|
||||
if err != nil {
|
||||
if err != sql.ErrNoRows {
|
||||
@@ -126,6 +154,22 @@ func (self *SnapshotDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneMo
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SnapshotDeleteTask) deleteExternalSnapshot(ctx context.Context, snapshot *models.SSnapshot) error {
|
||||
cloudRegion, err := snapshot.GetISnapshotRegion()
|
||||
if err != nil {
|
||||
log.Errorln(err, cloudRegion, snapshot.CloudregionId)
|
||||
return err
|
||||
}
|
||||
cloudSnapshot, err := cloudRegion.GetISnapshotById(snapshot.ExternalId)
|
||||
if err != nil {
|
||||
log.Errorln(err, cloudSnapshot)
|
||||
return err
|
||||
}
|
||||
cloudSnapshot.Delete()
|
||||
err = cloudprovider.WaitDeleted(cloudSnapshot, 10*time.Second, 300*time.Second)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SnapshotDeleteTask) StartReloadDisk(ctx context.Context, snapshot *models.SSnapshot, guest *models.SGuest) {
|
||||
self.SetStage("OnReloadDiskSnapshot", nil)
|
||||
guest.SetStatus(self.UserCred, models.VM_SNAPSHOT, "Start Reload Snapshot")
|
||||
@@ -139,6 +183,7 @@ func (self *SnapshotDeleteTask) StartReloadDisk(ctx context.Context, snapshot *m
|
||||
|
||||
func (self *SnapshotDeleteTask) StartDeleteSnapshot(ctx context.Context, snapshot *models.SSnapshot, guest *models.SGuest) {
|
||||
snapshot.SetStatus(self.UserCred, models.SNAPSHOT_DELETING, "On SnapshotDeleteTask StartDeleteSnapshot")
|
||||
params := jsonutils.NewDict()
|
||||
convertSnapshot, err := models.SnapshotManager.GetConvertSnapshot(snapshot)
|
||||
if err != nil {
|
||||
self.TaskFailed(ctx, snapshot, err.Error())
|
||||
@@ -148,7 +193,6 @@ func (self *SnapshotDeleteTask) StartDeleteSnapshot(ctx context.Context, snapsho
|
||||
self.TaskFailed(ctx, snapshot, "snapshot dose not have convert snapshot")
|
||||
return
|
||||
}
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("delete_snapshot", jsonutils.NewString(snapshot.Id))
|
||||
params.Set("disk_id", jsonutils.NewString(snapshot.DiskId))
|
||||
if !snapshot.OutOfChain {
|
||||
@@ -161,9 +205,9 @@ func (self *SnapshotDeleteTask) StartDeleteSnapshot(ctx context.Context, snapsho
|
||||
} else {
|
||||
params.Set("auto_deleted", jsonutils.JSONTrue)
|
||||
}
|
||||
guest.SetStatus(self.UserCred, models.VM_SNAPSHOT_DELETE, "Start Delete Snapshot")
|
||||
|
||||
self.SetStage("OnDeleteSnapshot", nil)
|
||||
guest.SetStatus(self.UserCred, models.VM_SNAPSHOT, "Start Delete Snapshot")
|
||||
err = guest.GetDriver().RequestDeleteSnapshot(ctx, guest, self, params)
|
||||
if err != nil {
|
||||
self.TaskFailed(ctx, snapshot, err.Error())
|
||||
@@ -180,30 +224,36 @@ func (self *SnapshotDeleteTask) DeleteStaticSnapshot(ctx context.Context, snapsh
|
||||
}
|
||||
|
||||
func (self *SnapshotDeleteTask) OnDeleteSnapshot(ctx context.Context, snapshot *models.SSnapshot, data jsonutils.JSONObject) {
|
||||
if !jsonutils.QueryBoolean(data, "deleted", false) {
|
||||
log.Infof("OnDeleteSnapshot with no deleted")
|
||||
return
|
||||
}
|
||||
snapshot.SetStatus(self.UserCred, models.SNAPSHOT_READY, "OnDeleteSnapshot")
|
||||
if snapshot.OutOfChain {
|
||||
if len(snapshot.ExternalId) == 0 {
|
||||
if !jsonutils.QueryBoolean(data, "deleted", false) {
|
||||
log.Infof("OnDeleteSnapshot with no deleted")
|
||||
return
|
||||
}
|
||||
snapshot.SetStatus(self.UserCred, models.SNAPSHOT_READY, "OnDeleteSnapshot")
|
||||
if snapshot.OutOfChain {
|
||||
snapshot.RealDelete(ctx, self.UserCred)
|
||||
self.TaskComplete(ctx, snapshot, nil)
|
||||
} else {
|
||||
guest, _ := snapshot.GetGuest()
|
||||
var FakeDelete = false
|
||||
if snapshot.CreatedBy == models.MANUAL && snapshot.FakeDeleted == false {
|
||||
FakeDelete = true
|
||||
}
|
||||
if FakeDelete {
|
||||
models.SnapshotManager.TableSpec().Update(snapshot, func() error {
|
||||
snapshot.OutOfChain = true
|
||||
return nil
|
||||
})
|
||||
} else {
|
||||
snapshot.RealDelete(ctx, self.UserCred)
|
||||
}
|
||||
self.SetStage("TaskComplete", nil)
|
||||
guest.StartSyncstatus(ctx, self.UserCred, "")
|
||||
}
|
||||
} else {
|
||||
snapshot.SetStatus(self.UserCred, models.SNAPSHOT_READY, "OnDeleteSnapshot")
|
||||
snapshot.RealDelete(ctx, self.UserCred)
|
||||
self.TaskComplete(ctx, snapshot, nil)
|
||||
} else {
|
||||
guest, _ := snapshot.GetGuest()
|
||||
var FakeDelete = false
|
||||
if snapshot.CreatedBy == models.MANUAL && snapshot.FakeDeleted == false {
|
||||
FakeDelete = true
|
||||
}
|
||||
if FakeDelete {
|
||||
models.SnapshotManager.TableSpec().Update(snapshot, func() error {
|
||||
snapshot.OutOfChain = true
|
||||
return nil
|
||||
})
|
||||
} else {
|
||||
snapshot.RealDelete(ctx, self.UserCred)
|
||||
}
|
||||
self.SetStage("TaskComplete", nil)
|
||||
guest.StartSyncstatus(ctx, self.UserCred, "")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-39
@@ -271,6 +271,19 @@ func (self *SRegion) resizeDisk(diskId string, size int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) resetDisk(diskId, snapshotId string) error {
|
||||
params := make(map[string]string)
|
||||
params["DiskId"] = diskId
|
||||
params["SnapshotId"] = snapshotId
|
||||
_, err := self.ecsRequest("ResetDisk", params)
|
||||
if err != nil {
|
||||
log.Errorf("ResetDisk %s to snapshot %s fail %s", diskId, snapshotId, err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SDisk) CreateISnapshot(name, desc string) (cloudprovider.ICloudSnapshot, error) {
|
||||
if snapshotId, err := self.storage.zone.region.CreateSnapshot(self.DiskId, name, desc); err != nil {
|
||||
log.Errorf("createSnapshot fail %s", err)
|
||||
@@ -278,8 +291,8 @@ func (self *SDisk) CreateISnapshot(name, desc string) (cloudprovider.ICloudSnaps
|
||||
} else if snapshot, err := self.getSnapshot(snapshotId); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
snapshot.disk = self
|
||||
if err := cloudprovider.WaitStatus(snapshot, string(SnapshotStatusAccoplished), 15*time.Second, 3600*time.Second); err != nil {
|
||||
snapshot.region = self.storage.zone.region
|
||||
if err := cloudprovider.WaitStatus(snapshot, models.SNAPSHOT_READY, 15*time.Second, 3600*time.Second); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snapshot, nil
|
||||
@@ -305,7 +318,7 @@ func (self *SDisk) GetISnapshot(snapshotId string) (cloudprovider.ICloudSnapshot
|
||||
if snapshot, err := self.getSnapshot(snapshotId); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
snapshot.disk = self
|
||||
snapshot.region = self.storage.zone.region
|
||||
return snapshot, nil
|
||||
}
|
||||
}
|
||||
@@ -335,47 +348,14 @@ func (self *SDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
|
||||
}
|
||||
isnapshots := make([]cloudprovider.ICloudSnapshot, len(snapshots))
|
||||
for i := 0; i < len(snapshots); i++ {
|
||||
snapshots[i].disk = self
|
||||
snapshots[i].region = self.storage.zone.region
|
||||
isnapshots[i] = &snapshots[i]
|
||||
}
|
||||
return isnapshots, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetSnapshots(instanceId string, diskId string, snapshotName string, snapshotIds []string, offset int, limit int) ([]SSnapshot, int, error) {
|
||||
if limit > 50 || limit <= 0 {
|
||||
limit = 50
|
||||
}
|
||||
params := make(map[string]string)
|
||||
params["RegionId"] = self.RegionId
|
||||
params["PageSize"] = fmt.Sprintf("%d", limit)
|
||||
params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
|
||||
|
||||
if len(instanceId) > 0 {
|
||||
params["InstanceId"] = instanceId
|
||||
}
|
||||
if len(diskId) > 0 {
|
||||
params["diskId"] = diskId
|
||||
}
|
||||
if len(snapshotName) > 0 {
|
||||
params["SnapshotName"] = snapshotName
|
||||
}
|
||||
if snapshotIds != nil && len(snapshotIds) > 0 {
|
||||
params["SnapshotIds"] = jsonutils.Marshal(snapshotIds).String()
|
||||
}
|
||||
|
||||
if body, err := self.ecsRequest("DescribeSnapshots", params); err != nil {
|
||||
log.Errorf("GetSnapshots fail %s", err)
|
||||
return nil, 0, err
|
||||
} else {
|
||||
snapshots := make([]SSnapshot, 0)
|
||||
if err := body.Unmarshal(&snapshots, "Snapshots", "Snapshot"); err != nil {
|
||||
log.Errorf("Unmarshal snapshot details fail %s", err)
|
||||
return nil, 0, err
|
||||
}
|
||||
total, _ := body.Int("TotalCount")
|
||||
return snapshots, int(total), nil
|
||||
}
|
||||
|
||||
func (self *SDisk) Reset(snapshotId string) error {
|
||||
return self.storage.zone.region.resetDisk(self.DiskId, snapshotId)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -571,6 +571,26 @@ func (self *SRegion) UpdateInstancePassword(instId string, passwd string) error
|
||||
return self.updateInstance(instId, "", "", passwd, "")
|
||||
}
|
||||
|
||||
// func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
|
||||
// eips, total, err := self.GetSnapshots("", 0, 50)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// for len(eips) < total {
|
||||
// var parts []SEipAddress
|
||||
// parts, total, err = self.GetEips("", len(eips), 50)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// eips = append(eips, parts...)
|
||||
// }
|
||||
// ret := make([]cloudprovider.ICloudEIP, len(eips))
|
||||
// for i := 0; i < len(eips); i += 1 {
|
||||
// ret[i] = &eips[i]
|
||||
// }
|
||||
// return ret, nil
|
||||
// }
|
||||
|
||||
func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
|
||||
eips, total, err := self.GetEips("", 0, 50)
|
||||
if err != nil {
|
||||
@@ -603,4 +623,4 @@ func (self *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error)
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
}
|
||||
return &eips[0], nil
|
||||
}
|
||||
}
|
||||
|
||||
+109
-14
@@ -4,17 +4,22 @@ import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type SnapshotStatusType string
|
||||
|
||||
const (
|
||||
SnapshotStatusAccoplished SnapshotStatusType = "accomplished"
|
||||
SnapshotStatusProgress SnapshotStatusType = "progressing"
|
||||
SnapshotStatusAccomplished SnapshotStatusType = "accomplished"
|
||||
SnapshotStatusProgress SnapshotStatusType = "progressing"
|
||||
SnapshotStatusFailed SnapshotStatusType = "failed"
|
||||
)
|
||||
|
||||
type SSnapshot struct {
|
||||
disk *SDisk
|
||||
region *SRegion
|
||||
|
||||
Progress string
|
||||
SnapshotId string
|
||||
SnapshotName string
|
||||
@@ -34,13 +39,37 @@ func (self *SSnapshot) GetName() string {
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetStatus() string {
|
||||
return string(self.Status)
|
||||
if self.Status == SnapshotStatusAccomplished {
|
||||
return models.SNAPSHOT_READY
|
||||
} else if self.Status == SnapshotStatusProgress {
|
||||
return models.SNAPSHOT_CREATING
|
||||
} else { // if self.Status == SnapshotStatusFailed
|
||||
return models.SNAPSHOT_FAILED
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetManagerId() string {
|
||||
return self.region.client.providerId
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetRegionId() string {
|
||||
return self.region.GetId()
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetSize() int32 {
|
||||
return self.SourceDiskSize
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetDiskId() string {
|
||||
return self.SourceDiskId
|
||||
}
|
||||
|
||||
func (self *SSnapshot) Refresh() error {
|
||||
if snapshot, err := self.disk.getSnapshot(self.SnapshotId); err != nil {
|
||||
if snapshots, total, err := self.region.GetSnapshots("", "", "", []string{self.SnapshotId}, 0, 1); err != nil {
|
||||
return err
|
||||
} else if err := jsonutils.Update(self, snapshot); err != nil {
|
||||
} else if total != 1 {
|
||||
return cloudprovider.ErrNotFound
|
||||
} else if err := jsonutils.Update(self, snapshots[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -54,20 +83,86 @@ func (self *SSnapshot) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SRegion) DeleteSnapshot(snapshotId string) error {
|
||||
params := make(map[string]string)
|
||||
params["SnapshotId"] = snapshotId
|
||||
_, err := self.ecsRequest("DeleteSnapshot", params)
|
||||
return err
|
||||
func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
|
||||
snapshots, total, err := self.GetSnapshots("", "", "", []string{}, 0, 50)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for len(snapshots) < total {
|
||||
var parts []SSnapshot
|
||||
parts, total, err = self.GetSnapshots("", "", "", []string{}, len(snapshots), 50)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
snapshots = append(snapshots, parts...)
|
||||
}
|
||||
ret := make([]cloudprovider.ICloudSnapshot, len(snapshots))
|
||||
for i := 0; i < len(snapshots); i += 1 {
|
||||
ret[i] = &snapshots[i]
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SSnapshot) Delete() error {
|
||||
if self.disk == nil {
|
||||
return fmt.Errorf("not init disk for snapshot %s", self.SnapshotId)
|
||||
if self.region == nil {
|
||||
return fmt.Errorf("not init region for snapshot %s", self.SnapshotId)
|
||||
}
|
||||
return self.disk.storage.zone.region.DeleteSnapshot(self.SnapshotId)
|
||||
params := make(map[string]string)
|
||||
params["SnapshotId"] = self.SnapshotId
|
||||
_, err := self.region.ecsRequest("DeleteSnapshot", params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetSnapshots(instanceId string, diskId string, snapshotName string, snapshotIds []string, offset int, limit int) ([]SSnapshot, int, error) {
|
||||
if limit > 50 || limit <= 0 {
|
||||
limit = 50
|
||||
}
|
||||
params := make(map[string]string)
|
||||
params["RegionId"] = self.RegionId
|
||||
params["PageSize"] = fmt.Sprintf("%d", limit)
|
||||
params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
|
||||
|
||||
if len(instanceId) > 0 {
|
||||
params["InstanceId"] = instanceId
|
||||
}
|
||||
if len(diskId) > 0 {
|
||||
params["diskId"] = diskId
|
||||
}
|
||||
if len(snapshotName) > 0 {
|
||||
params["SnapshotName"] = snapshotName
|
||||
}
|
||||
if snapshotIds != nil && len(snapshotIds) > 0 {
|
||||
params["SnapshotIds"] = jsonutils.Marshal(snapshotIds).String()
|
||||
}
|
||||
|
||||
body, err := self.ecsRequest("DescribeSnapshots", params)
|
||||
if err != nil {
|
||||
log.Errorf("GetSnapshots fail %s", err)
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
snapshots := make([]SSnapshot, 0)
|
||||
if err := body.Unmarshal(&snapshots, "Snapshots", "Snapshot"); err != nil {
|
||||
log.Errorf("Unmarshal snapshot details fail %s", err)
|
||||
return nil, 0, err
|
||||
}
|
||||
total, _ := body.Int("TotalCount")
|
||||
for i := 0; i < len(snapshots); i += 1 {
|
||||
snapshots[i].region = self
|
||||
}
|
||||
return snapshots, int(total), nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetISnapshotById(snapshotId string) (cloudprovider.ICloudSnapshot, error) {
|
||||
if snapshots, total, err := self.GetSnapshots("", "", "", []string{snapshotId}, 0, 1); err != nil {
|
||||
return nil, err
|
||||
} else if total != 1 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
} else {
|
||||
return &snapshots[0], nil
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user