snapshotpolicy list create delete apply cancel finish except that disk sync snapshot policy

add copyright

fix some imprefection

fix test file
This commit is contained in:
Rain
2019-08-16 14:03:15 +08:00
parent 9bc0c41b45
commit 577dce1bc5
27 changed files with 1042 additions and 261 deletions
+4 -2
View File
@@ -42,8 +42,10 @@ const (
DISK_POST_MIGRATE = "post_migrate"
DISK_MIGRATING = "migrating"
DISK_START_SNAPSHOT = "start_snapshot"
DISK_SNAPSHOTING = "snapshoting"
DISK_START_SNAPSHOT = "start_snapshot"
DISK_SNAPSHOTING = "snapshoting"
DISK_APPLY_SNAPSHOT_FAIL = "apply_snapshot_failed"
DISK_CALCEL_SNAPSHOT_FAIL = "cancel_snapshot_failed"
DISK_TYPE_SYS = "sys"
DISK_TYPE_SWAP = "swap"
+15
View File
@@ -48,3 +48,18 @@ type SSnapshotPolicyCreateInput struct {
RepeatWeekdays []int `json:"repeat_weekdays"`
TimePoints []int `json:"time_points"`
}
type SSnapshotPolicyCreateInternalInput struct {
apis.Meta
Name string
ProjectId string
DomainId string
ManagerId string
CloudregionId string
RetentionDays int
RepeatWeekdays uint8
TimePoints uint32
}
-1
View File
@@ -18,7 +18,6 @@ import (
"context"
"fmt"
"net/http"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
+4 -3
View File
@@ -80,8 +80,8 @@ type ICloudRegion interface {
CreateSnapshotPolicy(*SnapshotPolicyInput) (string, error)
DeleteSnapshotPolicy(string) error
ApplySnapshotPolicyToDisks(snapshotPolicyId string, diskIds []string) error
CancelSnapshotPolicyToDisks(diskIds []string) error
ApplySnapshotPolicyToDisks(snapshotPolicyId string, diskId string) error
CancelSnapshotPolicyToDisks(snapshotPolicyId string, diskId string) error
GetISnapshotPolicies() ([]ICloudSnapshotPolicy, error)
GetISnapshotPolicyById(snapshotPolicyId string) (ICloudSnapshotPolicy, error)
@@ -373,7 +373,7 @@ type ICloudDisk interface {
GetISnapshot(idStr string) (ICloudSnapshot, error)
GetISnapshots() ([]ICloudSnapshot, error)
GetExtSnapshotPolicyId() string
GetExtSnapshotPolicyIds() []string
Resize(ctx context.Context, newSizeMB int64) error
Reset(ctx context.Context, snapshotId string) (string, error)
@@ -393,6 +393,7 @@ type ICloudSnapshot interface {
type ICloudSnapshotPolicy interface {
IVirtualResource
IsActivated() bool
GetRetentionDays() int
GetRepeatWeekdays() ([]int, error)
GetTimePoints() ([]int, error)
+3 -71
View File
@@ -40,7 +40,6 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/httperrors"
@@ -95,9 +94,6 @@ type SDisk struct {
DiskType string `width:"32" charset:"ascii" nullable:"true" list:"user" update:"admin"` // Column(VARCHAR(32, charset='ascii'), nullable=True)
// # is persistent
Nonpersistent bool `default:"false" list:"user"` // Column(Boolean, default=False)
AutoSnapshot bool `default:"false" nullable:"true" get:"user" update:"user"`
SnapshotPolicyId string `width:"128" charset:"ascii" nullable:"true" get:"user" list:"user" update:"user" create:"optional"`
}
func (manager *SDiskManager) GetContextManagers() [][]db.IModelManager {
@@ -759,51 +755,6 @@ func (self *SDisk) PerformResize(ctx context.Context, userCred mcclient.TokenCre
return nil, self.StartDiskResizeTask(ctx, userCred, int64(sizeMb), "", &pendingUsage, guest)
}
func (self *SDisk) AllowPerformApplySnapshotPolicy(ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
data jsonutils.JSONObject) bool {
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "apply-snapshot-policy")
}
func (self *SDisk) PerformApplySnapshotPolicy(
ctx context.Context, userCred mcclient.TokenCredential,
query jsonutils.JSONObject, data jsonutils.JSONObject,
) (jsonutils.JSONObject, error) {
spv := validators.NewModelIdOrNameValidator("snapshotpolicy", "snapshotpolicy", userCred)
if err := spv.Validate(data.(*jsonutils.JSONDict)); err != nil {
return nil, err
}
sp := spv.Model.(*SSnapshotPolicy)
return nil, sp.StartApplySnapshotPolicyToDisks(ctx, userCred, []string{self.Id})
}
func (self *SDisk) AllowPerformCancelSnapshotPolicy(ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
data jsonutils.JSONObject) bool {
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "cancel-snapshot-policy")
}
func (self *SDisk) PerformCancelSnapshotPolicy(
ctx context.Context, userCred mcclient.TokenCredential,
query jsonutils.JSONObject, data jsonutils.JSONObject,
) (jsonutils.JSONObject, error) {
if len(self.SnapshotPolicyId) == 0 {
return nil, httperrors.NewBadRequestError("Disk dosen't apply any snapshot policy")
}
return nil, self.StartCancelSnapshotPolicyToDisks(ctx, userCred)
}
func (self *SDisk) StartCancelSnapshotPolicyToDisks(ctx context.Context, userCred mcclient.TokenCredential) error {
if task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyCancelTask", self, userCred, nil, "", "", nil); err != nil {
return err
} else {
task.ScheduleRun(nil)
}
return nil
}
func (self *SDisk) GetIStorage() (cloudprovider.ICloudStorage, error) {
storage := self.GetStorage()
if storage == nil {
@@ -1210,6 +1161,7 @@ func (self *SDisk) syncRemoveCloudDisk(ctx context.Context, userCred mcclient.To
self.SetStatus(userCred, api.DISK_UNKNOWN, "missing original disk after sync")
return err
}
// todo detach joint modle about snapshotpolicy and disk
return self.RealDelete(ctx, userCred)
}
@@ -1256,13 +1208,7 @@ func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.Toke
self.CreatedAt = createdAt
}
extPolicyId := extDisk.GetExtSnapshotPolicyId()
if len(extPolicyId) > 0 {
isp, _ := db.FetchByExternalId(SnapshotPolicyManager, extPolicyId)
if isp != nil {
self.SnapshotPolicyId = isp.GetId()
}
}
// todo sync disk's snapshotpolicy
return nil
})
@@ -1311,13 +1257,7 @@ func (manager *SDiskManager) newFromCloudDisk(ctx context.Context, userCred mccl
disk.CreatedAt = createAt
}
extPolicyId := extDisk.GetExtSnapshotPolicyId()
if len(extPolicyId) > 0 {
isp, _ := db.FetchByExternalId(SnapshotPolicyManager, extPolicyId)
if isp != nil {
disk.SnapshotPolicyId = isp.GetId()
}
}
// todo create new joint model about snapshotpolicy and disk
err = manager.TableSpec().Insert(&disk)
if err != nil {
@@ -1717,14 +1657,6 @@ func (self *SDisk) GetAttachedGuests() []SGuest {
return ret
}
func (self *SDisk) SetSnapshotPolicy(policyId string) error {
_, err := db.Update(self, func() error {
self.SnapshotPolicyId = policyId
return nil
})
return err
}
func (self *SDisk) SetDiskReady(ctx context.Context, userCred mcclient.TokenCredential, reason string) {
self.SetStatus(userCred, api.DISK_READY, reason)
guests := self.GetAttachedGuests()
+5 -2
View File
@@ -82,8 +82,9 @@ type IRegionDriver interface {
ValidateCreateSnapshotPolicyData(ctx context.Context, userCred mcclient.TokenCredential, data *compute.SSnapshotPolicyCreateInput) error
RequestCreateSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *SSnapshotPolicy, task taskman.ITask) error
RequestDeleteSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *SSnapshotPolicy, task taskman.ITask) error
RequestApplySnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *SSnapshotPolicy, task taskman.ITask, diskIds []string) error
RequestCancelSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, region cloudprovider.ICloudRegion, task taskman.ITask, diskIds []string) error
// Region Driver Snapshot Policy joint Disk Apis
ValidateCreateSnapshopolicyDiskData(ctx context.Context, userCred mcclient.TokenCredential, diskID string) error
// Region Driver Snapshot Apis
ValidateSnapshotDelete(ctx context.Context, snapshot *SSnapshot) error
@@ -93,6 +94,8 @@ type IRegionDriver interface {
SnapshotIsOutOfChain(disk *SDisk) bool
GetDiskResetParams(snapshot *SSnapshot) *jsonutils.JSONDict
OnDiskReset(ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk, snapshot *SSnapshot, data jsonutils.JSONObject) error
RequestApplySnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *SSnapshotPolicy, task taskman.ITask, diskId string) error
RequestCancelSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *SSnapshotPolicy, task taskman.ITask, diskId string) error
}
var regionDrivers map[string]IRegionDriver
+67 -55
View File
@@ -17,7 +17,6 @@ package models
import (
"context"
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/util/compare"
@@ -31,6 +30,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/bitmap"
)
type SSnapshotPolicyManager struct {
@@ -46,9 +46,9 @@ type SSnapshotPolicy struct {
RetentionDays int `nullable:"false" list:"user" get:"user" create:"required"`
// {repeat_weekdays: [1,2,3,4,5,6,7], time_points: [0...23]}
RepeatWeekdays string `charset:"utf8" list:"user" get:"user" create:"required"`
TimePoints string `charset:"utf8" list:"user" get:"user" create:"required"`
RepeatWeekdays uint8 `charset:"utf8" create:"required"`
TimePoints uint32 `charset:"utf8" create:"required"`
IsActivated bool `list:"user" get:"user" create:"optional" default:"true"`
}
var SnapshotPolicyManager *SSnapshotPolicyManager
@@ -97,10 +97,31 @@ func (manager *SSnapshotPolicyManager) ValidateCreateData(ctx context.Context, u
if err != nil {
return nil, err
}
data = input.JSON(input)
internalInput := manager.sSnapshotPolicyCreateInputToInternal(input)
data = internalInput.JSON(internalInput)
return data, nil
}
func (manager *SSnapshotPolicyManager) sSnapshotPolicyCreateInputToInternal(input *api.SSnapshotPolicyCreateInput) *api.SSnapshotPolicyCreateInternalInput {
ret := api.SSnapshotPolicyCreateInternalInput{
Meta: input.Meta,
Name: input.Name,
ProjectId: input.ProjectId,
DomainId: input.DomainId,
ManagerId: input.ManagerId,
CloudregionId: input.CloudregionId,
RetentionDays: input.RetentionDays,
}
ret.RepeatWeekdays = manager.RepeatWeekdaysParseIntArray(input.RepeatWeekdays)
ret.TimePoints = manager.TimePointsParseIntArray(input.TimePoints)
return &ret
}
func (manager *SSnapshotPolicyManager) sSnapshotPolicyCreateInputFromInternal(input *api.SSnapshotPolicyCreateInternalInput) *api.SSnapshotPolicyCreateInput {
return nil
}
func (self *SSnapshotPolicy) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
self.StartCreateSnapshotPolicy(ctx, userCred, ownerId, query, data)
}
@@ -131,9 +152,26 @@ func (self *SSnapshotPolicy) StartSnapshotPolicyDeleteTask(ctx context.Context,
func (self *SSnapshotPolicy) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
ret := self.SCloudregionResourceBase.GetCustomizeColumns(ctx, userCred, query)
ret.Update(self.SVirtualResourceBase.GetCustomizeColumns(ctx, userCred, query))
// more
weekdays := SnapshotPolicyManager.RepeatWeekdaysToIntArray(self.RepeatWeekdays)
timePoints := SnapshotPolicyManager.TimePointsToIntArray(self.TimePoints)
ret.Add(jsonutils.Marshal(weekdays), "repeat_weekdays")
ret.Add(jsonutils.Marshal(timePoints), "time_points")
return ret
}
func (self *SSnapshotPolicy) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
ret := jsonutils.NewDict()
// more
weekdays := SnapshotPolicyManager.RepeatWeekdaysToIntArray(self.RepeatWeekdays)
timePoints := SnapshotPolicyManager.TimePointsToIntArray(self.TimePoints)
ret.Add(jsonutils.Marshal(weekdays), "repeat_weekdays")
ret.Add(jsonutils.Marshal(timePoints), "time_points")
return ret, nil
}
func (self *SSnapshotPolicy) GetIRegion() (cloudprovider.ICloudRegion, error) {
provider, err := self.GetDriver()
if err != nil {
@@ -146,34 +184,25 @@ func (self *SSnapshotPolicy) GetIRegion() (cloudprovider.ICloudRegion, error) {
return provider.GetIRegionById(region.ExternalId)
}
func (self *SSnapshotPolicy) GenerateCreateSpParams() (*cloudprovider.SnapshotPolicyInput, error) {
idays, err := jsonutils.ParseString(self.RepeatWeekdays)
if err != nil {
return nil, fmt.Errorf("SnapshotPolicy %s Parse repeat weekdays error %s", self.Name, err)
}
weekdays := idays.(*jsonutils.JSONArray)
intWeekdays := make([]int, weekdays.Length())
for i, v := range weekdays.Value() {
t, err := v.Int()
if err != nil {
return nil, fmt.Errorf("parse weekdays error %s", weekdays)
}
intWeekdays[i] = int(t)
}
func (self *SSnapshotPolicyManager) RepeatWeekdaysParseIntArray(nums []int) uint8 {
return uint8(bitmap.IntArray2Uint(nums))
}
idays, err = jsonutils.ParseString(self.TimePoints)
if err != nil {
return nil, fmt.Errorf("SnapshotPolicy %s Parse time points error %s", self.Name, err)
}
timePoints := idays.(*jsonutils.JSONArray)
intTimePoints := make([]int, timePoints.Length())
for i, v := range timePoints.Value() {
t, err := v.Int()
if err != nil {
return nil, fmt.Errorf("parse weekdays error %s", timePoints)
}
intTimePoints[i] = int(t)
}
func (self *SSnapshotPolicyManager) RepeatWeekdaysToIntArray(n uint8) []int {
return bitmap.Uint2IntArray(uint32(n))
}
func (self *SSnapshotPolicyManager) TimePointsParseIntArray(nums []int) uint32 {
return bitmap.IntArray2Uint(nums)
}
func (self *SSnapshotPolicyManager) TimePointsToIntArray(n uint32) []int {
return bitmap.Uint2IntArray(n)
}
func (self *SSnapshotPolicy) GenerateCreateSpParams() (*cloudprovider.SnapshotPolicyInput, error) {
intWeekdays := SnapshotPolicyManager.RepeatWeekdaysToIntArray(self.RepeatWeekdays)
intTimePoints := SnapshotPolicyManager.TimePointsToIntArray(self.TimePoints)
return &cloudprovider.SnapshotPolicyInput{
RetentionDays: self.RetentionDays,
@@ -271,19 +300,20 @@ func (self *SSnapshotPolicy) SyncWithCloudSnapshotPolicy(ctx context.Context, us
if err != nil {
return err
}
self.RepeatWeekdays = jsonutils.Marshal(arw).String()
self.RepeatWeekdays = SnapshotPolicyManager.RepeatWeekdaysParseIntArray(arw)
atp, err := ext.GetTimePoints()
if err != nil {
return err
}
self.TimePoints = jsonutils.Marshal(atp).String()
self.TimePoints = SnapshotPolicyManager.TimePointsParseIntArray(atp)
return nil
})
db.OpsLog.LogSyncUpdate(self, diff, userCred)
SyncCloudProject(userCred, self, ownerId, ext, self.ManagerId)
return err
}
func (manager *SSnapshotPolicyManager) newFromCloudSnapshotPolicy(
ctx context.Context, userCred mcclient.TokenCredential,
ext cloudprovider.ICloudSnapshotPolicy, region *SCloudregion,
@@ -307,12 +337,12 @@ func (manager *SSnapshotPolicyManager) newFromCloudSnapshotPolicy(
if err != nil {
return nil, err
}
snapshotPolicy.RepeatWeekdays = jsonutils.Marshal(arw).String()
snapshotPolicy.RepeatWeekdays = SnapshotPolicyManager.RepeatWeekdaysParseIntArray(arw)
atp, err := ext.GetTimePoints()
if err != nil {
return nil, err
}
snapshotPolicy.TimePoints = jsonutils.Marshal(atp).String()
snapshotPolicy.TimePoints = SnapshotPolicyManager.TimePointsParseIntArray(atp)
err = manager.TableSpec().Insert(&snapshotPolicy)
if err != nil {
@@ -354,24 +384,6 @@ func (self *SSnapshotPolicy) StartApplySnapshotPolicyToDisks(ctx context.Context
return nil
}
// func (self *SSnapshotPolicy) AllowPerformCancelToDisks(ctx context.Context,
// userCred mcclient.TokenCredential,
// query jsonutils.JSONObject,
// data jsonutils.JSONObject) bool {
// return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "apply-to-disks")
// }
// func (self *SSnapshotPolicy) PerformCancelToDisks(
// ctx context.Context, userCred mcclient.TokenCredential,
// query jsonutils.JSONObject, data jsonutils.JSONObject,
// ) (jsonutils.JSONObject, error) {
// diskIds, err := self.preCheck(ctx, userCred, query, data)
// if err != nil {
// return nil, err
// }
// return nil, self.StartCancelSnapshotPolicyToDisks(ctx, userCred, diskIds)
// }
func (self *SSnapshotPolicy) preCheck(
ctx context.Context, userCred mcclient.TokenCredential,
query jsonutils.JSONObject, data jsonutils.JSONObject,
@@ -404,4 +416,4 @@ func (self *SSnapshotPolicy) preCheck(
return nil, httperrors.NewNotFoundError("Disks %v not found", notFoundDisks)
}
return diskIds, nil
}
}
+133
View File
@@ -0,0 +1,133 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package models
import (
"context"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/mcclient"
)
type SSnapshotPolicyDiskManager struct {
db.SVirtualJointResourceBaseManager
}
func (manager *SSnapshotPolicyDiskManager) GetMasterFieldName() string {
return "disk_id"
}
func (manager *SSnapshotPolicyDiskManager) GetSlaveFieldName() string {
return "snapshotpolicy_id"
}
var SnapshotPolicyDiskManager *SSnapshotPolicyDiskManager
func init() {
db.InitManager(func() {
SnapshotPolicyDiskManager = &SSnapshotPolicyDiskManager{
SVirtualJointResourceBaseManager: db.NewVirtualJointResourceBaseManager(
SSnapshotPolicyDisk{},
"snapshotpolicydisks_tbl",
"snapshotpolicydisk",
"snapshotpolicydisks",
DiskManager,
SnapshotPolicyManager,
),
}
SnapshotPolicyDiskManager.SetVirtualObject(SnapshotPolicyDiskManager)
})
}
type SSnapshotPolicyDisk struct {
db.SVirtualJointResourceBase
SnapshotpolicyId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"`
DiskId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"`
}
func (self *SSnapshotPolicyDisk) Detach(ctx context.Context, userCred mcclient.TokenCredential) error {
return db.DetachJoint(ctx, userCred, self)
}
func (self *SSnapshotPolicyDiskManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
cloudregionV := validators.NewModelIdOrNameValidator("cloudregion", "cloudregion", ownerId)
err := cloudregionV.Validate(data)
if err != nil {
return nil, err
}
cloudregion := cloudregionV.Model.(*SCloudregion)
diskId, _ := data.GetString(self.GetMasterManager().Keyword())
err = cloudregion.GetDriver().ValidateCreateSnapshopolicyDiskData(ctx, userCred, diskId)
if err != nil {
return nil, err
}
return data, nil
}
func (self *SSnapshotPolicyDiskManager) FetchAllSnapshotPolicyOfDisk(ctx context.Context, userCred mcclient.TokenCredential, diskID string) ([]SSnapshotPolicyDisk, error) {
q := self.Query()
q.Equals(self.GetMasterFieldName(), diskID)
ret := make([]SSnapshotPolicyDisk, 0)
err := db.FetchModelObjects(self, q, &ret)
if err != nil {
return nil, err
}
return ret, nil
}
func (self *SSnapshotPolicyDisk) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
diskID := self.DiskId
model, err := DiskManager.FetchById(diskID)
if err != nil {
log.Errorf("Fetch disk by ID %s failed", diskID)
}
disk := model.(*SDisk)
snapshotPolicyID := self.SnapshotpolicyId
taskData := jsonutils.NewDict()
taskData.Add(jsonutils.NewString(snapshotPolicyID), "snapshot_policy_id")
task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyApplyTask", disk, userCred, taskData, "", "", nil)
if err != nil {
log.Errorf("SnapshotPolicyApplyTask newTask error %s", err)
} else {
task.ScheduleRun(nil)
}
}
func (self *SSnapshotPolicyDisk) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
diskID := self.DiskId
model, err := DiskManager.FetchById(diskID)
if err != nil {
return errors.Wrapf(err, "Fetch disk by ID %s failed", diskID)
}
disk := model.(*SDisk)
snapshotPolicyID := self.SnapshotpolicyId
taskData := jsonutils.NewDict()
taskData.Add(jsonutils.NewString(snapshotPolicyID), "snapshot_policy_id")
task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyCancelTask", disk, userCred, taskData, "", "", nil)
if err != nil {
return errors.Wrapf(err, "SnapshotPolicyCancelTask newTask error %s", err)
} else {
task.ScheduleRun(nil)
}
return nil
}
+15 -17
View File
@@ -823,27 +823,25 @@ func daysValidate(days []int, min, max int) ([]int, error) {
return days, nil
}
func (self *SAliyunRegionDriver) ValidateCreateSnapshopolicyDiskData(ctx context.Context, userCred mcclient.TokenCredential, diskID string) error {
ret, err := models.SnapshotPolicyDiskManager.FetchAllSnapshotPolicyOfDisk(ctx, userCred, diskID)
if err != nil {
return err
}
if len(ret) != 0 {
return httperrors.NewBadRequestError("One disk could't attach two snapshot policy in aliyun; please detach last one first.")
}
return nil
}
func (self *SAliyunRegionDriver) ValidateCreateSnapshotPolicyData(ctx context.Context, userCred mcclient.TokenCredential, data *compute.SSnapshotPolicyCreateInput) error {
var err error
err := self.SManagedVirtualizationRegionDriver.ValidateCreateSnapshotPolicyData(ctx, userCred, data)
if err != nil {
return err
}
if data.RetentionDays < -1 || data.RetentionDays == 0 || data.RetentionDays > 65535 {
return httperrors.NewInputParameterError("Retention days must in 1~65535 or -1")
}
if len(data.RepeatWeekdays) == 0 {
return httperrors.NewMissingParameterError("repeat_weekdays")
}
data.RepeatWeekdays, err = daysValidate(data.RepeatWeekdays, 1, 7)
if err != nil {
return httperrors.NewInputParameterError(err.Error())
}
if len(data.TimePoints) == 0 {
return httperrors.NewInputParameterError("time_points")
}
data.TimePoints, err = daysValidate(data.TimePoints, 0, 23)
if err != nil {
return httperrors.NewInputParameterError(err.Error())
}
return nil
}
+6 -2
View File
@@ -138,11 +138,11 @@ func (self *SBaseRegionDriver) RequestDeleteSnapshotPolicy(ctx context.Context,
return fmt.Errorf("Not Implement RequestDeleteSnapshotPolicy")
}
func (self *SBaseRegionDriver) RequestApplySnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask, diskIds []string) error {
func (self *SBaseRegionDriver) RequestApplySnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask, diskId string) error {
return fmt.Errorf("Not Implement RequestApplySnapshotPolicy")
}
func (self *SBaseRegionDriver) RequestCancelSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, region cloudprovider.ICloudRegion, task taskman.ITask, diskIds []string) error {
func (self *SBaseRegionDriver) RequestCancelSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask, diskId string) error {
return fmt.Errorf("Not Implement RequestApplySnapshotPolicy")
}
@@ -173,3 +173,7 @@ func (self *SBaseRegionDriver) GetDiskResetParams(snapshot *models.SSnapshot) *j
func (self *SBaseRegionDriver) OnDiskReset(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, snapshot *models.SSnapshot, data *jsonutils.JSONObject) error {
return fmt.Errorf("Not Implement OnDiskReset")
}
func (self *SBaseRegionDriver) ValidateCreateSnapshopolicyDiskData(ctx context.Context, userCred mcclient.TokenCredential, diskID string) error {
return fmt.Errorf("Not Implement ValidateCreateSnapshotpolicyDiskData")
}
+34 -4
View File
@@ -25,6 +25,7 @@ import (
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/apis/compute"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
@@ -1087,13 +1088,13 @@ func (self *SManagedVirtualizationRegionDriver) RequestDeleteSnapshotPolicy(ctx
return nil
}
func (self *SManagedVirtualizationRegionDriver) RequestApplySnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask, diskIds []string) error {
func (self *SManagedVirtualizationRegionDriver) RequestApplySnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask, diskId string) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
iRegion, err := sp.GetIRegion()
if err != nil {
return nil, err
}
err = iRegion.ApplySnapshotPolicyToDisks(sp.GetExternalId(), diskIds)
err = iRegion.ApplySnapshotPolicyToDisks(sp.GetExternalId(), diskId)
if err != nil {
return nil, err
}
@@ -1102,9 +1103,13 @@ func (self *SManagedVirtualizationRegionDriver) RequestApplySnapshotPolicy(ctx c
return nil
}
func (self *SManagedVirtualizationRegionDriver) RequestCancelSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, region cloudprovider.ICloudRegion, task taskman.ITask, diskIds []string) error {
func (self *SManagedVirtualizationRegionDriver) RequestCancelSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask, diskId string) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
err := region.CancelSnapshotPolicyToDisks(diskIds)
iRegion, err := sp.GetIRegion()
if err != nil {
return nil, err
}
err = iRegion.CancelSnapshotPolicyToDisks(sp.GetExternalId(), diskId)
if err != nil {
return nil, err
}
@@ -1183,3 +1188,28 @@ func (self *SManagedVirtualizationRegionDriver) OnDiskReset(ctx context.Context,
}
return iDisk.Refresh()
}
func (self *SManagedVirtualizationRegionDriver) ValidateCreateSnapshotPolicyData(ctx context.Context, userCred mcclient.TokenCredential, data *compute.SSnapshotPolicyCreateInput) error {
var err error
if len(data.RepeatWeekdays) == 0 {
return httperrors.NewMissingParameterError("repeat_weekdays")
}
data.RepeatWeekdays, err = daysValidate(data.RepeatWeekdays, 1, 7)
if err != nil {
return httperrors.NewInputParameterError(err.Error())
}
if len(data.TimePoints) == 0 {
return httperrors.NewInputParameterError("time_points")
}
data.TimePoints, err = daysValidate(data.TimePoints, 0, 23)
if err != nil {
return httperrors.NewInputParameterError(err.Error())
}
return nil
}
func (self *SManagedVirtualizationRegionDriver) ValidateCreateSnapshopolicyDiskData(ctx context.Context, userCred mcclient.TokenCredential, diskID string) error {
return nil
}
+14 -2
View File
@@ -20,16 +20,17 @@ import (
"regexp"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/onecloud/pkg/util/rand"
"yunion.io/x/onecloud/pkg/apis/compute"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rand"
)
type SQcloudRegionDriver struct {
@@ -743,3 +744,14 @@ func (self *SQcloudRegionDriver) ValidateCreateLoadbalancerBackendData(ctx conte
data.Set("cloudregion_id", jsonutils.NewString(lb.CloudregionId))
return data, nil
}
func (self *SQcloudRegionDriver) ValidateCreateSnapshotPolicyData(ctx context.Context, userCred mcclient.TokenCredential, data *compute.SSnapshotPolicyCreateInput) error {
err := self.SManagedVirtualizationRegionDriver.ValidateCreateSnapshotPolicyData(ctx, userCred, data)
if err != nil {
return err
}
if data.RetentionDays < -1 || data.RetentionDays == 0 || data.RetentionDays > 65535 {
return httperrors.NewInputParameterError("Retention days must in 1~65535 or -1")
}
return nil
}
+1
View File
@@ -153,6 +153,7 @@ func InitHandlers(app *appsrv.Application) {
models.CloudproviderRegionManager,
models.DBInstanceNetworkManager,
models.NetworkinterfacenetworkManager,
models.SnapshotPolicyDiskManager,
} {
db.RegisterModelManager(manager)
handler := db.NewJointModelHandler(manager)
+53 -90
View File
@@ -19,6 +19,7 @@ import (
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
@@ -81,86 +82,51 @@ type SnapshotPolicyApplyTask struct {
taskman.STask
}
func (self *SnapshotPolicyApplyTask) taskFail(ctx context.Context, sp *models.SSnapshotPolicy, reason string) {
stringIds, _ := getDiskIds(self)
disks := make([]models.SDisk, 0)
q := models.DiskManager.Query().In("id", stringIds)
err := db.FetchModelObjects(models.DiskManager, q, &disks)
if err == nil {
for i := 0; i < len(disks); i++ {
db.OpsLog.LogEvent(&disks[i], db.ACT_APPLY_SNAPSHOT_POLICY_FAILED, reason, self.UserCred)
logclient.AddActionLogWithStartable(self, &disks[i], logclient.ACT_APPLY_SNAPSHOT_POLICY, reason, self.UserCred, false)
}
func (self *SnapshotPolicyApplyTask) taskFail(ctx context.Context, disk *models.SDisk, snapshotPolicyId, reason string) {
jointModel, err := db.FetchJointByIds(models.SnapshotPolicyDiskManager, self.Id, snapshotPolicyId, jsonutils.JSONNull)
if err != nil {
log.Errorf("Fetch SnapshotPolicy %s Disk %s joint model failed, need to delete", self.Id, snapshotPolicyId)
return
}
snapshotPolicyDisk := jointModel.(*models.SSnapshotPolicyDisk)
err = snapshotPolicyDisk.Detach(ctx, self.UserCred)
if err != nil {
log.Errorf("Delete SnapshotPolicy %s Disk %s joint model failed, need to delete", self.Id, snapshotPolicyId)
}
disk.SetStatus(self.UserCred, compute.DISK_APPLY_SNAPSHOT_FAIL, reason)
db.OpsLog.LogEvent(disk, db.ACT_APPLY_SNAPSHOT_POLICY_FAILED, reason, self.UserCred)
logclient.AddActionLogWithStartable(self, disk, logclient.ACT_APPLY_SNAPSHOT_POLICY, reason, self.UserCred, false)
self.SetStageFailed(ctx, reason)
}
func getDiskIds(task *SnapshotPolicyApplyTask) ([]string, error) {
diskIds, err := task.Params.GetArray("disk_ids")
if err != nil {
return nil, fmt.Errorf("Missing parasm disk_ids")
}
stringIds := make([]string, len(diskIds))
for i := 0; i < len(diskIds); i++ {
stringIds[i], _ = diskIds[i].GetString()
}
return stringIds, nil
}
func (self *SnapshotPolicyApplyTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
snapshotPolicy := obj.(*models.SSnapshotPolicy)
disk := obj.(*models.SDisk)
snapshotPolicyID, _ := self.Params.GetString("snapshot_policy_id")
region := snapshotPolicy.GetRegion()
if region == nil {
self.taskFail(ctx, snapshotPolicy, fmt.Sprintf("failed to find region for snapshot policy %s", snapshotPolicy.Name))
return
}
stringIds, err := getDiskIds(self)
iregion, err := disk.GetIRegion()
if err != nil {
self.taskFail(ctx, snapshotPolicy, err.Error())
self.taskFail(ctx, disk, snapshotPolicyID, fmt.Sprintf("failed to find iregion for snapshot policy %s: %s", disk.Id, err.Error()))
return
}
diskExt, err := models.DiskManager.Query("external_id").In("id", stringIds).AllStringMap()
// fetch disk model by diksID
model, err := models.SnapshotPolicyManager.FetchById(snapshotPolicyID)
if err != nil {
self.taskFail(ctx, snapshotPolicy, fmt.Sprintf("Fetch disks external_id failed %s", err))
self.taskFail(ctx, disk, snapshotPolicyID, fmt.Sprintf("failed to fetch disk by id %s: %s", snapshotPolicyID, err.Error()))
return
}
diskExtIds := make([]string, 0)
for i := 0; i < len(diskExt); i++ {
val, ok := diskExt[i]["external_id"]
if ok {
diskExtIds = append(diskExtIds, val)
}
}
snapshotPolicy := model.(*models.SSnapshotPolicy)
self.SetStage("OnSnapshotPolicyApply", nil)
if err := region.GetDriver().RequestApplySnapshotPolicy(ctx, self.GetUserCred(), snapshotPolicy, self, diskExtIds); err != nil {
self.taskFail(ctx, snapshotPolicy, err.Error())
if err := iregion.ApplySnapshotPolicyToDisks(snapshotPolicy.ExternalId, disk.ExternalId); err != nil {
self.taskFail(ctx, disk, snapshotPolicyID, fmt.Sprintf("faile to attach snapshot policy %s and disk %s: %s", snapshotPolicy.Id, disk.Id, err.Error()))
}
}
func (self *SnapshotPolicyApplyTask) OnSnapshotPolicyApply(ctx context.Context, sp *models.SSnapshotPolicy, data jsonutils.JSONObject) {
stringIds, _ := getDiskIds(self)
disks := make([]models.SDisk, 0)
q := models.DiskManager.Query().In("id", stringIds)
err := db.FetchModelObjects(models.DiskManager, q, &disks)
if err != nil {
self.taskFail(ctx, sp, fmt.Sprintf("Fetch disks failed %s", err))
return
}
for i := 0; i < len(disks); i++ {
disks[i].SetSnapshotPolicy(sp.Id)
db.OpsLog.LogEvent(&disks[i], db.ACT_APPLY_SNAPSHOT_POLICY, nil, self.UserCred)
logclient.AddActionLogWithStartable(self, &disks[i], logclient.ACT_APPLY_SNAPSHOT_POLICY, nil, self.UserCred, true)
}
db.OpsLog.LogEvent(disk, db.ACT_APPLY_SNAPSHOT_POLICY, "", self.UserCred)
logclient.AddActionLogWithStartable(self, disk, logclient.ACT_APPLY_SNAPSHOT_POLICY, "", self.UserCred, true)
self.SetStageComplete(ctx, nil)
}
func (self *SnapshotPolicyApplyTask) OnSnapshotPolicyApplyFailed(ctx context.Context, sp *models.SSnapshotPolicy, data jsonutils.JSONObject) {
self.taskFail(ctx, sp, data.String())
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
@@ -169,7 +135,18 @@ type SnapshotPolicyCancelTask struct {
taskman.STask
}
func (self *SnapshotPolicyCancelTask) taskFail(ctx context.Context, disk *models.SDisk, reason string) {
func (self *SnapshotPolicyCancelTask) taskFail(ctx context.Context, disk *models.SDisk, snapshotPolicyId, reason string) {
jointModel, err := db.FetchJointByIds(models.SnapshotPolicyDiskManager, self.Id, snapshotPolicyId, jsonutils.JSONNull)
if err != nil {
log.Errorf("Fetch SnapshotPolicy %s Disk %s joint model failed, need to mark undelete", self.Id, snapshotPolicyId)
return
}
snapshotPolicyDisk := jointModel.(*models.SSnapshotPolicyDisk)
err = snapshotPolicyDisk.MarkUnDelete()
if err != nil {
log.Errorf("Mark undelete joint model snapshotPolicy %s and disk %s failes", snapshotPolicyId, disk.Id)
}
disk.SetStatus(self.UserCred, compute.DISK_CALCEL_SNAPSHOT_FAIL, reason)
db.OpsLog.LogEvent(disk, db.ACT_CANCEL_SNAPSHOT_POLICY_FAILED, reason, self.UserCred)
logclient.AddActionLogWithStartable(self, disk, logclient.ACT_CANCEL_SNAPSHOT_POLICY, reason, self.UserCred, false)
self.SetStageFailed(ctx, reason)
@@ -177,42 +154,28 @@ func (self *SnapshotPolicyCancelTask) taskFail(ctx context.Context, disk *models
func (self *SnapshotPolicyCancelTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
disk := obj.(*models.SDisk)
storage := disk.GetStorage()
if storage == nil {
self.taskFail(ctx, disk, fmt.Sprintf("failed to find storage for disk %s", disk.Name))
return
}
region := storage.GetRegion()
if region == nil {
self.taskFail(ctx, disk, fmt.Sprintf("failed to find region for disk %s", disk.Name))
snapshotPolicyID, _ := self.GetParams().GetString("snapshot_policy_id")
// get region
iregion, err := disk.GetIRegion()
if err != nil {
self.taskFail(ctx, disk, snapshotPolicyID, fmt.Sprintf("failed to find iregion for disk %s: %s", disk.Name, err.Error()))
return
}
iSnapshotPolicy, err := models.SnapshotPolicyManager.FetchById(disk.SnapshotPolicyId)
model, err := models.SnapshotPolicyManager.FetchById(snapshotPolicyID)
if err != nil {
self.taskFail(ctx, disk, fmt.Sprintf("failed to find snapshot policy for disk %s, %s", disk.Name, err))
self.taskFail(ctx, disk, snapshotPolicyID, fmt.Sprintf("failed to fetch disk by id %s: %s", snapshotPolicyID, err.Error()))
return
}
snapshotPolicy := iSnapshotPolicy.(*models.SSnapshotPolicy)
iRegion, err := snapshotPolicy.GetIRegion()
if err != nil {
self.taskFail(ctx, disk, fmt.Sprintf("failed to find region for snapshot policy %s", snapshotPolicy.Name))
return
}
self.SetStage("OnSnapshotPolicyCancel", nil)
if err := region.GetDriver().RequestCancelSnapshotPolicy(
ctx, self.GetUserCred(), iRegion, self, []string{disk.ExternalId}); err != nil {
self.taskFail(ctx, disk, err.Error())
}
}
func (self *SnapshotPolicyCancelTask) OnSnapshotPolicyCancel(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
disk.SetSnapshotPolicy("")
snapshotPolicy := model.(*models.SSnapshotPolicy)
self.SetStage("OnSnapshotPolicyApply", nil)
if err := iregion.CancelSnapshotPolicyToDisks(snapshotPolicy.ExternalId, disk.ExternalId); err != nil {
self.taskFail(ctx, disk, snapshotPolicyID, fmt.Sprintf("faile to detach snapshot policy %s and disk %s: %s", snapshotPolicy.Id, disk.Id, err.Error()))
}
db.OpsLog.LogEvent(disk, db.ACT_CANCEL_SNAPSHOT_POLICY, "", self.UserCred)
logclient.AddActionLogWithStartable(self, disk, logclient.ACT_CANCEL_SNAPSHOT_POLICY, "", self.UserCred, true)
self.SetStageComplete(ctx, nil)
}
func (self *SnapshotPolicyCancelTask) OnSnapshotPolicyCancelFailed(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
self.taskFail(ctx, disk, data.String())
}
@@ -0,0 +1,30 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package modules
var (
SnapshotPolicyDisk JointResourceManager
)
func init() {
SnapshotPolicyDisk = NewJointComputeManager(
"snapshotpolicydisk",
"snapshotpolicydisks",
[]string{"Disk_ID", "Snapshotpolicy_ID"},
[]string{},
&Disks,
&SnapshotPoliciy)
registerCompute(&SnapshotPolicyDisk)
}
+2 -2
View File
@@ -405,8 +405,8 @@ func (self *SDisk) GetCreatedAt() time.Time {
return self.CreationTime
}
func (self *SDisk) GetExtSnapshotPolicyId() string {
return self.AutoSnapshotPolicyId
func (self *SDisk) GetExtSnapshotPolicyIds() []string {
return []string{self.AutoSnapshotPolicyId}
}
func (self *SDisk) GetExpiredAt() time.Time {
@@ -0,0 +1,95 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud/aliyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type SSnapshotPolicyListOptions struct {
PolicyId string `help:"snapshot policy id"`
Offset int `help:"offset"`
Limit int `help:"limit"`
}
shellutils.R(&SSnapshotPolicyListOptions{}, "snapshot-policy-list", "list snapshot policy",
func(cli *aliyun.SRegion, args *SSnapshotPolicyListOptions) error {
snapshotPolicis, num, err := cli.GetSnapshotPolicies(args.PolicyId, args.Offset, args.Limit)
if err != nil {
return err
}
printList(snapshotPolicis, num, args.Offset, args.Limit, []string{})
return nil
},
)
type SSnapshotPolicyDeleteOptions struct {
ID string `help:"snapshot id"`
}
shellutils.R(&SSnapshotPolicyDeleteOptions{}, "snapshot-policy-delete", "delete snapshot policy",
func(cli *aliyun.SRegion, args *SSnapshotPolicyDeleteOptions) error {
err := cli.DeleteSnapshotPolicy(args.ID)
return err
},
)
type SSnapshotPolicyCreateOptions struct {
Name string `help:"snapshot name"`
RetentionDays int `help:"retention days"`
RepeatWeekdays []int `help:"auto snapshot which days of the week"`
TimePoints []int `help:"auto snapshot which hours of the day"`
}
shellutils.R(&SSnapshotPolicyCreateOptions{}, "snapshot-policy-create", "create snapshot policy",
func(cli *aliyun.SRegion, args *SSnapshotPolicyCreateOptions) error {
input := cloudprovider.SnapshotPolicyInput{
RetentionDays: args.RetentionDays,
RepeatWeekdays: args.RepeatWeekdays,
TimePoints: args.TimePoints,
PolicyName: args.Name,
}
_, err := cli.CreateSnapshotPolicy(&input)
if err != nil {
return err
}
return nil
},
)
type SSnapshotPolicyApplyOptions struct {
SNAPSHOTPOLICYID string `help:"snapshot policy id"`
DISKID string `help:"disk id"`
}
shellutils.R(&SSnapshotPolicyApplyOptions{}, "snapshot-policy-apply", "apply snapshot policy",
func(cli *aliyun.SRegion, args *SSnapshotPolicyApplyOptions) error {
err := cli.ApplySnapshotPolicyToDisks(args.SNAPSHOTPOLICYID, args.DISKID)
return err
},
)
type SSnapshotPolicyCancelOptions struct {
SNAPSHOTPOLICYID string `help:"snapshot policy id"`
DISKID string `help":disk id"`
}
shellutils.R(&SSnapshotPolicyCancelOptions{}, "snapshot-policy-cancel", "cancel snapshot policy",
func(cli *aliyun.SRegion, args *SSnapshotPolicyCancelOptions) error {
err := cli.CancelSnapshotPolicyToDisks(args.SNAPSHOTPOLICYID, args.DISKID)
return err
},
)
}
+12 -4
View File
@@ -135,6 +135,10 @@ func (self *SSnapshotPolicy) GetTimePoints() ([]int, error) {
return parsePolicy(self.TimePoints)
}
func (self *SSnapshotPolicy) IsActivated() bool {
return true
}
func (self *SRegion) GetISnapshotPolicies() ([]cloudprovider.ICloudSnapshotPolicy, error) {
snapshotPolicies, total, err := self.GetSnapshotPolicies("", 0, 50)
if err != nil {
@@ -159,8 +163,10 @@ func (self *SRegion) GetSnapshotPolicies(policyId string, offset int, limit int)
params := make(map[string]string)
params["RegionId"] = self.RegionId
params["PageSize"] = fmt.Sprintf("%d", limit)
params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
if limit != 0 {
params["PageSize"] = fmt.Sprintf("%d", limit)
params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
}
if len(policyId) > 0 {
params["AutoSnapshotPolicyId"] = policyId
@@ -253,10 +259,11 @@ func (self *SRegion) UpdateSnapshotPolicy(
return nil
}
func (self *SRegion) ApplySnapshotPolicyToDisks(snapshotPolicyId string, diskIds []string) error {
func (self *SRegion) ApplySnapshotPolicyToDisks(snapshotPolicyId string, diskId string) error {
params := make(map[string]string)
params["RegionId"] = self.RegionId
params["autoSnapshotPolicyId"] = snapshotPolicyId
diskIds := []string{diskId}
params["diskIds"] = jsonutils.Marshal(diskIds).String()
_, err := self.ecsRequest("ApplyAutoSnapshotPolicy", params)
if err != nil {
@@ -265,9 +272,10 @@ func (self *SRegion) ApplySnapshotPolicyToDisks(snapshotPolicyId string, diskIds
return nil
}
func (self *SRegion) CancelSnapshotPolicyToDisks(diskIds []string) error {
func (self *SRegion) CancelSnapshotPolicyToDisks(snapshotPolicyId string, diskId string) error {
params := make(map[string]string)
params["RegionId"] = self.RegionId
diskIds := []string{diskId}
params["diskIds"] = jsonutils.Marshal(diskIds).String()
_, err := self.ecsRequest("CancelAutoSnapshotPolicy", params)
if err != nil {
+15
View File
@@ -0,0 +1,15 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package aws
+2 -2
View File
@@ -16,8 +16,8 @@ package multicloud
type SDisk struct{}
func (self *SDisk) GetExtSnapshotPolicyId() string {
return ""
func (self *SDisk) GetExtSnapshotPolicyIds() []string {
return []string{""}
}
func (self *SDisk) GetIStorageId() string {
+2 -2
View File
@@ -186,11 +186,11 @@ func (cli *SObjectStoreClient) DeleteSnapshotPolicy(string) error {
return cloudprovider.ErrNotSupported
}
func (cli *SObjectStoreClient) ApplySnapshotPolicyToDisks(snapshotPolicyId string, diskIds []string) error {
func (cli *SObjectStoreClient) ApplySnapshotPolicyToDisks(snapshotPolicyId string, diskId string) error {
return cloudprovider.ErrNotSupported
}
func (cli *SObjectStoreClient) CancelSnapshotPolicyToDisks(diskIds []string) error {
func (cli *SObjectStoreClient) CancelSnapshotPolicyToDisks(snapshotPolicyId string, diskId string) error {
return cloudprovider.ErrNotSupported
}
@@ -0,0 +1,96 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud/qcloud"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type SSnapshotPolicyListOptions struct {
PolicyId string `help:"snapshot policy id"`
Offset int `help:"offset"`
Limit int `help:"limit"`
}
shellutils.R(&SSnapshotPolicyListOptions{}, "snapshot-policy-list", "list snapshot policy",
func(cli *qcloud.SRegion, args *SSnapshotPolicyListOptions) error {
snapshotPolicis, num, err := cli.GetSnapshotPolicies(args.PolicyId, args.Offset, args.Limit)
if err != nil {
return err
}
printList(snapshotPolicis, num, args.Offset, args.Limit, []string{})
return nil
},
)
type SSnapshotPolicyDeleteOptions struct {
ID string `help:"snapshot id"`
}
shellutils.R(&SSnapshotPolicyDeleteOptions{}, "snapshot-policy-delete", "delete snapshot policy",
func(cli *qcloud.SRegion, args *SSnapshotPolicyDeleteOptions) error {
err := cli.DeleteSnapshotPolicy(args.ID)
return err
},
)
type SSnapshotPolicyCreateOptions struct {
Name string `help:"snapshot name"`
RetentionDays int `help:"retention days"`
RepeatWeekdays []int `help:"auto snapshot which days of the week"`
TimePoints []int `help:"auto snapshot which hours of the day"`
}
shellutils.R(&SSnapshotPolicyCreateOptions{}, "snapshot-policy-create", "create snapshot policy",
func(cli *qcloud.SRegion, args *SSnapshotPolicyCreateOptions) error {
input := cloudprovider.SnapshotPolicyInput{
RetentionDays: args.RetentionDays,
RepeatWeekdays: args.RepeatWeekdays,
TimePoints: args.TimePoints,
PolicyName: args.Name,
}
_, err := cli.CreateSnapshotPolicy(&input)
if err != nil {
return err
}
return nil
},
)
type SSnapshotPolicyApplyOptions struct {
SNAPSHOTPOLICYID string `help:"snapshot policy id"`
DISKID string `help:"disk id"`
}
shellutils.R(&SSnapshotPolicyApplyOptions{}, "snapshot-policy-apply", "apply snapshot policy",
func(cli *qcloud.SRegion, args *SSnapshotPolicyApplyOptions) error {
err := cli.ApplySnapshotPolicyToDisks(args.SNAPSHOTPOLICYID, args.DISKID)
return err
},
)
type SSnapshotPolicyCancelOptions struct {
SNAPSHOTPOLICYID string `help:"snapshot policy id"`
DISKID string `help:"disk id"`
}
shellutils.R(&SSnapshotPolicyCancelOptions{}, "snapshot-policy-cancel", "cancel snapshot policy",
func(cli *qcloud.SRegion, args *SSnapshotPolicyCancelOptions) error {
err := cli.CancelSnapshotPolicyToDisks(args.SNAPSHOTPOLICYID, args.DISKID)
return err
},
)
}
+240
View File
@@ -0,0 +1,240 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package qcloud
import (
"fmt"
"strconv"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
const (
NORMAL = "NORMAL"
UNKOWN = "ISOLATED"
)
type SPolicy struct {
DayOfWeek []int
Hour []int
}
type SSnapshotPolicy struct {
region *SRegion
AutoSnapshotPolicyName string
AutoSnapshotPolicyId string
AutoSnapshotPolicyState string
RetentionDays int
Policy []SPolicy
Activated bool `json:"is_activated"`
IsPermanent bool
}
func (self *SSnapshotPolicy) GetId() string {
return self.AutoSnapshotPolicyId
}
func (self *SSnapshotPolicy) GetName() string {
return self.AutoSnapshotPolicyName
}
func (self *SSnapshotPolicy) GetGlobalId() string {
return self.GetId()
}
func (self *SSnapshotPolicy) GetStatus() string {
if self.AutoSnapshotPolicyState == NORMAL {
return api.SNAPSHOT_POLICY_READY
}
return api.SNAPSHOT_POLICY_UNKNOWN
}
func (self *SSnapshotPolicy) Refresh() error {
if snapshotPolicies, total, err := self.region.GetSnapshotPolicies(self.AutoSnapshotPolicyId, 0, 1); err != nil {
return err
} else if total != 1 {
return cloudprovider.ErrNotFound
} else if err := jsonutils.Update(self, snapshotPolicies[0]); err != nil {
return err
}
return nil
}
func (self *SSnapshotPolicy) IsEmulated() bool {
return false
}
func (self *SSnapshotPolicy) GetMetadata() *jsonutils.JSONDict {
return nil
}
func (self *SSnapshotPolicy) GetProjectId() string {
return ""
}
func (self *SSnapshotPolicy) GetRetentionDays() int {
return self.RetentionDays
}
func (self *SSnapshotPolicy) GetRepeatWeekdays() ([]int, error) {
if len(self.Policy) == 0 {
return nil, errors.Error("Policy Set Empty")
}
return self.Policy[0].DayOfWeek, nil
}
func (self *SSnapshotPolicy) GetTimePoints() ([]int, error) {
if len(self.Policy) == 0 {
return nil, errors.Error("Policy Set Empty")
}
return self.Policy[0].Hour, nil
}
func (self *SSnapshotPolicy) IsActivated() bool {
return self.Activated
}
func (self *SRegion) GetISnapshotPolicies() ([]cloudprovider.ICloudSnapshotPolicy, error) {
snapshotPolicies, total, err := self.GetSnapshotPolicies("", 0, 50)
if err != nil {
return nil, err
}
for len(snapshotPolicies) < total {
var parts []SSnapshotPolicy
parts, total, err = self.GetSnapshotPolicies("", len(snapshotPolicies), 50)
if err != nil {
return nil, err
}
snapshotPolicies = append(snapshotPolicies, parts...)
}
ret := make([]cloudprovider.ICloudSnapshotPolicy, len(snapshotPolicies))
for i := 0; i < len(snapshotPolicies); i += 1 {
ret[i] = &snapshotPolicies[i]
}
return ret, nil
}
func (self *SRegion) GetSnapshotPolicies(policyId string, offset int, limit int) ([]SSnapshotPolicy, int, error) {
params := make(map[string]string)
if len(policyId) > 0 {
params["AutoSnapshotPolicyIds.0"] = policyId
}
if limit != 0 {
params["Limit"] = strconv.Itoa(limit)
params["Offset"] = strconv.Itoa(offset)
}
body, err := self.cbsRequest("DescribeAutoSnapshotPolicies", params)
if err != nil {
return nil, 0, errors.Wrap(err, "Get Snapshot Policies failed")
}
snapshotPolicies := make([]SSnapshotPolicy, 0, 1)
if err := body.Unmarshal(&snapshotPolicies, "AutoSnapshotPolicySet"); err != nil {
return nil, 0, errors.Wrap(err, "Unmarshal snapshot policies detail failed")
}
return snapshotPolicies, len(snapshotPolicies), nil
}
func (self *SSnapshotPolicy) Delete() error {
if self.region == nil {
return fmt.Errorf("Not init region for snapshotPolicy %s", self.GetId())
}
return self.region.DeleteSnapshotPolicy(self.GetId())
}
func (self *SRegion) DeleteSnapshotPolicy(snapshotPolicyId string) error {
params := make(map[string]string)
params["AutoSnapshotPolicyIds.0"] = snapshotPolicyId
_, err := self.cbsRequest("DeleteAutoSnapshotPolicies", params)
if err != nil {
return errors.Wrapf(err, "delete auto snapshot policy %s failed", snapshotPolicyId)
}
return nil
}
func (self *SRegion) GetISnapshotPolicyById(snapshotPolicyId string) (cloudprovider.ICloudSnapshotPolicy, error) {
policies, _, err := self.GetSnapshotPolicies(snapshotPolicyId, 0, 1)
if err != nil {
return nil, err
}
if len(policies) == 0 {
return nil, cloudprovider.ErrNotFound
}
return &policies[0], nil
}
func (self *SRegion) CreateSnapshotPolicy(input *cloudprovider.SnapshotPolicyInput) (string, error) {
if input.RepeatWeekdays == nil {
return "", fmt.Errorf("Can't create snapshot policy with nil repeatWeekdays")
}
if input.TimePoints == nil {
return "", fmt.Errorf("Can't create snapshot policy with nil timePoints")
}
params := make(map[string]string)
params["RetentionDays"] = strconv.Itoa(input.RetentionDays)
dayOfWeekPrefix, hourPrefix := "Policy.0.DayOfWeek.", "Policy.0.Hour."
for index, day := range input.RepeatWeekdays {
if day == 0 {
day = 7
}
params[dayOfWeekPrefix+strconv.Itoa(index)] = strconv.Itoa(day)
}
if len(input.PolicyName) > 0 {
params["AutoSnapshotPolicyName"] = input.PolicyName
}
for index, hour := range input.TimePoints {
params[hourPrefix+strconv.Itoa(index)] = strconv.Itoa(hour)
}
body, err := self.cbsRequest("CreateAutoSnapshotPolicy", params)
if err != nil {
return "", errors.Wrap(err, "create auto snapshot policy failed")
}
id, _ := body.GetString("AutoSnapshotPolicyId")
return id, nil
}
func (self *SRegion) UpdateSnapshotPolicy(
snapshotPolicyId string, retentionDays *int,
repeatWeekdays, timePoints *jsonutils.JSONArray, policyName string,
) error {
// not implement
return nil
}
func (self *SRegion) ApplySnapshotPolicyToDisks(snapshotPolicyId string, diskId string) error {
params := make(map[string]string)
params["AutoSnapshotPolicyId"] = snapshotPolicyId
params["DiskIds.0"] = diskId
_, err := self.cbsRequest("BindAutoSnapshotPolicy", params)
if err != nil {
return errors.Wrapf(err, "Bind AutoSnapshotPolicy %s to Disk failed", snapshotPolicyId)
}
return nil
}
func (self *SRegion) CancelSnapshotPolicyToDisks(snapshotPolicyId string, diskId string) error {
params := make(map[string]string)
params["AutoSnapshotPolicyId"] = snapshotPolicyId
params["DiskIds.0"] = diskId
_, err := self.cbsRequest("UnbindAutoSnapshotPolicy", params)
if err != nil {
return errors.Wrapf(err, "Unbind AutoSnapshotPolicy %s of Disk failed", snapshotPolicyId)
}
return nil
}
+2 -2
View File
@@ -38,11 +38,11 @@ func (self *SRegion) DeleteSnapshotPolicy(string) error {
return fmt.Errorf("DeleteSnapshotPolicy not implement")
}
func (self *SRegion) ApplySnapshotPolicyToDisks(snapshotPolicyId string, diskIds []string) error {
func (self *SRegion) ApplySnapshotPolicyToDisks(snapshotPolicyId string, diskId string) error {
return fmt.Errorf("ApplySnapshotPolicyToDisks not implement")
}
func (self *SRegion) CancelSnapshotPolicyToDisks(diskIds []string) error {
func (self *SRegion) CancelSnapshotPolicyToDisks(snapshotPolicyId string, diskId string) error {
return fmt.Errorf("ApplySnapshotPolicyToDisks not implement")
}
+36
View File
@@ -0,0 +1,36 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package bitmap
func Uint2IntArray(n uint32) []int {
ret := make([]int, 0, 2)
var i uint = 0
for n != 0 {
if n&(1<<i) != 0 {
n &= uint32(^(1 << i))
ret = append(ret, int(i))
}
i++
}
return ret
}
func IntArray2Uint(nums []int) uint32 {
var ret uint32 = 0
for _, i := range nums {
ret |= (1 << uint(i))
}
return ret
}
+76
View File
@@ -0,0 +1,76 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package bitmap
import (
"math"
"testing"
)
func TestUint2IntArray(t *testing.T) {
oneCase := make([]int, 32)
for i := range oneCase {
oneCase[i] = i
}
testCase := []struct {
input uint32
want []int
}{
{24, []int{3, 4}},
{0, []int{}},
{math.MaxUint32, oneCase},
}
for _, tc := range testCase {
real := Uint2IntArray(tc.input)
if !sliceEqual(real, tc.want) {
t.Fatalf("want %v, but %v\n", tc.want, real)
}
}
}
func sliceEqual(a, b []int) bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return false
}
}
return true
}
func TestIntArray2Uint(t *testing.T) {
oneCase := make([]int, 32)
for i := range oneCase {
oneCase[i] = i
}
testCase := []struct {
want uint32
input []int
}{
{24, []int{3, 4}},
{0, []int{}},
{math.MaxUint32, oneCase},
}
for _, tc := range testCase {
real := IntArray2Uint(tc.input)
if tc.want != real {
t.Fatalf("want %d, but %d\n", tc.want, real)
}
}
}