Skip to content

Commit 292af4a

Browse files
committed
AppInterface enhancements for subscription
Added new translateSubscribe() and processSubscribe() functions to appInterface as per HLD sonic-net/SONiC#1287 Also added stub implementation of these functions to all existing app modules. It blindly treats all paths as non-db. Basic subscription features, without on_change, are enabled with this mapping. Signed-off-by: Sachin Holla <[email protected]>
1 parent 68e0341 commit 292af4a

15 files changed

+787
-220
lines changed

translib/acl_app.go

+16-66
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"reflect"
2727
"strconv"
2828
"strings"
29+
2930
"github.com/Azure/sonic-mgmt-common/translib/db"
3031
"github.com/Azure/sonic-mgmt-common/translib/ocbinds"
3132
"github.com/Azure/sonic-mgmt-common/translib/tlerr"
@@ -168,68 +169,8 @@ func (app *AclApp) translateGet(dbs [db.MaxDB]*db.DB) error {
168169
}
169170

170171
func (app *AclApp) translateAction(dbs [db.MaxDB]*db.DB) error {
171-
err := errors.New("Not supported")
172-
return err
173-
}
174-
175-
func (app *AclApp) translateSubscribe(dbs [db.MaxDB]*db.DB, path string) (*notificationOpts, *notificationInfo, error) {
176-
pathInfo := NewPathInfo(path)
177-
notifInfo := notificationInfo{dbno: db.ConfigDB}
178-
notSupported := tlerr.NotSupportedError{
179-
Format: "Subscribe not supported", Path: path}
180-
181-
if isSubtreeRequest(pathInfo.Template, "/openconfig-acl:acl/acl-sets") {
182-
// Subscribing to top level ACL record is not supported. It requires listening
183-
// to 2 tables (ACL and ACL_RULE); TransLib does not support it yet
184-
if pathInfo.HasSuffix("/acl-sets") ||
185-
pathInfo.HasSuffix("/acl-set") ||
186-
pathInfo.HasSuffix("/acl-set{}{}") {
187-
log.Errorf("Subscribe not supported for top level ACL %s", pathInfo.Template)
188-
return nil, nil, notSupported
189-
}
190-
191-
t, err := getAclTypeOCEnumFromName(pathInfo.Var("type"))
192-
if err != nil {
193-
return nil, nil, err
194-
}
195-
196-
aclkey := getAclKeyStrFromOCKey(pathInfo.Var("name"), t)
197-
198-
if strings.Contains(pathInfo.Template, "/acl-entry{}") {
199-
// Subscribe for one rule
200-
rulekey := "RULE_" + pathInfo.Var("sequence-id")
201-
notifInfo.table = db.TableSpec{Name: RULE_TABLE}
202-
notifInfo.key = asKey(aclkey, rulekey)
203-
notifInfo.needCache = !pathInfo.HasSuffix("/acl-entry{}")
204-
205-
} else if pathInfo.HasSuffix("/acl-entries") || pathInfo.HasSuffix("/acl-entry") {
206-
// Subscribe for all rules of an ACL
207-
notifInfo.table = db.TableSpec{Name: RULE_TABLE}
208-
notifInfo.key = asKey(aclkey, "*")
209-
210-
} else {
211-
// Subscibe for ACL fields only
212-
notifInfo.table = db.TableSpec{Name: ACL_TABLE}
213-
notifInfo.key = asKey(aclkey)
214-
notifInfo.needCache = true
215-
}
216-
217-
} else if isSubtreeRequest(pathInfo.Template, "/openconfig-acl:acl/interfaces") {
218-
// Right now interface binding config is maintained within ACL
219-
// table itself. Multiple ACLs can be bound to one intf; one
220-
// inname can occur in multiple ACL entries. So we cannot map
221-
// interface binding xpaths to specific ACL table entry keys.
222-
// For now subscribe for full ACL table!!
223-
notifInfo.table = db.TableSpec{Name: ACL_TABLE}
224-
notifInfo.key = asKey("*")
225-
notifInfo.needCache = true
226-
227-
} else {
228-
log.Errorf("Unknown path %s", pathInfo.Template)
229-
return nil, nil, notSupported
230-
}
231-
232-
return nil, &notifInfo, nil
172+
err := errors.New("Not supported")
173+
return err
233174
}
234175

235176
func (app *AclApp) processCreate(d *db.DB) (SetResponse, error) {
@@ -295,10 +236,10 @@ func (app *AclApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) {
295236
}
296237

297238
func (app *AclApp) processAction(dbs [db.MaxDB]*db.DB) (ActionResponse, error) {
298-
var resp ActionResponse
299-
err := errors.New("Not implemented")
239+
var resp ActionResponse
240+
err := errors.New("Not implemented")
300241

301-
return resp, err
242+
return resp, err
302243
}
303244

304245
func (app *AclApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, error) {
@@ -1716,10 +1657,19 @@ func getAclKeyStrFromOCKey(aclname string, acltype ocbinds.E_OpenconfigAcl_ACL_T
17161657
return aclN + "_" + aclT
17171658
}
17181659

1719-
/* Check if targetUriPath is child (subtree) of nodePath
1660+
/*
1661+
Check if targetUriPath is child (subtree) of nodePath
17201662
The return value can be used to decide if subtrees needs
17211663
to visited to fill the data or not.
17221664
*/
17231665
func isSubtreeRequest(targetUriPath string, nodePath string) bool {
17241666
return strings.HasPrefix(targetUriPath, nodePath)
17251667
}
1668+
1669+
func (app *AclApp) translateSubscribe(req *translateSubRequest) (*translateSubResponse, error) {
1670+
return emptySubscribeResponse(req.path)
1671+
}
1672+
1673+
func (app *AclApp) processSubscribe(req *processSubRequest) (processSubResponse, error) {
1674+
return processSubResponse{}, errors.New("not implemented")
1675+
}

translib/api_tests_app.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// //
1818
////////////////////////////////////////////////////////////////////////////////
1919

20+
//go:build test
2021
// +build test
2122

2223
package translib
@@ -101,8 +102,12 @@ func (app *apiTests) translateAction(dbs [db.MaxDB]*db.DB) error {
101102
return nil
102103
}
103104

104-
func (app *apiTests) translateSubscribe(dbs [db.MaxDB]*db.DB, path string) (*notificationOpts, *notificationInfo, error) {
105-
return nil, nil, nil
105+
func (app *apiTests) translateSubscribe(req *translateSubRequest) (*translateSubResponse, error) {
106+
return emptySubscribeResponse(req.path)
107+
}
108+
109+
func (app *apiTests) processSubscribe(req *processSubRequest) (processSubResponse, error) {
110+
return processSubResponse{}, tlerr.New("not implemented")
106111
}
107112

108113
func (app *apiTests) processCreate(d *db.DB) (SetResponse, error) {

translib/app_interface.go

+25-23
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// //
1212
// Unless required by applicable law or agreed to in writing, software //
1313
// distributed under the License is distributed on an "AS IS" BASIS, //
14-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
1515
// See the License for the specific language governing permissions and //
1616
// limitations under the License. //
1717
// //
@@ -31,22 +31,23 @@ package translib
3131

3232
import (
3333
"errors"
34-
log "github.com/golang/glog"
35-
"github.com/openconfig/ygot/ygot"
3634
"reflect"
3735
"strings"
36+
3837
"github.com/Azure/sonic-mgmt-common/translib/db"
38+
log "github.com/golang/glog"
39+
"github.com/openconfig/ygot/ygot"
3940
)
4041

41-
//Structure containing app module information
42+
// Structure containing app module information
4243
type appInfo struct {
4344
appType reflect.Type
4445
ygotRootType reflect.Type
4546
isNative bool
4647
tablesToWatch []*db.TableSpec
4748
}
4849

49-
//Structure containing the app data coming from translib infra
50+
// Structure containing the app data coming from translib infra
5051
type appData struct {
5152
path string
5253
payload []byte
@@ -59,23 +60,23 @@ type appData struct {
5960
// These include RESTCONF query parameters like - depth, fields etc.
6061
type appOptions struct {
6162

62-
// depth limits subtree levels in the response data.
63-
// 0 indicates unlimited depth.
64-
// Valid for GET API only.
65-
depth uint
63+
// depth limits subtree levels in the response data.
64+
// 0 indicates unlimited depth.
65+
// Valid for GET API only.
66+
depth uint
6667

67-
// deleteEmptyEntry indicates if the db entry should be deleted upon
68-
// deletion of last field. This is a non standard option.
69-
deleteEmptyEntry bool
68+
// deleteEmptyEntry indicates if the db entry should be deleted upon
69+
// deletion of last field. This is a non standard option.
70+
deleteEmptyEntry bool
7071
}
7172

72-
//map containing the base path to app module info
73+
// map containing the base path to app module info
7374
var appMap map[string]*appInfo
7475

75-
//array containing all the supported models
76+
// array containing all the supported models
7677
var models []ModelData
7778

78-
//Interface for all App Modules
79+
// Interface for all App Modules
7980
type appInterface interface {
8081
initialize(data appData)
8182
translateCreate(d *db.DB) ([]db.WatchKeys, error)
@@ -84,16 +85,17 @@ type appInterface interface {
8485
translateDelete(d *db.DB) ([]db.WatchKeys, error)
8586
translateGet(dbs [db.MaxDB]*db.DB) error
8687
translateAction(dbs [db.MaxDB]*db.DB) error
87-
translateSubscribe(dbs [db.MaxDB]*db.DB, path string) (*notificationOpts, *notificationInfo, error)
88+
translateSubscribe(req *translateSubRequest) (*translateSubResponse, error)
8889
processCreate(d *db.DB) (SetResponse, error)
8990
processUpdate(d *db.DB) (SetResponse, error)
9091
processReplace(d *db.DB) (SetResponse, error)
9192
processDelete(d *db.DB) (SetResponse, error)
9293
processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error)
9394
processAction(dbs [db.MaxDB]*db.DB) (ActionResponse, error)
95+
processSubscribe(req *processSubRequest) (processSubResponse, error)
9496
}
9597

96-
//App modules will use this function to register with App interface during boot up
98+
// App modules will use this function to register with App interface during boot up
9799
func register(path string, info *appInfo) error {
98100
var err error
99101
log.Info("Registering for path =", path)
@@ -114,7 +116,7 @@ func register(path string, info *appInfo) error {
114116
return err
115117
}
116118

117-
//Adds the model information to the supported models array
119+
// Adds the model information to the supported models array
118120
func addModel(model *ModelData) error {
119121
var err error
120122

@@ -124,7 +126,7 @@ func addModel(model *ModelData) error {
124126
return err
125127
}
126128

127-
//Translib infra will use this function get the app info for a given path
129+
// Translib infra will use this function get the app info for a given path
128130
func getAppModuleInfo(path string) (*appInfo, error) {
129131
log.Info("getAppModule called for path =", path)
130132

@@ -135,23 +137,23 @@ func getAppModuleInfo(path string) (*appInfo, error) {
135137

136138
log.Info("found the entry in the map for path =", pattern)
137139

138-
return app, nil
140+
return app, nil
139141
}
140142

141143
/* If no specific app registered fallback to default/common app */
142144
log.Infof("No app module registered for path %s hence fallback to default/common app", path)
143145
app := appMap["*"]
144146

145-
return app, nil
147+
return app, nil
146148
}
147149

148-
//Get all the supported models
150+
// Get all the supported models
149151
func getModels() []ModelData {
150152

151153
return models
152154
}
153155

154-
//Creates a new app from the appType and returns it as an appInterface
156+
// Creates a new app from the appType and returns it as an appInterface
155157
func getAppInterface(appType reflect.Type) (appInterface, error) {
156158
var err error
157159
appInstance := reflect.New(appType)

translib/common_app.go

+5-52
Original file line numberDiff line numberDiff line change
@@ -129,59 +129,12 @@ func (app *CommonApp) translateGet(dbs [db.MaxDB]*db.DB) error {
129129
return err
130130
}
131131

132-
func (app *CommonApp) translateSubscribe(dbs [db.MaxDB]*db.DB, path string) (*notificationOpts, *notificationInfo, error) {
133-
var err error
134-
var subscDt transformer.XfmrTranslateSubscribeInfo
135-
var notifInfo notificationInfo
136-
var notifOpts notificationOpts
137-
txCache := new(sync.Map)
138-
err = tlerr.NotSupportedError{Format: "Subscribe not supported", Path: path}
139-
140-
log.Info("tranlateSubscribe:path", path)
141-
subscDt, err = transformer.XlateTranslateSubscribe(path, dbs, txCache)
142-
if subscDt.PType == transformer.OnChange {
143-
notifOpts.pType = OnChange
144-
} else {
145-
notifOpts.pType = Sample
146-
}
147-
notifOpts.mInterval = subscDt.MinInterval
148-
notifOpts.isOnChangeSupported = subscDt.OnChange
149-
if err != nil {
150-
log.Infof("returning: notificationOpts - %v, nil, error - %v", notifOpts, err)
151-
return &notifOpts, nil, err
152-
}
153-
if subscDt.DbDataMap == nil {
154-
log.Infof("DB data is nil so returning: notificationOpts - %v, nil, error - %v", notifOpts, err)
155-
return &notifOpts, nil, err
156-
} else {
157-
for dbNo, dbDt := range(subscDt.DbDataMap) {
158-
if (len(dbDt) == 0) { //ideally all tables for a given uri should be from same DB
159-
continue
160-
}
161-
log.Infof("Adding to notifInfo, Db Data - %v for DB No - %v", dbDt, dbNo)
162-
notifInfo.dbno = dbNo
163-
// in future there will be, multi-table in a DB, support from translib, for now its just single table
164-
for tblNm, tblDt := range(dbDt) {
165-
notifInfo.table = db.TableSpec{Name:tblNm}
166-
if (len(tblDt) == 1) {
167-
for tblKy := range(tblDt) {
168-
notifInfo.key = asKey(tblKy)
169-
notifInfo.needCache = subscDt.NeedCache
170-
}
171-
} else {
172-
if (len(tblDt) > 1) {
173-
log.Warningf("More than one DB key found for subscription path - %v", path)
174-
} else {
175-
log.Warningf("No DB key found for subscription path - %v", path)
176-
}
177-
return &notifOpts, nil, err
178-
}
132+
func (app *CommonApp) translateSubscribe(req *translateSubRequest) (*translateSubResponse, error) {
133+
return emptySubscribeResponse(req.path)
134+
}
179135

180-
}
181-
}
182-
}
183-
log.Infof("For path - %v, returning: notifOpts - %v, notifInfo - %v, error - nil", path, notifOpts, notifInfo)
184-
return &notifOpts, &notifInfo, nil
136+
func (app *CommonApp) processSubscribe(req *processSubRequest) (processSubResponse, error) {
137+
return processSubResponse{}, errors.New("not implemented")
185138
}
186139

187140
func (app *CommonApp) translateAction(dbs [db.MaxDB]*db.DB) error {

0 commit comments

Comments
 (0)