mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-21 06:09:39 +08:00
Merge pull request #3696 from swordqiu/hotfix/qj-aliyun-delete-network-failed
fix: network-delete may fail immidiately after deleting vm
This commit is contained in:
@@ -418,7 +418,7 @@ func init() {
|
||||
})
|
||||
|
||||
type NetworkAddressOptions struct {
|
||||
NETWORK string `help:"if of network to query"`
|
||||
NETWORK string `help:"id or name of network to query"`
|
||||
}
|
||||
R(&NetworkAddressOptions{}, "network-addresses", "Query used addresses of network", func(s *mcclient.ClientSession, args *NetworkAddressOptions) error {
|
||||
result, err := modules.Networks.GetSpecific(s, args.NETWORK, "addresses", nil)
|
||||
@@ -433,4 +433,16 @@ func init() {
|
||||
printList(&listResult, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type NetworkSyncOptions struct {
|
||||
NETWORK string `help:"id or name of network to sync"`
|
||||
}
|
||||
R(&NetworkSyncOptions{}, "network-sync", "Sync network status", func(s *mcclient.ClientSession, args *NetworkSyncOptions) error {
|
||||
result, err := modules.Networks.PerformAction(s, args.NETWORK, "sync", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -158,4 +158,13 @@ func init() {
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&VpcUpdateStatusOptions{}, "vpc-sync", "Synchronize the status of a vpc", func(s *mcclient.ClientSession, args *VpcUpdateStatusOptions) error {
|
||||
result, err := modules.Vpcs.PerformAction(s, args.ID, "sync", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ const (
|
||||
NETWORK_STATUS_DELETING = "deleting"
|
||||
NETWORK_STATUS_DELETED = "deleted"
|
||||
NETWORK_STATUS_DELETE_FAILED = "delete_failed"
|
||||
NETWORK_STATUS_START_SYNC = "start_sync"
|
||||
NETWORK_STATUS_SYNCING = "sync"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -24,6 +24,8 @@ const (
|
||||
VPC_STATUS_DELETE_FAILED = "delete_failed"
|
||||
VPC_STATUS_DELETED = "deleted"
|
||||
VPC_STATUS_UNKNOWN = "unknown"
|
||||
VPC_STATUS_START_SYNC = "start_sync"
|
||||
VPC_STATUS_SYNCING = "sync"
|
||||
|
||||
MAX_VPC_PER_REGION = 3
|
||||
|
||||
|
||||
@@ -2418,3 +2418,28 @@ func (network *SNetwork) GetDetailsAddresses(ctx context.Context, userCred mccli
|
||||
result.Add(jsonutils.Marshal(netAddrs), "addresses")
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (net *SNetwork) AllowPerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return net.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, net, "sync")
|
||||
}
|
||||
|
||||
func (net *SNetwork) PerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
vpc := net.GetVpc()
|
||||
if vpc != nil && vpc.IsManaged() {
|
||||
err := net.StartNetworkSyncstatusTask(ctx, userCred, "")
|
||||
return nil, err
|
||||
} else {
|
||||
return nil, httperrors.NewUnsupportOperationError("on-premise network cannot sync status")
|
||||
}
|
||||
}
|
||||
|
||||
func (net *SNetwork) StartNetworkSyncstatusTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "NetworkSyncstatusTask", net, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
log.Errorf("create NetworkSyncstatusTask fail %s", err)
|
||||
return err
|
||||
}
|
||||
net.SetStatus(userCred, api.NETWORK_STATUS_START_SYNC, "synchronize")
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -763,3 +763,27 @@ func (self *SVpc) SyncRemoteWires(ctx context.Context, userCred mcclient.TokenCr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vpc *SVpc) AllowPerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsAdminAllowPerform(userCred, vpc, "sync")
|
||||
}
|
||||
|
||||
func (vpc *SVpc) PerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if vpc.IsManaged() {
|
||||
err := vpc.StartVpcSyncstatusTask(ctx, userCred, "")
|
||||
return nil, err
|
||||
} else {
|
||||
return nil, httperrors.NewUnsupportOperationError("on-premise vpc cannot sync status")
|
||||
}
|
||||
}
|
||||
|
||||
func (vpc *SVpc) StartVpcSyncstatusTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "VpcSyncstatusTask", vpc, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
log.Errorf("create NetworkSyncstatusTask fail %s", err)
|
||||
return err
|
||||
}
|
||||
vpc.SetStatus(userCred, api.VPC_STATUS_START_SYNC, "synchronize")
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
// 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"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
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/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type NetworkSyncstatusTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(NetworkSyncstatusTask{})
|
||||
}
|
||||
|
||||
func (self *NetworkSyncstatusTask) taskFail(ctx context.Context, net *models.SNetwork, msg string) {
|
||||
net.SetStatus(self.UserCred, api.NETWORK_STATUS_UNKNOWN, msg)
|
||||
db.OpsLog.LogEvent(net, db.ACT_SYNC_STATUS, msg, self.GetUserCred())
|
||||
logclient.AddActionLogWithStartable(self, net, logclient.ACT_SYNC_STATUS, msg, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
}
|
||||
|
||||
func (self *NetworkSyncstatusTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
net := obj.(*models.SNetwork)
|
||||
|
||||
net.SetStatus(self.UserCred, api.NETWORK_STATUS_SYNCING, "synchronize")
|
||||
|
||||
extNet, err := net.GetINetwork()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to find ICloudNetwork for network %s", err)
|
||||
self.taskFail(ctx, net, msg)
|
||||
return
|
||||
}
|
||||
|
||||
err = extNet.Refresh()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to refresh ICloudNetwork status %s", err)
|
||||
self.taskFail(ctx, net, msg)
|
||||
return
|
||||
}
|
||||
|
||||
err = net.SyncWithCloudNetwork(ctx, self.UserCred, extNet, nil)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to sync network status %s", err)
|
||||
self.taskFail(ctx, net, msg)
|
||||
return
|
||||
}
|
||||
|
||||
logclient.AddActionLogWithStartable(self, net, logclient.ACT_SYNC_STATUS, nil, self.UserCred, true)
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// 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"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
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/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type VpcSyncstatusTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(VpcSyncstatusTask{})
|
||||
}
|
||||
|
||||
func (self *VpcSyncstatusTask) taskFail(ctx context.Context, vpc *models.SVpc, msg string) {
|
||||
vpc.SetStatus(self.UserCred, api.VPC_STATUS_UNKNOWN, msg)
|
||||
db.OpsLog.LogEvent(vpc, db.ACT_SYNC_STATUS, msg, self.GetUserCred())
|
||||
logclient.AddActionLogWithStartable(self, vpc, logclient.ACT_SYNC_STATUS, msg, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
}
|
||||
|
||||
func (self *VpcSyncstatusTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
vpc := obj.(*models.SVpc)
|
||||
|
||||
vpc.SetStatus(self.UserCred, api.VPC_STATUS_SYNCING, "synchronize")
|
||||
|
||||
extVpc, err := vpc.GetIVpc()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to find ICloudVpc for vpc %s", err)
|
||||
self.taskFail(ctx, vpc, msg)
|
||||
return
|
||||
}
|
||||
|
||||
err = extVpc.Refresh()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to refresh ICloudVpc status %s", err)
|
||||
self.taskFail(ctx, vpc, msg)
|
||||
return
|
||||
}
|
||||
|
||||
err = vpc.SyncWithCloudVpc(ctx, self.UserCred, extVpc)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to sync vpc status %s", err)
|
||||
self.taskFail(ctx, vpc, msg)
|
||||
return
|
||||
}
|
||||
|
||||
logclient.AddActionLogWithStartable(self, vpc, logclient.ACT_SYNC_STATUS, nil, self.UserCred, true)
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -186,7 +186,20 @@ func (self *SVSwitch) Delete() error {
|
||||
log.Errorf("fail to dissociateWithSNAT")
|
||||
return err
|
||||
}
|
||||
return self.wire.zone.region.DeleteVSwitch(self.VSwitchId)
|
||||
err = cloudprovider.Wait(10*time.Second, 60*time.Second, func() (bool, error) {
|
||||
err := self.wire.zone.region.DeleteVSwitch(self.VSwitchId)
|
||||
if err != nil {
|
||||
// delete network immediately after deleting vm on it
|
||||
// \"Code\":\"DependencyViolation\",\"Message\":\"Specified object has dependent resources.\"}
|
||||
if isError(err, "DependencyViolation") {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
} else {
|
||||
return true, nil
|
||||
}
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SVSwitch) GetAllocTimeoutSeconds() int {
|
||||
|
||||
Reference in New Issue
Block a user