Skip to content

Commit 3b46b03

Browse files
Merge branch 'master' of https://github.com/Azure/sonic-utilities into rates
Conflicts: scripts/portstat
2 parents d9adb96 + 13bd06b commit 3b46b03

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+299199
-537
lines changed

.gitignore

+26-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,28 @@
1+
# Compiled Python files
2+
*.pyc
3+
scripts/aclshowc
4+
scripts/neighbor_advertiserc
5+
scripts/port2aliasc
6+
7+
# Generated by packaging
8+
*.egg-info/
9+
.eggs/
110
build/
2-
deb_dist/
311
dist/
4-
*.egg-info/
5-
*.pyc
6-
.cache
7-
*.tar.gz
12+
13+
# Unit test coverage
14+
.coverage
15+
coverage.xml
16+
htmlcov/
17+
18+
# Ignores for sonic-utilities-data
19+
sonic-utilities-data/debian/*
20+
!sonic-utilities-data/debian/changelog
21+
!sonic-utilities-data/debian/compat
22+
!sonic-utilities-data/debian/control
23+
!sonic-utilities-data/debian/copyright
24+
!sonic-utilities-data/debian/install
25+
!sonic-utilities-data/debian/rules
26+
sonic-utilities-data_*.deb
27+
sonic-utilities-data_*.buildinfo
28+
sonic-utilities-data_*.changes

README.md

+65-3
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,73 @@
99

1010
Command-line utilities for SONiC
1111

12-
## How to run unit test
13-
```python
14-
python2 -m py.test -v
12+
This repository produces two packages, as follows:
13+
14+
### sonic-utilities
15+
16+
A Python wheel package, containing all the Python source code for the command-line utilities
17+
18+
#### Setting up a build/test environment
19+
20+
The sonic-utilities package depends on a number of other packages, many of which are available via PyPI, but some are part of the SONiC codebase. When building/testing the package, setuptools/pip will attempt to install the packages available from PyPI. However, you will need to manually build and install the SONiC dependencies before attempting to build or test the package.
21+
22+
Currently, this list of dependencies is as follows:
23+
24+
25+
- libyang_1.0.73_amd64.deb
26+
- libyang-cpp_1.0.73_amd64.deb
27+
- python2-yang_1.0.73_amd64.deb
28+
- python3-yang_1.0.73_amd64.deb
29+
- redis_dump_load-1.1-py2-none-any.whl
30+
- swsssdk-2.0.1-py2-none-any.whl
31+
- sonic_py_common-1.0-py2-none-any.whl
32+
- sonic_config_engine-1.0-py2-none-any.whl
33+
- sonic_yang_mgmt-1.0-py2-none-any.whl
34+
- sonic_yang_models-1.0-py3-none-any.whl
35+
36+
37+
A convenient alternative is to let the SONiC build system configure a build enviroment for you. This can be done by cloning the [sonic-buildimage](https://github.com/Azure/sonic-buildimage) repo, building the sonic-utilities package inside the Debian Buster slave container, and staying inside the container once the build finishes. During the build process, the SONiC build system will build and install all the necessary dependencies inside the container. After following the instructions to clone and initialize the sonic-buildimage repo, this can be done as follows:
38+
39+
1. Configure the build environment for an ASIC type (any type will do, here we use `generic`)
40+
```
41+
make configure PLATFORM=generic
42+
```
43+
44+
2. Build the sonic-utilities Python wheel package inside the Buster slave container, and tell the build system to keep the container alive when finished
45+
```
46+
make NOJESSIE=1 NOSTRETCH=1 KEEP_SLAVE_ON=yes target/python-wheels/sonic_utilities-1.2-py2-none-any.whl
47+
```
48+
49+
3. When the build finishes, your prompt will change to indicate you are inside the slave container. Change into the `src/sonic-utilities/` directory
50+
```
51+
user@911799f161a0:/sonic$ cd src/sonic-utilities/
52+
```
53+
54+
4. You can now make changes to the sonic-utilities source and build the package or run unit tests with the commands below. When finished, you can exit the container by calling `exit`.
55+
56+
#### To build
57+
58+
```
59+
python2 setup.py bdist_wheel
60+
```
61+
62+
#### To run unit tests
63+
64+
```
65+
python2 setup.py test
1566
```
1667
68+
69+
### sonic-utilities-data
70+
71+
A Debian package, containing data files needed by the utilities (bash_completion files, Jinja2 templates, etc.)
72+
73+
#### To build
74+
75+
Instructions for building the sonic-utilities-data package can be found in [sonic-utilities-data/README.md](https://github.com/Azure/sonic-utilities/blob/master/sonic-utilities-data/README.md)
76+
77+
---
78+
1779
## Contribution guide
1880
1981
All contributors must sign a contribution license agreement (CLA) before contributions can be accepted. This process is now automated via a GitHub bot when submitting new pull request. If the contributor has not yet signed a CLA, the bot will create a comment on the pull request containing a link to electronically sign the CLA.

acl_loader/main.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,9 @@ def convert_l2(self, table_name, rule_idx, rule):
413413
def convert_ip(self, table_name, rule_idx, rule):
414414
rule_props = {}
415415

416-
if rule.ip.config.protocol or rule.ip.config.protocol == 0: # 0 is a valid protocol number
416+
# FIXME: 0 is a valid protocol number, but openconfig seems to use it as a default value,
417+
# so there isn't currently a good way to check if the user defined proto=0 or not.
418+
if rule.ip.config.protocol:
417419
if self.ip_protocol_map.has_key(rule.ip.config.protocol):
418420
rule_props["IP_PROTOCOL"] = self.ip_protocol_map[rule.ip.config.protocol]
419421
else:

config/console.py

+162
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#!/usr/bin/env python
2+
3+
import click
4+
5+
import utilities_common.cli as clicommon
6+
7+
#
8+
# 'console' group ('config console ...')
9+
#
10+
@click.group('console')
11+
def console():
12+
"""Console-related configuration tasks"""
13+
pass
14+
15+
#
16+
# 'console add' group ('config console add ...')
17+
#
18+
@console.command('add')
19+
@clicommon.pass_db
20+
@click.argument('linenum', metavar='<line_number>', required=True, type=click.IntRange(0, 65535))
21+
@click.option('--baud', '-b', metavar='<baud>', required=True, type=click.INT)
22+
@click.option('--flowcontrol', '-f', metavar='<flow_control>', required=False, is_flag=True)
23+
@click.option('--devicename', '-d', metavar='<device_name>', required=False)
24+
def add_console_setting(db, linenum, baud, flowcontrol, devicename):
25+
"""Add Console-realted configuration tasks"""
26+
config_db = db.cfgdb
27+
28+
table = "CONSOLE_PORT"
29+
dataKey1 = 'baud_rate'
30+
dataKey2 = 'flow_control'
31+
dataKey3 = 'remote_device'
32+
33+
ctx = click.get_current_context()
34+
data = config_db.get_entry(table, linenum)
35+
if data:
36+
ctx.fail("Trying to add console port setting, which is already exists.")
37+
else:
38+
console_entry = { dataKey1: baud }
39+
console_entry[dataKey2] = "1" if flowcontrol else "0"
40+
41+
if devicename:
42+
if isExistingSameDevice(config_db, devicename, table):
43+
ctx.fail("Given device name {} has been used. Please enter a valid device name or remove the existing one !!".format(devicename))
44+
console_entry[dataKey3] = devicename
45+
46+
config_db.set_entry(table, linenum, console_entry)
47+
48+
49+
#
50+
# 'console del' group ('config console del ...')
51+
#
52+
@console.command('del')
53+
@clicommon.pass_db
54+
@click.argument('linenum', metavar='<line_number>', required=True, type=click.IntRange(0, 65535))
55+
def remove_console_setting(db, linenum):
56+
"""Remove Console-related configuration tasks"""
57+
config_db = db.cfgdb
58+
59+
table = "CONSOLE_PORT"
60+
61+
data = config_db.get_entry(table, linenum)
62+
if data:
63+
config_db.mod_entry(table, linenum, None)
64+
else:
65+
ctx = click.get_current_context()
66+
ctx.fail("Trying to delete console port setting, which is not present.")
67+
68+
#
69+
# 'console remote_device' group ('config console remote_device ...')
70+
#
71+
@console.command('remote_device')
72+
@clicommon.pass_db
73+
@click.argument('linenum', metavar='<line_number>', required=True, type=click.IntRange(0, 65535))
74+
@click.argument('devicename', metavar='<device_name>', required=False)
75+
def upate_console_remote_device_name(db, linenum, devicename):
76+
"""Update remote device name for a console line"""
77+
config_db = db.cfgdb
78+
ctx = click.get_current_context()
79+
80+
table = "CONSOLE_PORT"
81+
dataKey = 'remote_device'
82+
83+
data = config_db.get_entry(table, linenum)
84+
if data:
85+
if dataKey in data and devicename == data[dataKey]:
86+
# do nothing if the device name is same with existing configurtion
87+
return
88+
elif not devicename:
89+
# remove configuration key from console setting if user not give a remote device name
90+
data.pop(dataKey, None)
91+
config_db.mod_entry(table, linenum, data)
92+
elif isExistingSameDevice(config_db, devicename, table):
93+
ctx.fail("Given device name {} has been used. Please enter a valid device name or remove the existing one !!".format(devicename))
94+
else:
95+
data[dataKey] = devicename
96+
config_db.mod_entry(table, linenum, data)
97+
else:
98+
ctx.fail("Trying to update console port setting, which is not present.")
99+
100+
#
101+
# 'console baud' group ('config console baud ...')
102+
#
103+
@console.command('baud')
104+
@clicommon.pass_db
105+
@click.argument('linenum', metavar='<line_number>', required=True, type=click.IntRange(0, 65535))
106+
@click.argument('baud', metavar='<baud>', required=True, type=click.INT)
107+
def update_console_baud(db, linenum, baud):
108+
"""Update baud for a console line"""
109+
config_db = db.cfgdb
110+
ctx = click.get_current_context()
111+
112+
table = "CONSOLE_PORT"
113+
dataKey = 'baud_rate'
114+
115+
data = config_db.get_entry(table, linenum)
116+
if data:
117+
baud = str(baud)
118+
if dataKey in data and baud == data[dataKey]:
119+
# do nothing if the baud is same with existing configurtion
120+
return
121+
else:
122+
data[dataKey] = baud
123+
config_db.mod_entry(table, linenum, data)
124+
else:
125+
ctx.fail("Trying to update console port setting, which is not present.")
126+
127+
#
128+
# 'console flow_control' group ('config console flow_control ...')
129+
#
130+
@console.command('flow_control')
131+
@clicommon.pass_db
132+
@click.argument('mode', metavar='<mode>', required=True, type=click.Choice(["enable", "disable"]))
133+
@click.argument('linenum', metavar='<line_number>', required=True, type=click.IntRange(0, 65535))
134+
def update_console_flow_control(db, mode, linenum):
135+
"""Update flow control setting for a console line"""
136+
config_db = db.cfgdb
137+
ctx = click.get_current_context()
138+
139+
table = "CONSOLE_PORT"
140+
dataKey = 'flow_control'
141+
142+
innerMode = "1" if mode == "enable" else "0"
143+
144+
data = config_db.get_entry(table, linenum)
145+
if data:
146+
if dataKey in data and innerMode == data[dataKey]:
147+
# do nothing if the flow control setting is same with existing configurtion
148+
return
149+
else:
150+
data[dataKey] = innerMode
151+
config_db.mod_entry(table, linenum, data)
152+
else:
153+
ctx.fail("Trying to update console port setting, which is not present.")
154+
155+
def isExistingSameDevice(config_db, deviceName, table):
156+
"""Check if the given device name is conflict with existing device"""
157+
settings = config_db.get_table(table)
158+
for key,values in settings.items():
159+
if "remote_device" in values and deviceName == values["remote_device"]:
160+
return True
161+
162+
return False

config/main.py

+43-10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525

2626
import aaa
27+
import console
2728
import feature
2829
import kube
2930
import mlnx
@@ -750,6 +751,10 @@ def _restart_services(config_db):
750751

751752
execute_systemctl(services_to_restart, SYSTEMCTL_ACTION_RESTART)
752753

754+
# Reload Monit configuration to pick up new hostname in case it changed
755+
click.echo("Reloading Monit configuration ...")
756+
clicommon.run_command("sudo monit reload")
757+
753758

754759
def interface_is_in_vlan(vlan_member_table, interface_name):
755760
""" Check if an interface is in a vlan """
@@ -876,6 +881,7 @@ def config(ctx):
876881
# Add groups from other modules
877882
config.add_command(aaa.aaa)
878883
config.add_command(aaa.tacacs)
884+
config.add_command(console.console)
879885
config.add_command(feature.feature)
880886
config.add_command(kube.kubernetes)
881887
config.add_command(nat.nat)
@@ -1101,7 +1107,7 @@ def reload(db, filename, yes, load_sysinfo, no_service_restart):
11011107
client.set(config_db.INIT_INDICATOR, 1)
11021108

11031109
# Migrate DB contents to latest version
1104-
db_migrator='/usr/bin/db_migrator.py'
1110+
db_migrator='/usr/local/bin/db_migrator.py'
11051111
if os.path.isfile(db_migrator) and os.access(db_migrator, os.X_OK):
11061112
if namespace is None:
11071113
command = "{} -o migrate".format(db_migrator)
@@ -1182,13 +1188,10 @@ def load_minigraph(db, no_service_restart):
11821188
clicommon.run_command(command, display_cmd=True)
11831189
client.set(config_db.INIT_INDICATOR, 1)
11841190

1185-
# get the device type
1186-
device_type = _get_device_type()
1187-
1188-
# These commands are not run for host on multi asic platform
1189-
if num_npus == 1 or namespace is not DEFAULT_NAMESPACE:
1190-
if device_type != 'MgmtToRRouter':
1191-
clicommon.run_command('{}pfcwd start_default'.format(ns_cmd_prefix), display_cmd=True)
1191+
# get the device type
1192+
device_type = _get_device_type()
1193+
if device_type != 'MgmtToRRouter':
1194+
clicommon.run_command("pfcwd start_default", display_cmd=True)
11921195

11931196
# Update SONiC environmnet file
11941197
update_sonic_environment()
@@ -1200,7 +1203,7 @@ def load_minigraph(db, no_service_restart):
12001203
clicommon.run_command("config qos reload", display_cmd=True)
12011204

12021205
# Write latest db version string into db
1203-
db_migrator='/usr/bin/db_migrator.py'
1206+
db_migrator='/usr/local/bin/db_migrator.py'
12041207
if os.path.isfile(db_migrator) and os.access(db_migrator, os.X_OK):
12051208
for namespace in namespace_list:
12061209
if namespace is DEFAULT_NAMESPACE:
@@ -1236,8 +1239,38 @@ def hostname(new_hostname):
12361239
except SystemExit as e:
12371240
click.echo("Restarting hostname-config service failed with error {}".format(e))
12381241
raise
1242+
1243+
# Reload Monit configuration to pick up new hostname in case it changed
1244+
click.echo("Reloading Monit configuration ...")
1245+
clicommon.run_command("sudo monit reload")
1246+
12391247
click.echo("Please note loaded setting will be lost after system reboot. To preserve setting, run `config save`.")
12401248

1249+
#
1250+
# 'synchronous_mode' command ('config synchronous_mode ...')
1251+
#
1252+
@config.command('synchronous_mode')
1253+
@click.argument('sync_mode', metavar='<enable|disable>', required=True)
1254+
def synchronous_mode(sync_mode):
1255+
""" Enable or disable synchronous mode between orchagent and syncd \n
1256+
swss restart required to apply the configuration \n
1257+
Options to restart swss and apply the configuration: \n
1258+
1. config save -y \n
1259+
config reload -y \n
1260+
2. systemctl restart swss
1261+
"""
1262+
1263+
if sync_mode == 'enable' or sync_mode == 'disable':
1264+
config_db = ConfigDBConnector()
1265+
config_db.connect()
1266+
config_db.mod_entry('DEVICE_METADATA' , 'localhost', {"synchronous_mode" : sync_mode})
1267+
click.echo("""Wrote %s synchronous mode into CONFIG_DB, swss restart required to apply the configuration: \n
1268+
Option 1. config save -y \n
1269+
config reload -y \n
1270+
Option 2. systemctl restart swss""" % sync_mode)
1271+
else:
1272+
raise click.BadParameter("Error: Invalid argument %s, expect either enable or disable" % sync_mode)
1273+
12411274
#
12421275
# 'portchannel' group ('config portchannel ...')
12431276
#
@@ -2598,7 +2631,7 @@ def bind(ctx, interface_name, vrf_name):
25982631
state_db = SonicV2Connector(use_unix_socket_path=True, namespace=ctx.obj['namespace'])
25992632
state_db.connect(state_db.STATE_DB, False)
26002633
_hash = '{}{}'.format('INTERFACE_TABLE|', interface_name)
2601-
while state_db.get(state_db.STATE_DB, _hash, "state") == "ok":
2634+
while state_db.get_all(state_db.STATE_DB, _hash) != None:
26022635
time.sleep(0.01)
26032636
state_db.close(state_db.STATE_DB)
26042637
config_db.set_entry(table_name, interface_name, {"vrf_name": vrf_name})

0 commit comments

Comments
 (0)