feat(region): support merging mutli wires to a wire

This commit is contained in:
rainzm
2021-02-03 12:08:23 +08:00
parent 4be58eef5a
commit a4d3d5fa39
5 changed files with 96 additions and 9 deletions
+1 -1
View File
@@ -30,6 +30,6 @@ func init() {
cmd.Perform("public", new(options.WirePublicOptions))
cmd.Perform("private", new(options.WireOptions))
cmd.Perform("change-owner-candidate-domains", new(options.WireOptions))
cmd.Perform("merge", new(options.WireMergeOptions))
cmd.PerformWithKeyword("merge", "merge-from", new(options.WireMergeOptions))
cmd.Perform("merge-network", new(options.WireOptions))
}
+9
View File
@@ -101,5 +101,14 @@ type WireMergeInput struct {
MergeNetwork bool `json:"merge_network"`
}
type WireMergeFromInput struct {
// description: wire ids or names to be merged from
// required: true
Sources []string `json:"sources"`
// description: if merge networks under wire
// required: false
MergeNetwork bool `json:"merge_network"`
}
type WireMergeNetworkInput struct {
}
+81 -4
View File
@@ -26,6 +26,7 @@ import (
"yunion.io/x/pkg/tristate"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/pkg/util/netutils"
"yunion.io/x/pkg/util/sets"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
@@ -995,11 +996,87 @@ func (w *SWire) PerformMergeNetwork(ctx context.Context, userCred mcclient.Token
return nil, w.StartMergeNetwork(ctx, userCred, "")
}
func (w *SWire) AllowPerformMerge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return w.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, w, "merge")
func (sm *SWireManager) FetchByIdsOrNames(idOrNames []string) ([]SWire, error) {
if len(idOrNames) == 0 {
return nil, nil
}
q := sm.Query("")
if len(idOrNames) == 1 {
q.Filter(sqlchemy.OR(sqlchemy.Equals(q.Field("id"), idOrNames[0]), sqlchemy.Equals(q.Field("name"), idOrNames[0])))
} else {
q.Filter(sqlchemy.OR(sqlchemy.In(q.Field("id"), idOrNames[0]), sqlchemy.In(q.Field("name"), idOrNames[0])))
}
ret := make([]SWire, 0, len(idOrNames))
err := db.FetchModelObjects(sm, q, &ret)
if err != nil {
return nil, err
}
return ret, nil
}
func (w *SWire) PerformMerge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.WireMergeInput) (ret jsonutils.JSONObject, err error) {
func (w *SWire) AllowPerformMergeFrom(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return w.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, w, "merge-from")
}
func (w *SWire) PerformMergeFrom(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.WireMergeFromInput) (ret jsonutils.JSONObject, err error) {
if len(input.Sources) == 0 {
return nil, httperrors.NewMissingParameterError("sources")
}
defer func() {
if err != nil {
logclient.AddActionLogWithContext(ctx, w, logclient.ACT_MERGE, err.Error(), userCred, false)
}
}()
wires, err := WireManager.FetchByIdsOrNames(input.Sources)
if err != nil {
return
}
wireIdOrNameSet := sets.NewString(input.Sources...)
for i := range wires {
id, name := wires[i].GetId(), wires[i].GetName()
if wireIdOrNameSet.Has(id) {
wireIdOrNameSet.Delete(id)
continue
}
if wireIdOrNameSet.Has(name) {
wireIdOrNameSet.Delete(name)
}
}
if wireIdOrNameSet.Len() > 0 {
return nil, httperrors.NewInputParameterError("invalid wire id or name %v", wireIdOrNameSet.UnsortedList())
}
lockman.LockClass(ctx, WireManager, db.GetLockClassKey(WireManager, userCred))
defer lockman.ReleaseClass(ctx, WireManager, db.GetLockClassKey(WireManager, userCred))
for _, tw := range wires {
err = WireManager.handleWireIdChange(ctx, &wireIdChangeArgs{
oldWire: &tw,
newWire: w,
})
if err != nil {
return nil, errors.Wrapf(err, "unable to merge wire %s to %s", tw.GetId(), w.GetId())
}
if err = tw.Delete(ctx, userCred); err != nil {
return nil, err
}
}
logclient.AddActionLogWithContext(ctx, w, logclient.ACT_MERGE_FROM, "", userCred, true)
if input.MergeNetwork {
err = w.StartMergeNetwork(ctx, userCred, "")
if err != nil {
return nil, errors.Wrap(err, "unableto StartMergeNetwork")
}
}
return
}
func (w *SWire) AllowPerformMergeTo(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return w.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, w, "merge-to")
}
func (w *SWire) PerformMergeTo(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.WireMergeInput) (ret jsonutils.JSONObject, err error) {
if len(input.Target) == 0 {
return nil, httperrors.NewMissingParameterError("target")
}
@@ -1033,7 +1110,7 @@ func (w *SWire) PerformMerge(ctx context.Context, userCred mcclient.TokenCredent
return nil, err
}
if input.MergeNetwork {
err = w.StartMergeNetwork(ctx, userCred, "")
err = tw.StartMergeNetwork(ctx, userCred, "")
if err != nil {
return nil, errors.Wrap(err, "unableto StartMergeNetwork")
}
+4 -4
View File
@@ -91,13 +91,13 @@ func (wo *WirePublicOptions) Params() (jsonutils.JSONObject, error) {
}
type WireMergeOptions struct {
FROM string `help:"ID or name of merge wire from"`
TARGET string `help:"ID or name of merge wire target"`
MergeNetwork bool `help:"whether to merge network under wire"`
Froms []string `help:"IDs or names of merge wire from" json:"sources"`
TARGET string `help:"ID or name of merge wire target"`
MergeNetwork bool `help:"whether to merge network under wire"`
}
func (wo *WireMergeOptions) GetId() string {
return wo.FROM
return wo.TARGET
}
func (wo *WireMergeOptions) Params() (jsonutils.JSONObject, error) {
+1
View File
@@ -35,6 +35,7 @@ const (
ACT_GUEST_ATTACH_ISOLATED_DEVICE = "guest_attach_isolated_device"
ACT_GUEST_DETACH_ISOLATED_DEVICE = "guest_detach_isolated_device"
ACT_MERGE = "merge"
ACT_MERGE_FROM = "merge_from"
ACT_OFFLINE = "offline"
ACT_ONLINE = "online"
ACT_PRIVATE = "private"