mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-21 08:33:54 +08:00
log for snapshotpolicy docs auto sync add performCache for snapshotpolicy detach snapshotpolicy after detach disk and guest fix sync snapshot of disk in qcloud
709 lines
24 KiB
Go
709 lines
24 KiB
Go
// 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"
|
|
"fmt"
|
|
|
|
"yunion.io/x/jsonutils"
|
|
"yunion.io/x/log"
|
|
"yunion.io/x/pkg/errors"
|
|
"yunion.io/x/pkg/tristate"
|
|
"yunion.io/x/pkg/util/compare"
|
|
"yunion.io/x/sqlchemy"
|
|
|
|
api "yunion.io/x/onecloud/pkg/apis/compute"
|
|
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
|
"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/options"
|
|
"yunion.io/x/onecloud/pkg/httperrors"
|
|
"yunion.io/x/onecloud/pkg/mcclient"
|
|
"yunion.io/x/onecloud/pkg/util/bitmap"
|
|
"yunion.io/x/onecloud/pkg/util/validate"
|
|
)
|
|
|
|
type SSnapshotPolicyManager struct {
|
|
db.SVirtualResourceBaseManager
|
|
}
|
|
|
|
type SSnapshotPolicy struct {
|
|
db.SVirtualResourceBase
|
|
//db.SExternalizedResourceBase
|
|
//
|
|
//SManagedResourceBase
|
|
//SCloudregionResourceBase
|
|
|
|
RetentionDays int `nullable:"false" list:"user" get:"user" create:"required"`
|
|
|
|
// 0~6, 0 is Monday
|
|
RepeatWeekdays uint8 `charset:"utf8" create:"required"`
|
|
// 0~23
|
|
TimePoints uint32 `charset:"utf8" create:"required"`
|
|
IsActivated tristate.TriState `list:"user" get:"user" create:"optional" default:"true"`
|
|
}
|
|
|
|
var SnapshotPolicyManager *SSnapshotPolicyManager
|
|
|
|
func init() {
|
|
SnapshotPolicyManager = &SSnapshotPolicyManager{
|
|
SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
|
|
SSnapshotPolicy{},
|
|
"snapshotpolicies_tbl",
|
|
"snapshotpolicy",
|
|
"snapshotpolicies",
|
|
),
|
|
}
|
|
SnapshotPolicyManager.SetVirtualObject(SnapshotPolicyManager)
|
|
}
|
|
|
|
func (manager *SSnapshotPolicyManager) ValidateListConditions(ctx context.Context, userCred mcclient.TokenCredential,
|
|
query *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
|
|
|
input := &api.SSnapshotPolicyCreateInput{}
|
|
err := query.Unmarshal(input)
|
|
if err != nil {
|
|
return nil, httperrors.NewInputParameterError("Unmarshal input failed %s", err)
|
|
}
|
|
if query.Contains("repeat_weekdays") {
|
|
query.Remove("repeat_weekdays")
|
|
query.Add(jsonutils.NewInt(int64(manager.RepeatWeekdaysParseIntArray(input.RepeatWeekdays))), "repeat_weekdays")
|
|
}
|
|
if query.Contains("time_points") {
|
|
query.Remove("time_points")
|
|
query.Add(jsonutils.NewInt(int64(manager.RepeatWeekdaysParseIntArray(input.RepeatWeekdays))), "time_points")
|
|
}
|
|
return query, nil
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
|
|
return false
|
|
}
|
|
|
|
// ==================================================== fetch ==========================================================
|
|
func (manager *SSnapshotPolicyManager) GetSnapshotPoliciesAt(week, timePoint uint32) ([]string, error) {
|
|
|
|
q := manager.Query("id")
|
|
q = q.Filter(sqlchemy.Equals(sqlchemy.AND_Val("", q.Field("repeat_weekdays"), 1<<week), 1<<week))
|
|
q = q.Filter(sqlchemy.Equals(sqlchemy.AND_Val("", q.Field("time_points"), 1<<timePoint), 1<<timePoint))
|
|
q = q.Equals("is_activated", true)
|
|
|
|
sps := make([]SSnapshotPolicy, 0)
|
|
err := q.All(&sps)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(sps) > 0 {
|
|
ret := make([]string, len(sps))
|
|
for i := 0; i < len(sps); i++ {
|
|
ret[i] = sps[i].Id
|
|
}
|
|
return ret, nil
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (manager *SSnapshotPolicyManager) FetchSnapshotPolicyById(spId string) (*SSnapshotPolicy, error) {
|
|
sp, err := manager.FetchById(spId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return sp.(*SSnapshotPolicy), nil
|
|
}
|
|
|
|
func (manager *SSnapshotPolicyManager) FetchAllByIds(spIds []string) ([]SSnapshotPolicy, error) {
|
|
if spIds == nil || len(spIds) == 0 {
|
|
return []SSnapshotPolicy{}, nil
|
|
}
|
|
q := manager.Query().In("id", spIds)
|
|
sps := make([]SSnapshotPolicy, 0, 1)
|
|
err := db.FetchModelObjects(manager, q, &sps)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return sps, nil
|
|
}
|
|
|
|
// ==================================================== create =========================================================
|
|
|
|
func (manager *SSnapshotPolicyManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential,
|
|
ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
|
|
|
input := &api.SSnapshotPolicyCreateInput{}
|
|
err := data.Unmarshal(input)
|
|
if err != nil {
|
|
return nil, httperrors.NewInputParameterError("Unmarshal input failed %s", err)
|
|
}
|
|
input.ProjectId = ownerId.GetProjectId()
|
|
input.DomainId = ownerId.GetProjectDomainId()
|
|
|
|
err = db.NewNameValidator(manager, ownerId, input.Name, "")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if input.RetentionDays < -1 || input.RetentionDays == 0 || input.RetentionDays > options.Options.RetentionDaysLimit {
|
|
return nil, httperrors.NewInputParameterError("Retention days must in 1~%d or -1", options.Options.RetentionDaysLimit)
|
|
}
|
|
|
|
if len(input.RepeatWeekdays) == 0 {
|
|
return nil, httperrors.NewMissingParameterError("repeat_weekdays")
|
|
}
|
|
|
|
if len(input.RepeatWeekdays) > options.Options.RepeatWeekdaysLimit {
|
|
return nil, httperrors.NewInputParameterError("repeat_weekdays only contains %d days at most",
|
|
options.Options.RepeatWeekdaysLimit)
|
|
}
|
|
input.RepeatWeekdays, err = validate.DaysCheck(input.RepeatWeekdays, 1, 7)
|
|
if err != nil {
|
|
return nil, httperrors.NewInputParameterError(err.Error())
|
|
}
|
|
|
|
if len(input.TimePoints) == 0 {
|
|
return nil, httperrors.NewMissingParameterError("time_points")
|
|
}
|
|
if len(input.TimePoints) > options.Options.TimePointsLimit {
|
|
return nil, httperrors.NewInputParameterError("time_points only contains %d points at most", options.Options.TimePointsLimit)
|
|
}
|
|
input.TimePoints, err = validate.DaysCheck(input.TimePoints, 0, 23)
|
|
if err != nil {
|
|
return nil, httperrors.NewInputParameterError(err.Error())
|
|
}
|
|
|
|
internalInput := manager.sSnapshotPolicyCreateInputToInternal(input)
|
|
data = internalInput.JSON(internalInput)
|
|
return data, nil
|
|
}
|
|
|
|
// ==================================================== update =========================================================
|
|
|
|
func (sp *SSnapshotPolicy) AllowPerformUpdate(ctx context.Context, userCred mcclient.TokenCredential,
|
|
query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
|
// no fo now
|
|
return false
|
|
//return sp.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, sp, "update")
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) PerformUpdate(ctx context.Context, userCred mcclient.TokenCredential,
|
|
query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
|
//check param
|
|
input := &api.SSnapshotPolicyCreateInput{}
|
|
err := data.Unmarshal(input)
|
|
if err != nil {
|
|
return nil, httperrors.NewInputParameterError("Unmarshel input failed %s", err)
|
|
}
|
|
err = sp.UpdateParamCheck(input)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return nil, sp.StartSnapshotPolicyUpdateTask(ctx, userCred, input)
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) StartSnapshotPolicyUpdateTask(ctx context.Context, userCred mcclient.TokenCredential,
|
|
input *api.SSnapshotPolicyCreateInput) error {
|
|
|
|
params := jsonutils.NewDict()
|
|
params.Add(jsonutils.Marshal(input), "input")
|
|
sp.SetStatus(userCred, api.SNAPSHOT_POLICY_UPDATING, "")
|
|
if task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyUpdateTask", sp, userCred, params,
|
|
"", "", nil); err == nil {
|
|
return err
|
|
} else {
|
|
task.ScheduleRun(nil)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// UpdateParamCheck check if update parameters are correct and need to update
|
|
func (sp *SSnapshotPolicy) UpdateParamCheck(input *api.SSnapshotPolicyCreateInput) error {
|
|
var err error
|
|
updateNum := 0
|
|
|
|
if input.RetentionDays != 0 {
|
|
if input.RetentionDays < -1 || input.RetentionDays > 65535 {
|
|
return httperrors.NewInputParameterError("Retention days must in 1~65535 or -1")
|
|
}
|
|
if input.RetentionDays != sp.RetentionDays {
|
|
updateNum++
|
|
}
|
|
}
|
|
|
|
if input.RepeatWeekdays != nil && len(input.RepeatWeekdays) != 0 {
|
|
input.RepeatWeekdays, err = validate.DaysCheck(input.RepeatWeekdays, 1, 7)
|
|
if err != nil {
|
|
return httperrors.NewInputParameterError(err.Error())
|
|
}
|
|
if sp.RepeatWeekdays != SnapshotPolicyManager.RepeatWeekdaysParseIntArray(input.RepeatWeekdays) {
|
|
updateNum++
|
|
}
|
|
}
|
|
|
|
if input.TimePoints != nil && len(input.TimePoints) != 0 {
|
|
input.TimePoints, err = validate.DaysCheck(input.TimePoints, 0, 23)
|
|
if err != nil {
|
|
return httperrors.NewInputParameterError(err.Error())
|
|
}
|
|
if sp.TimePoints != SnapshotPolicyManager.TimePointsParseIntArray(input.TimePoints) {
|
|
updateNum++
|
|
}
|
|
}
|
|
|
|
if updateNum == 0 {
|
|
return httperrors.NewInputParameterError("Do not need to update")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ==================================================== delete =========================================================
|
|
|
|
func (sp *SSnapshotPolicy) DetachAfterDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
|
err := SnapshotPolicyDiskManager.SyncDetachBySnapshotpolicy(ctx, userCred, nil, sp)
|
|
if err != nil {
|
|
return errors.Wrap(err, "detach after delete failed")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.
|
|
JSONObject, data jsonutils.JSONObject) error {
|
|
|
|
// check if sp bind to some disks
|
|
sds, err := SnapshotPolicyDiskManager.FetchAllBySnapshotpolicyID(ctx, userCred, sp.GetId())
|
|
if err != nil {
|
|
return errors.Wrap(err, "fetch bind info failed")
|
|
}
|
|
if len(sds) != 0 {
|
|
return httperrors.NewBadRequestError("Couldn't delete snapshot policy binding to disks")
|
|
}
|
|
sp.SetStatus(userCred, api.SNAPSHOT_POLICY_DELETING, "")
|
|
return sp.StartSnapshotPolicyDeleteTask(ctx, userCred, jsonutils.NewDict(), "")
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) StartSnapshotPolicyDeleteTask(ctx context.Context, userCred mcclient.TokenCredential,
|
|
params *jsonutils.JSONDict, parentTaskId string) error {
|
|
|
|
task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyDeleteTask", sp, userCred, params,
|
|
parentTaskId, "", nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
task.ScheduleRun(nil)
|
|
return nil
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential,
|
|
query jsonutils.JSONObject) *jsonutils.JSONDict {
|
|
|
|
ret, _ := sp.getMoreDetails(ctx, userCred, query)
|
|
return ret
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential,
|
|
query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
|
|
|
|
return sp.getMoreDetails(ctx, userCred, query)
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) getMoreDetails(ctx context.Context, userCred mcclient.TokenCredential,
|
|
query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
|
|
|
|
ret := query.(*jsonutils.JSONDict)
|
|
// more
|
|
weekdays := SnapshotPolicyManager.RepeatWeekdaysToIntArray(sp.RepeatWeekdays)
|
|
timePoints := SnapshotPolicyManager.TimePointsToIntArray(sp.TimePoints)
|
|
ret.Add(jsonutils.Marshal(weekdays), "repeat_weekdays")
|
|
ret.Add(jsonutils.Marshal(timePoints), "time_points")
|
|
count, err := SnapshotPolicyDiskManager.FetchDiskCountBySPID(sp.Id)
|
|
if err != nil {
|
|
return ret, err
|
|
}
|
|
ret.Add(jsonutils.NewInt(int64(count)), "binding_disk_count")
|
|
return ret, nil
|
|
}
|
|
|
|
// ==================================================== sync ===========================================================
|
|
func (manager *SSnapshotPolicyManager) SyncSnapshotPolicies(ctx context.Context, userCred mcclient.TokenCredential,
|
|
provider *SCloudprovider, region *SCloudregion, cloudSPs []cloudprovider.ICloudSnapshotPolicy,
|
|
syncOwnerId mcclient.IIdentityProvider) compare.SyncResult {
|
|
|
|
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, syncOwnerId))
|
|
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, syncOwnerId))
|
|
syncResult := compare.SyncResult{}
|
|
|
|
// Fetch allsnapshotpolicy caches
|
|
spCaches, err := SnapshotPolicyCacheManager.FetchAllByRegionProvider(region.GetId(), provider.GetId())
|
|
if err != nil {
|
|
syncResult.Error(err)
|
|
return syncResult
|
|
}
|
|
spIdSet, spIds := make(map[string]struct{}), make([]string, 0, 2)
|
|
for _, spCache := range spCaches {
|
|
if _, ok := spIdSet[spCache.SnapshotpolicyId]; !ok {
|
|
spIds = append(spIds, spCache.SnapshotpolicyId)
|
|
spIdSet[spCache.SnapshotpolicyId] = struct{}{}
|
|
}
|
|
}
|
|
|
|
// Fetch allsnapshotpolicy of caches above
|
|
snapshotPolicies, err := manager.FetchAllByIds(spIds)
|
|
if err != nil {
|
|
syncResult.Error(err)
|
|
return syncResult
|
|
}
|
|
|
|
// structure two sets (externalID, snapshotpolicyCache), (snapshotPolicyID, snapshotPolicy)
|
|
spSet, spCacheSet := make(map[string]*SSnapshotPolicy), make(map[string]*SSnapshotPolicyCache)
|
|
for i := range snapshotPolicies {
|
|
spSet[snapshotPolicies[i].GetId()] = &snapshotPolicies[i]
|
|
}
|
|
for i := range spCaches {
|
|
externalId := spCaches[i].ExternalId
|
|
if len(externalId) != 0 {
|
|
spCacheSet[spCaches[i].ExternalId] = &spCaches[i]
|
|
}
|
|
}
|
|
|
|
// start sync
|
|
// add forsnapshotpolicy and cache
|
|
// delete forsnapshotpolicy cache
|
|
added := make([]cloudprovider.ICloudSnapshotPolicy, 0, 1)
|
|
removed := make([]*SSnapshotPolicyCache, 0, 1)
|
|
for _, cloudSP := range cloudSPs {
|
|
spCache, ok := spCacheSet[cloudSP.GetGlobalId()]
|
|
if !ok {
|
|
added = append(added, cloudSP)
|
|
continue
|
|
}
|
|
snapshotPolicy := spSet[spCache.SnapshotpolicyId]
|
|
if !snapshotPolicy.Equals(cloudSP) {
|
|
removed = append(removed, spCache)
|
|
added = append(added, cloudSP)
|
|
}
|
|
}
|
|
|
|
for i := range removed {
|
|
// changesnapshotpolicy cache
|
|
err := removed[i].RealDetele(ctx, userCred)
|
|
if err != nil {
|
|
syncResult.DeleteError(err)
|
|
}
|
|
}
|
|
|
|
for i := range added {
|
|
locol, err := manager.newFromCloudSnapshotPolicy(ctx, userCred, added[i], region, syncOwnerId, provider)
|
|
if err != nil {
|
|
syncResult.AddError(err)
|
|
} else {
|
|
syncMetadata(ctx, userCred, locol, added[i])
|
|
syncResult.Add()
|
|
}
|
|
}
|
|
return compare.SyncResult{}
|
|
}
|
|
|
|
func (manager *SSnapshotPolicyManager) newFromCloudSnapshotPolicy(
|
|
ctx context.Context, userCred mcclient.TokenCredential,
|
|
ext cloudprovider.ICloudSnapshotPolicy, region *SCloudregion,
|
|
syncOwnerId mcclient.IIdentityProvider, provider *SCloudprovider,
|
|
) (*SSnapshotPolicy, error) {
|
|
|
|
snapshotPolicy := SSnapshotPolicy{}
|
|
snapshotPolicy.SetModelManager(manager, &snapshotPolicy)
|
|
|
|
newName, err := db.GenerateName(manager, syncOwnerId, ext.GetName())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
snapshotPolicy.Name = newName
|
|
snapshotPolicy.Status = ext.GetStatus()
|
|
snapshotPolicy.RetentionDays = ext.GetRetentionDays()
|
|
arw, err := ext.GetRepeatWeekdays()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
snapshotPolicy.RepeatWeekdays = SnapshotPolicyManager.RepeatWeekdaysParseIntArray(arw)
|
|
atp, err := ext.GetTimePoints()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
snapshotPolicy.TimePoints = SnapshotPolicyManager.TimePointsParseIntArray(atp)
|
|
|
|
snapshotPolicy.IsActivated = tristate.NewFromBool(ext.IsActivated())
|
|
|
|
err = manager.TableSpec().Insert(&snapshotPolicy)
|
|
if err != nil {
|
|
log.Errorf("newFromCloudEip fail %s", err)
|
|
return nil, err
|
|
}
|
|
|
|
// add cache
|
|
_, err = SnapshotPolicyCacheManager.NewCacheWithExternalId(ctx, userCred, snapshotPolicy.GetId(),
|
|
ext.GetGlobalId(), region.GetId(), provider.GetId())
|
|
if err != nil {
|
|
//snapshotpolicy has been exist so that created is successful although cache created is fail.
|
|
// disk will be sync aftersnapshotpolicy sync, cache must be right so that this sync is fail
|
|
log.Errorf("snapshotpolicy %s created successfully but corresponding cache created fail", snapshotPolicy.GetId())
|
|
return nil, errors.Wrapf(err, "snapshotpolicy %s created successfully but corresponding cache created fail",
|
|
snapshotPolicy.GetId())
|
|
}
|
|
|
|
SyncCloudProject(userCred, &snapshotPolicy, syncOwnerId, ext, provider.GetId())
|
|
|
|
db.OpsLog.LogEvent(&snapshotPolicy, db.ACT_CREATE, snapshotPolicy.GetShortDesc(ctx), userCred)
|
|
return &snapshotPolicy, nil
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) Equals(cloudSP cloudprovider.ICloudSnapshotPolicy) bool {
|
|
rws, err := cloudSP.GetRepeatWeekdays()
|
|
if err != nil {
|
|
return false
|
|
}
|
|
tps, err := cloudSP.GetTimePoints()
|
|
if err != nil {
|
|
return false
|
|
}
|
|
repeatWeekdays := SnapshotPolicyManager.RepeatWeekdaysParseIntArray(rws)
|
|
timePoints := SnapshotPolicyManager.TimePointsParseIntArray(tps)
|
|
|
|
return sp.RetentionDays == cloudSP.GetRetentionDays() && sp.RepeatWeekdays == repeatWeekdays && sp.
|
|
TimePoints == timePoints && sp.IsActivated.Bool() == cloudSP.IsActivated()
|
|
}
|
|
|
|
func (manager *SSnapshotPolicyManager) getProviderSnapshotPolicies(region *SCloudregion, provider *SCloudprovider) ([]SSnapshotPolicy, error) {
|
|
if region == nil && provider == nil {
|
|
return nil, fmt.Errorf("Region is nil or provider is nil")
|
|
}
|
|
snapshotPolicies := make([]SSnapshotPolicy, 0)
|
|
q := manager.Query().Equals("cloudregion_id", region.Id).Equals("manager_id", provider.Id)
|
|
err := db.FetchModelObjects(manager, q, &snapshotPolicies)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return snapshotPolicies, nil
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) syncRemoveCloudSnapshot(ctx context.Context, userCred mcclient.TokenCredential) error {
|
|
lockman.LockObject(ctx, sp)
|
|
defer lockman.ReleaseObject(ctx, sp)
|
|
|
|
err := sp.ValidateDeleteCondition(ctx)
|
|
if err != nil {
|
|
err = sp.SetStatus(userCred, api.SNAPSHOT_POLICY_UNKNOWN, "sync to delete")
|
|
} else {
|
|
err = sp.RealDelete(ctx, userCred)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
|
return nil
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
|
return db.DeleteModel(ctx, userCred, sp)
|
|
}
|
|
|
|
// ==================================================== utils ==========================================================
|
|
|
|
func (manager *SSnapshotPolicyManager) sSnapshotPolicyCreateInputToInternal(input *api.SSnapshotPolicyCreateInput,
|
|
) *api.SSnapshotPolicyCreateInternalInput {
|
|
ret := api.SSnapshotPolicyCreateInternalInput{
|
|
Meta: input.Meta,
|
|
Name: input.Name,
|
|
ProjectId: input.ProjectId,
|
|
DomainId: input.DomainId,
|
|
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 *SSnapshotPolicyManager) RepeatWeekdaysParseIntArray(nums []int) uint8 {
|
|
return uint8(bitmap.IntArray2Uint(nums))
|
|
}
|
|
|
|
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 (sp *SSnapshotPolicy) GenerateCreateSpParams() *cloudprovider.SnapshotPolicyInput {
|
|
intWeekdays := SnapshotPolicyManager.RepeatWeekdaysToIntArray(sp.RepeatWeekdays)
|
|
intTimePoints := SnapshotPolicyManager.TimePointsToIntArray(sp.TimePoints)
|
|
|
|
return &cloudprovider.SnapshotPolicyInput{
|
|
RetentionDays: sp.RetentionDays,
|
|
RepeatWeekdays: intWeekdays,
|
|
TimePoints: intTimePoints,
|
|
PolicyName: sp.Name,
|
|
}
|
|
}
|
|
|
|
// ==================================================== action =========================================================
|
|
func (sp *SSnapshotPolicy) AllowPerformCache(ctx context.Context, userCred mcclient.TokenCredential,
|
|
query jsonutils.JSONObject) bool {
|
|
|
|
return sp.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, sp, "cache")
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) PerformCache(ctx context.Context, userCred mcclient.TokenCredential,
|
|
query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
|
|
|
regionId := jsonutils.GetAnyString(data, []string{"region_id", "cloudregion_id"})
|
|
if len(regionId) == 0 {
|
|
return nil, httperrors.NewMissingParameterError("region_id or cloudregion_id")
|
|
}
|
|
providerId, err := data.GetString("provider_id")
|
|
if err != nil {
|
|
return nil, httperrors.NewMissingParameterError("provider_id")
|
|
}
|
|
_, err = SnapshotPolicyCacheManager.NewCache(ctx, userCred, sp.Id, regionId, providerId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) AllowPerformBindDisks(ctx context.Context, userCred mcclient.TokenCredential,
|
|
query jsonutils.JSONObject) bool {
|
|
|
|
return sp.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, sp, "bind-disks")
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) PerformBindDisks(ctx context.Context, userCred mcclient.TokenCredential,
|
|
query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
|
|
|
disks := jsonutils.GetArrayOfPrefix(data, "disk")
|
|
if len(disks) == 0 {
|
|
return nil, httperrors.NewMissingParameterError("disk.0 disk.1 ... ")
|
|
}
|
|
|
|
//database
|
|
diskSlice := make([]*SDisk, len(disks))
|
|
for i := range disks {
|
|
diskId, _ := disks[i].GetString()
|
|
disk := DiskManager.FetchDiskById(diskId)
|
|
if disk == nil {
|
|
return nil, httperrors.NewInputParameterError("no such disk %s", diskId)
|
|
}
|
|
disk.SetModelManager(DiskManager, disk)
|
|
diskSlice[i] = disk
|
|
}
|
|
|
|
taskDisk := make([]*SDisk, 0, len(diskSlice))
|
|
taskSpd := make([]*SSnapshotPolicyDisk, 0, len(diskSlice))
|
|
for _, disk := range diskSlice {
|
|
spd, err := SnapshotPolicyDiskManager.newSnapshotpolicyDisk(ctx, userCred, sp, disk)
|
|
if err == ErrExistSD {
|
|
if spd.Status == "init" {
|
|
taskDisk = append(taskDisk, disk)
|
|
taskSpd = append(taskSpd, spd)
|
|
}
|
|
continue
|
|
}
|
|
if err != nil {
|
|
return nil, fmt.Errorf("oper for database error")
|
|
}
|
|
taskDisk = append(taskDisk, disk)
|
|
taskSpd = append(taskSpd, spd)
|
|
}
|
|
|
|
for i := range taskDisk {
|
|
// field 'need_detach' is not needed, because the the subject is snapshot policy not disk
|
|
taskdata := jsonutils.NewDict()
|
|
taskdata.Add(jsonutils.Marshal(taskSpd[i]), "snapshotPolicyDisk")
|
|
taskdata.Add(jsonutils.Marshal(sp), "snapshotPolicy")
|
|
if task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyApplyTask", taskDisk[i], userCred, nil,
|
|
"", "", nil); err != nil {
|
|
continue
|
|
} else {
|
|
task.ScheduleRun(taskdata)
|
|
}
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) AllowPerformUnbindDisks(ctx context.Context, userCred mcclient.TokenCredential,
|
|
query jsonutils.JSONObject) bool {
|
|
|
|
return sp.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, sp, "bind-disks")
|
|
}
|
|
|
|
func (sp *SSnapshotPolicy) PerformUnbindDisks(ctx context.Context, userCred mcclient.TokenCredential,
|
|
query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
|
|
|
disks := jsonutils.GetArrayOfPrefix(data, "disk")
|
|
if len(disks) == 0 {
|
|
return nil, httperrors.NewMissingParameterError("disk.0 disk.1 ... ")
|
|
}
|
|
|
|
diskSlice := make([]*SDisk, len(disks))
|
|
for i := range disks {
|
|
diskId, _ := disks[i].GetString()
|
|
disk := DiskManager.FetchDiskById(diskId)
|
|
if disk == nil {
|
|
return nil, httperrors.NewInputParameterError("no such disk %s", diskId)
|
|
}
|
|
disk.SetModelManager(DiskManager, disk)
|
|
diskSlice[i] = disk
|
|
}
|
|
|
|
taskDisk := make([]*SDisk, 0, len(diskSlice))
|
|
taskSpd := make([]*SSnapshotPolicyDisk, 0, len(diskSlice))
|
|
for _, disk := range diskSlice {
|
|
spd, err := SnapshotPolicyDiskManager.FetchBySnapshotPolicyDisk(sp.Id, disk.GetId())
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if spd == nil {
|
|
continue
|
|
}
|
|
taskSpd = append(taskSpd, spd)
|
|
taskDisk = append(taskDisk, disk)
|
|
}
|
|
|
|
for i := range taskDisk {
|
|
taskdata := jsonutils.NewDict()
|
|
taskdata.Add(jsonutils.NewString(sp.Id), "snapshot_policy_id")
|
|
taskdata.Add(jsonutils.Marshal(taskSpd[i]), "snapshotPolicyDisk")
|
|
taskSpd[i].SetStatus(userCred, api.SNAPSHOT_POLICY_DISK_DELETING, "")
|
|
if task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyCancelTask", taskDisk[i], userCred, nil, "", "",
|
|
nil); err != nil {
|
|
continue
|
|
} else {
|
|
task.ScheduleRun(taskdata)
|
|
}
|
|
}
|
|
return nil, nil
|
|
}
|