Skip to content

Commit

Permalink
Merge pull request #248 from project-arlo/brcm_poc1101
Browse files Browse the repository at this point in the history
Brcm poc1101
  • Loading branch information
a-barboza authored Nov 5, 2019
2 parents c80c871 + 0932f55 commit edc1338
Show file tree
Hide file tree
Showing 53 changed files with 3,213 additions and 594 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ cp $(TOPDIR)/goyang-modified-files/annotate.go $(BUILD_GOPATH)/src/github.com/op
cp $(TOPDIR)/goyang-modified-files/goyang.patch .; \
patch -p1 < goyang.patch; rm -f goyang.patch; \
$(GO) install -v -gcflags "-N -l" $(BUILD_GOPATH)/src/github.com/openconfig/goyang
#Patch for jsonquery
cd $(BUILD_GOPATH)/src/github.com/antchfx/jsonquery; git reset --hard HEAD; \
git checkout 3b69d31134d889b501e166a035a4d5ecb8c6c367; git apply $(TOPDIR)/patches/jsonquery.patch

install:
$(INSTALL) -D $(REST_BIN) $(DESTDIR)/usr/sbin/rest_server
Expand Down
6 changes: 6 additions & 0 deletions debian/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.debhelper/
files
sonic-mgmt-framework.debhelper.log
sonic-mgmt-framework.substvars
sonic-mgmt-framework/

22 changes: 13 additions & 9 deletions models/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,23 @@ SERVER_DIST_GO := $(SERVER_DIST_DIR)/src/swagger
SERVER_DIST_UI := $(SERVER_DIST_DIR)/ui
SERVER_DIST_UI_HOME := $(SERVER_DIST_DIR)/ui/index.html

include codegen.config

YANGAPI_DIR := $(TOPDIR)/build/yaml
YANGAPI_SPECS := $(shell find $(YANGAPI_DIR) -name '*.yaml' | sort)
YANGAPI_NAMES := $(basename $(notdir $(YANGAPI_SPECS)))
YANGAPI_SPECS := $(shell find $(YANGAPI_DIR) -name '*.yaml')
YANGAPI_NAMES := $(filter-out $(YANGAPI_EXCLUDES), $(basename $(notdir $(YANGAPI_SPECS))))
YANGAPI_SERVERS := $(addsuffix /.yangapi_done, $(addprefix $(SERVER_CODEGEN_DIR)/, $(YANGAPI_NAMES)))

OPENAPI_DIR := openapi
OPENAPI_SPECS := $(shell find $(OPENAPI_DIR) -name '*.yaml' | sort)
OPENAPI_NAMES := $(basename $(notdir $(OPENAPI_SPECS)))
OPENAPI_DIR := openapi
OPENAPI_SPECS := $(shell find $(OPENAPI_DIR) -name '*.yaml')
OPENAPI_NAMES := $(filter-out $(OPENAPI_EXCLUDES), $(basename $(notdir $(OPENAPI_SPECS))))
OPENAPI_SERVERS := $(addsuffix /.openapi_done, $(addprefix $(SERVER_CODEGEN_DIR)/, $(OPENAPI_NAMES)))

PY_YANGAPI_NAMES := $(filter $(YANGAPI_NAMES), $(PY_YANGAPI_CLIENTS))
PY_OPENAPI_NAMES := $(filter $(OPENAPI_NAMES), $(PY_OPENAPI_CLIENTS))
PY_CLIENT_CODEGEN_DIR := $(BUILD_DIR)/swagger_client_py
PY_CLIENT_TARGETS := $(addsuffix .yangapi_client, $(addprefix $(PY_CLIENT_CODEGEN_DIR)/, $(YANGAPI_NAMES))) \
$(addsuffix .openapi_client, $(addprefix $(PY_CLIENT_CODEGEN_DIR)/, $(OPENAPI_NAMES)))
PY_CLIENT_TARGETS := $(addsuffix .yangapi_client, $(addprefix $(PY_CLIENT_CODEGEN_DIR)/, $(PY_YANGAPI_NAMES))) \
$(addsuffix .openapi_client, $(addprefix $(PY_CLIENT_CODEGEN_DIR)/, $(PY_OPENAPI_NAMES)))

UIGEN_DIR = $(TOPDIR)/tools/ui_gen
UIGEN_SRCS = $(shell find $(UIGEN_DIR) -type f)
Expand All @@ -58,12 +62,12 @@ all: go-server py-client

go-server: $(YANGAPI_SERVERS) $(OPENAPI_SERVERS) $(SERVER_DIST_INIT) $(SERVER_DIST_UI_HOME)

py-client: $(PY_CLIENT_CODEGEN_DIR)/. $(PY_CLIENT_TARGETS)

$(SERVER_DIST_UI_HOME): $(YANGAPI_SERVERS) $(OPENAPI_SERVERS) $(UIGEN_SRCS)
@echo "+++ Generating landing page for Swagger UI +++"
$(UIGEN_DIR)/src/uigen.py

py-client: $(PY_CLIENT_TARGETS)


.SECONDEXPANSION:

Expand Down
58 changes: 58 additions & 0 deletions models/codegen.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
################################################################################
# #
# Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or #
# its subsidiaries. #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
# You may obtain a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# #
################################################################################

# Build time configurations for swagger codegen
# Use makefile syntax

##
# YANGAPI_EXCLUDES indicates the yang modules to be excluded from codegen.
# Server and client code will not be generated for these yangs modules.
# By default server code will be generated for all yangs under models/yang
# and models/yang/sonic directories. Note that each entry should be yang
# module name which is used for generated yaml file name.
YANGAPI_EXCLUDES +=

##
# PY_YANGAPI_CLIENTS indicates the yang modules for which python client
# sdk code should be generated. By default client sdk code will not be
# generated to save build time and space. YANGAPI_EXCLUDES has priority
# over this list. Note that the entry should be the yang module name
# which is used for generated yaml file name.
PY_YANGAPI_CLIENTS += openconfig-interfaces
PY_YANGAPI_CLIENTS += openconfig-lldp
PY_YANGAPI_CLIENTS += openconfig-platform
PY_YANGAPI_CLIENTS += openconfig-system
PY_YANGAPI_CLIENTS += openconfig-spanning-tree
PY_YANGAPI_CLIENTS += sonic-vxlan
PY_YANGAPI_CLIENTS += sonic-sflow

##
# OPENAPI_EXCLUDES indicates the OpenAPI specs to be excluded from codegen.
# By default all yaml files under models/openapi directory are considered
# for codegen. Items should be the yaml file name without the .yaml extension.
# Eg: vlan.yaml should be specified as "OPENAPI_EXCLUDES += vlan"
OPENAPI_EXCLUDES +=

##
# PY_OPENAPI_CLIENTS indicates the OpenAPI specs for which python client
# sdk code should be generated. By default client sdk code is not generated.
# Items should be the yaml file name without the .yaml extension. Note
# that OPENAPI_EXCLUDES has priority over this list.
PY_OPENAPI_CLIENTS +=

20 changes: 18 additions & 2 deletions models/yang/openconfig-spanning-tree-ext.yang
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module openconfig-spanning-tree-ext {

import openconfig-spanning-tree { prefix oc-stp; }
import openconfig-spanning-tree-types { prefix oc-stp-types; }
import openconfig-yang-types { prefix oc-yang; }


identity PVST {
Expand Down Expand Up @@ -103,18 +104,32 @@ module openconfig-spanning-tree-ext {

grouping vlan-interface-extra-counters {
leaf tcn-sent {
type uint64;
type oc-yang:counter64;
description
"Tcn transmitted";
}

leaf tcn-received {
type uint64;
type oc-yang:counter64;
description
"Tcn received";
}
}

grouping rpvst-vlan-interface-extra-counters {
leaf config-bpdu-sent {
type oc-yang:counter64;
description
"Config BPDU transmitted";
}

leaf config-bpdu-received {
type oc-yang:counter64;
description
"Config BPDU received";
}
}

grouping stp-pvst-top {
description
"Top grouping for per vlan spanning tree configuration
Expand Down Expand Up @@ -192,6 +207,7 @@ module openconfig-spanning-tree-ext {

augment /oc-stp:stp/oc-stp:rapid-pvst/oc-stp:vlan/oc-stp:interfaces/oc-stp:interface/oc-stp:state/oc-stp:counters {
uses vlan-interface-extra-counters;
uses rpvst-vlan-interface-extra-counters;
}

augment /oc-stp:stp/oc-stp-ext:pvst/oc-stp-ext:vlan/oc-stp-ext:interfaces/oc-stp-ext:interface/oc-stp-ext:state {
Expand Down
17 changes: 16 additions & 1 deletion models/yang/sonic/sonic-vxlan.yang
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,21 @@ module sonic-vxlan {
}
}
}
}
container SUPPRESS_VLAN_NEIGH {

list SUPPRESS_VLAN_NEIGH_LIST {
key "name";

leaf name {
type string;
}
leaf suppress {
type string;
}

}
}

}

}
32 changes: 32 additions & 0 deletions patches/jsonquery.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
diff --git a/node.go b/node.go
index 76032bb..9960c17 100644
--- a/node.go
+++ b/node.go
@@ -110,6 +110,17 @@ func parseValue(x interface{}, top *Node, level int) {
addNode(n)
parseValue(vv, n, level+1)
}
+ case map[string]string:
+ var keys []string
+ for key := range v {
+ keys = append(keys, key)
+ }
+ sort.Strings(keys)
+ for _, key := range keys {
+ n := &Node{Data: key, Type: ElementNode, level: level}
+ addNode(n)
+ parseValue(v[key], n, level+1)
+ }
case map[string]interface{}:
// The Go’s map iteration order is random.
// (https://blog.golang.org/go-maps-in-action#Iteration-order)
@@ -155,3 +166,9 @@ func Parse(r io.Reader) (*Node, error) {
}
return parse(b)
}
+
+func ParseJsonMap(jsonMap *map[string]interface{}) (*Node, error) {
+ doc := &Node{Type: DocumentNode}
+ parseValue(*jsonMap, doc, 1)
+ return doc, nil
+}
100 changes: 73 additions & 27 deletions src/CLI/actioner/README_cli_client.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,88 @@
# Generic RESTful Python client
# Generic REST Client for CLI

A generic RESTful Python client for interacting with JSON APIs.
Actioner scripts can use the generic rest client **cli_client.py** to communicate to REST Server.
This client is tailor made to connect to local REST Server and handle the CLI actioner usecases.
All future CLI-REST integration enhancements (for RBAC) can be handled in this tool without
affecting individual actioner scripts.

## Usage
To use this tool, first create an `ApiClient` object.

To use this client you just need to import ApiClient and initialize it with an URL endpoint
```python
import cli_client as cc

from cli_client import ApiClient
api = ApiClient('#your_api_endpoint') #your_api_endpoint is optional default is https://localhost:443
api = cc.ApiClient()
```

Now that you have a RESTful API object you can start sending requests.
Create a path object for target REST resource. It accepts parameterized path template and parameter
values. Path template is similar to the template used by swagger. Parameter values will be URL-encoded
and substituted in the template to get REST resource path.

```python
path = cc.Path('/restconf/data/openconfig-acl:acl/acl-sets/acl-set={name},{type}/acl-entries',
name='MyNewAccessList', type='ACL_IPV4')
```

## Making a request
Invoke REST API.. `ApiClient` object supports get, post, put, patch and delete operations.
All these operations send a REST request and return a response object wrapping the REST response data.

The framework supports GET, PUT, POST, PATCH and DELETE requests:
```python
response = api.get(path)
```

from cli_client import ApiClient
api = ApiClient()
response = api.get('/authors/')
response = api.post('/authors/', {'title': 'Broadcom', 'author': 'Faraaz Mohammed'})
response = api.put('/author/faraaz/', {'dob': '06/09/2006'})
response = api.delete('/author/faraaz/')
Check API status through `response.ok()` function, which returns true if API was success - REST server
returned HTTP 2xx status code. `ok()` function returns false if server returned any other status response.

## To get the Response Data
response = api.get('/authors/')
Use response.content object
```python
if response.ok() {
respJson = response.content
# invoke renderer to display respJson
} else {
print response.error_message()
}
```

For Successful request response.content will contain valid JSON data
For Non-Successful request response.content will contain errors object returned by REST Server
If request was successful, `response.content` will hold the response data as JSON dictionary object.
If request failed, `response.content` will hold error JSON returned by the server. CLI displayable
error message can be extracted using `response.error_message()` function.

## Verifying Requests
Examples of other REST API calls.

Two helpers are built in to verify the success of requests made. `ok()` checks for a 20x status code and returns a boolean, `errors()` returns the body content as a dict object if the status code is not 20x:
```python
jsonDict = {}
jsonDict["acl-set"]=[{ "name":the_acl_name, .... }] # construct your request data json

response = api.get('/books/')
if response.ok():
print 'Success!'
else:
print req.errors()
# POST request
response = api.post(path, data=jsonDict)

# PUT request
reponse = api.put(path, data=jsonDict)

# PATCH request
response = api.patch(path, data=jsonDict)

# DELETE request
response = api.delete(path)
```

Above example used `response.error_message()` function to get ser displayable error message from
the REST response. REST server always returns error information in standard RESTCONF error format.
The `error_message()` function looks for the **error-message** attribute to get user displayable message.
A generic message will be returned based on **error-tag** attribute value if there was no **error-message**
attribute. This can be customized through an error formatter function as shown below.
Default error formatter is sufficient for most of the cases.

```python
if not response.ok():
print response.error_message(formatter_func=my_new_error_message_formatter)
```

The custom formtter function would receive RESTCONF error json and should return a string.
Below is a sample implementation which uses error-type attribute to format an error message.

```python
def my_new_error_message_formatter(error_entry):
if err_entry['error-type'] == 'protocol':
return "System error.. Please reboot!!"
return "Application error.. Please retry."
```

Loading

0 comments on commit edc1338

Please sign in to comment.