Skip to content

Commit

Permalink
Merge branch 'master' into sag-dev
Browse files Browse the repository at this point in the history
  • Loading branch information
superchild authored Dec 3, 2021
2 parents d9591b7 + 290ff5f commit c9f131d
Show file tree
Hide file tree
Showing 384 changed files with 31,507 additions and 5,207 deletions.
2 changes: 1 addition & 1 deletion .azure-pipelines/test-docker-sonic-vs-template.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
parameters:
- name: timeout
type: number
default: 180
default: 240

- name: log_artifact_name
type: string
Expand Down
19 changes: 11 additions & 8 deletions acl_loader/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ class AclLoader(object):
POLICER = "POLICER"
SESSION_PREFIX = "everflow"
SWITCH_CAPABILITY_TABLE = "SWITCH_CAPABILITY"
ACL_ACTIONS_CAPABILITY_FIELD = "ACL_ACTIONS"
ACL_STAGE_CAPABILITY_TABLE = "ACL_STAGE_CAPABILITY_TABLE"
ACL_ACTIONS_CAPABILITY_FIELD = "action_list"
ACL_ACTION_CAPABILITY_FIELD = "ACL_ACTION"

min_priority = 1
Expand Down Expand Up @@ -402,16 +403,18 @@ def validate_actions(self, table_name, action_props):
# Same information should be there in all state DB's
# as it is static information about switch capability
namespace_statedb = list(self.per_npu_statedb.values())[0]
capability = namespace_statedb.get_all(self.statedb.STATE_DB, "{}|switch".format(self.SWITCH_CAPABILITY_TABLE))
aclcapability = namespace_statedb.get_all(self.statedb.STATE_DB, "{}|{}".format(self.ACL_STAGE_CAPABILITY_TABLE, stage.upper()))
switchcapability = namespace_statedb.get_all(self.statedb.STATE_DB, "{}|switch".format(self.SWITCH_CAPABILITY_TABLE))
else:
capability = self.statedb.get_all(self.statedb.STATE_DB, "{}|switch".format(self.SWITCH_CAPABILITY_TABLE))
aclcapability = self.statedb.get_all(self.statedb.STATE_DB, "{}|{}".format(self.ACL_STAGE_CAPABILITY_TABLE, stage.upper()))
switchcapability = self.statedb.get_all(self.statedb.STATE_DB, "{}|switch".format(self.SWITCH_CAPABILITY_TABLE))
for action_key in dict(action_props):
key = "{}|{}".format(self.ACL_ACTIONS_CAPABILITY_FIELD, stage.upper())
if key not in capability:
action_list_key = self.ACL_ACTIONS_CAPABILITY_FIELD
if action_list_key not in aclcapability:
del action_props[action_key]
continue

values = capability[key].split(",")
values = aclcapability[action_list_key].split(",")
if action_key.upper() not in values:
del action_props[action_key]
continue
Expand All @@ -420,11 +423,11 @@ def validate_actions(self, table_name, action_props):
# Check if action_value is supported
action_value = action_props[action_key]
key = "{}|{}".format(self.ACL_ACTION_CAPABILITY_FIELD, action_key.upper())
if key not in capability:
if key not in switchcapability:
del action_props[action_key]
continue

if action_value not in capability[key]:
if action_value not in switchcapability[key]:
del action_props[action_key]
continue

Expand Down
17 changes: 15 additions & 2 deletions clear/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,12 @@ def dropcounters():
command = "dropstat -c clear"
run_command(command)

@cli.command()
def tunnelcounters():
"""Clear Tunnel counters"""
command = "tunnelstat -c"
run_command(command)

#
# 'clear watermarks
#
Expand Down Expand Up @@ -476,10 +482,17 @@ def statistics(db):
def remap_keys(dict):
return [{'key': k, 'value': v} for k, v in dict.items()]

# ("sonic-clear flowcnt-trap")
@cli.command()
def flowcnt_trap():
""" Clear trap flow counters """
command = "flow_counters_stat -c -t trap"
run_command(command)


# Load plugins and register them
helper = util_base.UtilHelper()
for plugin in helper.load_plugins(plugins):
helper.register_plugin(plugin, cli)
helper.load_and_register_plugins(plugins, cli)


if __name__ == '__main__':
Expand Down
Empty file added clear/plugins/auto/__init__.py
Empty file.
38 changes: 38 additions & 0 deletions config/aaa.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,44 @@ def login(auth_protocol):
add_table_kv('AAA', 'authentication', 'login', val)
authentication.add_command(login)

# cmd: aaa authorization
@click.command()
@click.argument('protocol', nargs=-1, type=click.Choice([ "tacacs+", "local", "tacacs+ local"]))
def authorization(protocol):
"""Switch AAA authorization [tacacs+ | local | '\"tacacs+ local\"']"""
if len(protocol) == 0:
click.echo('Argument "protocol" is required')
return

if len(protocol) == 1 and (protocol[0] == 'tacacs+' or protocol[0] == 'local'):
add_table_kv('AAA', 'authorization', 'login', protocol[0])
elif len(protocol) == 1 and protocol[0] == 'tacacs+ local':
add_table_kv('AAA', 'authorization', 'login', 'tacacs+,local')
else:
click.echo('Not a valid command')
aaa.add_command(authorization)

# cmd: aaa accounting
@click.command()
@click.argument('protocol', nargs=-1, type=click.Choice(["disable", "tacacs+", "local", "tacacs+ local"]))
def accounting(protocol):
"""Switch AAA accounting [disable | tacacs+ | local | '\"tacacs+ local\"']"""
if len(protocol) == 0:
click.echo('Argument "protocol" is required')
return

if len(protocol) == 1:
if protocol[0] == 'tacacs+' or protocol[0] == 'local':
add_table_kv('AAA', 'accounting', 'login', protocol[0])
elif protocol[0] == 'tacacs+ local':
add_table_kv('AAA', 'accounting', 'login', 'tacacs+,local')
elif protocol[0] == 'disable':
del_table_key('AAA', 'accounting', 'login')
else:
click.echo('Not a valid command')
else:
click.echo('Not a valid command')
aaa.add_command(accounting)

@click.group()
def tacacs():
Expand Down
110 changes: 91 additions & 19 deletions config/config_mgmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@
config_mgmt.py provides classes for configuration validation and for Dynamic
Port Breakout.
'''

import os
import re
import shutil
import syslog
import tempfile
import yang as ly
from json import load
from sys import flags
from time import sleep as tsleep
Expand Down Expand Up @@ -46,34 +51,38 @@ def __init__(self, source="configDB", debug=False, allowTablesWithoutYang=True):
try:
self.configdbJsonIn = None
self.configdbJsonOut = None
self.source = source
self.allowTablesWithoutYang = allowTablesWithoutYang

# logging vars
self.SYSLOG_IDENTIFIER = "ConfigMgmt"
self.DEBUG = debug

self.sy = sonic_yang.SonicYang(YANG_DIR, debug=debug)
# load yang models
self.sy.loadYangModel()
# load jIn from config DB or from config DB json file.
if source.lower() == 'configdb':
self.readConfigDB()
# treat any other source as file input
else:
self.readConfigDBJson(source)
# this will crop config, xlate and load.
self.sy.loadData(self.configdbJsonIn)

# Raise if tables without YANG models are not allowed but exist.
if not allowTablesWithoutYang and len(self.sy.tablesWithOutYang):
raise Exception('Config has tables without YANG models')
self.__init_sonic_yang()

except Exception as e:
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, msg=str(e))
raise Exception('ConfigMgmt Class creation failed')

return

def __init_sonic_yang(self):
self.sy = sonic_yang.SonicYang(YANG_DIR, debug=self.DEBUG)
# load yang models
self.sy.loadYangModel()
# load jIn from config DB or from config DB json file.
if self.source.lower() == 'configdb':
self.readConfigDB()
# treat any other source as file input
else:
self.readConfigDBJson(self.source)
# this will crop config, xlate and load.
self.sy.loadData(self.configdbJsonIn)

# Raise if tables without YANG models are not allowed but exist.
if not self.allowTablesWithoutYang and len(self.sy.tablesWithOutYang):
raise Exception('Config has tables without YANG models')

def __del__(self):
pass

Expand Down Expand Up @@ -213,6 +222,69 @@ def writeConfigDB(self, jDiff):

return

def add_module(self, yang_module_str):
"""
Validate and add new YANG module to the system.
Parameters:
yang_module_str (str): YANG module in string representation.
Returns:
None
"""

module_name = self.get_module_name(yang_module_str)
module_path = os.path.join(YANG_DIR, '{}.yang'.format(module_name))
if os.path.exists(module_path):
raise Exception('{} already exists'.format(module_name))
with open(module_path, 'w') as module_file:
module_file.write(yang_module_str)
try:
self.__init_sonic_yang()
except Exception:
os.remove(module_path)
raise

def remove_module(self, module_name):
"""
Remove YANG module from the system and validate.
Parameters:
module_name (str): YANG module name.
Returns:
None
"""

module_path = os.path.join(YANG_DIR, '{}.yang'.format(module_name))
if not os.path.exists(module_path):
return
temp = tempfile.NamedTemporaryFile(delete=False)
try:
shutil.move(module_path, temp.name)
self.__init_sonic_yang()
except Exception:
shutil.move(temp.name, module_path)
raise

@staticmethod
def get_module_name(yang_module_str):
"""
Read yangs module name from yang_module_str
Parameters:
yang_module_str(str): YANG module string.
Returns:
str: Module name
"""

# Instantiate new context since parse_module_mem() loads the module into context.
sy = sonic_yang.SonicYang(YANG_DIR)
module = sy.ctx.parse_module_mem(yang_module_str, ly.LYS_IN_YANG)
return module.name()


# End of Class ConfigMgmt

class ConfigMgmtDPB(ConfigMgmt):
Expand Down Expand Up @@ -417,8 +489,8 @@ def _deletePorts(self, ports=list(), force=False):
deps.extend(dep)

# No further action with no force and deps exist
if force == False and deps:
return configToLoad, deps, False;
if not force and deps:
return configToLoad, deps, False

# delets all deps, No topological sort is needed as of now, if deletion
# of deps fails, return immediately
Expand All @@ -436,8 +508,8 @@ def _deletePorts(self, ports=list(), force=False):
self.sy.deleteNode(str(xPathPort))

# Let`s Validate the tree now
if self.validateConfigData()==False:
return configToLoad, deps, False;
if not self.validateConfigData():
return configToLoad, deps, False

# All great if we are here, Lets get the diff
self.configdbJsonOut = self.sy.getData()
Expand Down
Loading

0 comments on commit c9f131d

Please sign in to comment.