mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-05-09 07:02:06 +08:00
155 lines
5.1 KiB
Go
155 lines
5.1 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 tasks
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"yunion.io/x/jsonutils"
|
|
"yunion.io/x/log"
|
|
|
|
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/cloudcommon/notifyclient"
|
|
"yunion.io/x/onecloud/pkg/compute/models"
|
|
"yunion.io/x/onecloud/pkg/util/logclient"
|
|
)
|
|
|
|
type ScalingGroupDeleteTask struct {
|
|
taskman.STask
|
|
}
|
|
|
|
func init() {
|
|
taskman.RegisterTask(ScalingGroupDeleteTask{})
|
|
}
|
|
|
|
func (self *ScalingGroupDeleteTask) taskFailed(ctx context.Context, sg *models.SScalingGroup, reason jsonutils.JSONObject) {
|
|
log.Errorf("scaling group delete task fail: %s", reason)
|
|
sg.SetStatus(self.UserCred, api.SG_STATUS_DELETE_FAILED, reason.String())
|
|
db.OpsLog.LogEvent(sg, db.ACT_DELETE_FAIL, reason, self.UserCred)
|
|
logclient.AddActionLogWithStartable(self, sg, logclient.ACT_DELETE, reason, self.UserCred, false)
|
|
self.SetStageFailed(ctx, reason)
|
|
}
|
|
|
|
func (self *ScalingGroupDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
|
sg := obj.(*models.SScalingGroup)
|
|
|
|
sg.SetStatus(self.UserCred, api.SG_STATUS_DELETING, "")
|
|
// Set all scaling policy's status as deleting
|
|
sps, err := sg.ScalingPolicies()
|
|
if err != nil {
|
|
self.taskFailed(ctx, sg, jsonutils.NewString(err.Error()))
|
|
return
|
|
}
|
|
spids := make([]string, len(sps))
|
|
for i := range sps {
|
|
spids[i] = sps[i].GetId()
|
|
err := func() error {
|
|
lockman.LockObject(ctx, &sps[i])
|
|
defer lockman.ReleaseObject(ctx, &sps[i])
|
|
return sps[i].SetStatus(self.UserCred, api.SP_STATUS_DELETING, "delete scaling group")
|
|
}()
|
|
if err != nil {
|
|
self.taskFailed(ctx, sg, jsonutils.NewString(fmt.Sprintf("set scaling policy %s as deleting status failed: %s",
|
|
sps[i].GetId(), err)))
|
|
return
|
|
}
|
|
}
|
|
|
|
log.Debugf("finish to mark all scaling policies deleted")
|
|
// wait for activites finished
|
|
sg.SetStatus(self.UserCred, api.SG_STATUS_WAIT_ACTIVITY_OVER, "wait all activities over")
|
|
waitSeconds, interval, seconds := 180, 5, 0
|
|
checkids := spids
|
|
allReady := false
|
|
for seconds < waitSeconds {
|
|
// onlyread, lock no need
|
|
tmpIds, err := models.ScalingActivityManager.FetchByStatus(ctx, checkids, []string{api.SA_STATUS_SUCCEED,
|
|
api.SA_STATUS_FAILED}, "not")
|
|
log.Debugf("scalingactivities not in 'succeed' or 'failed': %v", tmpIds)
|
|
if err != nil {
|
|
log.Errorf("ScalingActivityManager.FetchByStatus: %s", err.Error())
|
|
continue
|
|
}
|
|
if len(tmpIds) == 0 {
|
|
allReady = true
|
|
break
|
|
}
|
|
checkids = tmpIds
|
|
seconds += interval
|
|
time.Sleep(time.Duration(interval) * time.Second)
|
|
}
|
|
if err != nil {
|
|
self.taskFailed(ctx, sg, jsonutils.NewString(fmt.Sprintf("wait for all scaling activities finished: %s", err)))
|
|
return
|
|
}
|
|
if !allReady {
|
|
self.taskFailed(ctx, sg, jsonutils.NewString("some scaling activities are still in progress"))
|
|
return
|
|
}
|
|
|
|
count, err := sg.GuestNumber()
|
|
if err != nil {
|
|
self.taskFailed(ctx, sg, jsonutils.NewString(fmt.Sprintf("SScalingGroup.GuestNumber: %s", err)))
|
|
return
|
|
}
|
|
if count != 0 {
|
|
self.taskFailed(ctx, sg, jsonutils.NewString(fmt.Sprintf("There are some guests in ScalingGroup, please delete them firstly")))
|
|
return
|
|
}
|
|
|
|
// delete SScalingPolicies
|
|
policies, err := sg.ScalingPolicies()
|
|
if err != nil {
|
|
self.taskFailed(ctx, sg, jsonutils.NewString(fmt.Sprintf("SScalingGroup.ScalingPolicies: %s", err.Error())))
|
|
return
|
|
}
|
|
for i := range policies {
|
|
err := policies[i].RealDelete(ctx, self.UserCred)
|
|
if err != nil {
|
|
self.taskFailed(ctx, sg, jsonutils.NewString(fmt.Sprintf("delete scaling group '%s' failed: %s", policies[i].GetId(), err.Error())))
|
|
return
|
|
}
|
|
}
|
|
|
|
// delete SScalingAvtivities
|
|
activities, err := sg.Activities()
|
|
if err != nil {
|
|
self.taskFailed(ctx, sg, jsonutils.NewString(fmt.Sprintf("ScalingGroup.Activities: %s", err.Error())))
|
|
}
|
|
for i := range activities {
|
|
err := activities[i].Delete(ctx, self.UserCred)
|
|
if err != nil {
|
|
self.taskFailed(ctx, sg, jsonutils.NewString(fmt.Sprintf("delete scaling activity '%s' failed: %s", activities[i].Id, err.Error())))
|
|
return
|
|
}
|
|
}
|
|
|
|
err = sg.RealDelete(ctx, self.UserCred)
|
|
if err != nil {
|
|
self.taskFailed(ctx, sg, jsonutils.NewString(fmt.Sprintf("ScalingGroup.RealDelete: %s", err.Error())))
|
|
}
|
|
db.OpsLog.LogEvent(sg, db.ACT_DELETE, "", self.UserCred)
|
|
logclient.AddActionLogWithStartable(self, sg, logclient.ACT_DELETE, "", self.UserCred, true)
|
|
notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
|
|
Obj: sg,
|
|
Action: notifyclient.ActionDelete,
|
|
})
|
|
}
|