From 36c0f605f48cf322806762bf6abde0e27deb89bb Mon Sep 17 00:00:00 2001 From: Patricia Reinoso Date: Tue, 21 Jan 2025 10:23:42 +0100 Subject: [PATCH 01/10] delete dg from ns Signed-off-by: Patricia Reinoso --- configapi/api_default.go | 2 +- dbadapter/db_adapter.go | 27 ++++++++++++ docs/docs.go | 67 +++++++++++++---------------- go.mod | 6 +-- go.sum | 12 +++--- proto/server/configEvtHandler.go | 74 ++++++++++++++++++++++++++++++-- 6 files changed, 139 insertions(+), 49 deletions(-) diff --git a/configapi/api_default.go b/configapi/api_default.go index f3f8e2cb..55948371 100644 --- a/configapi/api_default.go +++ b/configapi/api_default.go @@ -240,7 +240,7 @@ func NetworkSliceSliceNameDelete(c *gin.Context) { // @Failure 401 {object} nil "Authorization failed" // @Failure 403 {object} nil "Forbidden" // @Failure 500 {object} nil "Error creating network slice" -// @Router /config/v1/network-slice/{sliceName [post] +// @Router /config/v1/network-slice/{sliceName} [post] func NetworkSliceSliceNamePost(c *gin.Context) { logger.ConfigLog.Debugf("Received NetworkSliceSliceNamePost ") if ret := NetworkSlicePostHandler(c, configmodels.Post_op); ret { diff --git a/dbadapter/db_adapter.go b/dbadapter/db_adapter.go index eb69284b..e56a8dc4 100644 --- a/dbadapter/db_adapter.go +++ b/dbadapter/db_adapter.go @@ -6,12 +6,14 @@ package dbadapter import ( + "context" "time" "github.com/omec-project/util/mongoapi" "github.com/omec-project/webconsole/backend/logger" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/mongo" ) type DBInterface interface { @@ -19,17 +21,22 @@ type DBInterface interface { RestfulAPIGetMany(collName string, filter bson.M) ([]map[string]interface{}, error) RestfulAPIPutOneTimeout(collName string, filter bson.M, putData map[string]interface{}, timeout int32, timeField string) bool RestfulAPIPutOne(collName string, filter bson.M, putData map[string]interface{}) (bool, error) + RestfulAPIPutOneWithContext(collName string, filter bson.M, putData map[string]interface{}, context context.Context) (bool, error) RestfulAPIPutOneNotUpdate(collName string, filter bson.M, putData map[string]interface{}) (bool, error) RestfulAPIPutMany(collName string, filterArray []primitive.M, putDataArray []map[string]interface{}) error RestfulAPIDeleteOne(collName string, filter bson.M) error + RestfulAPIDeleteOneWithContext(collName string, filter bson.M, context context.Context) error RestfulAPIDeleteMany(collName string, filter bson.M) error RestfulAPIMergePatch(collName string, filter bson.M, patchData map[string]interface{}) error RestfulAPIJSONPatch(collName string, filter bson.M, patchJSON []byte) error + RestfulAPIJSONPatchWithContext(collName string, filter bson.M, patchJSON []byte, context context.Context) error RestfulAPIJSONPatchExtend(collName string, filter bson.M, patchJSON []byte, dataName string) error RestfulAPIPost(collName string, filter bson.M, postData map[string]interface{}) (bool, error) RestfulAPIPostMany(collName string, filter bson.M, postDataArray []interface{}) error RestfulAPICount(collName string, filter bson.M) (int64, error) CreateIndex(collName string, keyField string) (bool, error) + StartSession() (mongo.Session, error) + SupportsTransactions() (bool, error) } var ( @@ -88,6 +95,10 @@ func (db *MongoDBClient) RestfulAPIPutOne(collName string, filter bson.M, putDat return db.MongoClient.RestfulAPIPutOne(collName, filter, putData) } +func (db *MongoDBClient) RestfulAPIPutOneWithContext(collName string, filter bson.M, putData map[string]interface{}, context context.Context) (bool, error) { + return db.MongoClient.RestfulAPIPutOneWithContext(collName, filter, putData, context) +} + func (db *MongoDBClient) RestfulAPIPutOneNotUpdate(collName string, filter bson.M, putData map[string]interface{}) (bool, error) { return db.MongoClient.RestfulAPIPutOneNotUpdate(collName, filter, putData) } @@ -100,6 +111,10 @@ func (db *MongoDBClient) RestfulAPIDeleteOne(collName string, filter bson.M) err return db.MongoClient.RestfulAPIDeleteOne(collName, filter) } +func (db *MongoDBClient) RestfulAPIDeleteOneWithContext(collName string, filter bson.M, context context.Context) error { + return db.MongoClient.RestfulAPIDeleteOneWithContext(collName, filter, context) +} + func (db *MongoDBClient) RestfulAPIDeleteMany(collName string, filter bson.M) error { return db.MongoClient.RestfulAPIDeleteMany(collName, filter) } @@ -112,6 +127,10 @@ func (db *MongoDBClient) RestfulAPIJSONPatch(collName string, filter bson.M, pat return db.MongoClient.RestfulAPIJSONPatch(collName, filter, patchJSON) } +func (db *MongoDBClient) RestfulAPIJSONPatchWithContext(collName string, filter bson.M, patchJSON []byte, context context.Context) error { + return db.MongoClient.RestfulAPIJSONPatchWithContext(collName, filter, patchJSON, context) +} + func (db *MongoDBClient) RestfulAPIJSONPatchExtend(collName string, filter bson.M, patchJSON []byte, dataName string) error { return db.MongoClient.RestfulAPIJSONPatchExtend(collName, filter, patchJSON, dataName) } @@ -131,3 +150,11 @@ func (db *MongoDBClient) RestfulAPICount(collName string, filter bson.M) (int64, func (db *MongoDBClient) CreateIndex(collName string, keyField string) (bool, error) { return db.MongoClient.CreateIndex(collName, keyField) } + +func (db *MongoDBClient) StartSession() (mongo.Session, error) { + return db.MongoClient.StartSession() +} + +func (db *MongoDBClient) SupportsTransactions() (bool, error) { + return db.MongoClient.SupportsTransactions() +} diff --git a/docs/docs.go b/docs/docs.go index 156c3e17..b6106b63 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1,6 +1,3 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2024 Canonical Ltd - // Package docs Code generated by swaggo/swag. DO NOT EDIT package docs @@ -849,14 +846,17 @@ const docTemplate = `{ } } }, - "/config/v1/network-slice/{sliceName": { - "post": { + "/config/v1/network-slice/{sliceName}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new network slice", + "description": "Return the network slice", + "produces": [ + "application/json" + ], "tags": [ "Network Slices" ], @@ -867,23 +867,14 @@ const docTemplate = `{ "name": "sliceName", "in": "path", "required": true - }, - { - "description": " ", - "name": "content", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/configmodels.Slice" - } } ], "responses": { "200": { - "description": "Network slice created" - }, - "400": { - "description": "Invalid network slice content" + "description": "Network slice", + "schema": { + "$ref": "#/definitions/configmodels.Slice" + } }, "401": { "description": "Authorization failed" @@ -891,23 +882,21 @@ const docTemplate = `{ "403": { "description": "Forbidden" }, + "404": { + "description": "Network slices not found" + }, "500": { - "description": "Error creating network slice" + "description": "Error retrieving network slice" } } - } - }, - "/config/v1/network-slice/{sliceName}": { - "get": { + }, + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Return the network slice", - "produces": [ - "application/json" - ], + "description": "Create a new network slice", "tags": [ "Network Slices" ], @@ -918,14 +907,23 @@ const docTemplate = `{ "name": "sliceName", "in": "path", "required": true + }, + { + "description": " ", + "name": "content", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/configmodels.Slice" + } } ], "responses": { "200": { - "description": "Network slice", - "schema": { - "$ref": "#/definitions/configmodels.Slice" - } + "description": "Network slice created" + }, + "400": { + "description": "Invalid network slice content" }, "401": { "description": "Authorization failed" @@ -933,11 +931,8 @@ const docTemplate = `{ "403": { "description": "Forbidden" }, - "404": { - "description": "Network slices not found" - }, "500": { - "description": "Error retrieving network slice" + "description": "Error creating network slice" } } }, diff --git a/go.mod b/go.mod index 40d44c18..d1b0dcdf 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 github.com/omec-project/config5g v1.5.5 github.com/omec-project/openapi v1.3.2 - github.com/omec-project/util v1.2.8 + github.com/omec-project/util v1.2.10 github.com/prometheus/client_golang v1.20.5 github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 @@ -49,7 +49,7 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/cpuid/v2 v2.2.9 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mailru/easyjson v0.7.6 // indirect @@ -72,7 +72,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.10.0 // indirect golang.org/x/arch v0.12.0 // indirect - golang.org/x/net v0.33.0 // indirect + golang.org/x/net v0.34.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect diff --git a/go.sum b/go.sum index 18a1a346..250263bd 100644 --- a/go.sum +++ b/go.sum @@ -77,8 +77,8 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= @@ -116,8 +116,8 @@ github.com/omec-project/config5g v1.5.5 h1:9ouNkogjNBPi4Qa0gz12Ab4pl8gp5XWvELTCD github.com/omec-project/config5g v1.5.5/go.mod h1:r5K7D2jMigypWWcWJDUZlgpcH8gOAvPT6phtKESGzNs= github.com/omec-project/openapi v1.3.2 h1:LhUA/vBKCswN0S8fc/dN5/xuUltLgoak6au2MAKwUkk= github.com/omec-project/openapi v1.3.2/go.mod h1:JByn0faBQbiWX/q3JA+FHOdQS9m6KdyHDF5VVjCGMms= -github.com/omec-project/util v1.2.8 h1:yiR/YfItbmm7to3chyLr+YxjcN3BvQUNre6fu75yFDI= -github.com/omec-project/util v1.2.8/go.mod h1:wTonG4t81Cf4zSNid3/SGYtEEWd926LBOXbD827/Bs0= +github.com/omec-project/util v1.2.10 h1:FaLz5Msn6wqq8tHREEE0F/GPGbZmz0dRLlWp3E82B5Y= +github.com/omec-project/util v1.2.10/go.mod h1:P+WFVCtuLfsrfTgWZLaR5S6QCnA94PT7KdV6KSAFbw8= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -203,8 +203,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= diff --git a/proto/server/configEvtHandler.go b/proto/server/configEvtHandler.go index 82cbe2d2..ca7df53e 100644 --- a/proto/server/configEvtHandler.go +++ b/proto/server/configEvtHandler.go @@ -5,6 +5,7 @@ package server import ( + context "context" "encoding/json" "fmt" "os/exec" @@ -18,6 +19,7 @@ import ( "github.com/omec-project/webconsole/configmodels" "github.com/omec-project/webconsole/dbadapter" "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" ) const ( @@ -190,14 +192,80 @@ func handleDeviceGroupDelete(configMsg *configmodels.ConfigMessage, subsUpdateCh config5gMsg.PrevDevGroup = getDeviceGroupByName(configMsg.DevGroupName) subsUpdateChan <- &config5gMsg } - filter := bson.M{"group-name": configMsg.DevGroupName} - err := dbadapter.CommonDBClient.RestfulAPIDeleteOne(devGroupDataColl, filter) + err := deleteDeviceGroupAsTransaction(configMsg.DevGroupName) if err != nil { - logger.DbLog.Warnln(err) + logger.DbLog.Errorw("failed to delete Device Group", "error", err) } rwLock.Unlock() } +func deleteDeviceGroupAsTransaction(deviceGroupName string) error { + session, err := dbadapter.CommonDBClient.StartSession() + if err != nil { + return fmt.Errorf("failed to initialize DB session: %w", err) + } + ctx := context.TODO() + defer session.EndSession(ctx) + filter := bson.M{"group-name": deviceGroupName} + return mongo.WithSession(ctx, session, func(sc mongo.SessionContext) error { + if err := session.StartTransaction(); err != nil { + return fmt.Errorf("failed to start transaction: %w", err) + } + if err = dbadapter.CommonDBClient.RestfulAPIDeleteOneWithContext(devGroupDataColl, filter, sc); err != nil { + if abortErr := session.AbortTransaction(sc); abortErr != nil { + logger.DbLog.Errorw("failed to abort transaction", "error", abortErr) + } + return fmt.Errorf("failed to delete Device Group from collection: %w", err) + } + if err = updateDeviceGroupListInNetworkSlices(deviceGroupName, sc); err != nil { + if abortErr := session.AbortTransaction(sc); abortErr != nil { + logger.DbLog.Errorw("failed to abort transaction", "error", abortErr) + } + return fmt.Errorf("failed to update network slices: %w", err) + } + return session.CommitTransaction(sc) + }) +} +func updateDeviceGroupListInNetworkSlices(deviceGroupName string, context context.Context) error { + filterByDeviceGroup := bson.M{ + "site-device-group": bson.M{ + "$elemMatch": bson.M{ + "$eq": deviceGroupName, + }, + }, + } + rawNetworkSlices, err := dbadapter.CommonDBClient.RestfulAPIGetMany(sliceDataColl, filterByDeviceGroup) + if err != nil { + return fmt.Errorf("failed to fetch network slices: %w", err) + } + for _, rawNetworkSlice := range rawNetworkSlices { + var networkSlice configmodels.Slice + if err = json.Unmarshal(configmodels.MapToByte(rawNetworkSlice), &networkSlice); err != nil { + return fmt.Errorf("error unmarshaling network slice: %v", err) + } + filteredDeviceGroups := []string{} + for _, deviceGroup := range networkSlice.SiteDeviceGroup { + if deviceGroup != deviceGroupName { + filteredDeviceGroups = append(filteredDeviceGroups, deviceGroup) + } + } + filteredDeviceGroupsJSON, err := json.Marshal(filteredDeviceGroups) + if err != nil { + return fmt.Errorf("error marshaling device groups: %v", err) + } + patchJSON := []byte( + fmt.Sprintf(`[{"op": "replace", "path": "/site-device-group", "value": %s}]`, + string(filteredDeviceGroupsJSON)), + ) + filterBySliceName := bson.M{"slice-name": networkSlice.SliceName} + err = dbadapter.CommonDBClient.RestfulAPIJSONPatchWithContext(sliceDataColl, filterBySliceName, patchJSON, context) + if err != nil { + return err + } + } + return nil +} + func handleNetworkSlicePost(configMsg *configmodels.ConfigMessage, subsUpdateChan chan *Update5GSubscriberMsg) { rwLock.Lock() if factory.WebUIConfig.Configuration.Mode5G { From 026cc2d4f0f0368c83035037d8092823a3827cc8 Mon Sep 17 00:00:00 2001 From: Patricia Reinoso Date: Tue, 21 Jan 2025 10:28:54 +0100 Subject: [PATCH 02/10] fix lint Signed-off-by: Patricia Reinoso --- docs/docs.go.license | 2 ++ proto/server/configEvtHandler.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 docs/docs.go.license diff --git a/docs/docs.go.license b/docs/docs.go.license new file mode 100644 index 00000000..001eccf1 --- /dev/null +++ b/docs/docs.go.license @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 Canonical Ltd diff --git a/proto/server/configEvtHandler.go b/proto/server/configEvtHandler.go index ca7df53e..a349c315 100644 --- a/proto/server/configEvtHandler.go +++ b/proto/server/configEvtHandler.go @@ -208,7 +208,7 @@ func deleteDeviceGroupAsTransaction(deviceGroupName string) error { defer session.EndSession(ctx) filter := bson.M{"group-name": deviceGroupName} return mongo.WithSession(ctx, session, func(sc mongo.SessionContext) error { - if err := session.StartTransaction(); err != nil { + if err = session.StartTransaction(); err != nil { return fmt.Errorf("failed to start transaction: %w", err) } if err = dbadapter.CommonDBClient.RestfulAPIDeleteOneWithContext(devGroupDataColl, filter, sc); err != nil { From 2b17dad0f339adf49eb17c4d213a4d05167a90ba Mon Sep 17 00:00:00 2001 From: Patricia Reinoso Date: Tue, 21 Jan 2025 10:31:49 +0100 Subject: [PATCH 03/10] fix lint Signed-off-by: Patricia Reinoso --- proto/server/configEvtHandler.go | 1 + 1 file changed, 1 insertion(+) diff --git a/proto/server/configEvtHandler.go b/proto/server/configEvtHandler.go index a349c315..f783061c 100644 --- a/proto/server/configEvtHandler.go +++ b/proto/server/configEvtHandler.go @@ -226,6 +226,7 @@ func deleteDeviceGroupAsTransaction(deviceGroupName string) error { return session.CommitTransaction(sc) }) } + func updateDeviceGroupListInNetworkSlices(deviceGroupName string, context context.Context) error { filterByDeviceGroup := bson.M{ "site-device-group": bson.M{ From f7daa69975e2f3147ad4200e7871f9fa4b0dc21a Mon Sep 17 00:00:00 2001 From: Patricia Reinoso Date: Wed, 22 Jan 2025 19:24:47 +0100 Subject: [PATCH 04/10] move delete from NS to the end Signed-off-by: Patricia Reinoso --- proto/server/configEvtHandler.go | 50 ++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/proto/server/configEvtHandler.go b/proto/server/configEvtHandler.go index f783061c..fe68b978 100644 --- a/proto/server/configEvtHandler.go +++ b/proto/server/configEvtHandler.go @@ -192,7 +192,9 @@ func handleDeviceGroupDelete(configMsg *configmodels.ConfigMessage, subsUpdateCh config5gMsg.PrevDevGroup = getDeviceGroupByName(configMsg.DevGroupName) subsUpdateChan <- &config5gMsg } - err := deleteDeviceGroupAsTransaction(configMsg.DevGroupName) + filter := bson.M{"group-name": configMsg.DevGroupName} + err := dbadapter.CommonDBClient.RestfulAPIDeleteOne(devGroupDataColl, filter) + //err := deleteDeviceGroupAsTransaction(configMsg.DevGroupName) if err != nil { logger.DbLog.Errorw("failed to delete Device Group", "error", err) } @@ -599,6 +601,42 @@ func updateSmfSelectionProviosionedData(snssai *models.Snssai, mcc, mnc, dnn, im } } +func deleteAmProvisionedData(imsi string) { + + filter := bson.M{"ueId": "imsi-" + imsi} + num, err := dbadapter.CommonDBClient.RestfulAPICount(amDataColl, filter) + if err != nil { + logger.DbLog.Warnln(err) + return + } + if num == 0 { + logger.DbLog.Infof("ALREADY DELETED %v", imsi) + return + } + /*update := bson.M{ + "gpsis": "", + "nssai": "", + "servingPlmnId": "", + "subscribedUeAmbr": "", + } + + _, errPost := dbadapter.CommonDBClient.RestfulAPIPutOne(amDataColl, filter, update) + */ + logger.DbLog.Infof("UPDATing %v", imsi) + patchJSON := []byte(`[ + {"op": "replace", "path": "/servingPlmnId", "value": "1"}, + {"op": "replace", "path": "/gpsis", "value": "[]"}, + {"op": "remove", "path": "/nssai/defaultSingleNssais"}, + {"op": "remove", "path": "/nssai/singleNssais"}, + {"op": "remove", "path": "/subscribedUeAmbr/uplink"}, + {"op": "remove", "path": "/subscribedUeAmbr/downlink"} + ]`) + errPost := dbadapter.CommonDBClient.RestfulAPIJSONPatch(amDataColl, filter, patchJSON) + if errPost != nil { + logger.DbLog.Warnln(errPost) + } +} + func isDeviceGroupExistInSlice(msg *Update5GSubscriberMsg) *configmodels.Slice { for name, slice := range getSlices() { for _, dgName := range slice.SiteDeviceGroup { @@ -709,10 +747,7 @@ func Config5GUpdateHandle(confChan chan *Update5GSubscriberMsg) { if errDelOneSmPol != nil { logger.DbLog.Warnln(errDelOneSmPol) } - errDelOneAmData := dbadapter.CommonDBClient.RestfulAPIDeleteOne(amDataColl, filter) - if errDelOneAmData != nil { - logger.DbLog.Warnln(errDelOneAmData) - } + deleteAmProvisionedData(imsi) errDelOneSmData := dbadapter.CommonDBClient.RestfulAPIDeleteOne(smDataColl, filter) if errDelOneSmData != nil { logger.DbLog.Warnln(errDelOneSmData) @@ -722,6 +757,11 @@ func Config5GUpdateHandle(confChan chan *Update5GSubscriberMsg) { logger.DbLog.Warnln(errDelOneSmfSel) } } + if confData.Msg.MsgMethod == configmodels.Delete_op { + if err := updateDeviceGroupListInNetworkSlices(confData.Msg.DevGroupName, context.TODO()); err != nil { + logger.DbLog.Warnln(err) + } + } } rwLock.RUnlock() From 8151408444099a9dc1806edb6faf37ab05fcaf76 Mon Sep 17 00:00:00 2001 From: Patricia Reinoso Date: Thu, 23 Jan 2025 12:52:49 +0100 Subject: [PATCH 05/10] fix removal of ns information Signed-off-by: Patricia Reinoso --- proto/server/configEvtHandler.go | 102 ++++++++++--------------------- 1 file changed, 31 insertions(+), 71 deletions(-) diff --git a/proto/server/configEvtHandler.go b/proto/server/configEvtHandler.go index fe68b978..917c9afa 100644 --- a/proto/server/configEvtHandler.go +++ b/proto/server/configEvtHandler.go @@ -602,7 +602,6 @@ func updateSmfSelectionProviosionedData(snssai *models.Snssai, mcc, mnc, dnn, im } func deleteAmProvisionedData(imsi string) { - filter := bson.M{"ueId": "imsi-" + imsi} num, err := dbadapter.CommonDBClient.RestfulAPICount(amDataColl, filter) if err != nil { @@ -610,30 +609,17 @@ func deleteAmProvisionedData(imsi string) { return } if num == 0 { - logger.DbLog.Infof("ALREADY DELETED %v", imsi) + logger.WebUILog.Infof("imsi-%v is no longer provisioned, no need to remove it", imsi) return } - /*update := bson.M{ - "gpsis": "", - "nssai": "", + update := bson.M{ + "gpsis": []string{}, + "nssai": nil, "servingPlmnId": "", - "subscribedUeAmbr": "", - } - - _, errPost := dbadapter.CommonDBClient.RestfulAPIPutOne(amDataColl, filter, update) - */ - logger.DbLog.Infof("UPDATing %v", imsi) - patchJSON := []byte(`[ - {"op": "replace", "path": "/servingPlmnId", "value": "1"}, - {"op": "replace", "path": "/gpsis", "value": "[]"}, - {"op": "remove", "path": "/nssai/defaultSingleNssais"}, - {"op": "remove", "path": "/nssai/singleNssais"}, - {"op": "remove", "path": "/subscribedUeAmbr/uplink"}, - {"op": "remove", "path": "/subscribedUeAmbr/downlink"} - ]`) - errPost := dbadapter.CommonDBClient.RestfulAPIJSONPatch(amDataColl, filter, patchJSON) - if errPost != nil { - logger.DbLog.Warnln(errPost) + "subscribedUeAmbr": nil, + } + if _, err = dbadapter.CommonDBClient.RestfulAPIPutOne(amDataColl, filter, update); err != nil { + logger.DbLog.Warnln(err) } } @@ -679,6 +665,27 @@ func getDeleteGroupsList(slice, prevSlice *configmodels.Slice) (names []string) return } +func deleteSubscribersInfo(imsis []string, mcc, mnc string) { + for _, imsi := range imsis { + filterImsiOnly := bson.M{"ueId": "imsi-" + imsi} + filter := bson.M{"ueId": "imsi-" + imsi, "servingPlmnId": mcc + mnc} + + if err := dbadapter.CommonDBClient.RestfulAPIDeleteOne(amPolicyDataColl, filterImsiOnly); err != nil { + logger.DbLog.Warnln(err) + } + if err := dbadapter.CommonDBClient.RestfulAPIDeleteOne(smPolicyDataColl, filterImsiOnly); err != nil { + logger.DbLog.Warnln(err) + } + if err := dbadapter.CommonDBClient.RestfulAPIDeleteOne(smDataColl, filter); err != nil { + logger.DbLog.Warnln(err) + } + if err := dbadapter.CommonDBClient.RestfulAPIDeleteOne(smfSelDataColl, filter); err != nil { + logger.DbLog.Warnln(err) + } + deleteAmProvisionedData(imsi) + } +} + func Config5GUpdateHandle(confChan chan *Update5GSubscriberMsg) { for confData := range confChan { switch confData.Msg.MsgType { @@ -734,29 +741,7 @@ func Config5GUpdateHandle(confChan chan *Update5GSubscriberMsg) { } dimsis := getDeletedImsisList(confData.Msg.DevGroup, confData.PrevDevGroup) - for _, imsi := range dimsis { - mcc := slice.SiteInfo.Plmn.Mcc - mnc := slice.SiteInfo.Plmn.Mnc - filterImsiOnly := bson.M{"ueId": "imsi-" + imsi} - filter := bson.M{"ueId": "imsi-" + imsi, "servingPlmnId": mcc + mnc} - errDelOneAmPol := dbadapter.CommonDBClient.RestfulAPIDeleteOne(amPolicyDataColl, filterImsiOnly) - if errDelOneAmPol != nil { - logger.DbLog.Warnln(errDelOneAmPol) - } - errDelOneSmPol := dbadapter.CommonDBClient.RestfulAPIDeleteOne(smPolicyDataColl, filterImsiOnly) - if errDelOneSmPol != nil { - logger.DbLog.Warnln(errDelOneSmPol) - } - deleteAmProvisionedData(imsi) - errDelOneSmData := dbadapter.CommonDBClient.RestfulAPIDeleteOne(smDataColl, filter) - if errDelOneSmData != nil { - logger.DbLog.Warnln(errDelOneSmData) - } - errDelOneSmfSel := dbadapter.CommonDBClient.RestfulAPIDeleteOne(smfSelDataColl, filter) - if errDelOneSmfSel != nil { - logger.DbLog.Warnln(errDelOneSmfSel) - } - } + deleteSubscribersInfo(dimsis, slice.SiteInfo.Plmn.Mcc, slice.SiteInfo.Plmn.Mnc) if confData.Msg.MsgMethod == configmodels.Delete_op { if err := updateDeviceGroupListInNetworkSlices(confData.Msg.DevGroupName, context.TODO()); err != nil { logger.DbLog.Warnln(err) @@ -803,32 +788,7 @@ func Config5GUpdateHandle(confChan chan *Update5GSubscriberMsg) { for _, dgname := range dgnames { devGroupConfig := getDeviceGroupByName(dgname) if devGroupConfig != nil { - for _, imsi := range devGroupConfig.Imsis { - mcc := confData.PrevSlice.SiteInfo.Plmn.Mcc - mnc := confData.PrevSlice.SiteInfo.Plmn.Mnc - filterImsiOnly := bson.M{"ueId": "imsi-" + imsi} - filter := bson.M{"ueId": "imsi-" + imsi, "servingPlmnId": mcc + mnc} - errDelOneAmPol := dbadapter.CommonDBClient.RestfulAPIDeleteOne(amPolicyDataColl, filterImsiOnly) - if errDelOneAmPol != nil { - logger.DbLog.Warnln(errDelOneAmPol) - } - errDelOneSmPol := dbadapter.CommonDBClient.RestfulAPIDeleteOne(smPolicyDataColl, filterImsiOnly) - if errDelOneSmPol != nil { - logger.DbLog.Warnln(errDelOneSmPol) - } - errDelOneAmData := dbadapter.CommonDBClient.RestfulAPIDeleteOne(amDataColl, filter) - if errDelOneAmData != nil { - logger.DbLog.Warnln(errDelOneAmData) - } - errDelOneSmData := dbadapter.CommonDBClient.RestfulAPIDeleteOne(smDataColl, filter) - if errDelOneSmData != nil { - logger.DbLog.Warnln(errDelOneSmData) - } - errDelOneSmfSel := dbadapter.CommonDBClient.RestfulAPIDeleteOne(smfSelDataColl, filter) - if errDelOneSmfSel != nil { - logger.DbLog.Warnln(errDelOneSmfSel) - } - } + deleteSubscribersInfo(devGroupConfig.Imsis, confData.PrevSlice.SiteInfo.Plmn.Mcc, confData.PrevSlice.SiteInfo.Plmn.Mnc) } } rwLock.RUnlock() From f790bec6d79503d5043a72ca7ce4311a9d011739 Mon Sep 17 00:00:00 2001 From: Patricia Reinoso Date: Thu, 23 Jan 2025 13:38:19 +0100 Subject: [PATCH 06/10] use pull to modify element in list Signed-off-by: Patricia Reinoso --- dbadapter/db_adapter.go | 5 ++ proto/server/configEvtHandler.go | 89 ++++++-------------------------- 2 files changed, 20 insertions(+), 74 deletions(-) diff --git a/dbadapter/db_adapter.go b/dbadapter/db_adapter.go index e56a8dc4..322973f2 100644 --- a/dbadapter/db_adapter.go +++ b/dbadapter/db_adapter.go @@ -34,6 +34,7 @@ type DBInterface interface { RestfulAPIPost(collName string, filter bson.M, postData map[string]interface{}) (bool, error) RestfulAPIPostMany(collName string, filter bson.M, postDataArray []interface{}) error RestfulAPICount(collName string, filter bson.M) (int64, error) + RestfulAPIPullOne(collName string, filter bson.M, putData map[string]interface{}) error CreateIndex(collName string, keyField string) (bool, error) StartSession() (mongo.Session, error) SupportsTransactions() (bool, error) @@ -147,6 +148,10 @@ func (db *MongoDBClient) RestfulAPICount(collName string, filter bson.M) (int64, return db.MongoClient.RestfulAPICount(collName, filter) } +func (db *MongoDBClient) RestfulAPIPullOne(collName string, filter bson.M, putData map[string]interface{}) error { + return db.MongoClient.RestfulAPIPullOne(collName, filter, putData) +} + func (db *MongoDBClient) CreateIndex(collName string, keyField string) (bool, error) { return db.MongoClient.CreateIndex(collName, keyField) } diff --git a/proto/server/configEvtHandler.go b/proto/server/configEvtHandler.go index 917c9afa..03ba7184 100644 --- a/proto/server/configEvtHandler.go +++ b/proto/server/configEvtHandler.go @@ -5,7 +5,6 @@ package server import ( - context "context" "encoding/json" "fmt" "os/exec" @@ -19,7 +18,6 @@ import ( "github.com/omec-project/webconsole/configmodels" "github.com/omec-project/webconsole/dbadapter" "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" ) const ( @@ -194,81 +192,12 @@ func handleDeviceGroupDelete(configMsg *configmodels.ConfigMessage, subsUpdateCh } filter := bson.M{"group-name": configMsg.DevGroupName} err := dbadapter.CommonDBClient.RestfulAPIDeleteOne(devGroupDataColl, filter) - //err := deleteDeviceGroupAsTransaction(configMsg.DevGroupName) if err != nil { logger.DbLog.Errorw("failed to delete Device Group", "error", err) } rwLock.Unlock() } -func deleteDeviceGroupAsTransaction(deviceGroupName string) error { - session, err := dbadapter.CommonDBClient.StartSession() - if err != nil { - return fmt.Errorf("failed to initialize DB session: %w", err) - } - ctx := context.TODO() - defer session.EndSession(ctx) - filter := bson.M{"group-name": deviceGroupName} - return mongo.WithSession(ctx, session, func(sc mongo.SessionContext) error { - if err = session.StartTransaction(); err != nil { - return fmt.Errorf("failed to start transaction: %w", err) - } - if err = dbadapter.CommonDBClient.RestfulAPIDeleteOneWithContext(devGroupDataColl, filter, sc); err != nil { - if abortErr := session.AbortTransaction(sc); abortErr != nil { - logger.DbLog.Errorw("failed to abort transaction", "error", abortErr) - } - return fmt.Errorf("failed to delete Device Group from collection: %w", err) - } - if err = updateDeviceGroupListInNetworkSlices(deviceGroupName, sc); err != nil { - if abortErr := session.AbortTransaction(sc); abortErr != nil { - logger.DbLog.Errorw("failed to abort transaction", "error", abortErr) - } - return fmt.Errorf("failed to update network slices: %w", err) - } - return session.CommitTransaction(sc) - }) -} - -func updateDeviceGroupListInNetworkSlices(deviceGroupName string, context context.Context) error { - filterByDeviceGroup := bson.M{ - "site-device-group": bson.M{ - "$elemMatch": bson.M{ - "$eq": deviceGroupName, - }, - }, - } - rawNetworkSlices, err := dbadapter.CommonDBClient.RestfulAPIGetMany(sliceDataColl, filterByDeviceGroup) - if err != nil { - return fmt.Errorf("failed to fetch network slices: %w", err) - } - for _, rawNetworkSlice := range rawNetworkSlices { - var networkSlice configmodels.Slice - if err = json.Unmarshal(configmodels.MapToByte(rawNetworkSlice), &networkSlice); err != nil { - return fmt.Errorf("error unmarshaling network slice: %v", err) - } - filteredDeviceGroups := []string{} - for _, deviceGroup := range networkSlice.SiteDeviceGroup { - if deviceGroup != deviceGroupName { - filteredDeviceGroups = append(filteredDeviceGroups, deviceGroup) - } - } - filteredDeviceGroupsJSON, err := json.Marshal(filteredDeviceGroups) - if err != nil { - return fmt.Errorf("error marshaling device groups: %v", err) - } - patchJSON := []byte( - fmt.Sprintf(`[{"op": "replace", "path": "/site-device-group", "value": %s}]`, - string(filteredDeviceGroupsJSON)), - ) - filterBySliceName := bson.M{"slice-name": networkSlice.SliceName} - err = dbadapter.CommonDBClient.RestfulAPIJSONPatchWithContext(sliceDataColl, filterBySliceName, patchJSON, context) - if err != nil { - return err - } - } - return nil -} - func handleNetworkSlicePost(configMsg *configmodels.ConfigMessage, subsUpdateChan chan *Update5GSubscriberMsg) { rwLock.Lock() if factory.WebUIConfig.Configuration.Mode5G { @@ -686,6 +615,20 @@ func deleteSubscribersInfo(imsis []string, mcc, mnc string) { } } +func removeDeviceGroupFromNetworkSlice(deviceGroupName string) { + filterByDeviceGroup := bson.M{ + "site-device-group": bson.M{ + "$elemMatch": bson.M{ + "$eq": deviceGroupName, + }, + }, + } + update := bson.M{"site-device-group": deviceGroupName} + if err := dbadapter.CommonDBClient.RestfulAPIPullOne(sliceDataColl, filterByDeviceGroup, update); err != nil { + logger.DbLog.Errorw("failed to remove device group from network slice", "device group", deviceGroupName, "error", err) + } +} + func Config5GUpdateHandle(confChan chan *Update5GSubscriberMsg) { for confData := range confChan { switch confData.Msg.MsgType { @@ -743,9 +686,7 @@ func Config5GUpdateHandle(confChan chan *Update5GSubscriberMsg) { dimsis := getDeletedImsisList(confData.Msg.DevGroup, confData.PrevDevGroup) deleteSubscribersInfo(dimsis, slice.SiteInfo.Plmn.Mcc, slice.SiteInfo.Plmn.Mnc) if confData.Msg.MsgMethod == configmodels.Delete_op { - if err := updateDeviceGroupListInNetworkSlices(confData.Msg.DevGroupName, context.TODO()); err != nil { - logger.DbLog.Warnln(err) - } + removeDeviceGroupFromNetworkSlice(confData.Msg.DevGroupName) } } rwLock.RUnlock() From 2207c027f6f02ec055ce2f9012729169869aa4c1 Mon Sep 17 00:00:00 2001 From: Patricia Reinoso Date: Thu, 23 Jan 2025 14:22:29 +0100 Subject: [PATCH 07/10] rename functions Signed-off-by: Patricia Reinoso --- proto/server/configEvtHandler.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proto/server/configEvtHandler.go b/proto/server/configEvtHandler.go index 03ba7184..32019fe3 100644 --- a/proto/server/configEvtHandler.go +++ b/proto/server/configEvtHandler.go @@ -530,7 +530,7 @@ func updateSmfSelectionProviosionedData(snssai *models.Snssai, mcc, mnc, dnn, im } } -func deleteAmProvisionedData(imsi string) { +func removeDeviceGroupInfoFromAmData(imsi string) { filter := bson.M{"ueId": "imsi-" + imsi} num, err := dbadapter.CommonDBClient.RestfulAPICount(amDataColl, filter) if err != nil { @@ -594,7 +594,7 @@ func getDeleteGroupsList(slice, prevSlice *configmodels.Slice) (names []string) return } -func deleteSubscribersInfo(imsis []string, mcc, mnc string) { +func removeSubscriberEntriesAssociatedToDeviceGroups(imsis []string, mcc, mnc string) { for _, imsi := range imsis { filterImsiOnly := bson.M{"ueId": "imsi-" + imsi} filter := bson.M{"ueId": "imsi-" + imsi, "servingPlmnId": mcc + mnc} @@ -611,7 +611,7 @@ func deleteSubscribersInfo(imsis []string, mcc, mnc string) { if err := dbadapter.CommonDBClient.RestfulAPIDeleteOne(smfSelDataColl, filter); err != nil { logger.DbLog.Warnln(err) } - deleteAmProvisionedData(imsi) + removeDeviceGroupInfoFromAmData(imsi) } } @@ -684,7 +684,7 @@ func Config5GUpdateHandle(confChan chan *Update5GSubscriberMsg) { } dimsis := getDeletedImsisList(confData.Msg.DevGroup, confData.PrevDevGroup) - deleteSubscribersInfo(dimsis, slice.SiteInfo.Plmn.Mcc, slice.SiteInfo.Plmn.Mnc) + removeSubscriberEntriesAssociatedToDeviceGroups(dimsis, slice.SiteInfo.Plmn.Mcc, slice.SiteInfo.Plmn.Mnc) if confData.Msg.MsgMethod == configmodels.Delete_op { removeDeviceGroupFromNetworkSlice(confData.Msg.DevGroupName) } @@ -729,7 +729,7 @@ func Config5GUpdateHandle(confChan chan *Update5GSubscriberMsg) { for _, dgname := range dgnames { devGroupConfig := getDeviceGroupByName(dgname) if devGroupConfig != nil { - deleteSubscribersInfo(devGroupConfig.Imsis, confData.PrevSlice.SiteInfo.Plmn.Mcc, confData.PrevSlice.SiteInfo.Plmn.Mnc) + removeSubscriberEntriesAssociatedToDeviceGroups(devGroupConfig.Imsis, confData.PrevSlice.SiteInfo.Plmn.Mcc, confData.PrevSlice.SiteInfo.Plmn.Mnc) } } rwLock.RUnlock() From 21622e460d58491fb78db137453b11683eaa2f8b Mon Sep 17 00:00:00 2001 From: Patricia Reinoso Date: Fri, 24 Jan 2025 11:18:05 +0100 Subject: [PATCH 08/10] update existing amdata instead of overwriting Signed-off-by: Patricia Reinoso --- proto/server/configEvtHandler.go | 1 + 1 file changed, 1 insertion(+) diff --git a/proto/server/configEvtHandler.go b/proto/server/configEvtHandler.go index 32019fe3..b680a477 100644 --- a/proto/server/configEvtHandler.go +++ b/proto/server/configEvtHandler.go @@ -459,6 +459,7 @@ func updateAmProvisionedData(snssai *models.Snssai, qos *configmodels.DeviceGrou "$or": []bson.M{ {"servingPlmnId": mcc + mnc}, {"servingPlmnId": bson.M{"$exists": false}}, + {"servingPlmnId": ""}, }, } _, errPost := dbadapter.CommonDBClient.RestfulAPIPost(amDataColl, filter, amDataBsonA) From d97437d07665472c1e807944d6760c70575b9e96 Mon Sep 17 00:00:00 2001 From: Patricia Reinoso Date: Fri, 31 Jan 2025 14:07:19 +0100 Subject: [PATCH 09/10] propagate to NF Signed-off-by: Patricia Reinoso --- proto/server/clientEvtHandler.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proto/server/clientEvtHandler.go b/proto/server/clientEvtHandler.go index b11b4795..de0a9a3a 100644 --- a/proto/server/clientEvtHandler.go +++ b/proto/server/clientEvtHandler.go @@ -10,6 +10,7 @@ import ( "encoding/json" "math/rand" "net/http" + "slices" "strconv" "strings" "time" @@ -680,6 +681,9 @@ func clientEventMachine(client *clientNF) { if ok, sliceName := isDeviceGroupInExistingSlices(client, name); ok { client.clientLog.Infof("DeviceGroup: %v deleted, slice of this device group: %v", name, sliceName) slice := client.slicesConfigClient[sliceName] + slice.SiteDeviceGroup = slices.DeleteFunc(slice.SiteDeviceGroup, func(deviceGroupName string) bool { + return name == deviceGroupName + }) fillSlice(client, slice.SliceName, slice, sliceProto) dimsis := getDeletedImsisList(nil, cReqMsg.lastDevGroup) sliceProto.DeletedImsis = dimsis From 7220ee41d3db572bc5dc26068fe02e34cd171987 Mon Sep 17 00:00:00 2001 From: Patricia Reinoso Date: Mon, 3 Feb 2025 15:16:16 +0100 Subject: [PATCH 10/10] avoid filling network slices Signed-off-by: Patricia Reinoso --- proto/server/clientEvtHandler.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/proto/server/clientEvtHandler.go b/proto/server/clientEvtHandler.go index de0a9a3a..bd6cb65a 100644 --- a/proto/server/clientEvtHandler.go +++ b/proto/server/clientEvtHandler.go @@ -488,6 +488,17 @@ func clientEventMachine(client *clientNF) { lastDevGroup = client.devgroupsConfigClient[configMsg.DevGroupName] client.clientLog.Debugf("Received delete configuration for Device Group: %v ", configMsg.DevGroupName) delete(client.devgroupsConfigClient, configMsg.DevGroupName) + + if !client.metadataReqtd { + if ok, sliceName := isDeviceGroupInExistingSlices(client, configMsg.DevGroupName); ok { + client.clientLog.Infof("DeviceGroup: %v deleted, slice of this device group: %v", configMsg.DevGroupName, sliceName) + slice := client.slicesConfigClient[sliceName] + slice.SiteDeviceGroup = slices.DeleteFunc(slice.SiteDeviceGroup, func(deviceGroupName string) bool { + return configMsg.DevGroupName == deviceGroupName + }) + } + } + } if configMsg.Slice != nil {