Skip to content

Commit

Permalink
[Mellanox] Add python3 support for Mellanox platform API (sonic-net#6175
Browse files Browse the repository at this point in the history
)

python2 is end of life and SONiC is going to support python3. This PR is going to support:

1. Mellanox SONiC platform API python3 support
2. Install both python2 and python3 verson of Mellanox SONiC platform API or pmon and host side
  • Loading branch information
Junchao-Mellanox authored Dec 11, 2020
1 parent 2cd236c commit 51c77b1
Show file tree
Hide file tree
Showing 12 changed files with 131 additions and 60 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"skip_ledd": true,
"skip_fancontrol": true,
"delay_xcvrd": true
"delay_xcvrd": true,
"python2_daemons": ["xcvrd"]
}

16 changes: 11 additions & 5 deletions files/build_templates/sonic_debian_extension.j2
Original file line number Diff line number Diff line change
Expand Up @@ -640,11 +640,17 @@ sudo cp $files_path/$MLNX_SSD_FW_UPDATE $FILESYSTEM_ROOT/usr/bin/$MLNX_SSD_FW_UP
j2 platform/mellanox/mlnx-fw-upgrade.j2 | sudo tee $FILESYSTEM_ROOT/usr/bin/mlnx-fw-upgrade.sh
sudo chmod 755 $FILESYSTEM_ROOT/usr/bin/mlnx-fw-upgrade.sh

# Install mlnx-sonic-platform-common Python 2 package
MLNX_PLATFORM_COMMON_PY2_WHEEL_NAME=$(basename {{mlnx_platform_api_py2_wheel_path}})
sudo cp {{mlnx_platform_api_py2_wheel_path}} $FILESYSTEM_ROOT/$MLNX_PLATFORM_COMMON_PY2_WHEEL_NAME
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install $MLNX_PLATFORM_COMMON_PY2_WHEEL_NAME
sudo rm -rf $FILESYSTEM_ROOT/$MLNX_PLATFORM_COMMON_PY2_WHEEL_NAME
# Install mlnx-sonic-platform Python 2 package
MLNX_SONIC_PLATFORM_PY2_WHEEL_NAME=$(basename {{mlnx_platform_api_py2_wheel_path}})
sudo cp {{mlnx_platform_api_py2_wheel_path}} $FILESYSTEM_ROOT/$MLNX_SONIC_PLATFORM_PY2_WHEEL_NAME
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install $MLNX_SONIC_PLATFORM_PY2_WHEEL_NAME
sudo rm -rf $FILESYSTEM_ROOT/$MLNX_SONIC_PLATFORM_PY2_WHEEL_NAME

# Install mlnx-sonic-platform Python 3 package
MLNX_SONIC_PLATFORM_PY3_WHEEL_NAME=$(basename {{mlnx_platform_api_py3_wheel_path}})
sudo cp {{mlnx_platform_api_py3_wheel_path}} $FILESYSTEM_ROOT/$MLNX_SONIC_PLATFORM_PY3_WHEEL_NAME
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install $MLNX_SONIC_PLATFORM_PY3_WHEEL_NAME
sudo rm -rf $FILESYSTEM_ROOT/$MLNX_SONIC_PLATFORM_PY3_WHEEL_NAME
{% endif %}

{%- if SONIC_ROUTING_STACK == "frr" %}
Expand Down
4 changes: 4 additions & 0 deletions platform/mellanox/mlnx-platform-api.dep
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ DEP_FILES += $(shell git ls-files -- $(SPATH) | grep -Ev ' ')
$(SONIC_PLATFORM_API_PY2)_CACHE_MODE := GIT_CONTENT_SHA
$(SONIC_PLATFORM_API_PY2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST)
$(SONIC_PLATFORM_API_PY2)_DEP_FILES := $(filter-out $(SLINKS),$(DEP_FILES))

$(SONIC_PLATFORM_API_PY3)_CACHE_MODE := GIT_CONTENT_SHA
$(SONIC_PLATFORM_API_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST)
$(SONIC_PLATFORM_API_PY3)_DEP_FILES := $(filter-out $(SLINKS),$(DEP_FILES))
10 changes: 10 additions & 0 deletions platform/mellanox/mlnx-platform-api.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,13 @@ $(SONIC_PLATFORM_API_PY2)_DEPENDS = $(SONIC_PY_COMMON_PY2) $(SONIC_PLATFORM_COMM
SONIC_PYTHON_WHEELS += $(SONIC_PLATFORM_API_PY2)

export mlnx_platform_api_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_API_PY2))"

# SONIC_PLATFORM_API_PY3 package

SONIC_PLATFORM_API_PY3 = mlnx_platform_api-1.0-py3-none-any.whl
$(SONIC_PLATFORM_API_PY3)_SRC_PATH = $(PLATFORM_PATH)/mlnx-platform-api
$(SONIC_PLATFORM_API_PY3)_PYTHON_VERSION = 3
$(SONIC_PLATFORM_API_PY3)_DEPENDS = $(SONIC_PY_COMMON_PY3) $(SONIC_PLATFORM_COMMON_PY3) $(SONIC_CONFIG_ENGINE_PY3) $(SONIC_PLATFORM_API_PY2)
SONIC_PYTHON_WHEELS += $(SONIC_PLATFORM_API_PY3)

export mlnx_platform_api_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_API_PY3))"
1 change: 1 addition & 0 deletions platform/mellanox/mlnx-platform-api/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
'Natural Language :: English',
'Operating System :: POSIX :: Linux',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.7',
'Topic :: Utilities',
],
keywords='sonic SONiC platform PLATFORM',
Expand Down
32 changes: 18 additions & 14 deletions platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,15 @@ def __init__(self):
self.sfp_module_initialized = False
self.sfp_event_initialized = False
self.reboot_cause_initialized = False
self.sdk_handle = None
logger.log_info("Chassis loaded successfully")


def __del__(self):
if self.sfp_event_initialized:
self.sfp_event.deinitialize()

if self.sfp_module_initialized:
if self.sdk_handle:
from sonic_platform.sfp import deinitialize_sdk_handle
deinitialize_sdk_handle(self.sdk_handle)

Expand Down Expand Up @@ -115,11 +116,6 @@ def initialize_sfp(self):
from sonic_platform.sfp import initialize_sdk_handle

self.sfp_module = SFP
self.sdk_handle = initialize_sdk_handle()

if self.sdk_handle is None:
self.sfp_module_initialized = False
return

# Initialize SFP list
port_position_tuple = self._get_port_position_tuple_by_platform_name()
Expand All @@ -130,23 +126,31 @@ def initialize_sfp(self):

for index in range(self.PORT_START, self.PORT_END + 1):
if index in range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1):
sfp_module = SFP(index, 'QSFP', self.sdk_handle, self.platform_name)
sfp_module = SFP(index, 'QSFP', self.get_sdk_handle, self.platform_name)
else:
sfp_module = SFP(index, 'SFP', self.sdk_handle, self.platform_name)
sfp_module = SFP(index, 'SFP', self.get_sdk_handle, self.platform_name)

self._sfp_list.append(sfp_module)

self.sfp_module_initialized = True


def get_sdk_handle(self):
if not self.sdk_handle:
self.sdk_handle = initialize_sdk_handle()
if self.sdk_handle is None:
logger.log_error('Failed to open SDK handle')
return self.sdk_handle


def initialize_thermals(self):
from sonic_platform.thermal import initialize_chassis_thermals
# Initialize thermals
initialize_chassis_thermals(self.platform_name, self._thermal_list)


def initialize_eeprom(self):
from eeprom import Eeprom
from .eeprom import Eeprom
# Initialize EEPROM
self._eeprom = Eeprom()
# Get chassis name and model from eeprom
Expand Down Expand Up @@ -385,11 +389,11 @@ def get_reboot_cause(self):
if not self.reboot_cause_initialized:
self.initialize_reboot_cause()

for reset_file, reset_cause in self.reboot_major_cause_dict.iteritems():
for reset_file, reset_cause in self.reboot_major_cause_dict.items():
if self._verify_reboot_cause(reset_file):
return reset_cause, ''

for reset_file, reset_cause in self.reboot_minor_cause_dict.iteritems():
for reset_file, reset_cause in self.reboot_minor_cause_dict.items():
if self._verify_reboot_cause(reset_file):
return self.REBOOT_CAUSE_HARDWARE_OTHER, reset_cause

Expand All @@ -410,17 +414,17 @@ def _show_capabilities(self):
"""
for s in self._sfp_list:
try:
print "index {} tx disable {} dom {} calibration {} temp {} volt {} power (tx {} rx {})".format(s.index,
print("index {} tx disable {} dom {} calibration {} temp {} volt {} power (tx {} rx {})".format(s.index,
s.dom_tx_disable_supported,
s.dom_supported,
s.calibration,
s.dom_temp_supported,
s.dom_volt_supported,
s.dom_rx_power_supported,
s.dom_tx_power_supported
)
))
except:
print "fail to retrieve capabilities for module index {}".format(s.index)
print("fail to retrieve capabilities for module index {}".format(s.index))


def get_change_event(self, timeout=0):
Expand Down
68 changes: 46 additions & 22 deletions platform/mellanox/mlnx-platform-api/sonic_platform/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@
#
# implementation of new platform api
#############################################################################
from __future__ import print_function


try:
import os
import io
import re
import sys
import glob
import tempfile
import subprocess
import ConfigParser
if sys.version_info[0] > 2:
import configparser
else:
import ConfigParser as configparser

from sonic_platform_base.component_base import ComponentBase
except ImportError as e:
Expand Down Expand Up @@ -52,7 +55,7 @@ def __extract_contents(self, mpfa_path):
contents_path = tempfile.mkdtemp(prefix='mpfa-')

cmd = self.MPFA_EXTRACT_COMMAND.format(mpfa_path, contents_path)
subprocess.check_call(cmd.split())
subprocess.check_call(cmd.split(), universal_newlines=True)

self.__contents_path = contents_path

Expand All @@ -62,7 +65,7 @@ def __parse_metadata(self, contents_path):
if not os.path.isfile(metadata_path):
raise RuntimeError("MPFA metadata doesn't exist: path={}".format(metadata_path))

cp = ConfigParser.ConfigParser()
cp = configparser.ConfigParser()
with io.open(metadata_path, 'r') as metadata_ini:
cp.readfp(metadata_ini)

Expand All @@ -79,7 +82,7 @@ def extract(self):
def cleanup(self):
if os.path.exists(self.__contents_path):
cmd = self.MPFA_CLEANUP_COMMAND.format(self.__contents_path)
subprocess.check_call(cmd.split())
subprocess.check_call(cmd.split(), universal_newlines=True)

self.__contents_path = None
self.__metadata = None
Expand Down Expand Up @@ -117,11 +120,14 @@ def __mount_onie_fs(self):
self.__umount_onie_fs()

cmd = "fdisk -l | grep 'ONIE boot' | awk '{print $1}'"
fs_path = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).rstrip('\n')
fs_path = subprocess.check_output(cmd,
stderr=subprocess.STDOUT,
shell=True,
universal_newlines=True).rstrip('\n')

os.mkdir(fs_mountpoint)
cmd = "mount -n -r -t ext4 {} {}".format(fs_path, fs_mountpoint)
subprocess.check_call(cmd, shell=True)
subprocess.check_call(cmd, shell=True, universal_newlines=True)

fs_onie_path = os.path.join(fs_mountpoint, 'onie/tools/lib/onie')
os.symlink(fs_onie_path, onie_path)
Expand All @@ -137,7 +143,7 @@ def __umount_onie_fs(self):

if os.path.ismount(fs_mountpoint):
cmd = "umount -rf {}".format(fs_mountpoint)
subprocess.check_call(cmd, shell=True)
subprocess.check_call(cmd, shell=True, universal_newlines=True)

if os.path.exists(fs_mountpoint):
os.rmdir(fs_mountpoint)
Expand All @@ -146,31 +152,33 @@ def __stage_update(self, image_path):
cmd = self.ONIE_FW_UPDATE_CMD_ADD.format(image_path)

try:
subprocess.check_call(cmd.split())
subprocess.check_call(cmd.split(), universal_newlines=True)
except subprocess.CalledProcessError as e:
raise RuntimeError("Failed to stage firmware update: {}".format(str(e)))

def __unstage_update(self, image_path):
cmd = self.ONIE_FW_UPDATE_CMD_REMOVE.format(os.path.basename(image_path))

try:
subprocess.check_call(cmd.split())
subprocess.check_call(cmd.split(), universal_newlines=True)
except subprocess.CalledProcessError as e:
raise RuntimeError("Failed to unstage firmware update: {}".format(str(e)))

def __trigger_update(self):
cmd = self.ONIE_FW_UPDATE_CMD_UPDATE

try:
subprocess.check_call(cmd.split())
subprocess.check_call(cmd.split(), universal_newlines=True)
except subprocess.CalledProcessError as e:
raise RuntimeError("Failed to trigger firmware update: {}".format(str(e)))

def __is_update_staged(self, image_path):
cmd = self.ONIE_FW_UPDATE_CMD_SHOW_PENDING

try:
output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).rstrip('\n')
output = subprocess.check_output(cmd.split(),
stderr=subprocess.STDOUT,
universal_newlines=True).rstrip('\n')
except subprocess.CalledProcessError as e:
raise RuntimeError("Failed to get pending firmware updates: {}".format(str(e)))

Expand Down Expand Up @@ -255,7 +263,9 @@ def get_onie_firmware_info(self, image_path):
cmd = self.ONIE_IMAGE_INFO_COMMAND.format(image_path)

try:
output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).rstrip('\n')
output = subprocess.check_output(cmd.split(),
stderr=subprocess.STDOUT,
universal_newlines=True).rstrip('\n')
except subprocess.CalledProcessError as e:
raise RuntimeError("Failed to get ONIE firmware info: {}".format(str(e)))

Expand All @@ -275,7 +285,9 @@ def update_firmware(self, image_path):
cmd = self.ONIE_FW_UPDATE_CMD_SHOW_PENDING

try:
output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).rstrip('\n')
output = subprocess.check_output(cmd.split(),
stderr=subprocess.STDOUT,
universal_newlines=True).rstrip('\n')
except subprocess.CalledProcessError as e:
raise RuntimeError("Failed to get pending firmware updates: {}".format(str(e)))

Expand Down Expand Up @@ -340,7 +352,11 @@ def _read_generic_file(filename, len, ignore_errors=False):
@staticmethod
def _get_command_result(cmdline):
try:
proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT)
proc = subprocess.Popen(cmdline,
stdout=subprocess.PIPE,
shell=True,
stderr=subprocess.STDOUT,
universal_newlines=True)
stdout = proc.communicate()[0]
rc = proc.wait()
result = stdout.rstrip('\n')
Expand Down Expand Up @@ -445,7 +461,7 @@ def __install_firmware(self, image_path):

try:
print("INFO: Installing {} firmware update".format(self.name))
subprocess.check_call(cmd.split())
subprocess.check_call(cmd.split(), universal_newlines=True)
except subprocess.CalledProcessError as e:
print("ERROR: Failed to update {} firmware: {}".format(self.name, str(e)))
return False
Expand All @@ -456,7 +472,9 @@ def get_firmware_version(self):
cmd = self.SSD_INFO_COMMAND

try:
output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).rstrip('\n')
output = subprocess.check_output(cmd.split(),
stderr=subprocess.STDOUT,
universal_newlines=True).rstrip('\n')
except subprocess.CalledProcessError as e:
raise RuntimeError("Failed to get {} info: {}".format(self.name, str(e)))

Expand All @@ -470,7 +488,9 @@ def get_available_firmware_version(self, image_path):
cmd = self.SSD_FIRMWARE_INFO_COMMAND.format(image_path)

try:
output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).rstrip('\n')
output = subprocess.check_output(cmd.split(),
stderr=subprocess.STDOUT,
universal_newlines=True).rstrip('\n')
except subprocess.CalledProcessError as e:
raise RuntimeError("Failed to get {} firmware info: {}".format(self.name, str(e)))

Expand Down Expand Up @@ -503,7 +523,9 @@ def get_firmware_update_notification(self, image_path):
cmd = self.SSD_FIRMWARE_INFO_COMMAND.format(image_path)

try:
output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).rstrip('\n')
output = subprocess.check_output(cmd.split(),
stderr=subprocess.STDOUT,
universal_newlines=True).rstrip('\n')
except subprocess.CalledProcessError as e:
raise RuntimeError("Failed to get {} firmware info: {}".format(self.name, str(e)))

Expand Down Expand Up @@ -575,7 +597,9 @@ def get_firmware_version(self):
cmd = self.BIOS_VERSION_COMMAND

try:
version = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).rstrip('\n')
version = subprocess.check_output(cmd.split(),
stderr=subprocess.STDOUT,
universal_newlines=True).rstrip('\n')
except subprocess.CalledProcessError as e:
raise RuntimeError("Failed to get {} version: {}".format(self.name, str(e)))

Expand Down Expand Up @@ -652,7 +676,7 @@ def __install_firmware(self, image_path):

try:
print("INFO: Installing {} firmware update: path={}".format(self.name, image_path))
subprocess.check_call(cmd.split())
subprocess.check_call(cmd.split(), universal_newlines=True)
except subprocess.CalledProcessError as e:
print("ERROR: Failed to update {} firmware: {}".format(self.name, str(e)))
return False
Expand Down Expand Up @@ -721,7 +745,7 @@ def get_component_list(cls):
cpld_number = cls._read_generic_file(cls.CPLD_NUMBER_FILE, cls.CPLD_NUMBER_MAX_LENGTH)
cpld_number = cpld_number.rstrip('\n')

for cpld_idx in xrange(1, int(cpld_number) + 1):
for cpld_idx in range(1, int(cpld_number) + 1):
component_list.append(cls(cpld_idx))

return component_list
Loading

0 comments on commit 51c77b1

Please sign in to comment.