Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BFN] Added support for tofino3 profiles naming #2148

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 28 additions & 19 deletions config/plugins/barefoot.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import subprocess
from sonic_py_common import device_info
from swsscommon.swsscommon import ConfigDBConnector
from show.plugins.barefoot import check_profile, get_chip_family

def abort_if_false(ctx, param, value):
if not value:
Expand All @@ -14,41 +15,49 @@ def abort_if_false(ctx, param, value):
def barefoot():
pass

def check_supported_profile(profile, chip_family):
"""Check if profile is supported"""
if chip_family == 'tofino' and profile[0] != 'x' or \
chip_family == 'tofino2' and profile[0] != 'y':
return False
return True

def check_profile_exist(profile, chip_family):
"""Check if profile exists"""
completed_process = subprocess.run(['docker', 'exec', '-it', 'syncd',
'test', '-d', '/opt/bfn/install_' + profile + '_' + chip_family])

if completed_process.returncode != 0:
click.echo('No profile with the provided name found for {}'.format(chip_family))
raise click.Abort()
return True

@barefoot.command()
@click.option('-y', '--yes', is_flag=True, callback=abort_if_false,
expose_value=False, prompt='Swss service will be restarted, continue?')
@click.argument('profile')
def profile(profile):
# Check if profile can be changed
completed_process = subprocess.run(['docker', 'exec', '-it', 'syncd',
'test', '-h', '/opt/bfn/install'])
if completed_process.returncode != 0:
if check_profile():
click.echo('Cannot change profile: default one is in use')
raise click.Abort()

# Get chip family
hwsku_dir = device_info.get_path_to_hwsku_dir()
with open(hwsku_dir + '/switch-tna-sai.conf') as file:
chip_family = json.load(file)['chip_list'][0]['chip_family'].lower()

chip_family = get_chip_family()

# Check if profile is supported
if chip_family == 'tofino' and profile[0] == 'y' or \
chip_family == 'tofino2' and profile[0] == 'x':
if check_supported_profile(profile, chip_family) == False:
click.echo('Specified profile is unsupported on the system')
raise click.Abort()

# Check if profile exists
completed_process = subprocess.run(['docker', 'exec', '-it', 'syncd',
'test', '-d', '/opt/bfn/install_' + profile + '_profile'])
if completed_process.returncode != 0:
click.echo('No profile with the provided name found')
raise click.Abort()

check_profile_exist(profile, chip_family)

# Update configuration
config_db = ConfigDBConnector()
config_db.connect()
config_db.mod_entry('DEVICE_METADATA', 'localhost',
{'p4_profile': profile + '_profile'})
profile += '_' + chip_family
config_db.mod_entry('DEVICE_METADATA', 'localhost', {'p4_profile': profile})
subprocess.run(['systemctl', 'restart', 'swss'], check=True)

def register(cli):
Expand Down
7 changes: 7 additions & 0 deletions show/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,10 @@ def firmware(args):
subprocess.check_call(cmd, shell=True)
except subprocess.CalledProcessError as e:
sys.exit(e.returncode)

# 'barefoot' subcommand ("show platform barefoot")
@platform.command()
def barefoot():
"""Show Barefoot profile information"""
cmd = "barefoot profile"
clicommon.run_command(cmd)
59 changes: 41 additions & 18 deletions show/plugins/barefoot.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,60 @@
def barefoot():
pass

def check_profile():
"""Check if profile can be changed"""
ret = subprocess.run(['docker', 'exec', '-it', 'syncd',
'test', '-h', '/opt/bfn/install'])
if ret.returncode != 0:
taras-keryk marked this conversation as resolved.
Show resolved Hide resolved
return True
return False

def get_chip_family():
"""Get chip family"""
hwsku_dir = device_info.get_path_to_hwsku_dir()
with open(hwsku_dir + '/switch-tna-sai.conf') as file:
chip_family = json.load(file)['chip_list'][0]['chip_family'].lower()
return chip_family

def get_current_profile():
"""Get current profile"""
return subprocess.run('docker exec -it syncd readlink /opt/bfn/install | sed '
r's/install_\\\(.\*\\\)_tofino.\*/\\1/'
r' | sed "s/$/\r/"', check=True, shell=True).stdout

def get_available_profiles(opts):
"""Get available profiles"""
return subprocess.run('docker exec -it syncd find /opt/bfn -mindepth 1 '
r'-maxdepth 1 -type d,l ' + opts +
r' | sed s%/opt/bfn/install_\\\(.\*\\\)_tofino.\*%\\1%'
r' | sed "s/$/\r/"', shell=True).stdout

@barefoot.command()
def profile():
# Check if profile can be changed
completed_process = subprocess.run(['docker', 'exec', '-it', 'syncd',
'test', '-h', '/opt/bfn/install'])
if completed_process.returncode != 0:
if check_profile():
click.echo('Current profile: default')
return

# Get chip family
hwsku_dir = device_info.get_path_to_hwsku_dir()
with open(hwsku_dir + '/switch-tna-sai.conf') as file:
chip_family = json.load(file)['chip_list'][0]['chip_family'].lower()

chip_family = get_chip_family()

# Print current profile
click.echo('Current profile: ', nl=False)
subprocess.run('docker exec -it syncd readlink /opt/bfn/install | sed '
r's/install_\\\(.\*\\\)_profile/\\1/', check=True, shell=True)

# Exclude current and unsupported profiles
click.echo(get_current_profile(), nl=False)

# Check supported profiles
opts = ''
if chip_family == 'tofino':
opts = r'\! -name install_y\*_profile '
opts = r' -name install_x\*_' + chip_family
elif chip_family == 'tofino2':
opts = r'\! -name install_x\*_profile '

opts = r' -name install_y\*_' + chip_family
else:
opts = r' -name \*_' + chip_family

# Print profile list
click.echo('Available profile(s):')
subprocess.run('docker exec -it syncd find /opt/bfn -mindepth 1 '
r'-maxdepth 1 -type d -name install_\*_profile ' + opts + '| sed '
r's%/opt/bfn/install_\\\(.\*\\\)_profile%\\1%', shell=True)
click.echo(get_available_profiles(opts), nl=False)

def register(cli):
version_info = device_info.get_sonic_version_info()
Expand Down
211 changes: 211 additions & 0 deletions tests/barefoot_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import os
import sys
import textwrap
import json
from unittest.mock import patch, mock_open

import pytest
from click.testing import CliRunner
import utilities_common.cli as cli

import show.main as show
import config.main as config
import show.plugins.barefoot as bfshow
import config.plugins.barefoot as bfconfig

@pytest.fixture(scope='class')
def config_env():
os.environ["UTILITIES_UNIT_TESTING"] = "1"
yield
os.environ["UTILITIES_UNIT_TESTING"] = "0"

class TestStdout:
stdout = ""

class TestReturncode:
returncode = False

class TestShowPlatformBarefoot(object):

def test_config_barefoot(self):
runner = CliRunner()
expected_output = ""
result = CliRunner().invoke(show.cli.commands["platform"], ["barefoot"])
assert result.output == expected_output

def test_config_profile(self):
runner = CliRunner()
expected_output = "Swss service will be restarted, continue? [y/N]: \nAborted!\n"
result = runner.invoke(bfconfig.barefoot.commands['profile'], ['x1'])
print("result.exit_code:", result.exit_code)
print("result.output:", result.output)
assert result.output == expected_output

def test_check_profile_exist(self):
ret = TestReturncode()
ret.returncode = 0
with patch('show.plugins.barefoot.subprocess.run', return_value=ret):
result = bfconfig.check_profile_exist("x1", "tofino")
assert result == True

def test_show_profile(self):
runner = CliRunner()
expected_output = "Current profile: default\n"
result = runner.invoke(bfshow.barefoot.commands['profile'], [])
print("result.exit_code:", result.exit_code)
print("result.output:", result.output)
assert result.output == expected_output

def test_get_chip_family1(self):
with patch('show.plugins.barefoot.device_info.get_path_to_hwsku_dir', return_value=""):
chip_family = json.dumps({"chip_list": [{"instance": 0,"chip_family": "tofino"}]})
with patch('show.plugins.barefoot.open', mock_open(read_data=chip_family)):
result = bfshow.get_chip_family()
assert result == "tofino"

def test_get_chip_family2(self):
with patch('config.plugins.barefoot.device_info.get_path_to_hwsku_dir', return_value=""):
chip_family = json.dumps({"chip_list": [{"instance": 0,"chip_family": "tofino2"}]})
with patch('show.plugins.barefoot.open', mock_open(read_data=chip_family)):
result = bfconfig.get_chip_family()
assert result == "tofino2"

def test_get_chip_family3(self):
with patch('config.plugins.barefoot.device_info.get_path_to_hwsku_dir', return_value=""):
chip_family = json.dumps({"chip_list": [{"instance": 0,"chip_family": "tofino3"}]})
with patch('show.plugins.barefoot.open', mock_open(read_data=chip_family)):
result = bfconfig.get_chip_family()
assert result == "tofino3"

def test_show_profile_default(self):
runner = CliRunner()
expected_output = "Current profile: default\n"
with patch("show.plugins.barefoot.check_profile", return_value=1):
print(show.plugins.barefoot.check_profile())
result = runner.invoke(bfshow.barefoot.commands['profile'], [])
print("result.exit_code:", result.exit_code)
print("result.output:", result.output)
assert result.output == expected_output

def test_check_profile1(self):
ret = TestReturncode()
ret.returncode = 1
with patch('show.plugins.barefoot.subprocess.run', return_value=ret):
result = bfshow.check_profile()
print(result)
assert result == True

def test_check_profile2(self):
ret = TestReturncode()
ret.returncode = 1
with patch('config.plugins.barefoot.subprocess.run', return_value=ret):
result = bfconfig.check_profile()
print(result)
assert result == True

def test_check_profile3(self):
ret = TestReturncode()
ret.returncode = 0
with patch('show.plugins.barefoot.subprocess.run', return_value=ret):
result = bfshow.check_profile()
print(result)
assert result == False

def test_check_profile4(self):
ret = TestReturncode()
ret.returncode = 0
with patch('config.plugins.barefoot.subprocess.run', return_value=ret):
result = bfconfig.check_profile()
print(result)
assert result == False

def test_check_supported_profile1(self):
result = bfconfig.check_supported_profile("x1", "tofino")
print(result)
assert result == True

def test_check_supported_profile2(self):
result = bfconfig.check_supported_profile("y2", "tofino2")
print(result)
assert result == True

def test_check_supported_profile3(self):
result = bfconfig.check_supported_profile("x1", "tofino2")
print(result)
assert result == False

def test_check_supported_profile4(self):
result = bfconfig.check_supported_profile("y2", "tofino")
print(result)
assert result == False

def test_get_current_profile(self):
profile = TestStdout()
profile.stdout = "y2"
with patch('show.plugins.barefoot.subprocess.run', return_value=profile):
result = bfshow.get_current_profile()
assert result == "y2"

def test_get_available_profiles(self):
profile = TestStdout()
profile.stdout = "x2"
with patch('show.plugins.barefoot.subprocess.run', return_value=profile):
result = bfshow.get_available_profiles("install_x1_tofino")
assert result == "x2"

def test_show_profile(self):
runner = CliRunner()
expected_output = """\
Current profile: x2
Available profile(s):
x1
x2
y2
y3
"""
with patch("show.plugins.barefoot.check_profile", return_value=False):
with patch("show.plugins.barefoot.get_chip_family", return_value="tofino"):
with patch("show.plugins.barefoot.get_current_profile", return_value="x2\n"):
with patch("show.plugins.barefoot.get_available_profiles", return_value="x1\nx2\ny2\ny3\n"):
result = runner.invoke(bfshow.barefoot.commands['profile'], [])
print("result.exit_code:", result.exit_code)
print("result.output:", result.output)
assert result.output == expected_output

def test_show_profile2(self):
runner = CliRunner()
expected_output = """\
Current profile: y2
Available profile(s):
x1
x2
y2
y3
"""
with patch("show.plugins.barefoot.check_profile", return_value=False):
with patch("show.plugins.barefoot.get_chip_family", return_value="tofino2"):
with patch("show.plugins.barefoot.get_current_profile", return_value="y2\n"):
with patch("show.plugins.barefoot.get_available_profiles", return_value="x1\nx2\ny2\ny3\n"):
result = runner.invoke(bfshow.barefoot.commands['profile'], [])
print("result.exit_code:", result.exit_code)
print("result.output:", result.output)
assert result.output == expected_output

def test_show_profile3(self):
runner = CliRunner()
expected_output = """\
Current profile: y2
Available profile(s):
x1
x2
y2
y3
"""
with patch("show.plugins.barefoot.check_profile", return_value=False):
with patch("show.plugins.barefoot.get_chip_family", return_value="tofino3"):
with patch("show.plugins.barefoot.get_current_profile", return_value="y2\n"):
with patch("show.plugins.barefoot.get_available_profiles", return_value="x1\nx2\ny2\ny3\n"):
result = runner.invoke(bfshow.barefoot.commands['profile'], [])
print("result.exit_code:", result.exit_code)
print("result.output:", result.output)
assert result.output == expected_output