diff --git a/controller/interfaces/networkelement/networkElement.go b/controller/interfaces/networkelement/networkElement.go index 01a81bd66aab660c00431d4b3d08f7a7c70ff9aa..fd9f9cfb817f77b0b2dbaecee7684a5a387c988a 100644 --- a/controller/interfaces/networkelement/networkElement.go +++ b/controller/interfaces/networkelement/networkElement.go @@ -16,6 +16,7 @@ import ( type NetworkElement interface { ID() uuid.UUID GetModel() ygot.GoStruct + GetModelAsFilteredCopy() (ygot.GoStruct, error) CreateModelCopy() (ygot.ValidatedGoStruct, error) Transport() transport.Transport Name() string diff --git a/controller/nucleus/gnmi_transport.go b/controller/nucleus/gnmi_transport.go index f1c46a97c1de91b085c7e34f6208ef90b447ded2..d1a3a820a417fc86676132d4c82e38ce44def6a2 100644 --- a/controller/nucleus/gnmi_transport.go +++ b/controller/nucleus/gnmi_transport.go @@ -122,22 +122,22 @@ func (g *Gnmi) applyDiff(ctx context.Context, payload change.Payload, path *gpb. return customerrs.NoNewChangesError{Original: payload.Original, Modified: payload.Modified} } - if op := ctx.Value(types.CtxKeyOperation); op == ppb.ApiOperation_API_OPERATION_UPDATE || op == ppb.ApiOperation_API_OPERATION_REPLACE { - filteredUpdates := make([]*gpb.Update, 0) - for _, u := range diff.Update { - rootSchema := schema.RootSchema() - pathString, err := ygot.PathToString(u.GetPath()) - if err != nil { - return err - } - entry := rootSchema.Find(pathString) - if !entry.ReadOnly() { - filteredUpdates = append(filteredUpdates, u) - } - } - - diff.Update = filteredUpdates - } + //if op := ctx.Value(types.CtxKeyOperation); op == ppb.ApiOperation_API_OPERATION_UPDATE || op == ppb.ApiOperation_API_OPERATION_REPLACE { + // filteredUpdates := make([]*gpb.Update, 0) + // for _, u := range diff.Update { + // rootSchema := schema.RootSchema() + // pathString, err := ygot.PathToString(u.GetPath()) + // if err != nil { + // return err + // } + // entry := rootSchema.Find(pathString) + // if !entry.ReadOnly() { + // filteredUpdates = append(filteredUpdates, u) + // } + // } + + // diff.Update = filteredUpdates + //} req, err := createSetRequest(ctx, diff) if err != nil { diff --git a/controller/nucleus/networkElement.go b/controller/nucleus/networkElement.go index 692253286282564b4c197873f4f292382deee727..3e8b0ee52ec4ece49ba3a1b218c5857749d74801 100644 --- a/controller/nucleus/networkElement.go +++ b/controller/nucleus/networkElement.go @@ -13,6 +13,7 @@ import ( "github.com/docker/docker/pkg/namesgenerator" "github.com/google/uuid" "github.com/openconfig/ygot/ygot" + "github.com/openconfig/ygot/ytypes" "go.mongodb.org/mongo-driver/bson" "google.golang.org/protobuf/proto" ) @@ -112,6 +113,16 @@ func (n *CommonNetworkElement) GetModel() ygot.GoStruct { return n.Model } +// GetModelAsFilteredCopy returns the ygot representation of the Network +// Element, but as copy with read-only fields removed. +func (n *CommonNetworkElement) GetModelAsFilteredCopy() (ygot.GoStruct, error) { + filteredModelCopy, err := createFilteredCopy(n) + if err != nil { + return nil, err + } + return filteredModelCopy, nil +} + // CreateModelCopy returns a copy of the ygot representation of the Network Element. func (n *CommonNetworkElement) CreateModelCopy() (ygot.ValidatedGoStruct, error) { return createValidatedCopy(n) @@ -186,6 +197,16 @@ func (n *CsbiNetworkElement) GetModel() ygot.GoStruct { return n.Model } +// GetModelAsFilteredCopy returns the ygot representation of the Network +// Element, but as copy with read-only fields removed. +func (n *CsbiNetworkElement) GetModelAsFilteredCopy() (ygot.GoStruct, error) { + filteredModelCopy, err := createFilteredCopy(n) + if err != nil { + return nil, err + } + return filteredModelCopy, nil +} + // CreateModelCopy returns a copy of the ygot representation of the Network Element. func (n *CsbiNetworkElement) CreateModelCopy() (ygot.ValidatedGoStruct, error) { return createValidatedCopy(n) @@ -235,6 +256,38 @@ func createValidatedCopy(n networkelement.NetworkElement) (ygot.ValidatedGoStruc return validatedCpy, nil } +func createFilteredCopy(n networkelement.NetworkElement) (ygot.GoStruct, error) { + root, err := ygot.DeepCopy(n.SBI().Schema().Root) + if err != nil { + return nil, err + } + ygotDeepCopy, ok := root.(ygot.GoStruct) + if !ok { + return nil, &customerrs.InvalidTypeAssertionError{ + Value: root, + Type: (*ygot.ValidatedGoStruct)(nil), + } + } + + modelAsString, err := n.GetModelAsString() + if err != nil { + } + + path, err := ygot.StringToPath("/", ygot.StructuredPath) + if err != nil { + return nil, err + } + + // Use unmarshall from the network elements SBI to unmarshall ygot json in go struct. + opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreReadOnlyFields{}, &ytypes.IgnoreExtraFields{}} + err = n.SBI().Unmarshal([]byte(modelAsString), path, ygotDeepCopy, opts...) + if err != nil { + return nil, err + } + + return ygotDeepCopy, nil +} + // IsTransportValid returns a boolean if the transport of a network element is valid. func (n *CsbiNetworkElement) IsTransportValid() bool { if n.transportOptions != nil && n.transportOptions.Address != "" { diff --git a/controller/nucleus/principalNetworkDomain.go b/controller/nucleus/principalNetworkDomain.go index 495da957c97b670814186d3a308def8a4bc1a2ac..e5b768de7f1ab61fbe61fa3a700a554c682f4609 100644 --- a/controller/nucleus/principalNetworkDomain.go +++ b/controller/nucleus/principalNetworkDomain.go @@ -544,7 +544,7 @@ func (pnd *pndImplementation) ChangeMNE(duid uuid.UUID, operation ppb.ApiOperati } if entry.IsDir() { - opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}} + opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}, &ytypes.IgnoreReadOnlyFields{}} if err := mne.SBI().Unmarshal([]byte(value[0]), p, validatedCpy, opts...); err != nil { return uuid.Nil, err } @@ -575,7 +575,12 @@ func (pnd *pndImplementation) ChangeMNE(duid uuid.UUID, operation ppb.ApiOperati return mne.Transport().Set(ctx, payload, pathToSet, schema) } - ch := NewChange(duid, mne.GetModel(), validatedCpy, callback) + filteredCurrentModel, err := mne.GetModelAsFilteredCopy() + if err != nil { + return uuid.Nil, err + } + + ch := NewChange(duid, filteredCurrentModel, validatedCpy, callback) if err := pnd.changes.Add(ch); err != nil { return uuid.Nil, err