diff --git a/pkg/cloudcommon/db/standalone_anon.go b/pkg/cloudcommon/db/standalone_anon.go index cf31383154..768e879545 100644 --- a/pkg/cloudcommon/db/standalone_anon.go +++ b/pkg/cloudcommon/db/standalone_anon.go @@ -323,6 +323,12 @@ type IClassMetadataOwner interface { GetAllClassMetadata() (map[string]string, error) } +type ClassMetadataOwner map[string]string + +func (w ClassMetadataOwner) GetAllClassMetadata() (map[string]string, error) { + return w, nil +} + func IsInSameClass(ctx context.Context, cmo1, cmo2 IClassMetadataOwner) (bool, error) { pureTags, err := cmo1.GetAllClassMetadata() if err != nil { diff --git a/pkg/compute/models/hosts.go b/pkg/compute/models/hosts.go index 4ba6719e6c..cf1f8e8617 100644 --- a/pkg/compute/models/hosts.go +++ b/pkg/compute/models/hosts.go @@ -4197,6 +4197,13 @@ func (self *SHost) addNetif(ctx context.Context, userCred mcclient.TokenCredenti if err != nil { return httperrors.NewBadRequestError("%v", err) } + // inherit wire's class metadata + if sw != nil { + err := db.Inherit(ctx, sw, self) + if err != nil { + return errors.Wrapf(err, "unable to inherit class metadata from sw %s", sw.GetName()) + } + } } if len(ipAddr) > 0 { err = self.EnableNetif(ctx, userCred, netif, "", ipAddr, "", "", reserve, requireDesignatedIp) diff --git a/pkg/compute/models/networks.go b/pkg/compute/models/networks.go index 4e1ea2eee2..883693be02 100644 --- a/pkg/compute/models/networks.go +++ b/pkg/compute/models/networks.go @@ -1638,6 +1638,26 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred if input.ServerType != api.NETWORK_TYPE_EIP { input.BgpType = "" } + // check class metadata + if wire != nil { + var projectId string + if len(input.ProjectId) > 0 { + projectId = input.ProjectId + } else { + projectId = ownerId.GetProjectId() + } + project, err := db.TenantCacheManager.FetchTenantById(ctx, projectId) + if err != nil { + return input, errors.Wrapf(err, "unable to fetch tenant by id %s", projectId) + } + ok, err := db.IsInSameClass(ctx, wire, project) + if err != nil { + return input, errors.Wrapf(err, "unable to check if wire and project is in same class") + } + if !ok { + return input, httperrors.NewForbiddenError("the wire %s and project %s has different class metadata", wire.GetName(), project.GetName()) + } + } var ( ipStart = ipRange.StartIp() @@ -2767,6 +2787,15 @@ func (manager *SNetworkManager) PerformTryCreateNetwork(ctx context.Context, use return nil, err } newNetwork.PostCreate(ctx, userCred, userCred, query, input.JSON(input)) + // inherit wire's class metadata + wire, err := newNetwork.GetWire() + if err != nil { + return nil, errors.Wrap(err, "unable to get wire") + } + err = db.Inherit(ctx, wire, newNetwork) + if err != nil { + return nil, errors.Wrap(err, "unable to inherit wire") + } } return ret, nil } @@ -2804,6 +2833,21 @@ func (network *SNetwork) ClearSchedDescCache() error { } func (network *SNetwork) PerformChangeOwner(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeProjectOwnerInput) (jsonutils.JSONObject, error) { + wire, err := network.GetWire() + if err != nil { + return nil, errors.Wrap(err, "unable to get wire") + } + project, err := db.TenantCacheManager.FetchTenantById(ctx, input.ProjectId) + if err != nil { + return nil, errors.Wrapf(err, "unable to get project %s", input.ProjectId) + } + ok, err := db.IsInSameClass(ctx, wire, project) + if err != nil { + return nil, errors.Wrap(err, "unable to check if the wire and project is in same class") + } + if !ok { + return nil, httperrors.NewForbiddenError("the wire %s and the project %s has different class metadata", wire.GetName(), project.GetName()) + } ret, err := network.SSharableVirtualResourceBase.PerformChangeOwner(ctx, userCred, query, input) if err != nil { return nil, err diff --git a/pkg/compute/models/wires.go b/pkg/compute/models/wires.go index 046fe50fbf..a8ded1e729 100644 --- a/pkg/compute/models/wires.go +++ b/pkg/compute/models/wires.go @@ -1280,6 +1280,23 @@ func (wm *SWireManager) handleWireIdChange(ctx context.Context, args *wireIdChan return nil } +func (wire *SWire) PerformSetClassMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformSetClassMetadataInput) (jsonutils.JSONObject, error) { + vpc, err := wire.GetVpc() + if err != nil { + return nil, errors.Wrapf(err, "unable to get vpc of wire %s", wire.GetId()) + } + if vpc.GetId() != api.DEFAULT_VPC_ID { + ok, err := db.IsInSameClass(ctx, vpc, db.ClassMetadataOwner(input)) + if err != nil { + return nil, errors.Wrapf(err, "unable to check if vpc and wire are in same class") + } + if !ok { + return nil, httperrors.NewForbiddenError("the vpc %s and this wire have different class metadata", vpc.GetName()) + } + } + return wire.SStatusInfrasResourceBase.PerformSetClassMetadata(ctx, userCred, query, input) +} + // 二层网络列表 func (manager *SWireManager) ListItemFilter( ctx context.Context, @@ -1448,6 +1465,18 @@ func (model *SWire) CustomizeCreate(ctx context.Context, userCred mcclient.Token return model.SInfrasResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data) } +func (model *SWire) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) { + model.SStatusInfrasResourceBase.PostCreate(ctx, userCred, ownerId, query, data) + vpc, err := model.GetVpc() + if err != nil { + log.Errorf("unable to getvpc of wire %s: %s", model.GetId(), vpc.GetId()) + } + err = db.Inherit(ctx, vpc, model) + if err != nil { + log.Errorf("unable to inhert vpc to model %s: %s", model.GetId(), err.Error()) + } +} + func (wire *SWire) GetChangeOwnerCandidateDomainIds() []string { candidates := [][]string{} vpc, _ := wire.GetVpc()