Merge branch 'sonic-net:master' into config

This commit is contained in:
Iris Hsu 2022-10-05 15:23:23 +08:00 committed by GitHub
commit 6d4196fcc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2465 changed files with 276880 additions and 33194 deletions

View File

@ -18,29 +18,44 @@ schedules:
- 202006
always: true
resources:
repositories:
- repository: buildimage
type: github
name: sonic-net/sonic-buildimage
ref: master
endpoint: sonic-net
pool: sonicbld
parameters:
- name: 'jobFilters'
type: object
default:
- vs
- barefoot
- broadcom
- centec
- centec-arm64
- generic
- marvell-armhf
- mellanox
stages:
- stage: Build
variables:
CACHE_MODE: none
VERSION_CONTROL_OPTIONS: 'SONIC_VERSION_CONTROL_COMPONENTS='
- name: CACHE_MODE
value: none
- name: VERSION_CONTROL_OPTIONS
value: 'SONIC_VERSION_CONTROL_COMPONENTS='
- template: .azure-pipelines/template-variables.yml@buildimage
jobs:
- template: azure-pipelines-build.yml
parameters:
buildOptions: '${{ variables.VERSION_CONTROL_OPTIONS }} SONIC_BUILD_JOBS=$(nproc) ENABLE_IMAGE_SIGNATURE=y'
jobFilters: ${{ parameters.jobFilters }}
buildOptions: '${{ variables.VERSION_CONTROL_OPTIONS }} ENABLE_DOCKER_BASE_PULL=n SONIC_BUILD_JOBS=$(nproc) ENABLE_IMAGE_SIGNATURE=y'
preSteps:
- script: |
containers=$(docker container ls | grep "sonic-slave" | awk '{ print $1 }')
if [ ! -z "$containers" ]; then
docker container kill $containers || true
sleep 5
fi
images=$(docker images 'sonic-slave-*' -a -q)
if [ ! -z "$images" ]; then
docker rmi -f $images
fi
displayName: 'Cleanup sonic slave'
- template: .azure-pipelines/template-clean-sonic-slave.yml@buildimage
- stage: UpgradeVersions
jobs:
- job: UpgradeVersions
@ -64,14 +79,14 @@ stages:
default_platform=broadcom
artifacts=$(find $(Pipeline.Workspace) -maxdepth 1 -type d -name 'sonic-buildimage.*' | grep -v "sonic-buildimage.${default_platform}")
echo "artifacts$artifacts"
cp -r $(Pipeline.Workspace)/sonic-buildimage.${default_platform}/versions target/
cp -r $(Pipeline.Workspace)/sonic-buildimage.${default_platform}/target/versions target/
make freeze FREEZE_VERSION_OPTIONS=-r
find files/build/versions
ordered_artifacts=$(echo "$artifacts" | grep -v -E "arm64|armhf" && echo "$artifacts" | grep -E "arm64|armhf")
for artifact in $ordered_artifacts
do
rm -rf target/versions
cp -r $artifact/versions target/
cp -r $artifact/target/versions target/
OPTIONS="-a -d"
[[ "$artifact" == *arm64* || "$artifact" == *armhf* ]] && OPTIONS="-d"
make freeze FREEZE_VERSION_OPTIONS="$OPTIONS"

View File

@ -16,6 +16,9 @@ parameters:
- name: 'jobGroups'
type: object
default: ''
- name: 'qemuOrCrossBuild'
type: boolean
default: false
jobs:
- template: azure-pipelines-image-template.yml
@ -30,11 +33,15 @@ jobs:
BUILD_OPTIONS: ${{ parameters.buildOptions }}
DOCKER_DATA_ROOT_FOR_MULTIARCH: /data/march/docker
dbg_image: no
asan_image: no
swi_image: no
raw_image: no
docker_syncd_rpc_image: no
syncd_rpc_image: no
platform_rpc: no
${{ if parameters.qemuOrCrossBuild }}:
SONIC_SLAVE_DOCKER_DRIVER: 'vfs'
CACHE_MODE: 'none'
${{ if ne(parameters.jobGroups, '') }}:
jobGroups: ${{ parameters.jobGroups }}
${{ if eq(parameters.jobGroups, '') }}:
@ -42,6 +49,7 @@ jobs:
- name: vs
variables:
dbg_image: yes
asan_image: yes
- name: barefoot
variables:
@ -50,6 +58,7 @@ jobs:
swi_image: yes
- name: broadcom
timeoutInMinutes: 1440
variables:
dbg_image: yes
swi_image: yes
@ -64,7 +73,8 @@ jobs:
platform_rpc: centec
- name: centec-arm64
pool: sonicbld-arm64
${{ if not(parameters.qemuOrCrossBuild) }}:
pool: sonicbld-arm64
timeoutInMinutes: 2880
variables:
PLATFORM_ARCH: arm64
@ -78,7 +88,8 @@ jobs:
dbg_image: yes
- name: marvell-armhf
pool: sonicbld-armhf
${{ if not(parameters.qemuOrCrossBuild) }}:
pool: sonicbld-armhf
timeoutInMinutes: 2880
variables:
PLATFORM_ARCH: armhf
@ -97,6 +108,7 @@ jobs:
platform_rpc: nephos
buildSteps:
- template: template-skipvstest.yml
- bash: |
set -ex
if [ $(GROUP_NAME) == vs ]; then
@ -104,6 +116,10 @@ jobs:
make $BUILD_OPTIONS INSTALL_DEBUG_TOOLS=y target/sonic-vs.img.gz
mv target/sonic-vs.img.gz target/sonic-vs-dbg.img.gz
fi
if [ $(asan_image) == yes ]; then
make $BUILD_OPTIONS ENABLE_ASAN=y target/docker-sonic-vs.gz
mv target/docker-sonic-vs.gz target/docker-sonic-vs-asan.gz
fi
make $BUILD_OPTIONS target/docker-sonic-vs.gz target/sonic-vs.img.gz target/docker-ptf.gz
if [ $(Build.Reason) != 'PullRequest' ];then
gzip -kd target/sonic-vs.img.gz
@ -123,6 +139,9 @@ jobs:
fi
if [ $(docker_syncd_rpc_image) == yes ]; then
make $BUILD_OPTIONS ENABLE_SYNCD_RPC=y target/docker-syncd-$(platform_rpc)-rpc.gz
if [ $(GROUP_NAME) == broadcom ]; then
make $BUILD_OPTIONS ENABLE_SYNCD_RPC=y target/docker-syncd-$(platform_rpc)-dnx-rpc.gz
fi
fi
if [ $(syncd_rpc_image) == yes ]; then
make $BUILD_OPTIONS ENABLE_SYNCD_RPC=y target/sonic-$(GROUP_NAME).bin
@ -131,3 +150,4 @@ jobs:
make $BUILD_OPTIONS target/sonic-$(GROUP_NAME).bin
fi
displayName: "Build sonic image"
- template: check-dirty-version.yml

View File

@ -0,0 +1,33 @@
parameters:
- name: connectionName
type: string
default: sonic-dev-connection
- name: kevaultName
type: string
default: sonic-kv
- name: certificateName
type: string
default: sonic-secure-boot
steps:
- task: AzureKeyVault@2
inputs:
connectedServiceName: ${{ parameters.connectionName }}
keyVaultName: ${{ parameters.kevaultName }}
secretsFilter: ${{ parameters.certificateName }}
- script: |
set -e
TMP_FILE=$(mktemp)
echo "$CERTIFICATE" | base64 -d > $TMP_FILE
sudo mkdir -p /etc/certificates
mkdir -p $(Build.StagingDirectory)/target
# Save the public key
openssl pkcs12 -in $TMP_FILE -clcerts --nokeys -nodes -passin pass: | sed -z -e "s/.*\(-----BEGIN CERTIFICATE\)/\1/" > $(SIGNING_CERT)
# Save the private key
openssl pkcs12 -in $TMP_FILE -nocerts -nodes -passin pass: | sed -z -e "s/.*\(-----BEGIN PRIVATE KEY\)/\1/" | sudo tee $(SIGNING_KEY) 1>/dev/null
ls -lt $(SIGNING_CERT) $(SIGNING_KEY)
rm $TMP_FILE
env:
CERTIFICATE: $(${{ parameters.certificateName }})
displayName: "Save certificate"

View File

@ -28,7 +28,7 @@ jobs:
- template: cleanup.yml
- ${{ parameters.preSteps }}
- script: |
if [ -n "$(CACHE_MODE)" ] && echo $(PLATFORM_AZP) | grep -E -q "^(vs|broadcom|mellanox)$"; then
if [ -n "$(CACHE_MODE)" ] && echo $(PLATFORM_AZP) | grep -E -q "^(vs|broadcom|mellanox|marvell-armhf)$"; then
CACHE_OPTIONS="SONIC_DPKG_CACHE_METHOD=$(CACHE_MODE) SONIC_DPKG_CACHE_SOURCE=/nfs/dpkg_cache/$(PLATFORM_AZP)"
BUILD_OPTIONS="$(BUILD_OPTIONS) $CACHE_OPTIONS"
echo "##vso[task.setvariable variable=BUILD_OPTIONS]$BUILD_OPTIONS"
@ -43,22 +43,28 @@ jobs:
[ -n "$SYSTEM_PULLREQUEST_PULLREQUESTID" ] && BRANCH_NAME="$SYSTEM_PULLREQUEST_TARGETBRANCH-$SYSTEM_PULLREQUEST_PULLREQUESTNUMBER"
git checkout -b $BRANCH_NAME
sudo modprobe overlay
pip3 install MarkupSafe==2.0.1 --force-reinstall
sudo apt-get install -y acl
sudo bash -c "echo 1 > /proc/sys/vm/compact_memory"
ENABLE_DOCKER_BASE_PULL=y make PLATFORM=$(PLATFORM_AZP) PLATFORM_ARCH=$(PLATFORM_ARCH) $(BUILD_OPTIONS) configure
displayName: 'Make configure'
postSteps:
- script: cp target -r $(Build.ArtifactStagingDirectory)/
- script: |
mkdir -p $(Build.ArtifactStagingDirectory)/target
mv target/* $(Build.ArtifactStagingDirectory)/target/
displayName: Copy Artifacts
condition: always()
- publish: $(Build.ArtifactStagingDirectory)
artifact: 'sonic-buildimage.$(GROUP_NAME)$(GROUP_EXTNAME)'
displayName: "Archive sonic image"
- publish: $(Build.ArtifactStagingDirectory)
condition: failed()
condition: or(failed(), canceled())
artifact: 'sonic-buildimage.$(GROUP_NAME)$(GROUP_EXTNAME)$(System.JobAttempt)'
displayName: "Archive failed sonic image"
- ${{ if ne(variables['Build.Reason'], 'PullRequest') }}:
- template: trigger-publish-artifacts-build.yml
parameters:
artifactName: 'sonic-buildimage.$(GROUP_NAME)$(GROUP_EXTNAME)'
publishPrefix: '$(Build.DefinitionName)/$(Build.SourceBranchName)/$(GROUP_NAME)'
- ${{ parameters.postSteps }}
- template: cleanup.yml
jobGroups: ${{ parameters.jobGroups }}

View File

@ -1,5 +1,7 @@
variables:
${{ if and(ge(variables['Build.SourceBranchName'], '202012'), le(variables['Build.SourceBranchName'], '299999')) }}:
${{ if eq(variables['Build.Reason'],'PullRequest') }}:
VERSION_CONTROL_OPTIONS: 'SONIC_VERSION_CONTROL_COMPONENTS=$([[ "$(System.PullRequest.TargetBranch)" =~ ^20[2-9][0-9]{3}$ ]] && echo deb,py2,py3,web,git,docker)'
${{ elseif ne(variables['Build.SourceBranchName'],'master') }}:
VERSION_CONTROL_OPTIONS: 'SONIC_VERSION_CONTROL_COMPONENTS=deb,py2,py3,web,git,docker'
${{ if or(lt(variables['Build.SourceBranchName'], '202012'), gt(variables['Build.SourceBranchName'], '299999')) }}:
${{ else }}:
VERSION_CONTROL_OPTIONS: ''

View File

@ -0,0 +1,19 @@
pr: none
trigger: none
schedules:
- cron: "0 0 * * *"
displayName: Daily build
branches:
include:
- master
- 202???
resources:
repositories:
- repository: buildimage
type: github
name: sonic-net/sonic-buildimage
ref: master
endpoint: sonic-net
jobs:
- template: .azure-pipelines/template-commonlib.yml@buildimage

View File

@ -0,0 +1,16 @@
steps:
- script: |
. functions.sh
SONIC_VERSION=$(sonic_get_version)
echo "SONIC_VERSION=$SONIC_VERSION"
if [[ "$SONIC_VERSION" == *dirty* ]]; then
# Print the detail dirty info
git status --untracked-files=no -s --ignore-submodules
# Exit with error, if it is a PR build
if [ "$(Build.Reason)" == "PullRequest" ]; then
echo "Build failed for the dirty version: $SONIC_VERSION" 1>&2
exit 1
fi
fi
displayName: "Check the dirty version"

View File

@ -1,44 +0,0 @@
# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml
# Build and push sonic-slave-[buster|jessie|stretch] images for amd64/armhf/arm64
schedules:
- cron: "0 8 * * *"
branches:
include:
- master
- 202012
always: true
trigger: none
pr:
branches:
include:
- master
paths:
include:
- sonic-slave-jessie
- sonic-slave-stretch
- sonic-slave-buster
- sonic-slave-bullseye
parameters:
- name: 'dists'
type: object
default:
- bullseye
- buster
- stretch
stages:
- stage: Build
jobs:
- ${{ each dist in parameters.dists }}:
- ${{ if contains(variables['Build.DefinitionName'], dist) }}:
- template: docker-sonic-slave-template.yml
parameters:
pool: sonicbld-arm64
arch: arm64
dist: ${{ dist }}

View File

@ -1,44 +0,0 @@
# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml
# Build and push sonic-slave-[buster|jessie|stretch] images for amd64/armhf/arm64
schedules:
- cron: "0 8 * * *"
branches:
include:
- master
- 202012
always: true
trigger: none
pr:
branches:
include:
- master
paths:
include:
- sonic-slave-jessie
- sonic-slave-stretch
- sonic-slave-buster
- sonic-slave-bullseye
parameters:
- name: 'dists'
type: object
default:
- bullseye
- buster
- stretch
stages:
- stage: Build
jobs:
- ${{ each dist in parameters.dists }}:
- ${{ if contains(variables['Build.DefinitionName'], dist) }}:
- template: docker-sonic-slave-template.yml
parameters:
pool: sonicbld-armhf
arch: armhf
dist: ${{ dist }}

View File

@ -3,7 +3,6 @@
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml
# Build and push sonic-slave-[buster|jessie|stretch] images for amd64/armhf/arm64
parameters:
- name: arch
type: string
@ -11,6 +10,9 @@ parameters:
- amd64
- armhf
- arm64
- name: march
type: string
default: ''
- name: dist
type: string
values:
@ -33,76 +35,44 @@ parameters:
- sonicbld-armhf
jobs:
- job: Build_${{ parameters.dist }}_${{ parameters.arch }}
- job: Build_${{ parameters.dist }}_${{ parameters.march }}${{ parameters.arch }}
timeoutInMinutes: 360
variables:
- template: /.azure-pipelines/template-variables.yml@buildimage
- template: /.azure-pipelines/azure-pipelines-repd-build-variables.yml@buildimage
pool: ${{ parameters.pool }}
steps:
- template: cleanup.yml
- template: /.azure-pipelines/template-clean-sonic-slave.yml@buildimage
- checkout: self
clean: true
submodules: recursive
- task: Docker@2
displayName: Login to ACR
inputs:
command: login
containerRegistry: ${{ parameters.registry_conn }}
- bash: |
set -ex
image_tag=$(BLDENV=${{ parameters.dist }} make -f Makefile.work showtag PLATFORM=generic PLATFORM_ARCH=${{ parameters.arch }} | grep sonic-slave | tail -n 1)
image_latest=$(echo $(echo $image_tag | awk -F: '{print$1}'):latest)
docker rmi $image_tag || true
SLAVE_DIR=sonic-slave-${{ parameters.dist }}
if [ x${{ parameters.pool }} == x"sonicbld" ]; then
if [ x${{ parameters.arch }} == x"amd64" ]; then
SLAVE_BASE_IMAGE=${SLAVE_DIR}
SLAVE_BASE_IMAGE_UPLOAD=${SLAVE_DIR}
elif [ x${{ parameters.pool }} == x"sonicbld" ]; then
SLAVE_BASE_IMAGE=${SLAVE_DIR}-march-${{ parameters.arch }}
SLAVE_BASE_IMAGE_UPLOAD=${SLAVE_DIR}-march-${{ parameters.arch }}
fi
elif [[ x${{ parameters.pool }} == x"sonicbld-armhf" && x${{ parameters.arch }} == x"armhf" ]]; then
SLAVE_BASE_IMAGE=${SLAVE_DIR}
SLAVE_BASE_IMAGE_UPLOAD=${SLAVE_DIR}-armhf
elif [[ x${{ parameters.pool }} == x"sonicbld-arm64" && x${{ parameters.arch }} == x"arm64" ]]; then
SLAVE_BASE_IMAGE=${SLAVE_DIR}
SLAVE_BASE_IMAGE_UPLOAD=${SLAVE_DIR}-arm64
else
echo "do not support build ${{ parameters.arch }} on ${{ parameters.pool }}"
exit 1
if [[ "$(Build.Reason)" =~ [a-zA-Z]*CI ]] && docker pull ${{ parameters.registry_url }}/${image_tag};then
exit 0
fi
if [ x"$(Build.SourceBranchName)" == x"202012" ]; then
BUILD_OPTIONS = 'SONIC_VERSION_CONTROL_COMPONENTS=deb,py2,py3,web,git,docker'
DOCKER_DATA_ROOT_FOR_MULTIARCH=/data/march/docker BLDENV=${{ parameters.dist }} make -f Makefile.work configure PLATFORM=generic PLATFORM_ARCH=${{ parameters.arch }} $args || docker image ls $image_tag
if [[ "$(Build.Reason)" == "PullRequest" ]];then
exit 0
fi
containers=$(docker container ls | grep "sonic-slave" | awk '{ print $1 }')
if [ ! -z "$containers" ]; then
docker container kill $containers || true
sleep 5
docker tag ${image_tag} ${REGISTRY_SERVER}/${image_tag}
docker push ${REGISTRY_SERVER}/${image_tag}
if [[ "${{ parameters.arch }}" == "amd64" ]];then
docker tag ${image_tag} ${REGISTRY_SERVER}/${image_latest}
docker push ${REGISTRY_SERVER}/${image_latest}
fi
images=$(docker images 'sonic-slave-*' -a -q)
if [ ! -z "$images" ]; then
docker rmi -f $images
fi
tmpfile=$(mktemp)
echo ${{ parameters.arch }} > .arch
DOCKER_DATA_ROOT_FOR_MULTIARCH=/data/march/docker BLDENV=${{ parameters.dist }} $(BUILD_OPTIONS) make -f Makefile.work sonic-slave-build | tee $tmpfile
SLAVE_BASE_TAG=$(grep "^Checking sonic-slave-base image:" $tmpfile | awk -F ':' '{print $3}')
SLAVE_TAG=$(grep "^Checking sonic-slave image:" $tmpfile | awk -F ':' '{print $3}')
mkdir -p target
docker tag $SLAVE_BASE_IMAGE:$SLAVE_BASE_TAG $REGISTRY_SERVER/$SLAVE_BASE_IMAGE_UPLOAD:latest
docker tag $SLAVE_BASE_IMAGE:$SLAVE_BASE_TAG $REGISTRY_SERVER/$SLAVE_BASE_IMAGE_UPLOAD:$SLAVE_BASE_TAG
set +x
echo "##vso[task.setvariable variable=VARIABLE_SLAVE_BASE_IMAGE]$SLAVE_BASE_IMAGE_UPLOAD"
echo "##vso[task.setvariable variable=VARIABLE_SLAVE_BASE_TAG]$SLAVE_BASE_TAG"
env:
REGISTRY_SERVER: ${{ parameters.registry_url }}
displayName: Build sonic-slave-${{ parameters.dist }}-${{ parameters.arch }}
- task: Docker@2
displayName: Upload image
inputs:
containerRegistry: ${{ parameters.registry_conn }}
repository: $(VARIABLE_SLAVE_BASE_IMAGE)
command: push
tags: |
$(VARIABLE_SLAVE_BASE_TAG)
latest

View File

@ -3,27 +3,37 @@
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml
# Build and push sonic-slave-[buster|jessie|stretch] images for amd64/armhf/arm64
resources:
repositories:
- repository: buildimage
type: github
name: sonic-net/sonic-buildimage
ref: master
endpoint: sonic-net
schedules:
- cron: "0 8 * * *"
- cron: "0 0 * * 0"
displayName: Weekly build
branches:
include:
- master
- 202012
- 202???
always: true
trigger: none
pr:
pr: none
trigger:
batch: true
branches:
include:
- master
- 202???
paths:
include:
- sonic-slave-jessie
- sonic-slave-stretch
- sonic-slave-buster
- sonic-slave-bullseye
- sonic-slave-*
- src/sonic-build-hooks
- files/build/versions
- Makefile
- Makefile.work
parameters:
- name: 'arches'
@ -52,8 +62,21 @@ stages:
- ${{ each dist in parameters.dists }}:
- ${{ if endswith(variables['Build.DefinitionName'], dist) }}:
- ${{ each arch in parameters.arches }}:
- template: docker-sonic-slave-template.yml
- template: .azure-pipelines/docker-sonic-slave-template.yml@buildimage
parameters:
pool: sonicbld
arch: ${{ arch }}
dist: ${{ dist }}
- stage: Build_march
dependsOn: []
jobs:
- ${{ each dist in parameters.dists }}:
- ${{ if endswith(variables['Build.DefinitionName'], dist) }}:
- ${{ each arch in parameters.arches }}:
- ${{ if ne(arch, 'amd64') }}:
- template: .azure-pipelines/docker-sonic-slave-template.yml@buildimage
parameters:
pool: sonicbld-${{ arch }}
arch: ${{ arch }}
dist: ${{ dist }}
march: march_

View File

@ -37,3 +37,8 @@ stages:
variables:
docker_syncd_rpc_image: yes
platform_rpc: mlnx
- name: marvell-armhf
pool: sonicbld-armhf
timeoutInMinutes: 1200
variables:
PLATFORM_ARCH: armhf

View File

@ -22,6 +22,18 @@ resources:
name: Cisco-8000-sonic/platform-cisco-8000
endpoint: cisco-connection
variables:
- group: SONIC-AKV-STROAGE-1
- name: StorageSASKey
value: $(sonicstorage-SasToken)
- name: SONIC_ENABLE_SECUREBOOT_SIGNATURE
value: y
- name: SIGNING_KEY
value: /etc/certificates/sonic-secure-boot-private.pem
- name: SIGNING_CERT
value: $(Build.StagingDirectory)/target/sonic-secure-boot-public.pem
stages:
- stage: Build
pool: sonic
@ -29,12 +41,14 @@ stages:
CACHE_MODE: wcache
SKIP_CHECKOUT: true
TERM: ''
PACKAGE_URL: "https://sonicstorage.blob.core.windows.net/packages"
jobs:
- template: azure-pipelines-build.yml
parameters:
buildOptions: 'USERNAME=admin SONIC_BUILD_JOBS=$(nproc) ${{ variables.VERSION_CONTROL_OPTIONS }}'
preSteps:
- template: azure-pipelines-download-certificate.yml
- checkout: self
submodules: recursive
path: s
@ -60,5 +74,34 @@ stages:
make PLATFORM=cisco-8000 platform/cisco-8000
tar xfz $(System.ArtifactsDirectory)/artifactory-*.tar.gz -C platform/cisco-8000
displayName: 'Setup cisco artifacts'
- script: |
set -ex
filename=$(find platform/cisco-8000/artifactory/sonic -name cisco-* -type f | head -n 1)
if [ -z "$filename" ]; then
echo "Cisco sai package not found" 1>&2
exit 1
fi
cd $(dirname $filename)
echo "PWD=$(pwd)"
ls -l cisco-*.deb
while read -r package; do
# Cisco version format: <VERSION>-sai-<sai-ver>-<distribution>-<COMMIT HASH>
# The <sai-ver> may contain several values in one build, the part is skipped when publishing to storage
# See https://github.com/Cisco-8000-sonic/sdk/blob/master/azure-pipelines.yml
# The $PACKAGE_URL is only accessible for AZP
version=$(echo $package | awk -F_ '{print $(NF-1)}' | cut -d- -f1,2,4,5)
package_url="$PACKAGE_URL/sai/ciscosai/master/$version/$package"
echo "Override package $package from $package_url"
wget "$package_url$StorageSASKey" -O "$package"
done < <(ls cisco-*.deb)
env:
StorageSASKey: $(StorageSASKey)
condition: ne(variables['Build.Reason'], 'PullRequest')
displayName: "Override cisco sai packages"
- script: |
echo "SONIC_ENABLE_SECUREBOOT_SIGNATURE := y" >> rules/config.user
echo "SIGNING_KEY := $(SIGNING_KEY)" >> rules/config.user
echo "SIGNING_CERT := $(SIGNING_CERT)" >> rules/config.user
displayName: "Enable secure boot signature"
jobGroups:
- name: cisco-8000

View File

@ -37,7 +37,7 @@ stages:
jobs:
- job:
pool: sonictest
pool: sonictest-ma
displayName: "kvmtest-multi-asic-t1-lag"
timeoutInMinutes: 240

View File

@ -18,18 +18,31 @@ schedules:
- 201911
- 201811
resources:
repositories:
- repository: buildimage
type: github
name: sonic-net/sonic-buildimage
ref: master
endpoint: sonic-net
trigger: none
pr: none
variables:
- template: .azure-pipelines/template-variables.yml@buildimage
stages:
- stage: Build
pool: sonicbld
variables:
- name: CACHE_MODE
value: wcache
- template: azure-pipelines-repd-build-variables.yml
- template: .azure-pipelines/azure-pipelines-repd-build-variables.yml@buildimage
jobs:
- template: azure-pipelines-build.yml
parameters:
buildOptions: 'USERNAME=admin SONIC_BUILD_JOBS=$(nproc) ${{ variables.VERSION_CONTROL_OPTIONS }}'
jobFilters: none
${{ if contains(variables['Build.DefinitionName'], 'cross') }}:
qemuOrCrossBuild: true

View File

@ -7,6 +7,12 @@ parameters:
type: string
- name: ptf_name
type: string
- name: vmtype
type: string
default: 'ceos'
- name: section
type: string
default: ''
- name: image
type: string
default: sonic-vs.img.gz
@ -38,14 +44,13 @@ steps:
git reset --hard origin/master
sed -i s/use_own_value/${username}/ ansible/veos_vtb
echo aaa > ansible/password.txt
docker exec sonic-mgmt bash -c "pushd /data/sonic-mgmt/ansible;./testbed-cli.sh -d /data/sonic-vm -m $(inventory) -t $(testbed_file) -k ceos refresh-dut ${{ parameters.tbname }} password.txt" && sleep 180
docker exec sonic-mgmt bash -c "pushd /data/sonic-mgmt/ansible;./testbed-cli.sh -d /data/sonic-vm -m $(inventory) -t $(testbed_file) -k ${{ parameters.vmtype }} refresh-dut ${{ parameters.tbname }} password.txt" && sleep 180
displayName: "Setup testbed"
- script: |
rm -rf $(Build.ArtifactStagingDirectory)/*
docker exec sonic-mgmt bash -c "/data/sonic-mgmt/tests/kvmtest.sh -en -T ${{ parameters.tbtype }} ${{ parameters.tbname }} ${{ parameters.dut }}"
docker exec sonic-mgmt bash -c "/data/sonic-mgmt/tests/kvmtest.sh -en -T ${{ parameters.tbtype }} ${{ parameters.tbname }} ${{ parameters.dut }} ${{ parameters.section }}"
displayName: "Run tests"
- script: |
# save dut state if test fails
virsh_version=$(virsh --version)
@ -75,17 +80,17 @@ steps:
condition: succeededOrFailed()
- publish: $(Build.ArtifactStagingDirectory)/kvmdump
artifact: sonic-buildimage.kvmtest.${{ parameters.tbtype}}.memdump@$(System.JobAttempt)
artifact: sonic-buildimage.kvmtest.${{ parameters.tbtype}}${{ parameters.section }}.memdump@$(System.JobAttempt)
displayName: "Archive sonic kvm memdump"
condition: failed()
- publish: $(Build.ArtifactStagingDirectory)/logs
artifact: sonic-buildimage.kvmtest.${{ parameters.tbtype }}.log@$(System.JobAttempt)
artifact: sonic-buildimage.kvmtest.${{ parameters.tbtype }}${{ parameters.section }}.log@$(System.JobAttempt)
displayName: "Archive sonic kvm logs"
condition: succeededOrFailed()
- task: PublishTestResults@2
inputs:
testResultsFiles: '$(Build.ArtifactStagingDirectory)/logs/**/*.xml'
testRunTitle: kvmtest.${{ parameters.tbtype }}
testRunTitle: kvmtest.${{ parameters.tbtype }}${{ parameters.section }}
condition: succeededOrFailed()

View File

@ -0,0 +1,10 @@
steps:
- script: |
set -x
containers=$(docker container ls -aq)
[ -n "$containers" ] && docker container rm -f $containers
docker images | grep "^<none>" | awk '{print$3}' | xargs -i docker rmi {}
images=$(docker images 'sonic-slave-*' -a -q)
[ -n "$images" ] && docker rmi -f $images
exit 0
displayName: 'Cleanup sonic slave'

View File

@ -0,0 +1,53 @@
parameters:
- name: archs
type: object
default:
- amd64
- armhf
- arm64
jobs:
- ${{ each arch in parameters.archs }}:
- job: Build_${{ arch }}
timeoutInMinutes: 120
${{ if eq(arch,'amd64') }}:
pool: sonicbld
${{ else }}:
pool: sonicbld-${{ arch }}
variables:
- template: template-variables.yml
steps:
- checkout: self
clean: true
submodules: recursive
- script: |
set -ex
branch=$(Build.SourceBranchName)
# replace all: '-' -> '_'
branch=${branch//-/_}
# replace all: 'a' -> 'A', DIST_MASTER is set in variable.
BRANCH=DIST_${branch^^}
# variable name is dynamic
bldenvs=${!BRANCH}
[ "$bldenvs" == "" ] && bldenvs="$(COMMON_LIB_BUILD_ENVS)"
for bldenv in $bldenvs
do
BLDENV=$bldenv make -f Makefile.work configure PLATFORM_ARCH=${{ arch }} PLATFORM=vs ENABLE_DOCKER_BASE_PULL=y
done
set +x
echo "##vso[task.setvariable variable=bldenvs;]$bldenvs"
displayName: Make configure
- script: |
set -ex
for bldenv in $(bldenvs)
do
SONIC_BUILD_JOBS=$(nproc) BLDENV=$bldenv make -f Makefile.work lib-packages ENABLE_DOCKER_BASE_PULL=y
done
mv target $(Build.ArtifactStagingDirectory)
displayName: Make common lib packages
- ${{ if eq(arch,'amd64') }}:
- publish: $(Build.ArtifactStagingDirectory)
artifact: common-lib
- ${{ else }}:
- publish: $(Build.ArtifactStagingDirectory)
artifact: common-lib.${{ arch }}

View File

@ -0,0 +1,12 @@
steps:
- ${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
- script: |
set -ex
tar_branch=origin/$(System.PullRequest.TargetBranch)
git diff $tar_branch..HEAD --name-only | grep -v -f .azure-pipelines/vstest-exclude && exit 0
git diff $tar_branch..HEAD --name-only | grep -f .azure-pipelines/vstest-include && exit 0
set +x
echo "Skip vstest jobs"
echo "##vso[task.setvariable variable=SKIP_VSTEST;isOutput=true]YES"
name: SetVar
displayName: "Check if vstest is needed."

View File

@ -0,0 +1,4 @@
variables:
DEFAULT_CONTAINER_REGISTRY: 'publicmirror.azurecr.io'
COMMON_LIB_BUILD_ENVS: 'bullseye'
SONIC_SLAVE_DOCKER_DRIVER: 'overlay2'

View File

@ -0,0 +1,62 @@
# The steps to trigger the pipeline to publish the artifacts
parameters:
- name: artifactName
type: string
default: ""
- name: publishPrefix
type: string
default: "$(Build.DefinitionName)/$(Build.SourceBranchName)"
steps:
- script: |
. functions.sh
sonic_version=$(sonic_get_version)
latest_tag=$(git describe --tags --abbrev=0)
docker_tags="$sonic_version $(Build.SourceBranchName)"
if [ "$(Build.SourceBranchName)" == "master" ]; then
docker_tags="$docker_tags latest"
fi
echo "##vso[task.setvariable variable=sonic_version]$sonic_version"
echo "##vso[task.setvariable variable=latest_tag]$latest_tag"
echo "##vso[task.setvariable variable=docker_tags]$docker_tags"
displayName: 'Set trigger build variables'
- task: TriggerBuild@4
inputs:
definitionIsInCurrentTeamProject: false
teamProject: internal
tfsServer: $(System.CollectionUri)
buildDefinition: 'publish-artifacts'
queueBuildForUserThatTriggeredBuild: true
ignoreSslCertificateErrors: false
useSameSourceVersion: false
useCustomSourceVersion: false
useSameBranch: false
waitForQueuedBuildsToFinish: false
storeInEnvironmentVariable: true
authenticationMethod: 'Personal Access Token'
password: '$(system.accesstoken)'
enableBuildInQueueCondition: false
dependentOnSuccessfulBuildCondition: false
dependentOnFailedBuildCondition: false
checkbuildsoncurrentbranch: false
failTaskIfConditionsAreNotFulfilled: false
buildParameters: ''
templateParameters: |
pipelineContext: {"buildId":"$(Build.BuildId)",
"pipelineId":"$(System.DefinitionId)",
"project": "$(System.TeamProject)",
"branchName":"$(Build.SourceBranchName)"},
artifactContext: {"artifactName":"${{ parameters.artifactName }}",
"artifactPatterns":"**/*.bin\n
**/*.swi\n
**/*.raw\n
**/*.img.gz\n
**/*-rpc.gz\n
**/python-saithrift*.deb"},
publishContext: {"publishPrefix":"${{ parameters.publishPrefix }}",
"keepArtifactName":false,
"dockerImagePatterns":"target/*-rpc.gz",
"dockerTags":"$(docker_tags)",
"version":"$(sonic_version)",
"latestTag":"$(latest_tag)"}

View File

@ -0,0 +1,4 @@
^platform
^.azure-pipelines
^files/build/versions
^sonic-slave-

View File

@ -0,0 +1,2 @@
^platform/vs
^.azure-pipelines/run-test-template.yml

74
.github/CODEOWNERS vendored
View File

@ -19,6 +19,9 @@
/Makefile.work @qiluo-msft @xumia @lguohan
/slave.mk @qiluo-msft @xumia @lguohan
/scripts @qiluo-msft @xumia @lguohan
/src/sonic-build-hooks/ @Azure/sonic-build
/src/debootstrap/ @Azure/sonic-build
/src/sonic-fips/ @Azure/sonic-build
# installer
/installer/ @qiluo-msft
@ -31,8 +34,77 @@
/dockers/docker-config-engine*/ @qiluo-msft
/dockers/docker-snmp/ @qiluo-msft
# src
# kernel
/src/sonic-linux-kernel/ @Azure/sonic-kernel
# devices
/device/ @Azure/sonic-platform
/src/sonic-platform-common/ @Azure/sonic-platform
/src/sonic-platform-daemons/ @Azure/sonic-platform
/src/sonic-platform-pde/ @Azure/sonic-platform
/src/lm-sensors/ @Azure/sonic-platform
/src/flashrom/ @Azure/sonic-platform
# common library
/src/initramfs-tools/ @qiluo-msft
/src/redis-dump-load/ @Azure/sonic-management
/src/sonic-py-common/ @Azure/sonic-management
/src/sonic-py-swsssdk/ @Azure/sonic-management
/src/sonic-swss-common/ @Azure/sonic-management
/src/bash/ @Azure/sonic-management
/src/tacacs/ @Azure/sonic-management
/src/radius/ @Azure/sonic-management
/src/swig/ @Azure/sonic-management
/src/socat/ @Azure/sonic-management
# redis
/src/redis/ @Azure/sonic-management
/src/hiredis/ @Azure/sonic-management
# yang
/src/sonic-yang-models/ @praveen-li @dgsudharsan @rathnasabapathyv @venkatmahalingam @qiluo-msft
/src/sonic-yang-mgmt/ @Azure/sonic-management
/src/libyang/ @Azure/sonic-management
/src/libyang1/ @Azure/sonic-management
/src/libyang2/ @Azure/sonic-management
# bgpcfgd
/src/sonic-bgpcfgd/ @StormLiangMS
# sonic-config-engine
/src/sonic-config-engine/ @Azure/sonic-management
# sonic-utilities
/src/sonic-utilities/ @Azure/sonic-management
# sonic-telemetry
/src/sonic-telemetry/ @Azure/sonic-management
# snmp
/src/sonic-snmpagent/ @Azure/sonic-management
/src/snmpd/ @Azure/sonic-management
# dhcp relay
/src/dhcp6relay/ @Azure/sonic-fundamentals
/src/dhcpmon/ @Azure/sonic-fundamentals
/src/isc-dhcp/ @Azure/sonic-fundamentals
# sflow
/src/sflow/ @Azure/sonic-dataplane
# sonic restapi
/src/sonic-restapi/ @Azure/sonic-dataplane
# sonic swss
/src/sonic-swss/ @Azure/sonic-dataplane
# linux networking, e.g., libnl3, iproute2, ifupdown2, ethtool
/src/libnl3/ @Azure/sonic-dataplane
/src/iproute2/ @Azure/sonic-dataplane
/src/ifupdown2/ @Azure/sonic-dataplane
/src/ethtool/ @Azure/sonic-dataplane
# ptf
/src/ptf/ @Azure/sonic-fundamentals
/src/ptf-py3/ @Azure/sonic-fundamentals
/src/scapy/ @Azure/sonic-fundamentals

View File

@ -31,6 +31,7 @@
- [ ] 202012
- [ ] 202106
- [ ] 202111
- [ ] 202205
#### Description for the changelog
<!--
@ -38,11 +39,13 @@ Write a short (one line) summary that describes the changes in this
pull request for inclusion in the changelog:
-->
#### Ensure to add label/tag for the feature raised. example - [PR#2174](https://github.com/sonic-net/sonic-utilities/pull/2174) where, Generic Config and Update feature has been labelled as GCU.
#### Link to config_db schema for YANG module changes
<!--
Provide a link to config_db schema for the table for which YANG model
is defined
Link should point to correct section on https://github.com/Azure/SONiC/wiki/Configuration.
Link should point to correct section on https://github.com/Azure/sonic-buildimage/blob/master/src/sonic-yang-models/doc/Configuration.md
-->
#### A picture of a cute animal (not mandatory but encouraged)

View File

@ -15,7 +15,7 @@ jobs:
- name: automerge
uses: 'pascalgn/automerge-action@v0.13.1'
env:
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
GITHUB_TOKEN: '${{ secrets.TOKEN }}'
MERGE_LABELS: 'automerge'
MERGE_METHOD: 'squash'
MERGE_FILTER_AUTHOR: 'mssonicbld'

21
.github/workflows/semgrep.yml vendored Normal file
View File

@ -0,0 +1,21 @@
name: Semgrep
on:
pull_request: {}
push:
branches:
- master
- '201[7-9][0-1][0-9]'
- '202[0-9][0-1][0-9]'
jobs:
semgrep:
name: Semgrep
runs-on: ubuntu-latest
container:
image: returntocorp/semgrep
steps:
- uses: actions/checkout@v3
- run: semgrep ci
env:
SEMGREP_RULES: p/default

3
.gitignore vendored
View File

@ -22,6 +22,9 @@ target/
*.img
*.pyc
# Slave docker log files
sonic-slave*/*.log
# Autogenerated Dockerfiles
sonic-slave*/Dockerfile
sonic-slave*/Dockerfile.user

63
.gitmodules vendored
View File

@ -1,15 +1,15 @@
[submodule "sonic-swss-common"]
path = src/sonic-swss-common
url = https://github.com/Azure/sonic-swss-common
url = https://github.com/sonic-net/sonic-swss-common
[submodule "sonic-linux-kernel"]
path = src/sonic-linux-kernel
url = https://github.com/Azure/sonic-linux-kernel
url = https://github.com/sonic-net/sonic-linux-kernel
[submodule "sonic-sairedis"]
path = src/sonic-sairedis
url = https://github.com/Azure/sonic-sairedis
url = https://github.com/sonic-net/sonic-sairedis
[submodule "sonic-swss"]
path = src/sonic-swss
url = https://github.com/Azure/sonic-swss
url = https://github.com/sonic-net/sonic-swss
[submodule "src/p4c-bm/p4c-bm"]
path = platform/p4/p4c-bm/p4c-bm
url = https://github.com/krambn/p4c-bm
@ -18,35 +18,35 @@
url = https://github.com/p4lang/p4-hlir
[submodule "sonic-dbsyncd"]
path = src/sonic-dbsyncd
url = https://github.com/Azure/sonic-dbsyncd
url = https://github.com/sonic-net/sonic-dbsyncd
[submodule "src/sonic-py-swsssdk"]
path = src/sonic-py-swsssdk
url = https://github.com/Azure/sonic-py-swsssdk.git
url = https://github.com/sonic-net/sonic-py-swsssdk.git
[submodule "src/sonic-snmpagent"]
path = src/sonic-snmpagent
url = https://github.com/Azure/sonic-snmpagent
url = https://github.com/sonic-net/sonic-snmpagent
[submodule "src/ptf"]
path = src/ptf
url = https://github.com/p4lang/ptf.git
[submodule "src/sonic-utilities"]
path = src/sonic-utilities
url = https://github.com/Azure/sonic-utilities
url = https://github.com/sonic-net/sonic-utilities
[submodule "platform/broadcom/sonic-platform-modules-arista"]
path = platform/broadcom/sonic-platform-modules-arista
url = https://github.com/aristanetworks/sonic
[submodule "src/sonic-platform-common"]
path = src/sonic-platform-common
url = https://github.com/Azure/sonic-platform-common
url = https://github.com/sonic-net/sonic-platform-common
[submodule "src/sonic-platform-daemons"]
path = src/sonic-platform-daemons
url = https://github.com/Azure/sonic-platform-daemons
url = https://github.com/sonic-net/sonic-platform-daemons
[submodule "src/sonic-platform-pde"]
path = src/sonic-platform-pde
url = https://github.com/Azure/sonic-platform-pdk-pde
url = https://github.com/sonic-net/sonic-platform-pdk-pde
[submodule "src/sonic-frr/frr"]
path = src/sonic-frr/frr
url = https://github.com/Azure/sonic-frr.git
branch = frr/7.5
url = https://github.com/sonic-net/sonic-frr.git
branch = frr/8.2
[submodule "platform/p4/p4-hlir/p4-hlir-v1.1"]
path = platform/p4/p4-hlir/p4-hlir-v1.1
url = https://github.com/p4lang/p4-hlir.git
@ -62,44 +62,53 @@
[submodule "src/redis-dump-load"]
path = src/redis-dump-load
url = https://github.com/p/redis-dump-load.git
[submodule "src/scapy"]
path = src/scapy
url = https://github.com/secdev/scapy.git
[submodule "platform/mellanox/mlnx-sai/SAI-Implementation"]
path = platform/mellanox/mlnx-sai/SAI-Implementation
url = https://github.com/Mellanox/SAI-Implementation
[submodule "src/sonic-mgmt-framework"]
path = src/sonic-mgmt-framework
url = https://github.com/Azure/sonic-mgmt-framework
[submodule "src/sonic-telemetry"]
path = src/sonic-telemetry
url = https://github.com/Azure/sonic-telemetry
url = https://github.com/sonic-net/sonic-mgmt-framework
[submodule "Switch-SDK-drivers"]
path = platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers
url = https://github.com/Mellanox/Switch-SDK-drivers
[submodule "src/sonic-ztp"]
path = src/sonic-ztp
url = https://github.com/Azure/sonic-ztp
url = https://github.com/sonic-net/sonic-ztp
[submodule "src/sonic-restapi"]
path = src/sonic-restapi
url = https://github.com/Azure/sonic-restapi.git
url = https://github.com/sonic-net/sonic-restapi.git
branch = master
[submodule "src/sonic-mgmt-common"]
path = src/sonic-mgmt-common
url = https://github.com/Azure/sonic-mgmt-common.git
url = https://github.com/sonic-net/sonic-mgmt-common.git
[submodule "src/wpasupplicant/sonic-wpa-supplicant"]
path = src/wpasupplicant/sonic-wpa-supplicant
url = https://github.com/Azure/sonic-wpa-supplicant.git
url = https://github.com/sonic-net/sonic-wpa-supplicant.git
[submodule "platform/broadcom/saibcm-modules-dnx"]
path = platform/broadcom/saibcm-modules-dnx
url = https://github.com/Azure/saibcm-modules.git
url = https://github.com/sonic-net/saibcm-modules.git
branch = sdk-6.5.22-gpl-dnx
[submodule "platform/broadcom/sonic-platform-modules-nokia"]
path = platform/broadcom/sonic-platform-modules-nokia
url = https://github.com/nokia/sonic-platform.git
[submodule "src/linkmgrd"]
path = src/linkmgrd
url = https://github.com/Azure/sonic-linkmgrd.git
url = https://github.com/sonic-net/sonic-linkmgrd.git
[submodule "src/sonic-p4rt/sonic-pins"]
path = src/sonic-p4rt/sonic-pins
url = https://github.com/Azure/sonic-pins.git
[submodule "src/thrift_0_14_1/thrift"]
path = src/thrift_0_14_1/thrift
url = https://github.com/apache/thrift.git
url = https://github.com/sonic-net/sonic-pins.git
[submodule "src/ptf-py3"]
path = src/ptf-py3
url = https://github.com/p4lang/ptf.git
[submodule "src/dhcprelay"]
path = src/dhcprelay
url = https://github.com/sonic-net/sonic-dhcp-relay.git
[submodule "src/sonic-host-services"]
path = src/sonic-host-services
url = https://github.com/sonic-net/sonic-host-services
[submodule "src/sonic-gnmi"]
path = src/sonic-gnmi
url = https://github.com/sonic-net/sonic-gnmi.git

View File

@ -5,6 +5,14 @@ NOSTRETCH ?= 0
NOBUSTER ?= 0
NOBULLSEYE ?= 0
override Q := @
ifeq ($(QUIET),n)
override Q :=
endif
override SONIC_OVERRIDE_BUILD_VARS += $(SONIC_BUILD_VARS)
override SONIC_OVERRIDE_BUILD_VARS += Q=$(Q)
export Q SONIC_OVERRIDE_BUILD_VARS
ifeq ($(NOJESSIE),0)
BUILD_JESSIE=1
endif
@ -29,49 +37,50 @@ PLATFORM_CHECKOUT_CMD := $(shell if [ -f $(PLATFORM_CHECKOUT_FILE) ]; then PLATF
%::
@echo "+++ --- Making $@ --- +++"
ifeq ($(NOJESSIE), 0)
EXTRA_DOCKER_TARGETS=$(notdir $@) make -f Makefile.work jessie
EXTRA_DOCKER_TARGETS=$(notdir $@) $(MAKE) -f Makefile.work jessie
endif
ifeq ($(NOSTRETCH), 0)
EXTRA_DOCKER_TARGETS=$(notdir $@) BLDENV=stretch make -f Makefile.work stretch
EXTRA_DOCKER_TARGETS=$(notdir $@) BLDENV=stretch $(MAKE) -f Makefile.work stretch
endif
ifeq ($(NOBUSTER), 0)
EXTRA_DOCKER_TARGETS=$(notdir $@) BLDENV=buster make -f Makefile.work buster
EXTRA_DOCKER_TARGETS=$(notdir $@) BLDENV=buster $(MAKE) -f Makefile.work buster
endif
ifeq ($(NOBULLSEYE), 0)
BLDENV=bullseye make -f Makefile.work $@
BLDENV=bullseye $(MAKE) -f Makefile.work $@
endif
BLDENV=bullseye $(MAKE) -f Makefile.work docker-cleanup
jessie:
@echo "+++ Making $@ +++"
ifeq ($(NOJESSIE), 0)
make -f Makefile.work jessie
$(MAKE) -f Makefile.work jessie
endif
stretch:
@echo "+++ Making $@ +++"
ifeq ($(NOSTRETCH), 0)
make -f Makefile.work stretch
$(MAKE) -f Makefile.work stretch
endif
buster:
@echo "+++ Making $@ +++"
ifeq ($(NOBUSTER), 0)
make -f Makefile.work buster
$(MAKE) -f Makefile.work buster
endif
init:
@echo "+++ Making $@ +++"
make -f Makefile.work $@
$(MAKE) -f Makefile.work $@
#
# Function to invoke target $@ in Makefile.work with proper BLDENV
#
define make_work
@echo "+++ Making $@ +++"
$(if $(BUILD_JESSIE),make -f Makefile.work $@,)
$(if $(BUILD_STRETCH),BLDENV=stretch make -f Makefile.work $@,)
$(if $(BUILD_BUSTER),BLDENV=buster make -f Makefile.work $@,)
$(if $(BUILD_BULLSEYE),BLDENV=bullseye make -f Makefile.work $@,)
$(if $(BUILD_JESSIE),$(MAKE) -f Makefile.work $@,)
$(if $(BUILD_STRETCH),BLDENV=stretch $(MAKE) -f Makefile.work $@,)
$(if $(BUILD_BUSTER),BLDENV=buster $(MAKE) -f Makefile.work $@,)
$(if $(BUILD_BULLSEYE),BLDENV=bullseye $(MAKE) -f Makefile.work $@,)
endef
.PHONY: $(PLATFORM_PATH)
@ -83,7 +92,7 @@ $(PLATFORM_PATH):
configure : $(PLATFORM_PATH)
$(call make_work, $@)
clean reset showtag sonic-slave-build sonic-slave-bash :
clean reset showtag docker-cleanup sonic-slave-build sonic-slave-bash :
$(call make_work, $@)
# Freeze the versions, see more detail options: scripts/versions_manager.py freeze -h

View File

@ -186,7 +186,7 @@ define GET_MOD_DEP_SHA
$(if $($(1)_DEP_FILES_MISSING), $(warning "[ DPKG ] Dependecy file(s) are not found for $(1) : $($(1)_DEP_FILES_MISSING)))
# Include package dependencies hash values into package hash calculation
$(eval $(1)_DEP_PKGS_SHA := $(foreach dfile,$(1)_MOD_DEP_PKGS,$(dfile)_DEP_MOD_SHA $(dfile)_MOD_HASH))
$(eval $(1)_DEP_PKGS_SHA := $(foreach dfile,$($(1)_MOD_DEP_PKGS),$($(dfile)_DEP_MOD_SHA) $($(dfile)_MOD_HASH)))
$(eval $(1)_DEP_MOD_SHA := $(shell bash -c "git hash-object $($(1)_DEP_MOD_SHA_FILES) && echo $($(1)_DEP_PKGS_SHA)" \
| sha1sum | awk '{print substr($$1,0,23);}'))
@ -561,6 +561,12 @@ define SHA_DEP_RULES
ALL_DEP_FILES_LIST += $(foreach pkg,$(2), $($(filter none,$($(1)_CACHE_MODE)), \
$(addsuffix .$(3),$(addprefix $(pkg)/, $(1))) \
$(addsuffix .$(3).sha,$(addprefix $(pkg)/, $(1)))))
$(foreach docker, $(filter $(SONIC_DOCKER_IMAGES), $(1)), \
$(eval $(docker)_DEP_FILES+=$(wildcard files/build/versions/default/*) \
$(wildcard files/build/versions/dockers/$(basename $(docker))/*)))
$(foreach docker, $(filter $(SONIC_DOCKER_DBG_IMAGES), $(1)), \
$(eval $(docker)_DEP_FILES+=$(wildcard files/build/versions/default/*) \
$(wildcard files/build/versions/dockers/$(patsubst %-$(DBG_IMAGE_MARK).gz,%,$(docker))/*)))
$(addsuffix .$(3),$(addprefix $(2)/, $(1))) : $(2)/%.$(3) : \
$(2)/%.flags $$$$($$$$*_DEP_FILES) $$$$(if $$$$($$$$*_SMDEP_FILES), $(2)/%.smdep)
@$$(eval $$*_DEP_FILES_MODIFIED := $$? )

View File

@ -10,6 +10,7 @@
# * ENABLE_ZTP: Enables zero touch provisioning.
# * SHUTDOWN_BGP_ON_START: Sets admin-down state for all bgp peerings after restart.
# * INCLUDE_KUBERNETES: Allows including Kubernetes
# * INCLUDE_KUBERNETES_MASTER: Allows including Kubernetes master
# * INCLUDE_MUX: Include MUX feature/services for TOR switch.
# * ENABLE_PFCWD_ON_START: Enable PFC Watchdog (PFCWD) on server-facing ports
# * by default for TOR switch.
@ -33,7 +34,7 @@
# * Default: yes
# * Values: yes, no
# * KERNEL_PROCURE_METHOD: Specifying method of obtaining kernel Debian package: download or build
# * TELEMETRY_WRITABLE: Enable write/config operations via the gNMI interface.
# * ENABLE_TRANSLIB_WRITE: Enable translib write/config operations via the gNMI interface.
# * Default: unset
# * Values: y
# * SONIC_DPKG_CACHE_METHOD: Specifying method of obtaining the Debian packages from cache: none or cache
@ -43,6 +44,12 @@
# * ENABLE_AUTO_TECH_SUPPORT: Enable the configuration for event-driven techsupport & coredump mgmt feature
# * Default: y
# * Values: y,n
# * INCLUDE_BOOTCHART: Install SONiC bootchart
# * Default: y
# * Values: y,n
# * ENABLE_BOOTCHART: Enable SONiC bootchart
# * Default: n
# * Values: y,n
#
###############################################################################
@ -90,6 +97,7 @@ $(shell rm -f .screen)
MAKEFLAGS += -B
CONFIGURED_ARCH := $(shell [ -f .arch ] && cat .arch || echo $(PLATFORM_ARCH))
CONFIGURED_PLATFORM = $(if $(PLATFORM),$(PLATFORM),$(shell cat .platform 2>/dev/null))
ifeq ($(CONFIGURED_ARCH),)
override CONFIGURED_ARCH = amd64
endif
@ -97,6 +105,12 @@ ifeq ($(PLATFORM_ARCH),)
override PLATFORM_ARCH = $(CONFIGURED_ARCH)
endif
ifeq ($(CONFIGURED_ARCH),amd64)
TARGET_BOOTLOADER = grub
else
TARGET_BOOTLOADER = uboot
endif
ifeq ($(BLDENV), bullseye)
SLAVE_DIR = sonic-slave-bullseye
else ifeq ($(BLDENV), buster)
@ -110,11 +124,15 @@ endif
# Define a do-nothing target for rules/config.user so that when
# the file is missing, make won't try to rebuld everything.
rules/config.user:
@echo -n ""
$(Q)echo -n ""
include rules/config
-include rules/config.user
ifneq ($(DEFAULT_CONTAINER_REGISTRY),)
override DEFAULT_CONTAINER_REGISTRY := $(DEFAULT_CONTAINER_REGISTRY)/
endif
ifeq ($(ENABLE_DOCKER_BASE_PULL),)
override ENABLE_DOCKER_BASE_PULL = n
endif
@ -122,31 +140,92 @@ endif
ifeq ($(CONFIGURED_ARCH),amd64)
SLAVE_BASE_IMAGE = $(SLAVE_DIR)
MULTIARCH_QEMU_ENVIRON = n
CROSS_BUILD_ENVIRON = n
else
ifeq ($(CONFIGURED_ARCH), $(COMPILE_HOST_ARCH))
SLAVE_BASE_IMAGE = $(SLAVE_DIR)
MULTIARCH_QEMU_ENVIRON = n
CROSS_BUILD_ENVIRON = n
else ifneq ($(CONFIGURED_ARCH),)
SLAVE_BASE_IMAGE = $(SLAVE_DIR)-march-$(CONFIGURED_ARCH)
ifneq ($(CROSS_BLDENV),)
MULTIARCH_QEMU_ENVIRON = n
CROSS_BUILD_ENVIRON = y
else
MULTIARCH_QEMU_ENVIRON = y
CROSS_BUILD_ENVIRON = n
endif
endif
endif
SLAVE_IMAGE = $(SLAVE_BASE_IMAGE)-$(USER_LC)
DOCKER_ROOT = $(PWD)/fsroot.docker.$(BLDENV)
# Support FIPS feature, armhf not supported yet
ifeq ($(PLATFORM_ARCH),armhf)
ENABLE_FIPS_FEATURE := n
ENABLE_FIPS := n
endif
ifeq ($(ENABLE_FIPS_FEATURE), n)
ifeq ($(ENABLE_FIPS), y)
$(error Cannot set fips config ENABLE_FIPS=y when ENABLE_FIPS_FEATURE=n)
endif
endif
# Generate the version control build info
$(shell SONIC_VERSION_CONTROL_COMPONENTS=$(SONIC_VERSION_CONTROL_COMPONENTS) \
TRUSTED_GPG_URLS=$(TRUSTED_GPG_URLS) PACKAGE_URL_PREFIX=$(PACKAGE_URL_PREFIX) \
scripts/generate_buildinfo_config.sh)
$(shell \
SONIC_VERSION_CONTROL_COMPONENTS=$(SONIC_VERSION_CONTROL_COMPONENTS) \
TRUSTED_GPG_URLS=$(TRUSTED_GPG_URLS) \
PACKAGE_URL_PREFIX=$(PACKAGE_URL_PREFIX) \
scripts/generate_buildinfo_config.sh)
# Generate the slave Dockerfile, and prepare build info for it
$(shell CONFIGURED_ARCH=$(CONFIGURED_ARCH) MULTIARCH_QEMU_ENVIRON=$(MULTIARCH_QEMU_ENVIRON) DOCKER_EXTRA_OPTS=$(DOCKER_EXTRA_OPTS) j2 $(SLAVE_DIR)/Dockerfile.j2 > $(SLAVE_DIR)/Dockerfile)
$(shell CONFIGURED_ARCH=$(CONFIGURED_ARCH) MULTIARCH_QEMU_ENVIRON=$(MULTIARCH_QEMU_ENVIRON) j2 $(SLAVE_DIR)/Dockerfile.user.j2 > $(SLAVE_DIR)/Dockerfile.user)
$(shell BUILD_SLAVE=y scripts/prepare_docker_buildinfo.sh $(SLAVE_BASE_IMAGE) $(SLAVE_DIR)/Dockerfile $(CONFIGURED_ARCH) "" $(BLDENV))
$(shell CONFIGURED_ARCH=$(CONFIGURED_ARCH) \
MULTIARCH_QEMU_ENVIRON=$(MULTIARCH_QEMU_ENVIRON) \
CROSS_BUILD_ENVIRON=$(CROSS_BUILD_ENVIRON) \
ENABLE_FIPS_FEATURE=$(ENABLE_FIPS_FEATURE) \
DOCKER_EXTRA_OPTS=$(DOCKER_EXTRA_OPTS) \
DEFAULT_CONTAINER_REGISTRY=$(DEFAULT_CONTAINER_REGISTRY) \
j2 $(SLAVE_DIR)/Dockerfile.j2 > $(SLAVE_DIR)/Dockerfile)
$(shell CONFIGURED_ARCH=$(CONFIGURED_ARCH) \
MULTIARCH_QEMU_ENVIRON=$(MULTIARCH_QEMU_ENVIRON) \
CROSS_BUILD_ENVIRON=$(CROSS_BUILD_ENVIRON) \
j2 $(SLAVE_DIR)/Dockerfile.user.j2 > $(SLAVE_DIR)/Dockerfile.user)
PREPARE_DOCKER=BUILD_SLAVE=y \
DEFAULT_CONTAINER_REGISTRY=$(DEFAULT_CONTAINER_REGISTRY) \
scripts/prepare_docker_buildinfo.sh \
$(SLAVE_BASE_IMAGE) \
$(SLAVE_DIR)/Dockerfile \
$(CONFIGURED_ARCH) \
"" \
$(BLDENV)
$(shell $(PREPARE_DOCKER) )
# Add the versions in the tag, if the version change, need to rebuild the slave
SLAVE_BASE_TAG = $(shell cat $(SLAVE_DIR)/Dockerfile $(SLAVE_DIR)/buildinfo/versions/versions-* src/sonic-build-hooks/hooks/* | sha1sum | awk '{print substr($$1,0,11);}')
SLAVE_TAG = $(shell cat $(SLAVE_DIR)/Dockerfile.user $(SLAVE_DIR)/Dockerfile $(SLAVE_DIR)/buildinfo/versions/versions-* | sha1sum | awk '{print substr($$1,0,11);}')
SLAVE_BASE_TAG = $(shell \
cat $(SLAVE_DIR)/Dockerfile \
$(SLAVE_DIR)/buildinfo/versions/versions-* \
src/sonic-build-hooks/hooks/* 2>/dev/null \
| sha1sum \
| awk '{print substr($$1,0,11);}')
# Calculate the slave TAG based on $(USER)/$(PWD)/$(CONFIGURED_PLATFORM) to get unique SHA ID
SLAVE_TAG = $(shell \
(cat $(SLAVE_DIR)/Dockerfile.user \
$(SLAVE_DIR)/Dockerfile \
$(SLAVE_DIR)/buildinfo/versions/versions-* \
.git/HEAD \
&& echo $(USER)/$(PWD)/$(CONFIGURED_PLATFORM)) \
| sha1sum \
| awk '{print substr($$1,0,11);}')
COLLECT_DOCKER=DEFAULT_CONTAINER_REGISTRY=$(DEFAULT_CONTAINER_REGISTRY) \
scripts/collect_docker_version_files.sh \
$(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) \
target
OVERLAY_MODULE_CHECK := \
lsmod | grep -q "^overlay " &>/dev/null || \
zgrep -q 'CONFIG_OVERLAY_FS=y' /proc/config.gz &>/dev/null || \
@ -155,6 +234,16 @@ OVERLAY_MODULE_CHECK := \
BUILD_TIMESTAMP := $(shell date +%Y%m%d\.%H%M%S)
# Create separate Docker lockfiles for saving vs. loading an image.
ifeq ($(DOCKER_LOCKDIR),)
override DOCKER_LOCKDIR := /tmp/docklock
endif
DOCKER_LOCKFILE_SAVE := $(DOCKER_LOCKDIR)/docker_save.lock
$(shell mkdir -m 0777 -p $(DOCKER_LOCKDIR))
$(shell [ -f $(DOCKER_LOCKFILE_SAVE) ] || (touch $(DOCKER_LOCKFILE_SAVE) && chmod 0777 $(DOCKER_LOCKFILE_SAVE)))
$(docker run --rm -v $(DOCKER_ROOT)\:/mount alpine sh -c 'rm -rf /mount/')
$(mkdir -p $(DOCKER_ROOT))
ifeq ($(DOCKER_BUILDER_MOUNT),)
override DOCKER_BUILDER_MOUNT := "$(PWD):/sonic"
endif
@ -165,6 +254,7 @@ endif
DOCKER_RUN := docker run --rm=true --privileged --init \
-v $(DOCKER_BUILDER_MOUNT) \
-v "$(DOCKER_LOCKDIR):$(DOCKER_LOCKDIR)" \
-w $(DOCKER_BUILDER_WORKDIR) \
-e "http_proxy=$(http_proxy)" \
-e "https_proxy=$(https_proxy)" \
@ -172,6 +262,11 @@ DOCKER_RUN := docker run --rm=true --privileged --init \
-i$(shell { if [ -t 0 ]; then echo t; fi }) \
$(SONIC_BUILDER_EXTRA_CMDLINE)
# Mount the $(DOCKER_ROOT) to /var/lib/docker in the slave container, the overlay fs is not supported as dockerd root folder.
ifneq ($(filter $(SONIC_SLAVE_DOCKER_DRIVER),overlay overlay2),)
DOCKER_RUN += -v $(DOCKER_ROOT):/var/lib/docker
endif
ifneq ($(DOCKER_BUILDER_USER_MOUNT),)
DOCKER_RUN += $(foreach mount,$(subst $(comma), ,$(DOCKER_BUILDER_USER_MOUNT)), $(addprefix -v , $(mount)))
endif
@ -184,13 +279,48 @@ ifneq ($(SONIC_DPKG_CACHE_SOURCE),)
DOCKER_RUN += -v "$(SONIC_DPKG_CACHE_SOURCE):/dpkg_cache:rw"
endif
ifeq ($(SONIC_ENABLE_SECUREBOOT_SIGNATURE), y)
ifneq ($(SIGNING_KEY),)
DOCKER_SIGNING_SOURCE := $(shell dirname $(SIGNING_KEY))
DOCKER_RUN += -v "$(DOCKER_SIGNING_SOURCE):$(DOCKER_SIGNING_SOURCE):ro"
endif
ifneq ($(SIGNING_CERT),)
DOCKER_SIGNING_SOURCE := $(shell dirname $(SIGNING_CERT))
DOCKER_RUN += -v "$(DOCKER_SIGNING_SOURCE):$(DOCKER_SIGNING_SOURCE):ro"
endif
endif
# User name and tag for "docker-*" images created by native dockerd mode.
ifeq ($(strip $(SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD)),y)
DOCKER_USERNAME = $(USER_LC)
DOCKER_USERTAG = $(SLAVE_TAG)
else
DOCKER_USERNAME = sonic
DOCKER_USERTAG = latest
endif
# Define canned sequence to clean up Docker image cache.
# - These are the remnants from building the runtime Docker images using native (host) Docker daemon.
# - Image naming convention differs on a shared build system vs. non-shared.
# $(docker-image-cleanup)
ifeq ($(SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD),y)
define docker-image-cleanup
@for i in $(shell docker images --quiet --filter 'dangling=true') ; do (docker rmi -f $$i &> /dev/null || true) ; done
@for i in $(shell docker images --quiet docker-*$(DOCKER_USERNAME):$(DOCKER_USERTAG)) ; do (docker rmi -f $$i &> /dev/null || true) ; done
endef
else
define docker-image-cleanup
@:
endef
endif
ifeq ($(SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD), y)
ifneq ($(MULTIARCH_QEMU_ENVIRON), y)
DOCKER_RUN += -v /var/run/docker.sock:/var/run/docker.sock
endif
endif
ifeq ($(MULTIARCH_QEMU_ENVIRON), y)
ifneq ($(filter y, $(MULTIARCH_QEMU_ENVIRON) $(CROSS_BUILD_ENVIRON)),)
ifeq ($(DOCKER_DATA_ROOT_FOR_MULTIARCH),)
DOCKER_DATA_ROOT_FOR_MULTIARCH := /var/lib/march/docker
endif
@ -231,17 +361,23 @@ endif
endif
DOCKER_BASE_BUILD = docker build --no-cache \
SPLIT_LOG = | tee
DOCKER_BASE_LOG = $(SLAVE_DIR)/$(SLAVE_BASE_IMAGE)_$(SLAVE_BASE_TAG).log
DOCKER_LOG = $(SLAVE_DIR)/$(SLAVE_IMAGE)_$(SLAVE_TAG).log
DOCKER_SLAVE_BASE_BUILD = docker build --no-cache \
-t $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) \
--build-arg http_proxy=$(http_proxy) \
--build-arg https_proxy=$(https_proxy) \
--build-arg no_proxy=$(no_proxy) \
$(SLAVE_DIR)
$(SLAVE_DIR) $(SPLIT_LOG) $(DOCKER_BASE_LOG)
DOCKER_BASE_PULL = docker pull \
$(REGISTRY_SERVER):$(REGISTRY_PORT)/$(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG)
DOCKER_BUILD = docker build --no-cache \
DOCKER_USER_BUILD = docker build --no-cache \
--build-arg user=$(USER) \
--build-arg uid=$(shell id -u) \
--build-arg guid=$(shell id -g) \
@ -249,16 +385,64 @@ DOCKER_BUILD = docker build --no-cache \
--build-arg slave_base_tag_ref=$(SLAVE_BASE_TAG) \
-t $(SLAVE_IMAGE):$(SLAVE_TAG) \
-f $(SLAVE_DIR)/Dockerfile.user \
$(SLAVE_DIR)
$(SLAVE_DIR) $(SPLIT_LOG) $(DOCKER_LOG)
SONIC_BUILD_INSTRUCTION := make \
DOCKER_SLAVE_BASE_INSPECT = \
{ \
echo Checking sonic-slave-base image: $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG); \
docker inspect --type image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) &> /dev/null; \
}
DOCKER_SLAVE_BASE_PULL_REGISTRY = \
[ $(ENABLE_DOCKER_BASE_PULL) == y ] && \
{ \
echo Image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) not found. Pulling...; \
$(DOCKER_BASE_PULL); \
} && \
{ \
docker tag $(REGISTRY_SERVER):$(REGISTRY_PORT)/$(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) && \
$(COLLECT_DOCKER); \
}\
SONIC_SLAVE_BASE_BUILD = \
{ \
$(DOCKER_SLAVE_BASE_INSPECT); \
} || \
{ \
$(DOCKER_SLAVE_BASE_PULL_REGISTRY); \
} || \
{ \
echo Image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) not found. Building... ; \
$(PREPARE_DOCKER) ; \
$(DOCKER_SLAVE_BASE_BUILD) ; \
$(COLLECT_DOCKER) ; \
}
DOCKER_SLAVE_USER_INSPECT = \
{ \
echo Checking sonic-slave-user image: $(SLAVE_IMAGE):$(SLAVE_TAG); \
docker inspect --type image $(SLAVE_IMAGE):$(SLAVE_TAG) &> /dev/null; \
}
SONIC_SLAVE_USER_BUILD = \
{ $(DOCKER_SLAVE_USER_INSPECT) } || \
{ \
echo Image $(SLAVE_IMAGE):$(SLAVE_TAG) not found. Building... ; \
$(DOCKER_USER_BUILD) ; \
}
SONIC_BUILD_INSTRUCTION := $(MAKE) \
-f slave.mk \
PLATFORM=$(PLATFORM) \
PLATFORM_ARCH=$(PLATFORM_ARCH) \
MULTIARCH_QEMU_ENVIRON=$(MULTIARCH_QEMU_ENVIRON) \
TARGET_BOOTLOADER=$(TARGET_BOOTLOADER) \
CROSS_BUILD_ENVIRON=$(CROSS_BUILD_ENVIRON) \
BUILD_NUMBER=$(BUILD_NUMBER) \
BUILD_TIMESTAMP=$(BUILD_TIMESTAMP) \
SONIC_IMAGE_VERSION=$(SONIC_IMAGE_VERSION) \
SLAVE_TAG=$(SLAVE_TAG) \
ENABLE_DHCP_GRAPH_SERVICE=$(ENABLE_DHCP_GRAPH_SERVICE) \
ENABLE_ZTP=$(ENABLE_ZTP) \
INCLUDE_PDE=$(INCLUDE_PDE) \
@ -267,6 +451,7 @@ SONIC_BUILD_INSTRUCTION := make \
KUBERNETES_VERSION=$(KUBERNETES_VERSION) \
KUBERNETES_CNI_VERSION=$(KUBERNETES_CNI_VERSION) \
K8s_GCR_IO_PAUSE_VERSION=$(K8s_GCR_IO_PAUSE_VERSION) \
INCLUDE_KUBERNETES_MASTER=$(INCLUDE_KUBERNETES_MASTER) \
SONIC_ENABLE_PFCWD_ON_START=$(ENABLE_PFCWD_ON_START) \
SONIC_ENABLE_SYNCD_RPC=$(ENABLE_SYNCD_RPC) \
SONIC_INSTALL_DEBUG_TOOLS=$(INSTALL_DEBUG_TOOLS) \
@ -283,104 +468,108 @@ SONIC_BUILD_INSTRUCTION := make \
HTTP_PROXY=$(http_proxy) \
HTTPS_PROXY=$(https_proxy) \
NO_PROXY=$(no_proxy) \
DOCKER_USERNAME=$(DOCKER_USERNAME) \
DOCKER_USERTAG=$(DOCKER_USERTAG) \
DOCKER_LOCKDIR=$(DOCKER_LOCKDIR) \
DOCKER_LOCKFILE_SAVE=$(DOCKER_LOCKFILE_SAVE) \
SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD=$(SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD) \
SONIC_INCLUDE_SYSTEM_TELEMETRY=$(INCLUDE_SYSTEM_TELEMETRY) \
INCLUDE_DHCP_RELAY=$(INCLUDE_DHCP_RELAY) \
INCLUDE_MACSEC=$(INCLUDE_MACSEC) \
SONIC_INCLUDE_RESTAPI=$(INCLUDE_RESTAPI) \
SONIC_INCLUDE_MUX=$(INCLUDE_MUX) \
TELEMETRY_WRITABLE=$(TELEMETRY_WRITABLE) \
ENABLE_TRANSLIB_WRITE=$(ENABLE_TRANSLIB_WRITE) \
EXTRA_DOCKER_TARGETS=$(EXTRA_DOCKER_TARGETS) \
BUILD_LOG_TIMESTAMP=$(BUILD_LOG_TIMESTAMP) \
SONIC_ENABLE_IMAGE_SIGNATURE=$(ENABLE_IMAGE_SIGNATURE) \
SONIC_ENABLE_SECUREBOOT_SIGNATURE=$(SONIC_ENABLE_SECUREBOOT_SIGNATURE) \
SONIC_DEFAULT_CONTAINER_REGISTRY=$(DEFAULT_CONTAINER_REGISTRY) \
ENABLE_HOST_SERVICE_ON_START=$(ENABLE_HOST_SERVICE_ON_START) \
SLAVE_DIR=$(SLAVE_DIR) \
ENABLE_AUTO_TECH_SUPPORT=$(ENABLE_AUTO_TECH_SUPPORT) \
BUILD_MULTIASIC_KVM=$(BUILD_MULTIASIC_KVM) \
ENABLE_ASAN=$(ENABLE_ASAN) \
SONIC_INCLUDE_BOOTCHART=$(INCLUDE_BOOTCHART) \
SONIC_ENABLE_BOOTCHART=$(ENABLE_BOOTCHART) \
ENABLE_FIPS_FEATURE=$(ENABLE_FIPS_FEATURE) \
ENABLE_FIPS=$(ENABLE_FIPS) \
SONIC_SLAVE_DOCKER_DRIVER=$(SONIC_SLAVE_DOCKER_DRIVER) \
$(SONIC_OVERRIDE_BUILD_VARS)
.PHONY: sonic-slave-build sonic-slave-bash init reset
ifeq ($(filter clean,$(MAKECMDGOALS)),)
COLLECT_BUILD_VERSION = { DBGOPT='$(DBGOPT)' scripts/collect_build_version_files.sh $$?; }
endif
ifdef SOURCE_FOLDER
DOCKER_RUN += -v $(SOURCE_FOLDER):/var/$(USER)/src
endif
ifeq "$(KEEP_SLAVE_ON)" "yes"
SLAVE_SHELL={ /bin/bash; }
endif
.DEFAULT_GOAL := all
%::
ifeq ($(MULTIARCH_QEMU_ENVIRON), y)
@$(DOCKER_MULTIARCH_CHECK)
%:: | sonic-build-hooks
ifneq ($(filter y, $(MULTIARCH_QEMU_ENVIRON) $(CROSS_BUILD_ENVIRON)),)
$(Q)$(DOCKER_MULTIARCH_CHECK)
ifneq ($(BLDENV), )
@$(DOCKER_SERVICE_MULTIARCH_CHECK)
@$(DOCKER_SERVICE_DOCKERFS_CHECK)
$(Q)$(DOCKER_SERVICE_MULTIARCH_CHECK)
$(Q)$(DOCKER_SERVICE_DOCKERFS_CHECK)
endif
endif
@$(OVERLAY_MODULE_CHECK)
$(Q)$(OVERLAY_MODULE_CHECK)
$(Q)$(SONIC_SLAVE_BASE_BUILD)
$(Q)$(SONIC_SLAVE_USER_BUILD)
@pushd src/sonic-build-hooks; TRUSTED_GPG_URLS=$(TRUSTED_GPG_URLS) make all; popd
@cp src/sonic-build-hooks/buildinfo/sonic-build-hooks* $(SLAVE_DIR)/buildinfo
@docker inspect --type image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) &> /dev/null || \
{ [ $(ENABLE_DOCKER_BASE_PULL) == y ] && { echo Image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) not found. Pulling...; } && \
$(DOCKER_BASE_PULL) && \
{ docker tag $(REGISTRY_SERVER):$(REGISTRY_PORT)/$(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) && \
scripts/collect_docker_version_files.sh $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) target ; } } || \
{ echo Image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) not found. Building... ; \
$(DOCKER_BASE_BUILD) ; \
scripts/collect_docker_version_files.sh $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) target ; }
@docker inspect --type image $(SLAVE_IMAGE):$(SLAVE_TAG) &> /dev/null || \
{ echo Image $(SLAVE_IMAGE):$(SLAVE_TAG) not found. Building... ; \
$(DOCKER_BUILD) ; }
ifeq "$(KEEP_SLAVE_ON)" "yes"
ifdef SOURCE_FOLDER
@$(DOCKER_RUN) -v $(SOURCE_FOLDER):/var/$(USER)/src $(SLAVE_IMAGE):$(SLAVE_TAG) bash -c "$(SONIC_BUILD_INSTRUCTION) $@; scripts/collect_build_version_files.sh \$$?; /bin/bash"
else
@$(DOCKER_RUN) $(SLAVE_IMAGE):$(SLAVE_TAG) bash -c "$(SONIC_BUILD_INSTRUCTION) $@; scripts/collect_build_version_files.sh \$$?; /bin/bash"
endif
else
@$(DOCKER_RUN) $(SLAVE_IMAGE):$(SLAVE_TAG) bash -c "$(SONIC_BUILD_INSTRUCTION) $@; scripts/collect_build_version_files.sh \$$?"
endif
$(Q)$(DOCKER_RUN) \
$(SLAVE_IMAGE):$(SLAVE_TAG) \
bash -c "$(SONIC_BUILD_INSTRUCTION) $@;$(COLLECT_BUILD_VERSION); $(SLAVE_SHELL)"
$(Q)$(docker-image-cleanup)
docker-cleanup:
$(Q)$(docker-image-cleanup)
.PHONY: sonic-build-hooks
sonic-build-hooks:
@pushd src/sonic-build-hooks; TRUSTED_GPG_URLS=$(TRUSTED_GPG_URLS) make all; popd
@cp src/sonic-build-hooks/buildinfo/sonic-build-hooks* $(SLAVE_DIR)/buildinfo
$(Q)pushd src/sonic-build-hooks; TRUSTED_GPG_URLS=$(TRUSTED_GPG_URLS) $(MAKE) all; popd
$(Q)mkdir -p $(SLAVE_DIR)/buildinfo
$(Q)cp src/sonic-build-hooks/buildinfo/sonic-build-hooks* $(SLAVE_DIR)/buildinfo
sonic-slave-base-build : sonic-build-hooks
sonic-slave-base-build : | sonic-build-hooks
ifeq ($(MULTIARCH_QEMU_ENVIRON), y)
@$(DOCKER_MULTIARCH_CHECK)
$(Q)$(DOCKER_MULTIARCH_CHECK)
endif
@$(OVERLAY_MODULE_CHECK)
@echo Checking sonic-slave-base image: $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG)
@docker inspect --type image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) &> /dev/null || \
{ [ $(ENABLE_DOCKER_BASE_PULL) == y ] && { echo Image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) not found. Pulling...; } && \
$(DOCKER_BASE_PULL) && \
{ docker tag $(REGISTRY_SERVER):$(REGISTRY_PORT)/$(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) && \
scripts/collect_docker_version_files.sh $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) target ; } } || \
{ echo Image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) not found. Building... ; \
$(DOCKER_BASE_BUILD) ; \
scripts/collect_docker_version_files.sh $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) target ; }
$(Q)$(OVERLAY_MODULE_CHECK)
$(Q)$(SONIC_SLAVE_BASE_BUILD)
sonic-slave-build : sonic-slave-base-build
@echo Checking sonic-slave image: $(SLAVE_IMAGE):$(SLAVE_TAG)
@docker inspect --type image $(SLAVE_IMAGE):$(SLAVE_TAG) &> /dev/null || \
{ echo Image $(SLAVE_IMAGE):$(SLAVE_TAG) not found. Building... ; \
$(DOCKER_BUILD) ; }
$(Q)$(SONIC_SLAVE_USER_BUILD)
sonic-slave-bash : sonic-slave-build
@$(DOCKER_RUN) -t $(SLAVE_IMAGE):$(SLAVE_TAG) bash
$(Q)$(DOCKER_RUN) -t $(SLAVE_IMAGE):$(SLAVE_TAG) bash
sonic-slave-run : sonic-slave-build
@$(DOCKER_RUN) $(SLAVE_IMAGE):$(SLAVE_TAG) bash -c "$(SONIC_RUN_CMDS)"
$(Q)$(DOCKER_RUN) $(SLAVE_IMAGE):$(SLAVE_TAG) bash -c "$(SONIC_RUN_CMDS)"
showtag:
@echo $(SLAVE_IMAGE):$(SLAVE_TAG)
@echo $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG)
$(Q)echo $(SLAVE_IMAGE):$(SLAVE_TAG)
$(Q)echo $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG)
init :
@git submodule update --init --recursive
@git submodule foreach --recursive '[ -f .git ] && echo "gitdir: $$(realpath --relative-to=. $$(cut -d" " -f2 .git))" > .git'
$(Q)git submodule update --init --recursive
$(Q)git submodule foreach --recursive '[ -f .git ] && echo "gitdir: $$(realpath --relative-to=. $$(cut -d" " -f2 .git))" > .git'
.ONESHELL : reset
reset :
@echo && echo -n "Warning! All local changes will be lost. Proceed? [y/N]: "
@read ans && (
$(Q)echo && echo -n "Warning! All local changes will be lost. Proceed? [y/N]: "
$(Q)read ans && (
if [ $$ans == y ]; then
echo "Resetting local repository. Please wait...";
$(DOCKER_RUN) $(SLAVE_IMAGE):$(SLAVE_TAG) sudo rm -rf fsroot;
sudo rm -rf fsroot*;
if [ "$(MULTIARCH_QEMU_ENVIRON)" == y ] && [[ "$(CONFIGURED_ARCH)" == "armhf" || "$(CONFIGURED_ARCH)" == "arm64" ]]; then
echo "Stopping march $(CONFIGURED_ARCH) docker"
sudo kill -9 `sudo cat /var/run/march/docker.pid` || true

View File

@ -14,9 +14,32 @@
[![Mellanox](https://dev.azure.com/mssonic/build/_apis/build/status/mellanox/Azure.sonic-buildimage.official.mellanox?branchName=master&label=Mellanox)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=139&branchName=master)
[![Marvell(armhf)](https://dev.azure.com/mssonic/build/_apis/build/status/marvell/Azure.sonic-buildimage.official.marvell-armhf?branchName=master&label=Marvell-armhf)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=141&branchName=master)
[![Nephos](https://dev.azure.com/mssonic/build/_apis/build/status/nephos/Azure.sonic-buildimage.official.nephos?branchName=master&label=Nephos)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=149&branchName=master)
[![P4](https://sonic-jenkins.westus2.cloudapp.azure.com/job/p4/job/buildimage-p4-all/badge/icon?subject=P4)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/p4/job/buildimage-p4-all)
[![VS](https://dev.azure.com/mssonic/build/_apis/build/status/vs/Azure.sonic-buildimage.official.vs?branchName=master&label=VS)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=142&branchName=master)
*202205 builds*:
[![Barefoot](https://dev.azure.com/mssonic/build/_apis/build/status/barefoot/Azure.sonic-buildimage.official.barefoot?branchName=202205&label=Barefoot)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=146&branchName=202205)
[![Broadcom](https://dev.azure.com/mssonic/build/_apis/build/status/broadcom/Azure.sonic-buildimage.official.broadcom?branchName=202205&label=Broadcom)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=138&branchName=202205)
[![Centec](https://dev.azure.com/mssonic/build/_apis/build/status/centec/Azure.sonic-buildimage.official.centec?branchName=202205&label=Centec)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=143&branchName=202205)
[![Centec(arm64)](https://dev.azure.com/mssonic/build/_apis/build/status/centec/Azure.sonic-buildimage.official.centec-arm64?branchName=202205&label=Centec-arm64)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=140&branchName=202205)
[![Innovium](https://dev.azure.com/mssonic/build/_apis/build/status/innovium/Azure.sonic-buildimage.official.innovium?branchName=202205&label=Innovium)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=148&branchName=202205)
[![Mellanox](https://dev.azure.com/mssonic/build/_apis/build/status/mellanox/Azure.sonic-buildimage.official.mellanox?branchName=202205&label=Mellanox)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=139&branchName=202205)
[![Marvell(armhf)](https://dev.azure.com/mssonic/build/_apis/build/status/marvell/Azure.sonic-buildimage.official.marvell-armhf?branchName=202205&label=Marvell-armhf)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=141&branchName=202205)
[![Nephos](https://dev.azure.com/mssonic/build/_apis/build/status/nephos/Azure.sonic-buildimage.official.nephos?branchName=202205&label=Nephos)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=149&branchName=202205)
[![VS](https://dev.azure.com/mssonic/build/_apis/build/status/vs/Azure.sonic-buildimage.official.vs?branchName=202205&label=VS)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=142&branchName=202205)
*202111 builds*
[![Barefoot](https://dev.azure.com/mssonic/build/_apis/build/status/barefoot/Azure.sonic-buildimage.official.barefoot?branchName=202111&label=Barefoot)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=146&branchName=202111)
[![Broadcom](https://dev.azure.com/mssonic/build/_apis/build/status/broadcom/Azure.sonic-buildimage.official.broadcom?branchName=202111&label=Broadcom)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=138&branchName=202111)
[![Centec](https://dev.azure.com/mssonic/build/_apis/build/status/centec/Azure.sonic-buildimage.official.centec?branchName=202111&label=Centec)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=143&branchName=202111)
[![Centec(arm64)](https://dev.azure.com/mssonic/build/_apis/build/status/centec/Azure.sonic-buildimage.official.centec-arm64?branchName=202111&label=Centec-arm64)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=140&branchName=202111)
[![Innovium](https://dev.azure.com/mssonic/build/_apis/build/status/innovium/Azure.sonic-buildimage.official.innovium?branchName=202111&label=Innovium)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=148&branchName=202111)
[![Mellanox](https://dev.azure.com/mssonic/build/_apis/build/status/mellanox/Azure.sonic-buildimage.official.mellanox?branchName=202111&label=Mellanox)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=139&branchName=202111)
[![Marvell(armhf)](https://dev.azure.com/mssonic/build/_apis/build/status/marvell/Azure.sonic-buildimage.official.marvell-armhf?branchName=202111&label=Marvell-armhf)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=141&branchName=202111)
[![Nephos](https://dev.azure.com/mssonic/build/_apis/build/status/nephos/Azure.sonic-buildimage.official.nephos?branchName=202111&label=Nephos)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=149&branchName=202111)
[![VS](https://dev.azure.com/mssonic/build/_apis/build/status/vs/Azure.sonic-buildimage.official.vs?branchName=202111&label=VS)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=142&branchName=202111)
*202012 builds*:
[![Barefoot](https://dev.azure.com/mssonic/build/_apis/build/status/barefoot/Azure.sonic-buildimage.official.barefoot?branchName=202012&label=Barefoot)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=146&branchName=202012)
@ -46,25 +69,13 @@
[![Nephos](https://dev.azure.com/mssonic/build/_apis/build/status/nephos/Azure.sonic-buildimage.official.nephos?branchName=201811&label=Nephos)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=149&branchName=201811)
[![VS](https://dev.azure.com/mssonic/build/_apis/build/status/vs/Azure.sonic-buildimage.official.vs?branchName=201811&label=VS)](https://dev.azure.com/mssonic/build/_build/latest?definitionId=142&branchName=201811)
*201807 builds*:
[![Broadcom](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201807/badge/icon?subject=Broadcom)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201807/)
[![Barefoot](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-201807/badge/icon?subject=Barefoot)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-201807/)
*201803 builds*:
[![Broadcom](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201803/badge/icon?subject=Broadcom)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201803/)
[![Nephos](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-201803/badge/icon?subject=Nephos)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-201803/)
[![Marvell](https://sonic-jenkins.westus2.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-201803/badge/icon?subject=Marvell)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-201803/)
[![Mellanox](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-201803/badge/icon?subject=Mellanox)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-201803/)
# sonic-buildimage
## Build SONiC Switch Images
# Description
Following is the instruction on how to build an [(ONIE)](https://github.com/opencomputeproject/onie) compatible network operating system (NOS) installer image for network switches, and also how to build docker images running inside the NOS. Note that SONiC image are build per ASIC platform. Switches using the same ASIC platform share a common image. For a list of supported switches and ASIC, please refer to this [list](https://github.com/Azure/SONiC/wiki/Supported-Devices-and-Platforms)
Following are the instructions on how to build an [(ONIE)](https://github.com/opencomputeproject/onie) compatible network operating system (NOS) installer image for network switches, and also how to build docker images running inside the NOS. Note that SONiC images are build per ASIC platform. Switches using the same ASIC platform share a common image. For a list of supported switches and ASIC, please refer to this [list](https://github.com/sonic-net/SONiC/wiki/Supported-Devices-and-Platforms)
# Hardware
@ -73,6 +84,8 @@ Any server can be a build image server as long as it has:
* Multiple cores to increase build speed
* Plenty of RAM (less than 8 GiB is likely to cause issues)
* 300G of free disk space
* KVM Virtualization Support.
> Note: If you are in a VM, make sure you have support for nested virtualization.
A good choice of OS for building SONiC is currently Ubuntu 20.04.
@ -92,7 +105,7 @@ sudo pip3 install j2cli
## Clone or fetch the code repository with all git submodules
To clone the code repository recursively, assuming git version 1.9 or newer:
git clone https://github.com/Azure/sonic-buildimage.git
git clone https://github.com/sonic-net/sonic-buildimage.git
## Usage
@ -127,16 +140,17 @@ To build SONiC installer image and docker images, run the following commands:
- PLATFORM=centec
- PLATFORM=nephos
- PLATFORM=innovium
- PLATFORM=p4
- PLATFORM=vs
## Usage for ARM Architecture
To build Arm32 bit for (ARMHF) platform
ARM build has dependency in docker version 18,
if docker version is 19, downgrade to 18 as below
sudo apt-get install --allow-downgrades -y docker-ce=5:18.09.0~3-0~ubuntu-xenial
sudo apt-get install --allow-downgrades -y docker-ce-cli=5:18.09.0~3-0~ubuntu-xenial
ARM build has dependency in docker version 18. If docker version is 19, downgrade to 18 with:
```
sudo apt-get install --allow-downgrades -y docker-ce=5:18.09.0~3-0~ubuntu-xenial
sudo apt-get install --allow-downgrades -y docker-ce-cli=5:18.09.0~3-0~ubuntu-xenial
```
To build Arm32 bit for (ARMHF) platform
# Execute make configure once to configure ASIC and ARCH
make configure PLATFORM=[ASIC_VENDOR] PLATFORM_ARCH=armhf
@ -149,6 +163,17 @@ To build Arm32 bit for (ARMHF) platform
make target/sonic-marvell-armhf.bin
To build Arm32 bit for (ARMHF) Marvell platform on amd64 host for debian buster using cross-compilation, run the following commands:
# Execute make configure once to configure ASIC and ARCH for cross-compilation build
NOJESSIE=1 NOSTRETCH=1 BLDENV=buster CROSS_BLDENV=1 make configure PLATFORM=marvell-armhf PLATFORM_ARCH=armhf
# Execute Arm32 build using cross-compilation environment
NOJESSIE=1 NOSTRETCH=1 BLDENV=buster CROSS_BLDENV=1 make target/sonic-marvell-armhf.bin
Running the above Arm32 build using cross-compilation instead of qemu emulator drastically reduces the build time.
To build Arm64 bit for platform
@ -203,10 +228,10 @@ Every target has a clean target, so in order to clean swss, execute:
It is recommended to use clean targets to clean all packages that are built together, like dev packages for instance. In order to be more familiar with build process and make some changes to it, it is recommended to read this short [Documentation](README.buildsystem.md).
## Build debug dockers and debug SONiC installer image:
SONiC build system supports building dockers and ONIE-image with debug tools and debug symbols, to help with live & core debugging. For details refer to [(SONiC Buildimage Guide)](https://github.com/Azure/sonic-buildimage/blob/master/README.buildsystem.md).
SONiC build system supports building dockers and ONIE-image with debug tools and debug symbols, to help with live & core debugging. For details refer to [SONiC Buildimage Guide](https://github.com/sonic-net/sonic-buildimage/blob/master/README.buildsystem.md).
## SAI Version
Please refer to [SONiC roadmap](https://github.com/Azure/SONiC/wiki/Sonic-Roadmap-Planning) on the SAI version for each SONiC release.
Please refer to [SONiC roadmap](https://github.com/sonic-net/SONiC/wiki/Sonic-Roadmap-Planning) on the SAI version for each SONiC release.
## Notes:
- If you are running make for the first time, a sonic-slave-${USER} docker image will be built automatically.
@ -228,11 +253,11 @@ This may take a while, but it is a one-time action, so please be patient.
- docker-syncd-invm.gz: docker image for the daemon to sync database and Innovium switch ASIC (gzip tar archive)
- docker-sonic-p4.gz: docker image for all-in-one for p4 software switch (gzip tar archive)
- docker-sonic-vs.gz: docker image for all-in-one for software virtual switch (gzip tar archive)
- docker-sonic-mgmt.gz: docker image for [managing, configuring and monitoring SONiC](https://github.com/Azure/sonic-mgmt) (gzip tar archive)
- docker-sonic-mgmt.gz: docker image for [managing, configuring and monitoring SONiC](https://github.com/sonic-net/sonic-mgmt) (gzip tar archive)
## Contribution Guide
All contributors must sign a contribution license agreement before contributions can be accepted. Contact [sonic-cla-agreements@microsoft.com](mailto:sonic-cla-agreements@microsoft.com).
All contributors must sign a contribution license agreement before contributions can be accepted. Visit [EasyCLA - Linux Foundation](https://easycla.lfx.linuxfoundation.org).
## GitHub Workflow

View File

@ -28,34 +28,63 @@ resources:
repositories:
- repository: sonic-mgmt
type: github
name: Azure/sonic-mgmt
endpoint: build
name: sonic-net/sonic-mgmt
endpoint: sonic-net
- repository: buildimage
type: github
name: sonic-net/sonic-buildimage
endpoint: sonic-net
ref: master
variables:
- template: .azure-pipelines/azure-pipelines-repd-build-variables.yml@buildimage
- template: .azure-pipelines/template-variables.yml@buildimage
- name: CACHE_MODE
value: rcache
- name: ENABLE_FIPS
value: y
stages:
- stage: BuildVS
pool: sonicbld
jobs:
- template: .azure-pipelines/azure-pipelines-build.yml
parameters:
buildOptions: 'USERNAME=admin SONIC_BUILD_JOBS=$(nproc) BUILD_MULTIASIC_KVM=y ${{ variables.VERSION_CONTROL_OPTIONS }}'
jobGroups:
- name: vs
- stage: Build
pool: sonicbld
variables:
- template: .azure-pipelines/azure-pipelines-repd-build-variables.yml
- name: CACHE_MODE
value: rcache
dependsOn: []
jobs:
- template: .azure-pipelines/azure-pipelines-build.yml
parameters:
buildOptions: 'USERNAME=admin SONIC_BUILD_JOBS=$(nproc) ${{ variables.VERSION_CONTROL_OPTIONS }}'
jobGroups:
- name: vs
- name: broadcom
variables:
swi_image: yes
- name: mellanox
- name: marvell-armhf
pool: sonicbld-armhf
timeoutInMinutes: 1200
variables:
PLATFORM_ARCH: armhf
- stage: Test
dependsOn: BuildVS
condition: and(ne(stageDependencies.BuildVS.outputs['vs.SetVar.SKIP_VSTEST'], 'YES'), in(dependencies.BuildVS.result, 'Succeeded', 'SucceededWithIssues'))
variables:
- name: inventory
value: veos_vtb
- name: testbed_file
value: vtestbed.csv
# For every test job:
# continueOnError: false means it's a required test job and will block merge if it fails
# continueOnError: true means it's an optional test job and will not block merge even though it fails(unless a required test job depends on its result)
jobs:
- job:
pool: sonictest
@ -84,6 +113,8 @@ stages:
- script: |
set -x
sudo apt-get update
sudo apt-get install libyang0.16 -y
sudo dpkg -i --force-confask,confnew ../libswsscommon_1.0.0_amd64.deb
sudo dpkg -i ../python3-swsscommon_1.0.0_amd64.deb
sudo docker load -i ../target/docker-sonic-vs.gz
@ -104,11 +135,11 @@ stages:
testResultsFiles: '**/tr.xml'
testRunTitle: vstest
- job:
- job: t0_part1
pool: sonictest
displayName: "kvmtest-t0"
displayName: "kvmtest-t0-part1"
timeoutInMinutes: 360
continueOnError: false
steps:
- template: .azure-pipelines/run-test-template.yml
parameters:
@ -116,12 +147,50 @@ stages:
tbname: vms-kvm-t0
ptf_name: ptf_vms6-1
tbtype: t0
section: part-1
- job: t0_part2
pool: sonictest
displayName: "kvmtest-t0-part2"
timeoutInMinutes: 360
continueOnError: false
steps:
- template: .azure-pipelines/run-test-template.yml
parameters:
dut: vlab-01
tbname: vms-kvm-t0
ptf_name: ptf_vms6-1
tbtype: t0
section: part-2
- job:
pool: sonictest
displayName: "kvmtest-t0"
timeoutInMinutes: 360
dependsOn:
- t0_part1
- t0_part2
condition: always()
continueOnError: false
variables:
resultOfPart1: $[ dependencies.t0_part1.result ]
resultOfPart2: $[ dependencies.t0_part2.result ]
steps:
- script: |
if [ $(resultOfPart1) == "Succeeded" ] && [ $(resultOfPart2) == "Succeeded" ]; then
echo "Both job kvmtest-t0-part1 and kvmtest-t0-part2 are passed."
exit 0
else
echo "Either job kvmtest-t0-part1 or job kvmtest-t0-part2 failed! Please check the detailed information."
exit 1
fi
- job:
pool: sonictest-t1-lag
displayName: "kvmtest-t1-lag"
timeoutInMinutes: 240
timeoutInMinutes: 360
continueOnError: false
steps:
- template: .azure-pipelines/run-test-template.yml
parameters:
@ -129,3 +198,31 @@ stages:
tbname: vms-kvm-t1-lag
ptf_name: ptf_vms6-2
tbtype: t1-lag
- job:
pool: sonictest-sonic-t0
displayName: "kvmtest-t0-sonic"
timeoutInMinutes: 360
continueOnError: true
steps:
- template: .azure-pipelines/run-test-template.yml
parameters:
dut: vlab-02
tbname: vms-kvm-t0-64-32
ptf_name: ptf_vms6-1
tbtype: t0-sonic
vmtype: vsonic
- job:
pool: sonictest-ma
displayName: "kvmtest-multi-asic-t1-lag"
timeoutInMinutes: 240
continueOnError: true
steps:
- template: .azure-pipelines/run-test-template.yml
parameters:
dut: vlab-08
tbname: vms-kvm-four-asic-t1-lag
ptf_name: ptf_vms6-4
tbtype: multi-asic-t1-lag-pr
image: sonic-4asic-vs.img.gz

View File

@ -31,8 +31,9 @@ set -x -e
CONFIGURED_ARCH=$([ -f .arch ] && cat .arch || echo amd64)
## docker engine version (with platform)
DOCKER_VERSION=5:20.10.7~3-0~debian-$IMAGE_DISTRO
LINUX_KERNEL_VERSION=5.10.0-8-2
DOCKER_VERSION=5:20.10.14~3-0~debian-$IMAGE_DISTRO
CONTAINERD_IO_VERSION=1.5.11-1
LINUX_KERNEL_VERSION=5.10.0-12-2
## Working directory to prepare the file system
FILESYSTEM_ROOT=./fsroot
@ -64,9 +65,12 @@ if [[ -d $FILESYSTEM_ROOT ]]; then
fi
mkdir -p $FILESYSTEM_ROOT
mkdir -p $FILESYSTEM_ROOT/$PLATFORM_DIR
mkdir -p $FILESYSTEM_ROOT/$PLATFORM_DIR/x86_64-grub
mkdir -p $FILESYSTEM_ROOT/$PLATFORM_DIR/grub
touch $FILESYSTEM_ROOT/$PLATFORM_DIR/firsttime
## ensure proc is mounted
sudo mount proc /proc -t proc || true
## make / as a mountpoint in chroot env, needed by dockerd
pushd $FILESYSTEM_ROOT
sudo mount --bind . .
@ -110,9 +114,19 @@ sudo cp files/apt/apt.conf.d/{81norecommends,apt-{clean,gzip-indexes,no-language
## Note: set lang to prevent locale warnings in your chroot
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y update
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y upgrade
echo '[INFO] Install and setup eatmydata'
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install eatmydata
sudo LANG=C chroot $FILESYSTEM_ROOT ln -s /usr/bin/eatmydata /usr/local/bin/dpkg
echo 'Dir::Bin::dpkg "/usr/local/bin/dpkg";' | sudo tee $FILESYSTEM_ROOT/etc/apt/apt.conf.d/00image-install-eatmydata > /dev/null
echo '[INFO] Install packages for building image'
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install makedev psmisc
if [[ $CROSS_BUILD_ENVIRON == y ]]; then
sudo LANG=C chroot $FILESYSTEM_ROOT dpkg --add-architecture $CONFIGURED_ARCH
fi
## Create device files
echo '[INFO] MAKEDEV'
if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then
@ -140,6 +154,23 @@ if [[ $CONFIGURED_ARCH == amd64 ]]; then
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install dmidecode hdparm
fi
## Sign the Linux kernel
if [ "$SONIC_ENABLE_SECUREBOOT_SIGNATURE" = "y" ]; then
if [ ! -f $SIGNING_KEY ]; then
echo "Error: SONiC linux kernel signing key missing"
exit 1
fi
if [ ! -f $SIGNING_CERT ]; then
echo "Error: SONiC linux kernel signing certificate missing"
exit 1
fi
echo '[INFO] Signing SONiC linux kernel image'
K=$FILESYSTEM_ROOT/boot/vmlinuz-${LINUX_KERNEL_VERSION}-${CONFIGURED_ARCH}
sbsign --key $SIGNING_KEY --cert $SIGNING_CERT --output /tmp/${K##*/} ${K}
sudo cp -f /tmp/${K##*/} ${K}
fi
## Update initramfs for booting with squashfs+overlay
cat files/initramfs-tools/modules | sudo tee -a $FILESYSTEM_ROOT/etc/initramfs-tools/modules > /dev/null
@ -162,6 +193,10 @@ sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista-
sudo cp files/initramfs-tools/resize-rootfs $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/resize-rootfs
sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/resize-rootfs
# Hook into initramfs: upgrade SSD from initramfs
sudo cp files/initramfs-tools/ssd-upgrade $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/ssd-upgrade
sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/ssd-upgrade
# Hook into initramfs: run fsck to repair a non-clean filesystem prior to be mounted
sudo cp files/initramfs-tools/fsck-rootfs $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/fsck-rootfs
sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/fsck-rootfs
@ -190,7 +225,7 @@ if [ -f platform/$CONFIGURED_PLATFORM/modules ]; then
fi
## Add mtd and uboot firmware tools package
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install u-boot-tools mtd-utils device-tree-compiler
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install u-boot-tools libubootenv-tool mtd-utils device-tree-compiler
## Install docker
echo '[INFO] Install docker'
@ -207,46 +242,70 @@ if [[ $CONFIGURED_ARCH == armhf ]]; then
# update ssl ca certificates for secure pem
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT c_rehash
fi
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT curl -o /tmp/docker.gpg -fsSL https://download.docker.com/linux/debian/gpg
sudo LANG=C chroot $FILESYSTEM_ROOT apt-key add /tmp/docker.gpg
sudo LANG=C chroot $FILESYSTEM_ROOT rm /tmp/docker.gpg
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT curl -o /tmp/docker.asc -fsSL https://download.docker.com/linux/debian/gpg
sudo LANG=C chroot $FILESYSTEM_ROOT mv /tmp/docker.asc /etc/apt/trusted.gpg.d/
sudo LANG=C chroot $FILESYSTEM_ROOT add-apt-repository \
"deb [arch=$CONFIGURED_ARCH] https://download.docker.com/linux/debian $IMAGE_DISTRO stable"
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get update
if dpkg --compare-versions ${DOCKER_VERSION} ge "18.09"; then
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install docker-ce=${DOCKER_VERSION} docker-ce-cli=${DOCKER_VERSION}
else
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install docker-ce=${DOCKER_VERSION}
fi
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install docker-ce=${DOCKER_VERSION} docker-ce-cli=${DOCKER_VERSION} containerd.io=${CONTAINERD_IO_VERSION}
# Uninstall 'python3-gi' installed as part of 'software-properties-common' to remove debian version of 'PyGObject'
# pip version of 'PyGObject' will be installed during installation of 'sonic-host-services'
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y remove software-properties-common gnupg2 python3-gi
if [ "$INCLUDE_KUBERNETES" == "y" ]
then
## Install Kubernetes
echo '[INFO] Install kubernetes'
install_kubernetes () {
local ver="$1"
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT curl -fsSL \
https://packages.cloud.google.com/apt/doc/apt-key.gpg | \
sudo LANG=C chroot $FILESYSTEM_ROOT apt-key add -
## Check out the sources list update matches current Debian version
sudo cp files/image_config/kubernetes/kubernetes.list $FILESYSTEM_ROOT/etc/apt/sources.list.d/
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get update
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install kubernetes-cni=${KUBERNETES_CNI_VERSION}-00
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install kubelet=${KUBERNETES_VERSION}-00
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install kubectl=${KUBERNETES_VERSION}-00
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install kubeadm=${KUBERNETES_VERSION}-00
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install kubelet=${ver}
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install kubectl=${ver}
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install kubeadm=${ver}
}
if [ "$INCLUDE_KUBERNETES" == "y" ]
then
## Install Kubernetes
echo '[INFO] Install kubernetes'
install_kubernetes ${KUBERNETES_VERSION}
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install kubernetes-cni=${KUBERNETES_CNI_VERSION}
else
echo '[INFO] Skipping Install kubernetes'
fi
if [ "$INCLUDE_KUBERNETES_MASTER" == "y" ]
then
## Install Kubernetes master
echo '[INFO] Install kubernetes master'
install_kubernetes ${MASTER_KUBERNETES_VERSION}
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT curl -fsSL \
https://packages.microsoft.com/keys/microsoft.asc | \
sudo LANG=C chroot $FILESYSTEM_ROOT apt-key add -
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT curl -fsSL \
https://packages.microsoft.com/keys/msopentech.asc | \
sudo LANG=C chroot $FILESYSTEM_ROOT apt-key add -
echo "deb [arch=amd64] https://packages.microsoft.com/repos/azurecore-debian $IMAGE_DISTRO main" | \
sudo tee $FILESYSTEM_ROOT/etc/apt/sources.list.d/azure.list
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get update
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install hyperv-daemons gnupg xmlstarlet
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install metricsext2
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y remove gnupg
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT curl -o /tmp/cri-dockerd.deb -fsSL \
https://github.com/Mirantis/cri-dockerd/releases/download/v${MASTER_CRI_DOCKERD}/cri-dockerd_${MASTER_CRI_DOCKERD}.3-0.debian-${IMAGE_DISTRO}_amd64.deb
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install -f /tmp/cri-dockerd.deb
sudo LANG=C chroot $FILESYSTEM_ROOT rm -f /tmp/cri-dockerd.deb
else
echo '[INFO] Skipping Install kubernetes master'
fi
## Add docker config drop-in to specify dockerd command line
sudo mkdir -p $FILESYSTEM_ROOT/etc/systemd/system/docker.service.d/
## Note: $_ means last argument of last command
sudo cp files/docker/docker.service.conf $_
## Fix systemd race between docker and containerd
sudo sed -i '/After=/s/$/ containerd.service/' $FILESYSTEM_ROOT/lib/systemd/system/docker.service
## Create default user
## Note: user should be in the group with the same name, and also in sudo/docker/redis groups
@ -285,6 +344,7 @@ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y in
python3-apt \
traceroute \
iputils-ping \
arping \
net-tools \
bsdmainutils \
ca-certificates \
@ -303,7 +363,6 @@ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y in
sysfsutils \
squashfs-tools \
grub2-common \
rsyslog \
screen \
hping3 \
tcptraceroute \
@ -326,10 +385,20 @@ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y in
fdisk \
gpg \
jq \
auditd
auditd \
linux-perf
# Change auditd log file path to fix auditd can't startup issue.
sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "sudo sed -i 's/^\s*log_file\s*=.*/log_file = \/var\/log\/audit.log/g' /etc/audit/auditd.conf"
# default rsyslog version is 8.2110.0 which has a bug on log rate limit,
# use backport version
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -t bullseye-backports -y install rsyslog
# Have systemd create the auditd log directory
sudo mkdir -p ${FILESYSTEM_ROOT}/etc/systemd/system/auditd.service.d
sudo tee ${FILESYSTEM_ROOT}/etc/systemd/system/auditd.service.d/log-directory.conf >/dev/null <<EOF
[Service]
LogsDirectory=audit
LogsDirectoryMode=0750
EOF
if [[ $CONFIGURED_ARCH == amd64 ]]; then
## Pre-install the fundamental packages for amd64 (x86)
@ -363,11 +432,17 @@ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y in
systemd-sysv \
ntp
if [[ $CONFIGURED_ARCH == amd64 ]]; then
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y download \
grub-pc-bin
if [[ $TARGET_BOOTLOADER == grub ]]; then
if [[ $CONFIGURED_ARCH == amd64 ]]; then
GRUB_PKG=grub-pc-bin
elif [[ $CONFIGURED_ARCH == arm64 ]]; then
GRUB_PKG=grub-efi-arm64-bin
fi
sudo mv $FILESYSTEM_ROOT/grub-pc-bin*.deb $FILESYSTEM_ROOT/$PLATFORM_DIR/x86_64-grub
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y download \
$GRUB_PKG
sudo mv $FILESYSTEM_ROOT/grub*.deb $FILESYSTEM_ROOT/$PLATFORM_DIR/grub
fi
## Disable kexec supported reboot which was installed by default
@ -376,7 +451,8 @@ sudo sed -i 's/LOAD_KEXEC=true/LOAD_KEXEC=false/' $FILESYSTEM_ROOT/etc/default/k
## Remove sshd host keys, and will regenerate on first sshd start
sudo rm -f $FILESYSTEM_ROOT/etc/ssh/ssh_host_*_key*
sudo cp files/sshd/host-ssh-keygen.sh $FILESYSTEM_ROOT/usr/local/bin/
sudo cp -f files/sshd/sshd.service $FILESYSTEM_ROOT/lib/systemd/system/ssh.service
sudo mkdir $FILESYSTEM_ROOT/etc/systemd/system/ssh.service.d
sudo cp files/sshd/override.conf $FILESYSTEM_ROOT/etc/systemd/system/ssh.service.d/override.conf
# Config sshd
# 1. Set 'UseDNS' to 'no'
# 2. Configure sshd to close all SSH connetions after 15 minutes of inactivity
@ -391,10 +467,16 @@ rm /files/etc/ssh/sshd_config/ClientAliveInterval
rm /files/etc/ssh/sshd_config/ClientAliveCountMax
touch /files/etc/ssh/sshd_config/EmptyLineHack
rename /files/etc/ssh/sshd_config/EmptyLineHack ""
set /files/etc/ssh/sshd_config/ClientAliveInterval 900
set /files/etc/ssh/sshd_config/ClientAliveCountMax 0
set /files/etc/ssh/sshd_config/ClientAliveInterval 300
set /files/etc/ssh/sshd_config/ClientAliveCountMax 1
ins #comment before /files/etc/ssh/sshd_config/ClientAliveInterval
set /files/etc/ssh/sshd_config/#comment[following-sibling::*[1][self::ClientAliveInterval]] "Close inactive client sessions after 15 minutes"
set /files/etc/ssh/sshd_config/#comment[following-sibling::*[1][self::ClientAliveInterval]] "Close inactive client sessions after 5 minutes"
rm /files/etc/ssh/sshd_config/MaxAuthTries
set /files/etc/ssh/sshd_config/MaxAuthTries 3
rm /files/etc/ssh/sshd_config/LogLevel
set /files/etc/ssh/sshd_config/LogLevel VERBOSE
rm /files/etc/ssh/sshd_config/Banner
set /files/etc/ssh/sshd_config/Banner /etc/issue
save
quit
EOF
@ -439,7 +521,7 @@ sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install 'setup
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install 'wheel==0.35.1'
# docker Python API package is needed by Ansible docker module as well as some SONiC applications
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install 'docker==4.3.1'
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install 'docker==5.0.3'
# Install scapy
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install 'scapy==2.4.4'
@ -484,6 +566,7 @@ export build_version="${SONIC_IMAGE_VERSION}"
export debian_version="$(cat $FILESYSTEM_ROOT/etc/debian_version)"
export kernel_version="${kversion}"
export asic_type="${sonic_asic_platform}"
export asic_subtype="${TARGET_MACHINE}"
export commit_id="$(git rev-parse --short HEAD)"
export branch="$(git rev-parse --abbrev-ref HEAD)"
export release="$(if [ -f $FILESYSTEM_ROOT/etc/sonic/sonic_release ]; then cat $FILESYSTEM_ROOT/etc/sonic/sonic_release; fi)"
@ -541,7 +624,7 @@ fi
## Update initramfs
sudo chroot $FILESYSTEM_ROOT update-initramfs -u
## Convert initrd image to u-boot format
if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then
if [[ $TARGET_BOOTLOADER == uboot ]]; then
INITRD_FILE=initrd.img-${LINUX_KERNEL_VERSION}-${CONFIGURED_ARCH}
if [[ $CONFIGURED_ARCH == armhf ]]; then
INITRD_FILE=initrd.img-${LINUX_KERNEL_VERSION}-armmp
@ -554,9 +637,16 @@ if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then
fi
fi
# Collect host image version files before cleanup
scripts/collect_host_image_version_files.sh $TARGET_PATH $FILESYSTEM_ROOT
# Remove GCC
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y remove gcc
# Remove eatmydata
sudo rm $FILESYSTEM_ROOT/etc/apt/apt.conf.d/00image-install-eatmydata $FILESYSTEM_ROOT/usr/local/bin/dpkg
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y remove eatmydata
## Clean up apt
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y autoremove
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get autoclean
@ -566,6 +656,9 @@ sudo LANG=C chroot $FILESYSTEM_ROOT bash -c 'rm -rf /usr/share/doc/* /usr/share/
## Clean up proxy
[ -n "$http_proxy" ] && sudo rm -f $FILESYSTEM_ROOT/etc/apt/apt.conf.d/01proxy
## Clean up pip cache
sudo LANG=C chroot $FILESYSTEM_ROOT pip3 cache purge
## Umount all
echo '[INFO] Umount all'
## Display all process details access /proc
@ -585,7 +678,6 @@ sudo rm -f $ONIE_INSTALLER_PAYLOAD $FILESYSTEM_SQUASHFS
## Note: -x to skip directories on different file systems, such as /proc
sudo du -hsx $FILESYSTEM_ROOT
sudo mkdir -p $FILESYSTEM_ROOT/var/lib/docker
scripts/collect_host_image_version_files.sh $TARGET_PATH $FILESYSTEM_ROOT
sudo mksquashfs $FILESYSTEM_ROOT $FILESYSTEM_SQUASHFS -comp zstd -b 1M -e boot -e var/lib/docker -e $PLATFORM_DIR
# Ensure admin gid is 1000
@ -597,7 +689,7 @@ fi
# ALERT: This bit of logic tears down the qemu based build environment used to
# perform builds for the ARM architecture. This must be the last step in this
# script before creating the Sonic installer payload zip file.
if [ $MULTIARCH_QEMU_ENVIRON == y ]; then
if [[ $MULTIARCH_QEMU_ENVIRON == y || $CROSS_BUILD_ENVIRON == y ]]; then
# Remove qemu arm bin executable used for cross-building
sudo rm -f $FILESYSTEM_ROOT/usr/bin/qemu*static || true
DOCKERFS_PATH=../dockerfs/
@ -607,5 +699,5 @@ fi
pushd $FILESYSTEM_ROOT && sudo tar czf $OLDPWD/$FILESYSTEM_DOCKERFS -C ${DOCKERFS_PATH}var/lib/docker .; popd
## Compress together with /boot, /var/lib/docker and $PLATFORM_DIR as an installer payload zip file
pushd $FILESYSTEM_ROOT && sudo zip $OLDPWD/$ONIE_INSTALLER_PAYLOAD -r boot/ $PLATFORM_DIR/; popd
pushd $FILESYSTEM_ROOT && sudo tar czf platform.tar.gz -C $PLATFORM_DIR . && sudo zip -n .gz $OLDPWD/$ONIE_INSTALLER_PAYLOAD -r boot/ platform.tar.gz; popd
sudo zip -g -n .squashfs:.gz $ONIE_INSTALLER_PAYLOAD $FILESYSTEM_SQUASHFS $FILESYSTEM_DOCKERFS

View File

@ -68,13 +68,15 @@ generate_kvm_image()
generate_onie_installer_image()
{
output_file=$OUTPUT_ONIE_IMAGE
[ -n "$1" ] && output_file=$1
# Copy platform-specific ONIE installer config files where onie-mk-demo.sh expects them
rm -rf ./installer/x86_64/platforms/
mkdir -p ./installer/x86_64/platforms/
rm -rf ./installer/${TARGET_PLATFORM}/platforms/
mkdir -p ./installer/${TARGET_PLATFORM}/platforms/
for VENDOR in `ls ./device`; do
for PLATFORM in `ls ./device/$VENDOR`; do
for PLATFORM in `ls ./device/$VENDOR | grep ^${TARGET_PLATFORM}`; do
if [ -f ./device/$VENDOR/$PLATFORM/installer.conf ]; then
cp ./device/$VENDOR/$PLATFORM/installer.conf ./installer/x86_64/platforms/$PLATFORM
cp ./device/$VENDOR/$PLATFORM/installer.conf ./installer/${TARGET_PLATFORM}/platforms/$PLATFORM
fi
done
@ -82,8 +84,8 @@ generate_onie_installer_image()
## Generate an ONIE installer image
## Note: Don't leave blank between lines. It is single line command.
./onie-mk-demo.sh $TARGET_PLATFORM $TARGET_MACHINE $TARGET_PLATFORM-$TARGET_MACHINE-$ONIEIMAGE_VERSION \
installer platform/$TARGET_MACHINE/platform.conf $OUTPUT_ONIE_IMAGE OS $IMAGE_VERSION $ONIE_IMAGE_PART_SIZE \
./onie-mk-demo.sh $CONFIGURED_ARCH $TARGET_MACHINE $TARGET_PLATFORM-$TARGET_MACHINE-$ONIEIMAGE_VERSION \
installer platform/$TARGET_MACHINE/platform.conf $output_file OS $IMAGE_VERSION $ONIE_IMAGE_PART_SIZE \
$ONIE_INSTALLER_PAYLOAD
}
@ -109,7 +111,7 @@ if [ "$IMAGE_TYPE" = "onie" ]; then
mkdir -p `dirname $OUTPUT_ONIE_IMAGE`
sudo rm -f $OUTPUT_ONIE_IMAGE
generate_device_list "./installer/$TARGET_PLATFORM/platforms_asic"
generate_device_list "./installer/platforms_asic"
generate_onie_installer_image
@ -119,12 +121,13 @@ if [ "$IMAGE_TYPE" = "onie" ]; then
elif [ "$IMAGE_TYPE" = "raw" ]; then
echo "Build RAW image"
tmp_output_onie_image=${OUTPUT_ONIE_IMAGE}.tmp
mkdir -p `dirname $OUTPUT_RAW_IMAGE`
sudo rm -f $OUTPUT_RAW_IMAGE
generate_device_list "./installer/$TARGET_PLATFORM/platforms_asic"
generate_device_list "./installer/platforms_asic"
generate_onie_installer_image
generate_onie_installer_image "$tmp_output_onie_image"
echo "Creating SONiC raw partition : $OUTPUT_RAW_IMAGE of size $RAW_IMAGE_DISK_SIZE MB"
fallocate -l "$RAW_IMAGE_DISK_SIZE"M $OUTPUT_RAW_IMAGE
@ -135,8 +138,9 @@ elif [ "$IMAGE_TYPE" = "raw" ]; then
## Generate a partition dump that can be used to 'dd' in-lieu of using the onie-nos-installer
## Run the installer
## The 'build' install mode of the installer is used to generate this dump.
sudo chmod a+x $OUTPUT_ONIE_IMAGE
sudo ./$OUTPUT_ONIE_IMAGE
sudo chmod a+x $tmp_output_onie_image
sudo ./$tmp_output_onie_image
rm $tmp_output_onie_image
[ -r $OUTPUT_RAW_IMAGE ] || {
echo "Error : $OUTPUT_RAW_IMAGE not generated!"
@ -155,7 +159,7 @@ elif [ "$IMAGE_TYPE" = "raw" ]; then
elif [ "$IMAGE_TYPE" = "kvm" ]; then
generate_device_list "./installer/$TARGET_PLATFORM/platforms_asic"
generate_device_list "./installer/platforms_asic"
generate_onie_installer_image
# Generate single asic KVM image
@ -187,6 +191,7 @@ elif [ "$IMAGE_TYPE" = "aboot" ]; then
zip -g $ABOOT_BOOT_IMAGE .imagehash
rm .imagehash
echo "SWI_VERSION=42.0.0" > version
echo "BUILD_DATE=$(date -d "${build_date}" -u +%Y%m%dT%H%M%SZ)" >> version
echo "SWI_MAX_HWEPOCH=2" >> version
echo "SWI_VARIANT=US" >> version
zip -g $OUTPUT_ABOOT_IMAGE version
@ -196,6 +201,14 @@ elif [ "$IMAGE_TYPE" = "aboot" ]; then
generate_device_list ".platforms_asic"
zip -g $OUTPUT_ABOOT_IMAGE .platforms_asic
if [ "$ENABLE_FIPS" = "y" ]; then
echo "sonic_fips=1" > kernel-cmdline
else
echo "sonic_fips=0" > kernel-cmdline
fi
zip -g $OUTPUT_ABOOT_IMAGE kernel-cmdline
rm kernel-cmdline
zip -g $OUTPUT_ABOOT_IMAGE $ABOOT_BOOT_IMAGE
rm $ABOOT_BOOT_IMAGE
if [ "$SONIC_ENABLE_IMAGE_SIGNATURE" = "y" ]; then

View File

@ -19,6 +19,7 @@ def main():
passwd_prompt = 'Password:'
cmd_prompt = "{}@sonic:~\$ $".format(args.u)
grub_selection = "The highlighted entry will be executed"
firsttime_prompt = 'firsttime_exit'
i = 0
while True:
@ -38,13 +39,17 @@ def main():
# bootup sonic image
while True:
i = p.expect([login_prompt, passwd_prompt, cmd_prompt])
i = p.expect([login_prompt, passwd_prompt, firsttime_prompt, cmd_prompt])
if i == 0:
# send user name
p.sendline(args.u)
elif i == 1:
# send password
p.sendline(args.P)
elif i == 2:
# fix a login timeout issue, caused by the login_prompt message mixed with the output message of the rc.local
time.sleep(1)
p.sendline()
else:
break

View File

@ -1,4 +1,4 @@
stable_size=71303168
stable_size=76303168
#polarity/lanemap is using TH2 style.
core_clock_frequency=893

View File

@ -1,3 +1,4 @@
CONSOLE_PORT=0x3f8
CONSOLE_DEV=0
CONSOLE_SPEED=115200
ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="intel_iommu=off modprobe.blacklist=i2c-ismt,i2c_ismt,i2c-i801,i2c_i801"

View File

@ -33,7 +33,7 @@
"std_kos":
[
"i2c_dev",
"i2c_mux_pca954x force_deselect_on_exit=1",
"i2c_mux_pca954x",
"optoe"
],
"description":"kernel modules are loaded while moving to pdf mode, but they should not be unloaded while moving to nonpddf mode.",
@ -105,7 +105,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x1", "dev_addr":"0x77", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x2"},
"dev_attr": { "virt_bus":"0x2", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"MUX2" },
@ -122,7 +122,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x2", "dev_addr":"0x71", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0xa"},
"dev_attr": { "virt_bus":"0xa", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PSU1" },
@ -161,7 +161,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x3", "dev_addr":"0x70", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x12"},
"dev_attr": { "virt_bus":"0x12", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT49" },

View File

@ -0,0 +1,2 @@
__all__ = [ "platform", "chassis", "sfp", "eeprom", "component", "psu", "thermal", "fan", "fan_drawer" ]
from . import platform

View File

@ -0,0 +1,255 @@
#############################################################################
# Edgecore
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Chassis information which are available in the platform
#
#############################################################################
import os
import sys
try:
from sonic_platform_base.chassis_base import ChassisBase
from .helper import APIHelper
from .event import SfpEvent
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
NUM_FAN_TRAY = 3
NUM_FAN = 2
NUM_PSU = 2
NUM_THERMAL = 3
PORT_START = 49
PORT_END = 54
NUM_COMPONENT = 2
HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/"
PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/"
REBOOT_CAUSE_FILE = "reboot-cause.txt"
PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt"
HOST_CHK_CMD = "which systemctl > /dev/null 2>&1"
SYSLED_FNODE = "/sys/class/leds/diag/brightness"
SYSLED_MODES = {
"0" : "STATUS_LED_COLOR_OFF",
"1" : "STATUS_LED_COLOR_GREEN",
"2" : "STATUS_LED_COLOR_AMBER",
"5" : "STATUS_LED_COLOR_GREEN_BLINK"
}
class Chassis(ChassisBase):
"""Platform-specific Chassis class"""
def __init__(self):
ChassisBase.__init__(self)
self._api_helper = APIHelper()
self.is_host = self._api_helper.is_host()
self.config_data = {}
self.__initialize_fan()
self.__initialize_psu()
self.__initialize_thermals()
self.__initialize_components()
self.__initialize_sfp()
self.__initialize_eeprom()
def __initialize_sfp(self):
from sonic_platform.sfp import Sfp
for index in range(0, PORT_END):
sfp = Sfp(index)
self._sfp_list.append(sfp)
self._sfpevent = SfpEvent(self._sfp_list)
self.sfp_module_initialized = True
def __initialize_fan(self):
from sonic_platform.fan_drawer import FanDrawer
for fant_index in range(NUM_FAN_TRAY):
fandrawer = FanDrawer(fant_index)
self._fan_drawer_list.append(fandrawer)
self._fan_list.extend(fandrawer._fan_list)
def __initialize_psu(self):
from sonic_platform.psu import Psu
for index in range(0, NUM_PSU):
psu = Psu(index)
self._psu_list.append(psu)
def __initialize_thermals(self):
from sonic_platform.thermal import Thermal
for index in range(0, NUM_THERMAL):
thermal = Thermal(index)
self._thermal_list.append(thermal)
def __initialize_eeprom(self):
from sonic_platform.eeprom import Tlv
self._eeprom = Tlv()
def __initialize_components(self):
from sonic_platform.component import Component
for index in range(0, NUM_COMPONENT):
component = Component(index)
self._component_list.append(component)
def __initialize_watchdog(self):
from sonic_platform.watchdog import Watchdog
self._watchdog = Watchdog()
def __is_host(self):
return os.system(HOST_CHK_CMD) == 0
def __read_txt_file(self, file_path):
try:
with open(file_path, 'r') as fd:
data = fd.read()
return data.strip()
except IOError:
pass
return None
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
return self._eeprom.get_product_name()
def get_presence(self):
"""
Retrieves the presence of the Chassis
Returns:
bool: True if Chassis is present, False if not
"""
return True
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
return True
def get_base_mac(self):
"""
Retrieves the base MAC address for the chassis
Returns:
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
return self._eeprom.get_mac()
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return self._eeprom.get_pn()
def get_serial(self):
"""
Retrieves the hardware serial number for the chassis
Returns:
A string containing the hardware serial number for this chassis.
"""
return self._eeprom.get_serial()
def get_system_eeprom_info(self):
"""
Retrieves the full content of system EEPROM information for the chassis
Returns:
A dictionary where keys are the type code defined in
OCP ONIE TlvInfo EEPROM format and values are their corresponding
values.
"""
return self._eeprom.get_eeprom()
def get_reboot_cause(self):
"""
Retrieves the cause of the previous reboot
Returns:
A tuple (string, string) where the first element is a string
containing the cause of the previous reboot. This string must be
one of the predefined strings in this class. If the first string
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
to pass a description of the reboot cause.
"""
reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE)
sw_reboot_cause = self._api_helper.read_txt_file(
reboot_cause_path) or "Unknown"
return ('REBOOT_CAUSE_NON_HARDWARE', sw_reboot_cause)
def get_change_event(self, timeout=0):
# SFP event
if not self.sfp_module_initialized:
self.__initialize_sfp()
return self._sfpevent.get_sfp_event(timeout)
def get_sfp(self, index):
"""
Retrieves sfp represented by (1-based) index <index>
Args:
index: An integer, the index (1-based) of the sfp to retrieve.
The index should be the sequence of a physical port in a chassis,
starting from 1.
For example, 1 for Ethernet0, 2 for Ethernet4 and so on.
Returns:
An object dervied from SfpBase representing the specified sfp
"""
sfp = None
if not self.sfp_module_initialized:
self.__initialize_sfp()
try:
# The index will start from 1
sfp = self._sfp_list[index-1]
except IndexError:
sys.stderr.write("SFP index {} out of range (1-{})\n".format(
index, len(self._sfp_list)))
return sfp
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return -1
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return False
def initizalize_system_led(self):
return True
def get_status_led(self):
val = self._api_helper.read_txt_file(SYSLED_FNODE)
return SYSLED_MODES[val] if val in SYSLED_MODES else "UNKNOWN"
def set_status_led(self, color):
mode = None
for key, val in SYSLED_MODES.items():
if val == color:
mode = key
break
if mode is None:
return False
else:
return self._api_helper.write_txt_file(SYSLED_FNODE, mode)

View File

@ -0,0 +1,172 @@
#############################################################################
# Edgecore
#
# Component contains an implementation of SONiC Platform Base API and
# provides the components firmware management function
#
#############################################################################
import shlex
import subprocess
try:
from sonic_platform_base.component_base import ComponentBase
from .helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CPLD_ADDR_MAPPING = {
"CPLD1": "3-0060"
}
SYSFS_PATH = "/sys/bus/i2c/devices/"
BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version"
COMPONENT_LIST= [
("CPLD1", "CPLD 1"),
("BIOS", "Basic Input/Output System")
]
class Component(ComponentBase):
"""Platform-specific Component class"""
DEVICE_TYPE = "component"
def __init__(self, component_index=0):
self._api_helper=APIHelper()
ComponentBase.__init__(self)
self.index = component_index
self.name = self.get_name()
def __run_command(self, command):
# Run bash command and print output to stdout
try:
process = subprocess.Popen(
shlex.split(command), stdout=subprocess.PIPE)
while True:
output = process.stdout.readline()
if output == '' and process.poll() is not None:
break
rc = process.poll()
if rc != 0:
return False
except Exception:
return False
return True
def __get_bios_version(self):
# Retrieves the BIOS firmware version
try:
with open(BIOS_VERSION_PATH, 'r') as fd:
bios_version = fd.read()
return bios_version.strip()
except Exception as e:
return None
def __get_cpld_version(self):
# Retrieves the CPLD firmware version
cpld_version = dict()
for cpld_name in CPLD_ADDR_MAPPING:
try:
cpld_path = "{}{}{}".format(SYSFS_PATH, CPLD_ADDR_MAPPING[cpld_name], '/version')
cpld_version_raw= self._api_helper.read_txt_file(cpld_path)
cpld_version[cpld_name] = "{}".format(int(cpld_version_raw,16))
except Exception as e:
print('Get exception when read cpld')
cpld_version[cpld_name] = 'None'
return cpld_version
def get_name(self):
"""
Retrieves the name of the component
Returns:
A string containing the name of the component
"""
return COMPONENT_LIST[self.index][0]
def get_description(self):
"""
Retrieves the description of the component
Returns:
A string containing the description of the component
"""
return COMPONENT_LIST[self.index][1]
def get_firmware_version(self):
"""
Retrieves the firmware version of module
Returns:
string: The firmware versions of the module
"""
fw_version = None
if self.name == "BIOS":
fw_version = self.__get_bios_version()
elif "CPLD" in self.name:
cpld_version = self.__get_cpld_version()
fw_version = cpld_version.get(self.name)
return fw_version
def install_firmware(self, image_path):
"""
Install firmware to module
Args:
image_path: A string, path to firmware image
Returns:
A boolean, True if install successfully, False if not
"""
raise NotImplementedError
def get_presence(self):
"""
Retrieves the presence of the device
Returns:
bool: True if device is present, False if not
"""
return True
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return 'N/A'
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return 'N/A'
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
return True
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device.
If the agent cannot determine the parent-relative position
for some reason, or if the associated value of
entPhysicalContainedIn is'0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device
or -1 if cannot determine the position
"""
return -1
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return False

View File

@ -0,0 +1,134 @@
try:
import os
import sys
import re
if sys.version_info[0] >= 3:
from io import StringIO
else:
from cStringIO import StringIO
from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CACHE_ROOT = '/var/cache/sonic/decode-syseeprom'
CACHE_FILE = 'syseeprom_cache'
NULL = 'N/A'
class Tlv(eeprom_tlvinfo.TlvInfoDecoder):
EEPROM_DECODE_HEADLINES = 6
def __init__(self):
self._eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom"
super(Tlv, self).__init__(self._eeprom_path, 0, '', True)
self._eeprom = self._load_eeprom()
def __parse_output(self, decode_output):
decode_output.replace('\0', '')
lines = decode_output.split('\n')
lines = lines[self.EEPROM_DECODE_HEADLINES:]
_eeprom_info_dict = dict()
for line in lines:
try:
match = re.search(
'(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+)', line)
if match is not None:
idx = match.group(1)
value = match.group(3).rstrip('\0')
_eeprom_info_dict[idx] = value
except Exception:
pass
return _eeprom_info_dict
def _load_eeprom(self):
original_stdout = sys.stdout
sys.stdout = StringIO()
try:
self.read_eeprom_db()
except Exception:
decode_output = sys.stdout.getvalue()
sys.stdout = original_stdout
return self.__parse_output(decode_output)
status = self.check_status()
if 'ok' not in status:
return False
if not os.path.exists(CACHE_ROOT):
try:
os.makedirs(CACHE_ROOT)
except Exception:
pass
#
# only the eeprom classes that inherit from eeprom_base
# support caching. Others will work normally
#
try:
self.set_cache_name(os.path.join(CACHE_ROOT, CACHE_FILE))
except Exception:
pass
e = self.read_eeprom()
if e is None:
return 0
try:
self.update_cache(e)
except Exception:
pass
self.decode_eeprom(e)
decode_output = sys.stdout.getvalue()
sys.stdout = original_stdout
(is_valid, valid_crc) = self.is_checksum_valid(e)
if not is_valid:
return False
return self.__parse_output(decode_output)
def _valid_tlv(self, eeprom_data):
tlvinfo_type_codes_list = [
self._TLV_CODE_PRODUCT_NAME,
self._TLV_CODE_PART_NUMBER,
self._TLV_CODE_SERIAL_NUMBER,
self._TLV_CODE_MAC_BASE,
self._TLV_CODE_MANUF_DATE,
self._TLV_CODE_DEVICE_VERSION,
self._TLV_CODE_LABEL_REVISION,
self._TLV_CODE_PLATFORM_NAME,
self._TLV_CODE_ONIE_VERSION,
self._TLV_CODE_MAC_SIZE,
self._TLV_CODE_MANUF_NAME,
self._TLV_CODE_MANUF_COUNTRY,
self._TLV_CODE_VENDOR_NAME,
self._TLV_CODE_DIAG_VERSION,
self._TLV_CODE_SERVICE_TAG,
self._TLV_CODE_VENDOR_EXT,
self._TLV_CODE_CRC_32
]
for code in tlvinfo_type_codes_list:
code_str = "0x{:X}".format(code)
eeprom_data[code_str] = eeprom_data.get(code_str, NULL)
return eeprom_data
def get_eeprom(self):
return self._valid_tlv(self._eeprom)
def get_pn(self):
return self._eeprom.get('0x22', NULL)
def get_serial(self):
return self._eeprom.get('0x23', NULL)
def get_mac(self):
return self._eeprom.get('0x24', NULL)
def get_product_name(self):
return self._eeprom.get('0x21', NULL)

View File

@ -0,0 +1,63 @@
try:
import time
from .helper import APIHelper
from sonic_py_common.logger import Logger
except ImportError as e:
raise ImportError(repr(e) + " - required module not found")
POLL_INTERVAL_IN_SEC = 1
class SfpEvent:
''' Listen to insert/remove sfp events '''
def __init__(self, sfp_list):
self._api_helper = APIHelper()
self._sfp_list = sfp_list
self._logger = Logger()
self._sfp_change_event_data = {'present': 0}
def get_presence_bitmap(self):
bitmap = 0
for sfp in self._sfp_list:
modpres = sfp.get_presence()
i=sfp.port_num-1
if modpres:
bitmap = bitmap | (1 << i)
return bitmap
def get_sfp_event(self, timeout=2000):
#now = time.time()
port_dict = {}
change_dict = {}
change_dict['sfp'] = port_dict
if timeout < 1000:
cd_ms = 1000
else:
cd_ms = timeout
while cd_ms > 0:
bitmap = self.get_presence_bitmap()
changed_ports = self._sfp_change_event_data['present'] ^ bitmap
if changed_ports != 0:
break
time.sleep(POLL_INTERVAL_IN_SEC)
# timeout=0 means wait for event forever
if timeout != 0:
cd_ms = cd_ms - POLL_INTERVAL_IN_SEC * 1000
if changed_ports != 0:
for sfp in self._sfp_list:
i=sfp.port_num-1
if (changed_ports & (1 << i)):
if (bitmap & (1 << i)) == 0:
port_dict[i+1] = '0'
else:
port_dict[i+1] = '1'
# Update the cache dict
self._sfp_change_event_data['present'] = bitmap
return True, change_dict
else:
return True, change_dict

View File

@ -0,0 +1,284 @@
#############################################################################
# Edgecore
#
# Module contains an implementation of SONiC Platform Base API and
# provides the fan status which are available in the platform
#
#############################################################################
try:
from sonic_platform_base.fan_base import FanBase
from .helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
PSU_FAN_MAX_RPM = 26688
SPEED_TOLERANCE = 15
CPLD_FAN_I2C_PATH = "/sys/bus/i2c/devices/3-0060/fan_"
I2C_PATH ="/sys/bus/i2c/devices/{}-00{}/"
PSU_HWMON_I2C_MAPPING = {
0: {
"num": 10,
"addr": "58"
},
1: {
"num": 11,
"addr": "59"
},
}
PSU_CPLD_I2C_MAPPING = {
0: {
"num": 10,
"addr": "50"
},
1: {
"num": 11,
"addr": "51"
},
}
FAN_NAME_LIST = ["FAN-1F", "FAN-1R", "FAN-2F", "FAN-2R",
"FAN-3F", "FAN-3R"]
class Fan(FanBase):
"""Platform-specific Fan class"""
def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0):
self._api_helper=APIHelper()
self.fan_index = fan_index
self.fan_tray_index = fan_tray_index
self.is_psu_fan = is_psu_fan
if self.is_psu_fan:
self.psu_index = psu_index
self.psu_i2c_num = PSU_HWMON_I2C_MAPPING[self.psu_index]['num']
self.psu_i2c_addr = PSU_HWMON_I2C_MAPPING[self.psu_index]['addr']
self.psu_hwmon_path = I2C_PATH.format(
self.psu_i2c_num, self.psu_i2c_addr)
self.psu_i2c_num = PSU_CPLD_I2C_MAPPING[self.psu_index]['num']
self.psu_i2c_addr = PSU_CPLD_I2C_MAPPING[self.psu_index]['addr']
self.psu_cpld_path = I2C_PATH.format(
self.psu_i2c_num, self.psu_i2c_addr)
FanBase.__init__(self)
def get_direction(self):
"""
Retrieves the direction of fan
Returns:
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
depending on fan direction
"""
if not self.is_psu_fan:
dir_str = "{}{}{}".format(CPLD_FAN_I2C_PATH, 'direction_', self.fan_tray_index+1)
val=self._api_helper.read_txt_file(dir_str)
if val is not None:
if int(val, 10)==0:#F2B
direction=self.FAN_DIRECTION_EXHAUST
else:
direction=self.FAN_DIRECTION_INTAKE
else:
direction=self.FAN_DIRECTION_EXHAUST
else: #For PSU
dir_str = "{}{}".format(self.psu_hwmon_path,'psu_fan_dir')
val=self._api_helper.read_txt_file(dir_str)
if val is not None:
if val=='F2B':
direction=self.FAN_DIRECTION_EXHAUST
else:
direction=self.FAN_DIRECTION_INTAKE
else:
direction=self.FAN_DIRECTION_EXHAUST
return direction
def get_speed(self):
"""
Retrieves the speed of fan as a percentage of full speed
Returns:
An integer, the percentage of full fan speed, in the range 0 (off)
to 100 (full speed)
"""
speed = 0
if self.is_psu_fan:
psu_fan_path= "{}{}".format(self.psu_hwmon_path, 'psu_fan1_speed_rpm')
fan_speed_rpm = self._api_helper.read_txt_file(psu_fan_path)
if fan_speed_rpm is not None:
speed = (int(fan_speed_rpm,10))*100/26688
if speed > 100:
speed=100
else:
return 0
elif self.get_presence():
speed_path = "{}{}".format(CPLD_FAN_I2C_PATH, 'duty_cycle_percentage')
speed=self._api_helper.read_txt_file(speed_path)
if speed is None:
return 0
return int(speed)
def get_target_speed(self):
"""
Retrieves the target (expected) speed of the fan
Returns:
An integer, the percentage of full fan speed, in the range 0 (off)
to 100 (full speed)
Note:
speed_pc = pwm_target/255*100
0 : when PWM mode is use
pwm : when pwm mode is not use
"""
return self.get_speed()
def get_speed_tolerance(self):
"""
Retrieves the speed tolerance of the fan
Returns:
An integer, the percentage of variance from target speed which is
considered tolerable
"""
return SPEED_TOLERANCE
def set_speed(self, speed):
"""
Sets the fan speed
Args:
speed: An integer, the percentage of full fan speed to set fan to,
in the range 0 (off) to 100 (full speed)
Returns:
A boolean, True if speed is set successfully, False if not
"""
if not self.is_psu_fan and self.get_presence():
speed_path = "{}{}".format(CPLD_FAN_I2C_PATH, 'duty_cycle_percentage')
return self._api_helper.write_txt_file(speed_path, int(speed))
return False
def set_status_led(self, color):
"""
Sets the state of the fan module status LED
Args:
color: A string representing the color with which to set the
fan module status LED
Returns:
bool: True if status LED state is set successfully, False if not
"""
return False #Not supported
def get_status_led(self):
"""
Gets the state of the fan status LED
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings above
"""
status=self.get_presence()
if status is None:
return self.STATUS_LED_COLOR_OFF
return {
1: self.STATUS_LED_COLOR_GREEN,
0: self.STATUS_LED_COLOR_RED
}.get(status, self.STATUS_LED_COLOR_OFF)
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
fan_name = FAN_NAME_LIST[self.fan_tray_index*2 + self.fan_index] \
if not self.is_psu_fan \
else "PSU-{} FAN-{}".format(self.psu_index+1, self.fan_index+1)
return fan_name
def get_presence(self):
"""
Retrieves the presence of the FAN
Returns:
bool: True if FAN is present, False if not
"""
if self.is_psu_fan:
present_path="{}{}".format(self.psu_cpld_path, 'psu_present')
else:
present_path = "{}{}{}".format(CPLD_FAN_I2C_PATH, 'present_', self.fan_tray_index+1)
val=self._api_helper.read_txt_file(present_path)
if val is not None:
return int(val, 10)==1
else:
return False
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
if self.is_psu_fan:
psu_fan_path= "{}{}".format(self.psu_hwmon_path, 'psu_fan1_fault')
val=self._api_helper.read_txt_file(psu_fan_path)
if val is not None:
return int(val, 10)==0
else:
return False
else:
path = "{}{}{}".format(CPLD_FAN_I2C_PATH, 'fault_', self.fan_tray_index+1)
val=self._api_helper.read_txt_file(path)
if val is not None:
return int(val, 10)==0
else:
return False
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return "N/A"
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return "N/A"
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device.
If the agent cannot determine the parent-relative position
for some reason, or if the associated value of
entPhysicalContainedIn is'0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device
or -1 if cannot determine the position
"""
return (self.fan_index+1) \
if not self.is_psu_fan else (self.psu_index+1)
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True if not self.is_psu_fan else False

View File

@ -0,0 +1,90 @@
########################################################################
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Fan-Drawers' information available in the platform.
#
########################################################################
try:
from sonic_platform_base.fan_drawer_base import FanDrawerBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
FANS_PER_FANTRAY = 2
class FanDrawer(FanDrawerBase):
"""Platform-specific Fan class"""
def __init__(self, fantray_index):
FanDrawerBase.__init__(self)
# FanTray is 0-based in platforms
self.fantrayindex = fantray_index
self.__initialize_fan_drawer()
def __initialize_fan_drawer(self):
from sonic_platform.fan import Fan
for i in range(FANS_PER_FANTRAY):
self._fan_list.append(Fan(self.fantrayindex, i))
def get_name(self):
"""
Retrieves the fan drawer name
Returns:
string: The name of the device
"""
return "FanTray{}".format(self.fantrayindex+1)
def get_presence(self):
"""
Retrieves the presence of the device
Returns:
bool: True if device is present, False if not
"""
return self._fan_list[0].get_presence()
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return self._fan_list[0].get_model()
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return self._fan_list[0].get_serial()
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
return self._fan_list[0].get_status()
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device.
If the agent cannot determine the parent-relative position
for some reason, or if the associated value of
entPhysicalContainedIn is'0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device
or -1 if cannot determine the position
"""
return (self.fantrayindex+1)
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True

View File

@ -0,0 +1,117 @@
import os
import struct
import subprocess
from mmap import *
from sonic_py_common import device_info
HOST_CHK_CMD = "docker > /dev/null 2>&1"
EMPTY_STRING = ""
class APIHelper():
def __init__(self):
(self.platform, self.hwsku) = device_info.get_platform_and_hwsku()
def is_host(self):
return os.system(HOST_CHK_CMD) == 0
def pci_get_value(self, resource, offset):
status = True
result = ""
try:
fd = os.open(resource, os.O_RDWR)
mm = mmap(fd, 0)
mm.seek(int(offset))
read_data_stream = mm.read(4)
result = struct.unpack('I', read_data_stream)
except Exception:
status = False
return status, result
def run_command(self, cmd):
status = True
result = ""
try:
p = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
raw_data, err = p.communicate()
if err == '':
result = raw_data.strip()
except Exception:
status = False
return status, result
def run_interactive_command(self, cmd):
try:
os.system(cmd)
except Exception:
return False
return True
def read_txt_file(self, file_path):
try:
with open(file_path, 'r', errors='replace') as fd:
data = fd.read()
return data.strip()
except IOError:
pass
return None
def write_txt_file(self, file_path, value):
try:
with open(file_path, 'w') as fd:
fd.write(str(value))
except IOError:
return False
return True
def ipmi_raw(self, netfn, cmd):
status = True
result = ""
try:
cmd = "ipmitool raw {} {}".format(str(netfn), str(cmd))
p = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
raw_data, err = p.communicate()
if err == '':
result = raw_data.strip()
else:
status = False
except Exception:
status = False
return status, result
def ipmi_fru_id(self, id, key=None):
status = True
result = ""
try:
cmd = "ipmitool fru print {}".format(str(
id)) if not key else "ipmitool fru print {0} | grep '{1}' ".format(str(id), str(key))
p = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
raw_data, err = p.communicate()
if err == '':
result = raw_data.strip()
else:
status = False
except Exception:
status = False
return status, result
def ipmi_set_ss_thres(self, id, threshold_key, value):
status = True
result = ""
try:
cmd = "ipmitool sensor thresh '{}' {} {}".format(str(id), str(threshold_key), str(value))
p = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
raw_data, err = p.communicate()
if err == '':
result = raw_data.strip()
else:
status = False
except Exception:
status = False
return status, result

View File

@ -0,0 +1,21 @@
#############################################################################
# Edgecore
#
# Module contains an implementation of SONiC Platform Base API and
# provides the platform information
#
#############################################################################
try:
from sonic_platform_base.platform_base import PlatformBase
from sonic_platform.chassis import Chassis
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Platform(PlatformBase):
"""Platform-specific Platform class"""
def __init__(self):
PlatformBase.__init__(self)
self._chassis = Chassis()

View File

@ -0,0 +1,269 @@
#############################################################################
# Edgecore
#
# Module contains an implementation of SONiC Platform Base API and
# provides the PSUs status which are available in the platform
#
#############################################################################
#import sonic_platform
try:
from sonic_platform_base.psu_base import PsuBase
from .helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
I2C_PATH ="/sys/bus/i2c/devices/{0}-00{1}/"
PSU_NAME_LIST = ["PSU-1", "PSU-2"]
PSU_NUM_FAN = [1, 1]
PSU_HWMON_I2C_MAPPING = {
0: {
"num": 10,
"addr": "58"
},
1: {
"num": 11,
"addr": "59"
},
}
PSU_CPLD_I2C_MAPPING = {
0: {
"num": 10,
"addr": "50"
},
1: {
"num": 11,
"addr": "51"
},
}
class Psu(PsuBase):
"""Platform-specific Psu class"""
def __init__(self, psu_index=0):
PsuBase.__init__(self)
self.index = psu_index
self._api_helper = APIHelper()
self.i2c_num = PSU_HWMON_I2C_MAPPING[self.index]["num"]
self.i2c_addr = PSU_HWMON_I2C_MAPPING[self.index]["addr"]
self.hwmon_path = I2C_PATH.format(self.i2c_num, self.i2c_addr)
self.i2c_num = PSU_CPLD_I2C_MAPPING[self.index]["num"]
self.i2c_addr = PSU_CPLD_I2C_MAPPING[self.index]["addr"]
self.cpld_path = I2C_PATH.format(self.i2c_num, self.i2c_addr)
self.__initialize_fan()
def __initialize_fan(self):
from sonic_platform.fan import Fan
for fan_index in range(0, PSU_NUM_FAN[self.index]):
fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index)
self._fan_list.append(fan)
def get_voltage(self):
"""
Retrieves current PSU voltage output
Returns:
A float number, the output voltage in volts,
e.g. 12.1
"""
vout_path = "{}{}".format(self.hwmon_path, 'psu_v_out')
vout_val=self._api_helper.read_txt_file(vout_path)
if vout_val is not None:
return float(vout_val)/ 1000
else:
return 0
def get_current(self):
"""
Retrieves present electric current supplied by PSU
Returns:
A float number, the electric current in amperes, e.g 15.4
"""
iout_path = "{}{}".format(self.hwmon_path, 'psu_i_out')
val=self._api_helper.read_txt_file(iout_path)
if val is not None:
return float(val)/1000
else:
return 0
def get_power(self):
"""
Retrieves current energy supplied by PSU
Returns:
A float number, the power in watts, e.g. 302.6
"""
pout_path = "{}{}".format(self.hwmon_path, 'psu_p_out')
val=self._api_helper.read_txt_file(pout_path)
if val is not None:
return float(val)/1000
else:
return 0
def get_powergood_status(self):
"""
Retrieves the powergood status of PSU
Returns:
A boolean, True if PSU has stablized its output voltages and passed all
its internal self-tests, False if not.
"""
return self.get_status()
def set_status_led(self, color):
"""
Sets the state of the PSU status LED
Args:
color: A string representing the color with which to set the PSU status LED
Note: Only support green and off
Returns:
bool: True if status LED state is set successfully, False if not
"""
return False #Controlled by HW
def get_status_led(self):
"""
Gets the state of the PSU status LED
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings above
"""
status=self.get_status()
if status is None:
return self.STATUS_LED_COLOR_OFF
return {
1: self.STATUS_LED_COLOR_GREEN,
0: self.STATUS_LED_COLOR_RED
}.get(status, self.STATUS_LED_COLOR_OFF)
def get_temperature(self):
"""
Retrieves current temperature reading from PSU
Returns:
A float number of current temperature in Celsius up to nearest thousandth
of one degree Celsius, e.g. 30.125
"""
temp_path = "{}{}".format(self.hwmon_path, 'psu_temp1_input')
val=self._api_helper.read_txt_file(temp_path)
if val is not None:
return float(val)/1000
else:
return 0
def get_temperature_high_threshold(self):
"""
Retrieves the high threshold temperature of PSU
Returns:
A float number, the high threshold temperature of PSU in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125
"""
return False #Not supported
def get_voltage_high_threshold(self):
"""
Retrieves the high threshold PSU voltage output
Returns:
A float number, the high threshold output voltage in volts,
e.g. 12.1
"""
vout_path = "{}{}".format(self.hwmon_path, 'psu_mfr_vout_max')
vout_val=self._api_helper.read_txt_file(vout_path)
if vout_val is not None:
return float(vout_val)/ 1000
else:
return 0
def get_voltage_low_threshold(self):
"""
Retrieves the low threshold PSU voltage output
Returns:
A float number, the low threshold output voltage in volts,
e.g. 12.1
"""
vout_path = "{}{}".format(self.hwmon_path, 'psu_mfr_vout_min')
vout_val=self._api_helper.read_txt_file(vout_path)
if vout_val is not None:
return float(vout_val)/ 1000
else:
return 0
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
return PSU_NAME_LIST[self.index]
def get_presence(self):
"""
Retrieves the presence of the PSU
Returns:
bool: True if PSU is present, False if not
"""
presence_path="{}{}".format(self.cpld_path, 'psu_present')
val=self._api_helper.read_txt_file(presence_path)
if val is not None:
return int(val, 10) == 1
else:
return 0
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
power_path="{}{}".format(self.cpld_path, 'psu_power_good')
val=self._api_helper.read_txt_file(power_path)
if val is not None:
return int(val, 10) == 1
else:
return 0
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
model_path="{}{}".format(self.cpld_path, 'psu_model_name')
model=self._api_helper.read_txt_file(model_path)
if model is None:
return "N/A"
return model
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
serial_path="{}{}".format(self.cpld_path, 'psu_serial_number')
serial=self._api_helper.read_txt_file(serial_path)
if serial is None:
return "N/A"
return serial
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return self.index+1
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True

View File

@ -0,0 +1,484 @@
#############################################################################
# Edgecore
#
# Sfp contains an implementation of SONiC Platform Base API and
# provides the sfp device status which are available in the platform
#
#############################################################################
import os
import time
import sys
from ctypes import create_string_buffer
try:
from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase
from .helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CPLD_I2C_PATH = "/sys/bus/i2c/devices/3-0060/"
class Sfp(SfpOptoeBase):
"""Platform-specific Sfp class"""
# Port number
PORT_START = 49
PORT_END = 54
# Path to sysfs
PLATFORM_ROOT_PATH = "/usr/share/sonic/device"
PMON_HWSKU_PATH = "/usr/share/sonic/hwsku"
HOST_CHK_CMD = "which systemctl > /dev/null 2>&1"
PLATFORM = "x86_64-accton_as4630_54pe-r0"
HWSKU = "Accton-AS4630-54PE"
_port_to_i2c_mapping = {
49: 18,
50: 19,
51: 20,
52: 21,
53: 22,
54: 23,
}
def __init__(self, sfp_index=0):
SfpOptoeBase.__init__(self)
self._api_helper=APIHelper()
# Init index
self.index = sfp_index
self.port_num = self.index + 1
# Init eeprom path
eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom'
self.port_to_eeprom_mapping = {}
for x in range(self.PORT_START, self.PORT_END + 1):
self.port_to_eeprom_mapping[x] = eeprom_path.format(self._port_to_i2c_mapping[x])
def get_eeprom_path(self):
return self.port_to_eeprom_mapping[self.port_num]
def __is_host(self):
return os.system(self.HOST_CHK_CMD) == 0
def __get_path_to_port_config_file(self):
platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM])
hwsku_path = "/".join([platform_path, self.HWSKU]
) if self.__is_host() else self.PMON_HWSKU_PATH
return "/".join([hwsku_path, "port_config.ini"])
def __read_eeprom_specific_bytes(self, offset, num_bytes):
sysfsfile_eeprom = None
eeprom_raw = []
for i in range(0, num_bytes):
eeprom_raw.append("0x00")
sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num]
try:
sysfsfile_eeprom = open(
sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0)
sysfsfile_eeprom.seek(offset)
raw = sysfsfile_eeprom.read(num_bytes)
if sys.version_info[0] >= 3:
for n in range(0, num_bytes):
eeprom_raw[n] = hex(raw[n])[2:].zfill(2)
else:
for n in range(0, num_bytes):
eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2)
except Exception:
pass
finally:
if sysfsfile_eeprom:
sysfsfile_eeprom.close()
return eeprom_raw
def get_reset_status(self):
"""
Retrieves the reset status of SFP
Returns:
A Boolean, True if reset enabled, False if disabled
"""
if self.port_num < 53: #Copper port and sfp ports are suported.
return False
reset_path="{}{}{}".format(CPLD_I2C_PATH , "module_reset_" , str(self.port_num))
val = self._api_helper.read_txt_file(reset_path)
if val is not None:
return int(val, 10) == 1
else:
return False
def get_rx_los(self):
"""
Retrieves the RX LOS (lost-of-signal) status of SFP
Returns:
A Boolean, True if SFP has RX LOS, False if not.
Note : RX LOS status is latched until a call to get_rx_los or a reset.
"""
rx_los = False
if self.port_num < 49: #Copper port, no sysfs
return False
if self.port_num < 53:
rx_path = "{}{}{}".format(CPLD_I2C_PATH, '/module_rx_los_', self.port_num)
rx_los=self._api_helper.read_txt_file(rx_path)
if rx_los is None:
return False
else:
rx_los_list = []
dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(
QSFP_CHANNL_RX_LOS_STATUS_OFFSET, QSFP_CHANNL_RX_LOS_STATUS_WIDTH) if self.get_presence() else None
if dom_channel_monitor_raw is not None:
rx_los_data = int(dom_channel_monitor_raw[0], 16)
rx_los_list.append(rx_los_data & 0x01 != 0)
rx_los_list.append(rx_los_data & 0x02 != 0)
rx_los_list.append(rx_los_data & 0x04 != 0)
rx_los_list.append(rx_los_data & 0x08 != 0)
rx_los = rx_los_list[0] and rx_los_list[1] and rx_los_list[2] and rx_los_list[3]
return rx_los
def get_tx_fault(self):
"""
Retrieves the TX fault status of SFP
Returns:
A Boolean, True if SFP has TX fault, False if not
Note : TX fault status is lached until a call to get_tx_fault or a reset.
"""
tx_fault = False
if self.port_num < 49: #Copper port, no sysfs
return False
if self.port_num < 53:
tx_path = "{}{}{}".format(CPLD_I2C_PATH, '/module_tx_fault_', self.port_num)
tx_fault=self._api_helper.read_txt_file(tx_path)
if tx_fault is None:
return False
else:
tx_fault_list = []
dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(
QSFP_CHANNL_TX_FAULT_STATUS_OFFSET, QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) if self.get_presence() else None
if dom_channel_monitor_raw is not None:
tx_fault_data = int(dom_channel_monitor_raw[0], 16)
tx_fault_list.append(tx_fault_data & 0x01 != 0)
tx_fault_list.append(tx_fault_data & 0x02 != 0)
tx_fault_list.append(tx_fault_data & 0x04 != 0)
tx_fault_list.append(tx_fault_data & 0x08 != 0)
tx_fault = tx_fault_list[0] and tx_fault_list[1] and tx_fault_list[2] and tx_fault_list[3]
return tx_fault
def get_tx_disable(self):
"""
Retrieves the tx_disable status of this SFP
Returns:
A Boolean, True if tx_disable is enabled, False if disabled
"""
if self.port_num < 49: #Copper port, no sysfs
return False
if self.port_num < 53:
tx_disable = False
tx_path = "{}{}{}".format(CPLD_I2C_PATH, '/module_tx_disable_', self.port_num)
tx_disable=self._api_helper.read_txt_file(tx_path)
if tx_disable is not None:
return tx_disable
else:
return False
else:
tx_disable_list = []
sfpd_obj = sff8436Dom()
if sfpd_obj is None:
return False
dom_control_raw = self.__read_eeprom_specific_bytes(
QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None
if dom_control_raw is not None:
dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0)
tx_disable_list.append(
'On' == dom_control_data['data']['TX1Disable']['value'])
tx_disable_list.append(
'On' == dom_control_data['data']['TX2Disable']['value'])
tx_disable_list.append(
'On' == dom_control_data['data']['TX3Disable']['value'])
tx_disable_list.append(
'On' == dom_control_data['data']['TX4Disable']['value'])
return tx_disable_list
def get_tx_disable_channel(self):
"""
Retrieves the TX disabled channels in this SFP
Returns:
A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent
TX channels which have been disabled in this SFP.
As an example, a returned value of 0x5 indicates that channel 0
and channel 2 have been disabled.
"""
if self.port_num < 53:
# SFP doesn't support this feature
return False
else:
tx_disable_list = self.get_tx_disable()
if tx_disable_list is None:
return 0
tx_disabled = 0
for i in range(len(tx_disable_list)):
if tx_disable_list[i]:
tx_disabled |= 1 << i
return tx_disabled
def get_lpmode(self):
"""
Retrieves the lpmode (low power mode) status of this SFP
Returns:
A Boolean, True if lpmode is enabled, False if disabled
"""
if self.port_num < 53:
# SFP doesn't support this feature
return False
else:
power_set=self.get_power_set()
power_override = self.get_power_override()
return power_set and power_override
def reset(self):
"""
Reset SFP and return all user module settings to their default srate.
Returns:
A boolean, True if successful, False if not
"""
# Check for invalid port_num
if self.port_num < 53: #Copper port and sfp ports are not supported.
return False
reset_path = "{}{}{}".format(CPLD_I2C_PATH, 'module_reset_', self.port_num)
ret = self._api_helper.write_txt_file(reset_path, 1)
if ret is not True:
return ret
time.sleep(0.01)
ret = self._api_helper.write_txt_file(reset_path, 0)
time.sleep(0.2)
return ret
def tx_disable(self, tx_disable):
"""
Disable SFP TX for all channels
Args:
tx_disable : A Boolean, True to enable tx_disable mode, False to disable
tx_disable mode.
Returns:
A boolean, True if tx_disable is set successfully, False if not
"""
if self.port_num < 49: #Copper port, no sysfs
return False
if self.port_num < 53:
tx_path = "{}{}{}".format(CPLD_I2C_PATH, '/module_tx_disable_', self.port_num)
ret = self._api_helper.write_txt_file(tx_path, 1 if tx_disable else 0)
if ret is not None:
time.sleep(0.01)
return ret
else:
return False
else:
if not self.get_presence():
return False
sysfsfile_eeprom = None
try:
tx_disable_ctl = 0xf if tx_disable else 0x0
buffer = create_string_buffer(1)
if sys.version_info[0] >= 3:
buffer[0] = tx_disable_ctl
else:
buffer[0] = chr(tx_disable_ctl)
# Write to eeprom
sysfsfile_eeprom = open(
self.port_to_eeprom_mapping[self.port_num], "r+b")
sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET)
sysfsfile_eeprom.write(buffer[0])
except IOError as e:
print ('Error: unable to open file: ',str(e))
return False
finally:
if sysfsfile_eeprom is not None:
sysfsfile_eeprom.close()
time.sleep(0.01)
return True
def tx_disable_channel(self, channel, disable):
"""
Sets the tx_disable for specified SFP channels
Args:
channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3,
e.g. 0x5 for channel 0 and channel 2.
disable : A boolean, True to disable TX channels specified in channel,
False to enable
Returns:
A boolean, True if successful, False if not
"""
if self.port_num < 53:
return False # SFP doesn't support this feature
else:
if not self.get_presence():
return False
sysfsfile_eeprom = None
try:
channel_state = self.get_tx_disable_channel()
for i in range(4):
channel_mask = (1 << i)
if not (channel & channel_mask):
continue
if disable:
channel_state |= channel_mask
else:
channel_state &= ~channel_mask
buffer = create_string_buffer(1)
if sys.version_info[0] >= 3:
buffer[0] = channel_state
else:
buffer[0] = chr(channel_state)
# Write to eeprom
sysfsfile_eeprom = open(
self.port_to_eeprom_mapping[self.port_num], "r+b")
sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET)
sysfsfile_eeprom.write(buffer[0])
except IOError as e:
print ('Error: unable to open file: ', str(e))
return False
finally:
if sysfsfile_eeprom is not None:
sysfsfile_eeprom.close()
time.sleep(0.01)
return True
def set_lpmode(self, lpmode):
"""
Sets the lpmode (low power mode) of SFP
Args:
lpmode: A Boolean, True to enable lpmode, False to disable it
Note : lpmode can be overridden by set_power_override
Returns:
A boolean, True if lpmode is set successfully, False if not
"""
if self.port_num < 53:
return False # SFP doesn't support this feature
else:
if lpmode is True:
self.set_power_override(True, True)
else:
self.set_power_override(False, False)
return True
def set_power_override(self, power_override, power_set):
"""
Sets SFP power level using power_override and power_set
Args:
power_override :
A Boolean, True to override set_lpmode and use power_set
to control SFP power, False to disable SFP power control
through power_override/power_set and use set_lpmode
to control SFP power.
power_set :
Only valid when power_override is True.
A Boolean, True to set SFP to low power mode, False to set
SFP to high power mode.
Returns:
A boolean, True if power-override and power_set are set successfully,
False if not
"""
if self.port_num < 53:
return False # SFP doesn't support this feature
else:
if not self.get_presence():
return False
try:
power_override_bit = (1 << 0) if power_override else 0
power_set_bit = (1 << 1) if power_set else (1 << 3)
buffer = create_string_buffer(1)
if sys.version_info[0] >= 3:
buffer[0] = (power_override_bit | power_set_bit)
else:
buffer[0] = chr(power_override_bit | power_set_bit)
# Write to eeprom
with open(self.port_to_eeprom_mapping[self.port_num], "r+b") as fd:
fd.seek(QSFP_POWEROVERRIDE_OFFSET)
fd.write(buffer[0])
time.sleep(0.01)
except IOError as e:
print ('Error: unable to open file: ', str(e))
return False
return True
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
name = None
sfputil_helper = SfpUtilHelper()
sfputil_helper.read_porttab_mappings(
self.__get_path_to_port_config_file())
name = sfputil_helper.logical[self.index] or "Unknown"
return name
def get_presence(self):
"""
Retrieves the presence of the device
Returns:
bool: True if device is present, False if not
"""
if self.port_num < 49: #Copper port, no sysfs
return False
present_path = "{}{}{}".format(CPLD_I2C_PATH, '/module_present_', self.port_num)
val=self._api_helper.read_txt_file(present_path)
if val is not None:
return int(val, 10)==1
else:
return False
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
return self.get_presence()
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return self.port_num
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True

View File

@ -0,0 +1,236 @@
#############################################################################
# Edgecore
#
# Thermal contains an implementation of SONiC Platform Base API and
# provides the thermal device status which are available in the platform
#
#############################################################################
import os
import os.path
import glob
try:
from sonic_platform_base.thermal_base import ThermalBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
PSU_I2C_PATH = "/sys/bus/i2c/devices/{}-00{}/"
PSU_I2C_MAPPING = {
0: {
"num": 10,
"addr": "58"
},
1: {
"num": 11,
"addr": "59"
},
}
PSU_CPLD_I2C_MAPPING = {
0: {
"num": 10,
"addr": "50"
},
1: {
"num": 11,
"addr": "51"
},
}
class Thermal(ThermalBase):
"""Platform-specific Thermal class"""
THERMAL_NAME_LIST = []
PSU_THERMAL_NAME_LIST = []
SYSFS_PATH = "/sys/bus/i2c/devices"
def __init__(self, thermal_index=0, is_psu=False, psu_index=0):
self.index = thermal_index
self.is_psu = is_psu
self.psu_index = psu_index
if self.is_psu:
psu_i2c_bus = PSU_I2C_MAPPING[psu_index]["num"]
psu_i2c_addr = PSU_I2C_MAPPING[psu_index]["addr"]
self.psu_hwmon_path = PSU_I2C_PATH.format(psu_i2c_bus,
psu_i2c_addr)
psu_i2c_bus = PSU_CPLD_I2C_MAPPING[psu_index]["num"]
psu_i2c_addr = PSU_CPLD_I2C_MAPPING[psu_index]["addr"]
self.cpld_path = PSU_I2C_PATH.format(psu_i2c_bus, psu_i2c_addr)
# Add thermal name
self.THERMAL_NAME_LIST.append("Temp sensor 1")
self.THERMAL_NAME_LIST.append("Temp sensor 2")
self.THERMAL_NAME_LIST.append("Temp sensor 3")
self.PSU_THERMAL_NAME_LIST.append("PSU-1 temp sensor 1")
self.PSU_THERMAL_NAME_LIST.append("PSU-2 temp sensor 1")
# Set hwmon path
i2c_path = {
0: "14-0048/hwmon/hwmon*/",
1: "24-004b/hwmon/hwmon*/",
2: "25-004a/hwmon/hwmon*/"
}.get(self.index, None)
self.hwmon_path = "{}/{}".format(self.SYSFS_PATH, i2c_path)
self.ss_key = self.THERMAL_NAME_LIST[self.index]
self.ss_index = 1
def __read_txt_file(self, file_path):
for filename in glob.glob(file_path):
try:
with open(filename, 'r') as fd:
data =fd.readline().rstrip()
return data
except IOError as e:
pass
return None
def __get_temp(self, temp_file):
if not self.is_psu:
temp_file_path = os.path.join(self.hwmon_path, temp_file)
else:
temp_file_path = temp_file
raw_temp = self.__read_txt_file(temp_file_path)
if raw_temp is not None:
return float(raw_temp)/1000
else:
return 0
def __set_threshold(self, file_name, temperature):
if self.is_psu:
return True
temp_file_path = os.path.join(self.hwmon_path, file_name)
for filename in glob.glob(temp_file_path):
try:
with open(filename, 'w') as fd:
fd.write(str(temperature))
return True
except IOError as e:
print("IOError")
def get_temperature(self):
"""
Retrieves current temperature reading from thermal
Returns:
A float number of current temperature in Celsius up to nearest thousandth
of one degree Celsius, e.g. 30.125
"""
if not self.is_psu:
temp_file = "temp{}_input".format(self.ss_index)
else:
temp_file = self.psu_hwmon_path + "psu_temp1_input"
return self.__get_temp(temp_file)
def get_high_threshold(self):
"""
Retrieves the high threshold temperature of thermal
Returns:
A float number, the high threshold temperature of thermal in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125
"""
if self.is_psu:
return 0
temp_file = "temp{}_max".format(self.ss_index)
return self.__get_temp(temp_file)
def set_high_threshold(self, temperature):
"""
Sets the high threshold temperature of thermal
Args :
temperature: A float number up to nearest thousandth of one degree Celsius,
e.g. 30.125
Returns:
A boolean, True if threshold is set successfully, False if not
"""
temp_file = "temp{}_max".format(self.ss_index)
temperature = temperature *1000
self.__set_threshold(temp_file, temperature)
return True
def get_name(self):
"""
Retrieves the name of the thermal device
Returns:
string: The name of the thermal device
"""
if self.is_psu:
return self.PSU_THERMAL_NAME_LIST[self.psu_index]
else:
return self.THERMAL_NAME_LIST[self.index]
def get_presence(self):
"""
Retrieves the presence of the Thermal
Returns:
bool: True if Thermal is present, False if not
"""
if self.is_psu:
val = self.__read_txt_file(self.cpld_path + "psu_present")
return int(val, 10) == 1
temp_file = "temp{}_input".format(self.ss_index)
temp_file_path = os.path.join(self.hwmon_path, temp_file)
raw_txt = self.__read_txt_file(temp_file_path)
if raw_txt is not None:
return True
else:
return False
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
if self.is_psu:
temp_file = self.psu_hwmon_path + "psu_temp_fault"
return self.get_presence() and (not int(
self.__read_txt_file(temp_file)))
file_str = "temp{}_input".format(self.ss_index)
file_path = os.path.join(self.hwmon_path, file_str)
raw_txt = self.__read_txt_file(file_path)
if raw_txt is None:
return False
else:
return int(raw_txt) != 0
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return "N/A"
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return "N/A"
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return self.index+1
def is_replaceable(self):
"""
Retrieves whether thermal module is replaceable
Returns:
A boolean value, True if replaceable, False if not
"""
return False

View File

@ -1,5 +1,5 @@
{
"skip_ledd": true,
"skip_thermalctld": true
"skip_pcied": true
}

View File

@ -1,3 +1,4 @@
CONSOLE_PORT=0x3f8
CONSOLE_DEV=0
CONSOLE_SPEED=115200
ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="intel_iommu=off modprobe.blacklist=i2c-ismt,i2c_ismt,i2c-i801,i2c_i801"

View File

@ -148,7 +148,7 @@ class SfpUtil(SfpUtilBase):
cage_num = port_num
if (port_num >= self.QSFP_PORT_START):
cage_num = (port_num - self.QSFP_PORT_START)/4
cage_num = cage_num + self.QSFP_PORT_START
cage_num = int(cage_num + self.QSFP_PORT_START)
return cage_num

View File

@ -1,5 +1,5 @@
{
"skip_ledd": true,
"skip_thermalctld": true
"skip_pcied": true
}

View File

@ -1,2 +1,2 @@
__all__ = ['chassis', 'eeprom', 'platform', 'psu', 'sfp', 'thermal', 'fan']
__all__ = [ "platform", "chassis", "sfp", "eeprom", "component", "psu", "thermal", "fan", "fan_drawer" ]
from . import platform

View File

@ -28,7 +28,14 @@ HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/"
PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/"
REBOOT_CAUSE_FILE = "reboot-cause.txt"
PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt"
HOST_CHK_CMD = "docker > /dev/null 2>&1"
HOST_CHK_CMD = "which systemctl > /dev/null 2>&1"
SYSLED_FNODE= "/sys/class/leds/as5835_54x_led::diag/brightness"
SYSLED_MODES = {
"0" : "STATUS_LED_COLOR_OFF",
"1" : "STATUS_LED_COLOR_GREEN",
"3" : "STATUS_LED_COLOR_AMBER"
}
class Chassis(ChassisBase):
@ -37,7 +44,6 @@ class Chassis(ChassisBase):
def __init__(self):
ChassisBase.__init__(self)
self._api_helper = APIHelper()
self._api_helper = APIHelper()
self.is_host = self._api_helper.is_host()
self.config_data = {}
@ -54,15 +60,16 @@ class Chassis(ChassisBase):
for index in range(0, PORT_END):
sfp = Sfp(index)
self._sfp_list.append(sfp)
self._sfpevent = SfpEvent(self._sfp_list)
self.sfp_module_initialized = True
def __initialize_fan(self):
from sonic_platform.fan import Fan
for fant_index in range(0, NUM_FAN_TRAY):
for fan_index in range(0, NUM_FAN):
fan = Fan(fant_index, fan_index)
self._fan_list.append(fan)
from sonic_platform.fan_drawer import FanDrawer
for fant_index in range(NUM_FAN_TRAY):
fandrawer = FanDrawer(fant_index)
self._fan_drawer_list.append(fandrawer)
self._fan_list.extend(fandrawer._fan_list)
def __initialize_psu(self):
from sonic_platform.psu import Psu
for index in range(0, NUM_PSU):
@ -84,12 +91,12 @@ class Chassis(ChassisBase):
for index in range(0, NUM_COMPONENT):
component = Component(index)
self._component_list.append(component)
def __initialize_watchdog(self):
from sonic_platform.watchdog import Watchdog
self._watchdog = Watchdog()
def __is_host(self):
return os.system(HOST_CHK_CMD) == 0
@ -101,23 +108,14 @@ class Chassis(ChassisBase):
except IOError:
pass
return None
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return self._eeprom.get_pn()
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
return self._api_helper.hwsku
return self._eeprom.get_product_name()
def get_presence(self):
"""
@ -144,7 +142,15 @@ class Chassis(ChassisBase):
"""
return self._eeprom.get_mac()
def get_serial_number(self):
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return self._eeprom.get_pn()
def get_serial(self):
"""
Retrieves the hardware serial number for the chassis
Returns:
@ -173,7 +179,7 @@ class Chassis(ChassisBase):
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
to pass a description of the reboot cause.
"""
reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE)
sw_reboot_cause = self._api_helper.read_txt_file(
reboot_cause_path) or "Unknown"
@ -185,10 +191,7 @@ class Chassis(ChassisBase):
# SFP event
if not self.sfp_module_initialized:
self.__initialize_sfp()
status, sfp_event = SfpEvent(self._sfp_list).get_sfp_event(timeout)
return status, sfp_event
return self._sfpevent.get_sfp_event(timeout)
def get_sfp(self, index):
"""
@ -212,3 +215,40 @@ class Chassis(ChassisBase):
sys.stderr.write("SFP index {} out of range (1-{})\n".format(
index, len(self._sfp_list)))
return sfp
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return -1
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return False
def initizalize_system_led(self):
return True
def get_status_led(self):
val = self._api_helper.read_txt_file(SYSLED_FNODE)
return SYSLED_MODES[val] if val in SYSLED_MODES else "UNKNOWN"
def set_status_led(self, color):
mode = None
for key, val in SYSLED_MODES.items():
if val == color:
mode = key
break
if mode is None:
return False
else:
return self._api_helper.write_txt_file(SYSLED_FNODE, mode)

View File

@ -1,5 +1,5 @@
#############################################################################
# Celestica
# Edgecore
#
# Component contains an implementation of SONiC Platform Base API and
# provides the components firmware management function
@ -67,14 +67,14 @@ class Component(ComponentBase):
with open(BIOS_VERSION_PATH, 'r') as fd:
bios_version = fd.read()
return bios_version.strip()
except Exception as e:
except Exception as e:
print('Get exception when read bios')
return None
def __get_cpld_version(self):
# Retrieves the CPLD firmware version
cpld_version = dict()
for cpld_name in CPLD_ADDR_MAPPING:
for cpld_name in CPLD_ADDR_MAPPING:
try:
cpld_path = "{}{}{}".format(SYSFS_PATH, CPLD_ADDR_MAPPING[cpld_name], '/version')
cpld_version_raw= self._api_helper.read_txt_file(cpld_path)
@ -126,3 +126,55 @@ class Component(ComponentBase):
A boolean, True if install successfully, False if not
"""
raise NotImplementedError
def get_presence(self):
"""
Retrieves the presence of the device
Returns:
bool: True if device is present, False if not
"""
return True
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return 'N/A'
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return 'N/A'
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
return True
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device.
If the agent cannot determine the parent-relative position
for some reason, or if the associated value of
entPhysicalContainedIn is'0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device
or -1 if cannot determine the position
"""
return -1
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return False

View File

@ -20,7 +20,7 @@ class Tlv(eeprom_tlvinfo.TlvInfoDecoder):
EEPROM_DECODE_HEADLINES = 6
def __init__(self):
self._eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom"
self._eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom"
super(Tlv, self).__init__(self._eeprom_path, 0, '', True)
self._eeprom = self._load_eeprom()
@ -123,9 +123,12 @@ class Tlv(eeprom_tlvinfo.TlvInfoDecoder):
def get_pn(self):
return self._eeprom.get('0x22', NULL)
def get_serial(self):
return self._eeprom.get('0x23', NULL)
def get_mac(self):
return self._eeprom.get('0x24', NULL)
def get_product_name(self):
return self._eeprom.get('0x21', NULL)

View File

@ -1,42 +1,49 @@
try:
import time
from .helper import APIHelper
from sonic_py_common.logger import Logger
except ImportError as e:
raise ImportError(repr(e) + " - required module not found")
POLL_INTERVAL_IN_SEC = 1
class SfpEvent:
''' Listen to insert/remove sfp events '''
def __init__(self, sfp_list):
self._api_helper = APIHelper()
self._sfp_list = sfp_list
self._logger = Logger()
self._sfp_change_event_data = {'present': 0}
sfp_change_event_data = {'valid': 0, 'last': 0, 'present': 0}
def get_sfp_event(self, timeout=2000):
now = time.time()
port_dict = {}
change_dict = {}
change_dict['sfp'] = port_dict
if timeout < 1000:
timeout = 1000
timeout = timeout / float(1000) # Convert to secs
if now < (self.sfp_change_event_data['last'] + timeout) and self.sfp_change_event_data['valid']:
return True, change_dict
def get_presence_bitmap(self):
bitmap = 0
for sfp in self._sfp_list:
modpres = sfp.get_presence()
i=sfp.port_num-1
if modpres:
bitmap = bitmap | (1 << i)
return bitmap
changed_ports = self.sfp_change_event_data['present'] ^ bitmap
if changed_ports:
def get_sfp_event(self, timeout=2000):
port_dict = {}
change_dict = {}
change_dict['sfp'] = port_dict
if timeout < 1000:
cd_ms = 1000
else:
cd_ms = timeout
while cd_ms > 0:
bitmap = self.get_presence_bitmap()
changed_ports = self._sfp_change_event_data['present'] ^ bitmap
if changed_ports != 0:
break
time.sleep(POLL_INTERVAL_IN_SEC)
# timeout=0 means wait for event forever
if timeout != 0:
cd_ms = cd_ms - POLL_INTERVAL_IN_SEC * 1000
if changed_ports != 0:
for sfp in self._sfp_list:
i=sfp.port_num-1
if (changed_ports & (1 << i)):
@ -47,9 +54,7 @@ class SfpEvent:
# Update the cache dict
self.sfp_change_event_data['present'] = bitmap
self.sfp_change_event_data['last'] = now
self.sfp_change_event_data['valid'] = 1
self._sfp_change_event_data['present'] = bitmap
return True, change_dict
else:
return True, change_dict

View File

@ -15,9 +15,10 @@ except ImportError as e:
raise ImportError(str(e) + "- required module not found")
PSU_FAN_MAX_RPM = 26688
CPLD_I2C_PATH = "/sys/bus/i2c/devices/3-0063/fan"
PSU_HWMON_I2C_PATH ="/sys/bus/i2c/devices/{}-00{}/"
PSU_I2C_MAPPING = {
SPEED_TOLERANCE = 15
CPLD_FAN_I2C_PATH = "/sys/bus/i2c/devices/3-0063/fan"
I2C_PATH ="/sys/bus/i2c/devices/{}-00{}/"
PSU_HWMON_I2C_MAPPING = {
0: {
"num": 11,
"addr": "58"
@ -28,6 +29,20 @@ PSU_I2C_MAPPING = {
},
}
PSU_CPLD_I2C_MAPPING = {
0: {
"num": 11,
"addr": "50"
},
1: {
"num": 12,
"addr": "53"
},
}
FAN_NAME_LIST = ["FAN-1F", "FAN-1R", "FAN-2F", "FAN-2R",
"FAN-3F", "FAN-3R", "FAN-4F", "FAN-4R",
"FAN-5F", "FAN-5R"]
@ -42,13 +57,18 @@ class Fan(FanBase):
self.is_psu_fan = is_psu_fan
if self.is_psu_fan:
self.psu_index = psu_index
self.psu_i2c_num = PSU_I2C_MAPPING[self.psu_index]['num']
self.psu_i2c_addr = PSU_I2C_MAPPING[self.psu_index]['addr']
self.psu_hwmon_path = PSU_HWMON_I2C_PATH.format(
self.psu_i2c_num = PSU_HWMON_I2C_MAPPING[self.psu_index]['num']
self.psu_i2c_addr = PSU_HWMON_I2C_MAPPING[self.psu_index]['addr']
self.psu_hwmon_path = I2C_PATH.format(
self.psu_i2c_num, self.psu_i2c_addr)
self.psu_i2c_num = PSU_CPLD_I2C_MAPPING[self.psu_index]['num']
self.psu_i2c_addr = PSU_CPLD_I2C_MAPPING[self.psu_index]['addr']
self.psu_cpld_path = I2C_PATH.format(
self.psu_i2c_num, self.psu_i2c_addr)
FanBase.__init__(self)
def get_direction(self):
"""
@ -60,9 +80,9 @@ class Fan(FanBase):
if not self.is_psu_fan:
dir_str = "{}{}{}".format(CPLD_I2C_PATH, self.fan_tray_index+1, '_direction')
dir_str = "{}{}{}".format(CPLD_FAN_I2C_PATH, self.fan_tray_index+1, '_direction')
val=self._api_helper.read_txt_file(dir_str)
if val is not None:
if val is not None:
if int(val, 10)==0:
direction=self.FAN_DIRECTION_EXHAUST
else:
@ -90,26 +110,26 @@ class Fan(FanBase):
Returns:
An integer, the percentage of full fan speed, in the range 0 (off)
to 100 (full speed)
"""
speed = 0
if self.is_psu_fan:
psu_fan_path= "{}{}".format(self.psu_hwmon_path, 'psu_fan1_speed_rpm')
fan_speed_rpm = self._api_helper.read_txt_file(psu_fan_path)
if fan_speed_rpm is not None:
speed = (int(fan_speed_rpm,10))*100/26688
speed = (int(fan_speed_rpm,10))*100/26688
if speed > 100:
speed=100
else:
return 0
elif self.get_presence():
speed_path = "{}{}".format(CPLD_I2C_PATH, '_duty_cycle_percentage')
speed_path = "{}{}".format(CPLD_FAN_I2C_PATH, '_duty_cycle_percentage')
speed=self._api_helper.read_txt_file(speed_path)
if speed is None:
return 0
return int(speed)
def get_target_speed(self):
"""
Retrieves the target (expected) speed of the fan
@ -123,7 +143,7 @@ class Fan(FanBase):
0 : when PWM mode is use
pwm : when pwm mode is not use
"""
return False #Not supported
return self.get_speed()
def get_speed_tolerance(self):
"""
@ -132,7 +152,7 @@ class Fan(FanBase):
An integer, the percentage of variance from target speed which is
considered tolerable
"""
return False #Not supported
return SPEED_TOLERANCE
def set_speed(self, speed):
"""
@ -146,7 +166,7 @@ class Fan(FanBase):
"""
if not self.is_psu_fan and self.get_presence():
speed_path = "{}{}".format(CPLD_I2C_PATH, '_duty_cycle_percentage')
speed_path = "{}{}".format(CPLD_FAN_I2C_PATH, '_duty_cycle_percentage')
return self._api_helper.write_txt_file(speed_path, int(speed))
return False
@ -195,17 +215,18 @@ class Fan(FanBase):
Returns:
bool: True if FAN is present, False if not
"""
present_path = "{}{}{}".format(CPLD_I2C_PATH, self.fan_tray_index+1, '_present')
val=self._api_helper.read_txt_file(present_path)
if not self.is_psu_fan:
if val is not None:
return int(val, 10)==1
else:
return False
if self.is_psu_fan:
present_path="{}{}".format(self.psu_cpld_path, 'psu_present')
else:
return True
present_path = "{}{}{}".format(CPLD_FAN_I2C_PATH, self.fan_tray_index+1, '_present')
val=self._api_helper.read_txt_file(present_path)
if val is not None:
return int(val, 10)==1
else:
return False
def get_status(self):
"""
@ -221,7 +242,7 @@ class Fan(FanBase):
else:
return False
else:
path = "{}{}{}".format(CPLD_I2C_PATH, self.fan_index+1, '_fault')
path = "{}{}{}".format(CPLD_FAN_I2C_PATH, self.fan_tray_index+1, '_fault')
val=self._api_helper.read_txt_file(path)
if val is not None:
return int(val, 10)==0
@ -245,3 +266,25 @@ class Fan(FanBase):
string: Serial number of device
"""
return "N/A"
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device.
If the agent cannot determine the parent-relative position
for some reason, or if the associated value of
entPhysicalContainedIn is'0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device
or -1 if cannot determine the position
"""
return (self.fan_index+1) \
if not self.is_psu_fan else (self.psu_index+1)
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True if not self.is_psu_fan else False

View File

@ -0,0 +1,90 @@
########################################################################
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Fan-Drawers' information available in the platform.
#
########################################################################
try:
from sonic_platform_base.fan_drawer_base import FanDrawerBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
FANS_PER_FANTRAY = 2
class FanDrawer(FanDrawerBase):
"""Platform-specific Fan class"""
def __init__(self, fantray_index):
FanDrawerBase.__init__(self)
# FanTray is 0-based in platforms
self.fantrayindex = fantray_index
self.__initialize_fan_drawer()
def __initialize_fan_drawer(self):
from sonic_platform.fan import Fan
for i in range(FANS_PER_FANTRAY):
self._fan_list.append(Fan(self.fantrayindex, i))
def get_name(self):
"""
Retrieves the fan drawer name
Returns:
string: The name of the device
"""
return "FanTray{}".format(self.fantrayindex+1)
def get_presence(self):
"""
Retrieves the presence of the device
Returns:
bool: True if device is present, False if not
"""
return self._fan_list[0].get_presence()
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return self._fan_list[0].get_model()
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return self._fan_list[0].get_serial()
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
return self._fan_list[0].get_status()
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device.
If the agent cannot determine the parent-relative position
for some reason, or if the associated value of
entPhysicalContainedIn is'0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device
or -1 if cannot determine the position
"""
return (self.fantrayindex+1)
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True

View File

@ -51,7 +51,7 @@ class APIHelper():
def read_txt_file(self, file_path):
try:
with open(file_path, 'r') as fd:
with open(file_path, 'r', errors='replace') as fd:
data = fd.read()
return data.strip()
except IOError:

View File

@ -10,7 +10,7 @@
try:
from sonic_platform_base.psu_base import PsuBase
#from sonic_platform.fan import Fan
from sonic_platform.thermal import Thermal
from .helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
@ -64,6 +64,8 @@ class Psu(PsuBase):
for fan_index in range(0, PSU_NUM_FAN[self.index]):
fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index)
self._fan_list.append(fan)
self._thermal_list.append(Thermal(is_psu=True, psu_index=self.index))
def get_voltage(self):
"""
@ -154,7 +156,7 @@ class Psu(PsuBase):
return float(val)/1000
else:
return 0
def get_temperature_high_threshold(self):
"""
Retrieves the high threshold temperature of PSU
@ -251,3 +253,20 @@ class Psu(PsuBase):
if serial is None:
return "N/A"
return serial
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return self.index+1
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True

View File

@ -13,108 +13,14 @@ import sys
from ctypes import create_string_buffer
try:
from sonic_platform_base.sfp_base import SfpBase
from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom
from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId
from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom
from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId
#from sonic_platform_base.sonic_sfp.sff8472 import sffbase
from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper
from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase
from .helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CPLD_I2C_PATH = "/sys/bus/i2c/devices/"
QSFP_INFO_OFFSET = 128
QSFP_DOM_OFFSET = 0
SFP_INFO_OFFSET = 0
SFP_DOM_OFFSET = 256
XCVR_INTFACE_BULK_OFFSET = 0
XCVR_INTFACE_BULK_WIDTH_QSFP = 20
XCVR_INTFACE_BULK_WIDTH_SFP = 21
XCVR_HW_REV_WIDTH_QSFP = 2
XCVR_HW_REV_WIDTH_SFP = 4
XCVR_CABLE_LENGTH_WIDTH_QSFP = 5
XCVR_VENDOR_NAME_OFFSET = 20
XCVR_VENDOR_NAME_WIDTH = 16
XCVR_VENDOR_OUI_OFFSET = 37
XCVR_VENDOR_OUI_WIDTH = 3
XCVR_VENDOR_PN_OFFSET = 40
XCVR_VENDOR_PN_WIDTH = 16
XCVR_HW_REV_OFFSET = 56
XCVR_HW_REV_WIDTH_OSFP = 2
XCVR_HW_REV_WIDTH_SFP = 4
XCVR_VENDOR_SN_OFFSET = 68
XCVR_VENDOR_SN_WIDTH = 16
XCVR_VENDOR_DATE_OFFSET = 84
XCVR_VENDOR_DATE_WIDTH = 8
XCVR_DOM_CAPABILITY_OFFSET = 92
XCVR_DOM_CAPABILITY_WIDTH = 1
# Offset for values in QSFP eeprom
QSFP_DOM_REV_OFFSET = 1
QSFP_DOM_REV_WIDTH = 1
QSFP_TEMPE_OFFSET = 22
QSFP_TEMPE_WIDTH = 2
QSFP_VOLT_OFFSET = 26
QSFP_VOLT_WIDTH = 2
QSFP_CHANNL_MON_OFFSET = 34
QSFP_CHANNL_MON_WIDTH = 16
QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24
QSFP_CONTROL_OFFSET = 86
QSFP_CONTROL_WIDTH = 8
QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3
QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1
QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4
QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1
QSFP_POWEROVERRIDE_OFFSET = 93
QSFP_POWEROVERRIDE_WIDTH = 1
QSFP_MODULE_THRESHOLD_OFFSET = 128
QSFP_MODULE_THRESHOLD_WIDTH = 24
QSFP_CHANNEL_THRESHOLD_OFFSET = 176
QSFP_CHANNEL_THRESHOLD_WIDTH = 16
qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)',
'Length OM2(m)', 'Length OM1(m)',
'Length Cable Assembly(m)')
qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes',
'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes',
'Fibre Channel link length/Transmitter Technology',
'Fibre Channel transmission media', 'Fibre Channel Speed')
# Offset for values in SFP eeprom
SFP_TEMPE_OFFSET = 96
SFP_TEMPE_WIDTH = 2
SFP_VOLT_OFFSET = 98
SFP_VOLT_WIDTH = 2
SFP_CHANNL_MON_OFFSET = 100
SFP_CHANNL_MON_WIDTH = 6
SFP_MODULE_THRESHOLD_OFFSET = 0
SFP_MODULE_THRESHOLD_WIDTH = 40
SFP_CHANNL_THRESHOLD_OFFSET = 112
SFP_CHANNL_THRESHOLD_WIDTH = 2
SFP_STATUS_CONTROL_OFFSET = 110
SFP_STATUS_CONTROL_WIDTH = 1
SFP_TX_DISABLE_HARD_BIT = 7
SFP_TX_DISABLE_SOFT_BIT = 6
sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)',
'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)',
'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)')
sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode',
'ESCONComplianceCodes', 'SONETComplianceCodes',
'EthernetComplianceCodes', 'FibreChannelLinkLength',
'FibreChannelTechnology', 'SFP+CableTechnology',
'FibreChannelTransmissionMedia', 'FibreChannelSpeed')
class Sfp(SfpBase):
class Sfp(SfpOptoeBase):
"""Platform-specific Sfp class"""
# Port number
@ -125,7 +31,7 @@ class Sfp(SfpBase):
# Path to sysfs
PLATFORM_ROOT_PATH = "/usr/share/sonic/device"
PMON_HWSKU_PATH = "/usr/share/sonic/hwsku"
HOST_CHK_CMD = "docker > /dev/null 2>&1"
HOST_CHK_CMD = "which systemctl > /dev/null 2>&1"
PLATFORM = "x86_64-accton_as5835_54x-r0"
HWSKU = "Accton-AS5835-54X"
@ -194,6 +100,7 @@ class Sfp(SfpBase):
}
def __init__(self, sfp_index=0):
SfpOptoeBase.__init__(self)
self._api_helper=APIHelper()
# Init index
self.index = sfp_index
@ -204,44 +111,15 @@ class Sfp(SfpBase):
self.port_to_eeprom_mapping = {}
for x in range(self.PORT_START, self.PORT_END + 1):
self.port_to_eeprom_mapping[x] = eeprom_path.format(self._port_to_i2c_mapping[x])
def get_eeprom_path(self):
return self.port_to_eeprom_mapping[self.port_num]
self.info_dict_keys = ['type', 'vendor_rev', 'serial', 'manufacturer', 'model', 'connector', 'encoding', 'ext_identifier',
'ext_rateselect_compliance', 'cable_type', 'cable_length', 'nominal_bit_rate', 'specification_compliance', 'vendor_date', 'vendor_oui',
'application_advertisement', 'type_abbrv_name']
self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'power_lpmode', 'tx_disable', 'tx_disable_channel', 'temperature', 'voltage',
'rx1power', 'rx2power', 'rx3power', 'rx4power', 'tx1bias', 'tx2bias', 'tx3bias', 'tx4bias', 'tx1power', 'tx2power', 'tx3power', 'tx4power']
self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', 'rxpowerhighwarning',
'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning']
SfpBase.__init__(self)
# For cage 1~38 are at cpld2, others are at cpld3.
def __get_cpld_num(self, port_num):
return 1 if (port_num < 39) else 2
def _convert_string_to_num(self, value_str):
if "-inf" in value_str:
return 'N/A'
elif "Unknown" in value_str:
return 'N/A'
elif 'dBm' in value_str:
t_str = value_str.rstrip('dBm')
return float(t_str)
elif 'mA' in value_str:
t_str = value_str.rstrip('mA')
return float(t_str)
elif 'C' in value_str:
t_str = value_str.rstrip('C')
return float(t_str)
elif 'Volts' in value_str:
t_str = value_str.rstrip('Volts')
return float(t_str)
else:
return 'N/A'
def __is_host(self):
return os.system(self.HOST_CHK_CMD) == 0
@ -277,422 +155,6 @@ class Sfp(SfpBase):
return eeprom_raw
def get_transceiver_info(self):
"""
Retrieves transceiver info of this SFP
Returns:
A dict which contains following keys/values :
========================================================================
keys |Value Format |Information
---------------------------|---------------|----------------------------
type |1*255VCHAR |type of SFP
vendor_rev |1*255VCHAR |vendor revision of SFP
serial |1*255VCHAR |serial number of the SFP
manufacturer |1*255VCHAR |SFP vendor name
model |1*255VCHAR |SFP model name
connector |1*255VCHAR |connector information
encoding |1*255VCHAR |encoding information
ext_identifier |1*255VCHAR |extend identifier
ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance
cable_length |INT |cable length in m
nominal_bit_rate |INT |nominal bit rate by 100Mbs
specification_compliance |1*255VCHAR |specification compliance
vendor_date |1*255VCHAR |vendor date
vendor_oui |1*255VCHAR |vendor OUI
application_advertisement |1*255VCHAR |supported applications advertisement
========================================================================
"""
# check present status
if self.port_num < 49:
sfpi_obj = sff8472InterfaceId() #SFP
else:
sfpi_obj = sff8436InterfaceId() #QSFP
if not self.get_presence() or not sfpi_obj:
return {}
if self.port_num < 49:
offset = SFP_INFO_OFFSET
sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_SFP)
else:
offset = QSFP_INFO_OFFSET
sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_QSFP)
sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(
sfp_interface_bulk_raw, 0)
sfp_vendor_name_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH)
sfp_vendor_name_data = sfpi_obj.parse_vendor_name(
sfp_vendor_name_raw, 0)
sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH)
sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(
sfp_vendor_pn_raw, 0)
if self.port_num < 49:
sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_SFP)
else:
sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_QSFP)
sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(
sfp_vendor_rev_raw, 0)
sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH)
sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(
sfp_vendor_sn_raw, 0)
sfp_vendor_oui_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH)
if sfp_vendor_oui_raw is not None:
sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(
sfp_vendor_oui_raw, 0)
sfp_vendor_date_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH)
sfp_vendor_date_data = sfpi_obj.parse_vendor_date(
sfp_vendor_date_raw, 0)
transceiver_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A')
compliance_code_dict = dict()
if sfp_interface_bulk_data:
transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value']
transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value']
transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value']
transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value']
transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value']
transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value']
transceiver_info_dict['manufacturer'] = sfp_vendor_name_data[
'data']['Vendor Name']['value'] if sfp_vendor_name_data else 'N/A'
transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] if sfp_vendor_pn_data else 'N/A'
transceiver_info_dict['vendor_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] if sfp_vendor_rev_data else 'N/A'
transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] if sfp_vendor_sn_data else 'N/A'
transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] if sfp_vendor_oui_data else 'N/A'
transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[
'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] if sfp_vendor_date_data else 'N/A'
transceiver_info_dict['cable_type'] = "Unknown"
transceiver_info_dict['cable_length'] = "Unknown"
if self.port_num < 49:
for key in sfp_cable_length_tup:
if key in sfp_interface_bulk_data['data']:
transceiver_info_dict['cable_type'] = key
transceiver_info_dict['cable_length'] = str(
sfp_interface_bulk_data['data'][key]['value'])
for key in sfp_compliance_code_tup:
if key in sfp_interface_bulk_data['data']['Specification compliance']['value']:
compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value']
transceiver_info_dict['specification_compliance'] = str(
compliance_code_dict)
transceiver_info_dict['nominal_bit_rate'] = str(
sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value'])
else:
for key in qsfp_cable_length_tup:
if key in sfp_interface_bulk_data['data']:
transceiver_info_dict['cable_type'] = key
transceiver_info_dict['cable_length'] = str(
sfp_interface_bulk_data['data'][key]['value'])
for key in qsfp_compliance_code_tup:
if key in sfp_interface_bulk_data['data']['Specification compliance']['value']:
compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value']
transceiver_info_dict['specification_compliance'] = str(
compliance_code_dict)
transceiver_info_dict['nominal_bit_rate'] = str(
sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value'])
return transceiver_info_dict
def get_transceiver_bulk_status(self):
"""
Retrieves transceiver bulk status of this SFP
Returns:
A dict which contains following keys/values :
========================================================================
keys |Value Format |Information
---------------------------|---------------|----------------------------
rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not.
tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not.
reset_status |BOOLEAN |reset status, True if SFP in reset, False if not.
lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not.
tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not.
tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0
| |to channel 3.
temperature |INT |module temperature in Celsius
voltage |INT |supply voltage in mV
tx<n>bias |INT |TX Bias Current in mA, n is the channel number,
| |for example, tx2bias stands for tx bias of channel 2.
rx<n>power |INT |received optical power in mW, n is the channel number,
| |for example, rx2power stands for rx power of channel 2.
tx<n>power |INT |TX output power in mW, n is the channel number,
| |for example, tx2power stands for tx power of channel 2.
========================================================================
"""
# check present status
if self.port_num < 49: #SFP case
sfpd_obj = sff8472Dom()
if not self.get_presence() or not sfpd_obj:
return {}
eeprom_ifraw = self.__read_eeprom_specific_bytes(0, SFP_DOM_OFFSET)
sfpi_obj = sff8472InterfaceId(eeprom_ifraw)
cal_type = sfpi_obj.get_calibration_type()
sfpd_obj._calibration_type = cal_type
offset = SFP_DOM_OFFSET
transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A')
dom_temperature_raw = self.__read_eeprom_specific_bytes(
(offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH)
if dom_temperature_raw is not None:
dom_temperature_data = sfpd_obj.parse_temperature(
dom_temperature_raw, 0)
transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
dom_voltage_raw = self.__read_eeprom_specific_bytes(
(offset + SFP_VOLT_OFFSET), SFP_VOLT_WIDTH)
if dom_voltage_raw is not None:
dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0)
transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(
(offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH)
if dom_channel_monitor_raw is not None:
dom_voltage_data = sfpd_obj.parse_channel_monitor_params(
dom_channel_monitor_raw, 0)
transceiver_dom_info_dict['tx1power'] = dom_voltage_data['data']['TXPower']['value']
transceiver_dom_info_dict['rx1power'] = dom_voltage_data['data']['RXPower']['value']
transceiver_dom_info_dict['tx1bias'] = dom_voltage_data['data']['TXBias']['value']
else: #QSFP case
sfpd_obj = sff8436Dom()
sfpi_obj = sff8436InterfaceId()
if not self.get_presence() or not sfpi_obj or not sfpd_obj:
return {}
transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A')
offset = QSFP_DOM_OFFSET
offset_xcvr = QSFP_INFO_OFFSET
# QSFP capability byte parse, through this byte can know whether it support tx_power or not.
# TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436,
# need to add more code for determining the capability and version compliance
# in SFF-8636 dom capability definitions evolving with the versions.
qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes(
(offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH)
if qsfp_dom_capability_raw is not None:
qspf_dom_capability_data = sfpi_obj.parse_dom_capability(
qsfp_dom_capability_raw, 0)
else:
return None
dom_temperature_raw = self.__read_eeprom_specific_bytes(
(offset + QSFP_TEMPE_OFFSET), QSFP_TEMPE_WIDTH)
if dom_temperature_raw is not None:
dom_temperature_data = sfpd_obj.parse_temperature(
dom_temperature_raw, 0)
transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
dom_voltage_raw = self.__read_eeprom_specific_bytes(
(offset + QSFP_VOLT_OFFSET), QSFP_VOLT_WIDTH)
if dom_voltage_raw is not None:
dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0)
transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
qsfp_dom_rev_raw = self.__read_eeprom_specific_bytes(
(offset + QSFP_DOM_REV_OFFSET), QSFP_DOM_REV_WIDTH)
if qsfp_dom_rev_raw is not None:
qsfp_dom_rev_data = sfpd_obj.parse_sfp_dom_rev(qsfp_dom_rev_raw, 0)
qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value']
# The tx_power monitoring is only available on QSFP which compliant with SFF-8636
# and claimed that it support tx_power with one indicator bit.
dom_channel_monitor_data = {}
dom_channel_monitor_raw = None
qsfp_tx_power_support = qspf_dom_capability_data['data']['Tx_power_support']['value']
if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')):
dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(
(offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WIDTH)
if dom_channel_monitor_raw is not None:
dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(
dom_channel_monitor_raw, 0)
else:
dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(
(offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH)
if dom_channel_monitor_raw is not None:
dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(
dom_channel_monitor_raw, 0)
transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TX1Power']['value']
transceiver_dom_info_dict['tx2power'] = dom_channel_monitor_data['data']['TX2Power']['value']
transceiver_dom_info_dict['tx3power'] = dom_channel_monitor_data['data']['TX3Power']['value']
transceiver_dom_info_dict['tx4power'] = dom_channel_monitor_data['data']['TX4Power']['value']
if dom_channel_monitor_raw:
transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RX1Power']['value']
transceiver_dom_info_dict['rx2power'] = dom_channel_monitor_data['data']['RX2Power']['value']
transceiver_dom_info_dict['rx3power'] = dom_channel_monitor_data['data']['RX3Power']['value']
transceiver_dom_info_dict['rx4power'] = dom_channel_monitor_data['data']['RX4Power']['value']
transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value']
transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value']
transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value']
transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value']
#End of else
for key in transceiver_dom_info_dict:
transceiver_dom_info_dict[key] = self._convert_string_to_num(
transceiver_dom_info_dict[key])
transceiver_dom_info_dict['rx_los'] = self.get_rx_los()
transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault()
transceiver_dom_info_dict['reset_status'] = self.get_reset_status()
transceiver_dom_info_dict['lp_mode'] = self.get_lpmode()
return transceiver_dom_info_dict
def get_transceiver_threshold_info(self):
"""
Retrieves transceiver threshold info of this SFP
Returns:
A dict which contains following keys/values :
========================================================================
keys |Value Format |Information
---------------------------|---------------|----------------------------
temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius.
templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius.
temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius.
templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius.
vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV.
vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV.
vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV.
vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV.
rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm.
rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm.
rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm.
rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm.
txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm.
txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm.
txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm.
txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm.
txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA.
txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA.
txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA.
txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA.
========================================================================
"""
# check present status
if self.port_num < 49:
sfpd_obj = sff8472Dom()
if not self.get_presence() and not sfpd_obj:
return {}
eeprom_ifraw = self.__read_eeprom_specific_bytes(0, SFP_DOM_OFFSET)
sfpi_obj = sff8472InterfaceId(eeprom_ifraw)
cal_type = sfpi_obj.get_calibration_type()
sfpd_obj._calibration_type = cal_type
offset = SFP_DOM_OFFSET
transceiver_dom_threshold_info_dict = dict.fromkeys(
self.threshold_dict_keys, 'N/A')
dom_module_threshold_raw = self.__read_eeprom_specific_bytes(
(offset + SFP_MODULE_THRESHOLD_OFFSET), SFP_MODULE_THRESHOLD_WIDTH)
if dom_module_threshold_raw is not None:
dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(
dom_module_threshold_raw, 0)
transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value']
transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value']
transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value']
transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value']
transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VoltageHighAlarm']['value']
transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VoltageLowAlarm']['value']
transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data[
'data']['VoltageHighWarning']['value']
transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VoltageLowWarning']['value']
transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value']
transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value']
transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value']
transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value']
transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value']
transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value']
transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value']
transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value']
transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value']
transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value']
transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value']
transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value']
for key in transceiver_dom_threshold_info_dict:
transceiver_dom_threshold_info_dict[key] = self._convert_string_to_num(
transceiver_dom_threshold_info_dict[key])
return transceiver_dom_threshold_info_dict
else:
sfpd_obj = sff8436Dom()
if not self.get_presence() or not sfpd_obj:
return {}
transceiver_dom_threshold_dict = dict.fromkeys(
self.threshold_dict_keys, 'N/A')
dom_thres_raw = self.__read_eeprom_specific_bytes(
QSFP_MODULE_THRESHOLD_OFFSET, QSFP_MODULE_THRESHOLD_WIDTH) if self.get_presence() and sfpd_obj else None
if dom_thres_raw:
module_threshold_values = sfpd_obj.parse_module_threshold_values(
dom_thres_raw, 0)
module_threshold_data = module_threshold_values.get('data')
if module_threshold_data:
transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['TempHighAlarm']['value']
transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['TempLowAlarm']['value']
transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['TempHighWarning']['value']
transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['TempLowWarning']['value']
transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['VccHighAlarm']['value']
transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['VccLowAlarm']['value']
transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['VccHighWarning']['value']
transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['VccLowWarning']['value']
dom_thres_raw = self.__read_eeprom_specific_bytes(
QSFP_CHANNEL_THRESHOLD_OFFSET, QSFP_CHANNEL_THRESHOLD_WIDTH) if self.get_presence() and sfpd_obj else None
channel_threshold_values = sfpd_obj.parse_channel_threshold_values(
dom_thres_raw, 0)
channel_threshold_data = channel_threshold_values.get('data')
if channel_threshold_data:
transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['RxPowerHighAlarm']['value']
transceiver_dom_threshold_dict['rxpowerlowalarm'] = channel_threshold_data['RxPowerLowAlarm']['value']
transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['RxPowerHighWarning']['value']
transceiver_dom_threshold_dict['rxpowerlowwarning'] = channel_threshold_data['RxPowerLowWarning']['value']
transceiver_dom_threshold_dict['txpowerhighalarm'] = "0.0dBm"
transceiver_dom_threshold_dict['txpowerlowalarm'] = "0.0dBm"
transceiver_dom_threshold_dict['txpowerhighwarning'] = "0.0dBm"
transceiver_dom_threshold_dict['txpowerlowwarning'] = "0.0dBm"
transceiver_dom_threshold_dict['txbiashighalarm'] = channel_threshold_data['TxBiasHighAlarm']['value']
transceiver_dom_threshold_dict['txbiaslowalarm'] = channel_threshold_data['TxBiasLowAlarm']['value']
transceiver_dom_threshold_dict['txbiashighwarning'] = channel_threshold_data['TxBiasHighWarning']['value']
transceiver_dom_threshold_dict['txbiaslowwarning'] = channel_threshold_data['TxBiasLowWarning']['value']
for key in transceiver_dom_threshold_dict:
transceiver_dom_threshold_dict[key] = self._convert_string_to_num(
transceiver_dom_threshold_dict[key])
return transceiver_dom_threshold_dict
def get_reset_status(self):
"""
Retrieves the reset status of SFP
@ -725,8 +187,10 @@ class Sfp(SfpBase):
rx_path = "{}{}{}{}".format(CPLD_I2C_PATH, cpld_path, '/module_rx_los_', self.port_num)
rx_los=self._api_helper.read_txt_file(rx_path)
if rx_los is None:
return False
if int(rx_los, 10) == 1:
return [True]
else:
return [False]
#status_control_raw = self.__read_eeprom_specific_bytes(
# SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH)
#if status_control_raw:
@ -743,15 +207,18 @@ class Sfp(SfpBase):
rx_los_list.append(rx_los_data & 0x02 != 0)
rx_los_list.append(rx_los_data & 0x04 != 0)
rx_los_list.append(rx_los_data & 0x08 != 0)
rx_los = rx_los_list[0] and rx_los_list[1] and rx_los_list[2] and rx_los_list[3]
return rx_los
return rx_los_list
else:
return [False]*4
def get_tx_fault(self):
"""
Retrieves the TX fault status of SFP
Returns:
A Boolean, True if SFP has TX fault, False if not
A list of boolean values, representing the TX fault status
of each available channel, value is True if SFP channel
has TX fault, False if not.
E.g., for a tranceiver with four channels: [False, False, True, False]
Note : TX fault status is lached until a call to get_tx_fault or a reset.
"""
tx_fault = False
@ -761,8 +228,10 @@ class Sfp(SfpBase):
tx_path = "{}{}{}{}".format(CPLD_I2C_PATH, cpld_path, '/module_tx_fault_', self.port_num)
tx_fault=self._api_helper.read_txt_file(tx_path)
if tx_fault is None:
return False
if int(tx_fault, 10) == 1:
return [True]
else:
return [False]
#status_control_raw = self.__read_eeprom_specific_bytes(
# SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH)
#if status_control_raw:
@ -778,15 +247,19 @@ class Sfp(SfpBase):
tx_fault_list.append(tx_fault_data & 0x02 != 0)
tx_fault_list.append(tx_fault_data & 0x04 != 0)
tx_fault_list.append(tx_fault_data & 0x08 != 0)
tx_fault = tx_fault_list[0] and tx_fault_list[1] and tx_fault_list[2] and tx_fault_list[3]
return tx_fault_list
else:
return [False]*4
return tx_fault
def get_tx_disable(self):
"""
Retrieves the tx_disable status of this SFP
Returns:
A Boolean, True if tx_disable is enabled, False if disabled
A list of boolean values, representing the TX disable status
of each available channel, value is True if SFP channel
is TX disabled, False if not.
E.g., for a tranceiver with four channels: [False, False, True, False]
"""
if self.port_num < 49:
tx_disable = False
@ -806,10 +279,11 @@ class Sfp(SfpBase):
# tx_disable_soft = (sffbase().test_bit(
# data, SFP_TX_DISABLE_SOFT_BIT) != 0)
# tx_disable = tx_disable_hard | tx_disable_soft
if tx_disable is not None:
return tx_disable
if int(tx_disable, 10)==0:
return [False]
else:
return False
return [True]
else:
tx_disable_list = []
@ -829,8 +303,9 @@ class Sfp(SfpBase):
'On' == dom_control_data['data']['TX3Disable']['value'])
tx_disable_list.append(
'On' == dom_control_data['data']['TX4Disable']['value'])
return tx_disable_list
return tx_disable_list
else:
return [False]*4
def get_tx_disable_channel(self):
"""
@ -841,18 +316,14 @@ class Sfp(SfpBase):
As an example, a returned value of 0x5 indicates that channel 0
and channel 2 have been disabled.
"""
if self.port_num < 49:
# SFP doesn't support this feature
return False
else:
tx_disable_list = self.get_tx_disable()
if tx_disable_list is None:
return 0
tx_disabled = 0
for i in range(len(tx_disable_list)):
if tx_disable_list[i]:
tx_disabled |= 1 << i
return tx_disabled
tx_disable_list = self.get_tx_disable()
if tx_disable_list is None:
return 0
tx_disabled = 0
for i in range(len(tx_disable_list)):
if tx_disable_list[i]:
tx_disabled |= 1 << i
return tx_disabled
def get_lpmode(self):
"""
@ -915,78 +386,6 @@ class Sfp(SfpBase):
return power_override
def get_temperature(self):
"""
Retrieves the temperature of this SFP
Returns:
An integer number of current temperature in Celsius
"""
transceiver_dom_info_dict = self.get_transceiver_bulk_status()
return transceiver_dom_info_dict.get("temperature", "N/A")
def get_voltage(self):
"""
Retrieves the supply voltage of this SFP
Returns:
An integer number of supply voltage in mV
"""
transceiver_dom_info_dict = self.get_transceiver_bulk_status()
return transceiver_dom_info_dict.get("voltage", "N/A")
def get_tx_bias(self):
"""
Retrieves the TX bias current of this SFP
Returns:
A list of four integer numbers, representing TX bias in mA
for channel 0 to channel 4.
Ex. ['110.09', '111.12', '108.21', '112.09']
"""
transceiver_dom_info_dict = self.get_transceiver_bulk_status()
tx1_bs = transceiver_dom_info_dict.get("tx1bias", "N/A")
if self.port_num < 49:
return [tx1_bs, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else []
tx2_bs = transceiver_dom_info_dict.get("tx2bias", "N/A")
tx3_bs = transceiver_dom_info_dict.get("tx3bias", "N/A")
tx4_bs = transceiver_dom_info_dict.get("tx4bias", "N/A")
return [tx1_bs, tx2_bs, tx3_bs, tx4_bs] if transceiver_dom_info_dict else []
def get_rx_power(self):
"""
Retrieves the received optical power for this SFP
Returns:
A list of four integer numbers, representing received optical
power in mW for channel 0 to channel 4.
Ex. ['1.77', '1.71', '1.68', '1.70']
"""
transceiver_dom_info_dict = self.get_transceiver_bulk_status()
rx1_pw = transceiver_dom_info_dict.get("rx1power", "N/A")
if self.port_num < 49:
return [rx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else []
rx2_pw = transceiver_dom_info_dict.get("rx2power", "N/A")
rx3_pw = transceiver_dom_info_dict.get("rx3power", "N/A")
rx4_pw = transceiver_dom_info_dict.get("rx4power", "N/A")
return [rx1_pw, rx2_pw, rx3_pw, rx4_pw] if transceiver_dom_info_dict else []
def get_tx_power(self):
"""
Retrieves the TX power of this SFP
Returns:
A list of four integer numbers, representing TX power in mW
for channel 0 to channel 4.
Ex. ['1.86', '1.86', '1.86', '1.86']
"""
transceiver_dom_info_dict = self.get_transceiver_bulk_status()
tx1_pw = transceiver_dom_info_dict.get("tx1power", "N/A")
if self.port_num < 49:
return [tx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else []
tx2_pw = transceiver_dom_info_dict.get("tx2power", "N/A")
tx3_pw = transceiver_dom_info_dict.get("tx3power", "N/A")
tx4_pw = transceiver_dom_info_dict.get("tx4power", "N/A")
return [tx1_pw, tx2_pw, tx3_pw, tx4_pw]
def reset(self):
"""
Reset SFP and return all user module settings to their default srate.
@ -1000,15 +399,15 @@ class Sfp(SfpBase):
cpld_path = self._cpld_mapping[cpld_i]
reset_path = "{}{}{}{}".format(CPLD_I2C_PATH, cpld_path, '/module_reset_', self.port_num)
ret = self._api_helper.write_txt_file(reset_path, 1)
if ret is not True:
time.sleep(0.01)
ret = self.self._api_helper.write_txt_file(reset_path, 0)
time.sleep(0.2)
return ret
else:
return False
if ret is not True:
return ret
time.sleep(0.01)
ret = self._api_helper.write_txt_file(reset_path, 0)
time.sleep(0.2)
return ret
def tx_disable(self, tx_disable):
"""
@ -1120,7 +519,7 @@ class Sfp(SfpBase):
if self.port_num < 49:
return False # SFP doesn't support this feature
else:
if lpmode is True:
if lpmode:
self.set_power_override(True, True)
else:
self.set_power_override(False, False)
@ -1195,28 +594,27 @@ class Sfp(SfpBase):
else:
return False
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
transceiver_dom_info_dict = self.get_transceiver_info()
return transceiver_dom_info_dict.get("model", "N/A")
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
transceiver_dom_info_dict = self.get_transceiver_info()
return transceiver_dom_info_dict.get("serial", "N/A")
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
return self.get_presence() and self.get_transceiver_bulk_status()
return self.get_presence()
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return self.port_num
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True

View File

@ -15,22 +15,53 @@ try:
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
PSU_I2C_PATH = "/sys/bus/i2c/devices/{}-00{}/"
PSU_HWMON_I2C_MAPPING = {
0: {
"num": 11,
"addr": "58"
},
1: {
"num": 12,
"addr": "5b"
},
}
PSU_CPLD_I2C_MAPPING = {
0: {
"num": 11,
"addr": "50"
},
1: {
"num": 12,
"addr": "53"
},
}
THERMAL_NAME_LIST = ["Temp sensor 1", "Temp sensor 2",
"Temp sensor 3", "Temp sensor 4"]
PSU_THERMAL_NAME_LIST = ["PSU-1 temp sensor 1", "PSU-2 temp sensor 2"]
SYSFS_PATH = "/sys/bus/i2c/devices"
class Thermal(ThermalBase):
"""Platform-specific Thermal class"""
THERMAL_NAME_LIST = []
SYSFS_PATH = "/sys/bus/i2c/devices"
def __init__(self, thermal_index=0):
def __init__(self, thermal_index=0, is_psu=False, psu_index=0):
self.index = thermal_index
self.is_psu = is_psu
self.psu_index = psu_index
# Add thermal name
self.THERMAL_NAME_LIST.append("Temp sensor 1")
self.THERMAL_NAME_LIST.append("Temp sensor 2")
self.THERMAL_NAME_LIST.append("Temp sensor 3")
self.THERMAL_NAME_LIST.append("Temp sensor 4")
if self.is_psu:
psu_i2c_bus = PSU_HWMON_I2C_MAPPING[psu_index]["num"]
psu_i2c_addr = PSU_HWMON_I2C_MAPPING[psu_index]["addr"]
self.psu_hwmon_path = PSU_I2C_PATH.format(psu_i2c_bus,
psu_i2c_addr)
psu_i2c_bus = PSU_CPLD_I2C_MAPPING[psu_index]["num"]
psu_i2c_addr = PSU_CPLD_I2C_MAPPING[psu_index]["addr"]
self.cpld_path = PSU_I2C_PATH.format(psu_i2c_bus, psu_i2c_addr)
# Set hwmon path
i2c_path = {
0: "18-004b/hwmon/hwmon*/",
@ -38,9 +69,9 @@ class Thermal(ThermalBase):
2: "20-0049/hwmon/hwmon*/",
3: "21-004a/hwmon/hwmon*/"
}.get(self.index, None)
self.hwmon_path = "{}/{}".format(self.SYSFS_PATH, i2c_path)
self.ss_key = self.THERMAL_NAME_LIST[self.index]
self.hwmon_path = "{}/{}".format(SYSFS_PATH, i2c_path)
self.ss_key = THERMAL_NAME_LIST[self.index]
self.ss_index = 1
def __read_txt_file(self, file_path):
@ -51,20 +82,23 @@ class Thermal(ThermalBase):
return data
except IOError as e:
pass
return None
def __get_temp(self, temp_file):
temp_file_path = os.path.join(self.hwmon_path, temp_file)
if not self.is_psu:
temp_file_path = os.path.join(self.hwmon_path, temp_file)
else:
temp_file_path = temp_file
raw_temp = self.__read_txt_file(temp_file_path)
if raw_temp is not None:
return float(raw_temp)/1000
else:
return 0
return 0
def __set_threshold(self, file_name, temperature):
if self.is_psu:
return True
temp_file_path = os.path.join(self.hwmon_path, file_name)
for filename in glob.glob(temp_file_path):
try:
@ -73,6 +107,8 @@ class Thermal(ThermalBase):
return True
except IOError as e:
print("IOError")
return False
def get_temperature(self):
@ -82,7 +118,11 @@ class Thermal(ThermalBase):
A float number of current temperature in Celsius up to nearest thousandth
of one degree Celsius, e.g. 30.125
"""
temp_file = "temp{}_input".format(self.ss_index)
if not self.is_psu:
temp_file = "temp{}_input".format(self.ss_index)
else:
temp_file = self.psu_hwmon_path + "psu_temp1_input"
return self.__get_temp(temp_file)
def get_high_threshold(self):
@ -92,6 +132,9 @@ class Thermal(ThermalBase):
A float number, the high threshold temperature of thermal in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125
"""
if self.is_psu:
return 80
temp_file = "temp{}_max".format(self.ss_index)
return self.__get_temp(temp_file)
@ -116,7 +159,10 @@ class Thermal(ThermalBase):
Returns:
string: The name of the thermal device
"""
return self.THERMAL_NAME_LIST[self.index]
if self.is_psu:
return PSU_THERMAL_NAME_LIST[self.psu_index]
else:
return THERMAL_NAME_LIST[self.index]
def get_presence(self):
"""
@ -124,6 +170,9 @@ class Thermal(ThermalBase):
Returns:
bool: True if Thermal is present, False if not
"""
if self.is_psu:
val = self.__read_txt_file(self.cpld_path + "psu_present")
return int(val, 10) == 1
temp_file = "temp{}_input".format(self.ss_index)
temp_file_path = os.path.join(self.hwmon_path, temp_file)
raw_txt = self.__read_txt_file(temp_file_path)
@ -138,11 +187,49 @@ class Thermal(ThermalBase):
Returns:
A boolean value, True if device is operating properly, False if not
"""
if self.is_psu:
temp_file = self.psu_hwmon_path + "psu_temp_fault"
return self.get_presence() and (not int(
self.__read_txt_file(temp_file)))
file_str = "temp{}_input".format(self.ss_index)
file_path = os.path.join(self.hwmon_path, file_str)
raw_txt = self.__read_txt_file(file_path)
if raw_txt is None:
return False
else:
else:
return int(raw_txt) != 0
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return "N/A"
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return "N/A"
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return self.index+1
def is_replaceable(self):
"""
Retrieves whether thermal module is replaceable
Returns:
A boolean value, True if replaceable, False if not
"""
return False

View File

@ -0,0 +1,15 @@
{
"services_to_ignore": [],
"devices_to_ignore": [
"asic",
"psu.temperature"
],
"user_defined_checkers": [],
"polling_interval": 60,
"led_color": {
"fault": "STATUS_LED_COLOR_AMBER",
"normal": "STATUS_LED_COLOR_GREEN",
"booting": "STATUS_LED_COLOR_GREEN"
}
}

View File

@ -49,6 +49,10 @@
"pddf_fan_module",
"pddf_led_module",
"pddf_sysstatus_module"
],
"custom_kos":
[
"pddf_custom_psu"
]
},
@ -108,7 +112,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x0", "dev_addr":"0x77", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x1"},
"dev_attr": { "virt_bus":"0x1", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"MUX2" },
@ -124,7 +128,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x1", "dev_addr":"0x70", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x9"},
"dev_attr": { "virt_bus":"0x9", "idle_state":"-2"},
"channel":
[
{ "chn":"2", "dev":"FAN-CTRL" },
@ -143,7 +147,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x1", "dev_addr":"0x71", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x11"},
"dev_attr": { "virt_bus":"0x11", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PSU1" },
@ -161,7 +165,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x2", "dev_addr":"0x70", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x21"},
"dev_attr": { "virt_bus":"0x21", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"MUX5" },
@ -181,7 +185,8 @@
{
"interface":
[
{ "itf":"pmbus", "dev":"PSU2-PMBUS"}
{ "itf":"pmbus", "dev":"PSU2-PMBUS"},
{ "itf":"eeprom", "dev":"PSU2-EEPROM" }
]
}
},
@ -195,10 +200,8 @@
"attr_list":
[
{ "attr_name":"psu_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_offset":"0x2", "attr_mask":"0x1", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"psu_model_name", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"10" },
{ "attr_name":"psu_power_good", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_offset":"0x2", "attr_mask":"0x4", "attr_cmpval":"0x4", "attr_len":"1"},
{ "attr_name":"psu_mfr_id", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0X99", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"10" },
{ "attr_name":"psu_serial_num", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x9e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"20" },
{ "attr_name":"psu_fan_dir", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0xc3", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"5"},
{ "attr_name":"psu_v_out", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x8b", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_i_out", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
@ -208,7 +211,21 @@
]
}
},
"PSU2-EEPROM":
{
"dev_info": { "device_type":"PSU-EEPROM", "device_name":"PSU2-EEPROM", "device_parent":"MUX2", "virt_parent":"PSU2"},
"i2c":
{
"topo_info":{ "parent_bus":"0xd", "dev_addr":"0x53", "dev_type":"psu_eeprom"},
"attr_list":
[
{ "attr_name":"psu_model_name", "attr_devaddr":"0x53", "attr_devtype":"eeprom", "attr_offset":"0x15", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"11" },
{ "attr_name":"psu_serial_num", "attr_devaddr":"0x53", "attr_devtype":"eeprom", "attr_offset":"0x2e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"17" }
]
}
},
"PSU1":
{
"dev_info": { "device_type":"PSU", "device_name":"PSU1", "device_parent":"MUX3" },
@ -217,7 +234,8 @@
{
"interface":
[
{ "itf":"pmbus", "dev":"PSU1-PMBUS"}
{ "itf":"pmbus", "dev":"PSU1-PMBUS"},
{ "itf":"eeprom", "dev":"PSU1-EEPROM" }
]
}
},
@ -230,11 +248,9 @@
"topo_info": { "parent_bus":"0x11", "dev_addr":"0x59", "dev_type":"psu_pmbus"},
"attr_list":
[
{ "attr_name":"psu_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_offset":"0x2", "attr_mask":"0x2", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"psu_model_name", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"10" },
{ "attr_name":"psu_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_offset":"0x2", "attr_mask":"0x2", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"psu_power_good", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_offset":"0x2", "attr_mask":"0x8", "attr_cmpval":"0x8", "attr_len":"1"},
{ "attr_name":"psu_mfr_id", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0X99", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"10" },
{ "attr_name":"psu_serial_num", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x9e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"20" },
{ "attr_name":"psu_fan_dir", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xc3", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"5"},
{ "attr_name":"psu_v_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8b", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_i_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
@ -244,7 +260,19 @@
]
}
},
"PSU1-EEPROM":
{
"dev_info": { "device_type":"PSU-EEPROM", "device_name":"PSU1-EEPROM", "device_parent":"MUX2", "virt_parent":"PSU1"},
"i2c":
{
"topo_info":{ "parent_bus":"0x11", "dev_addr":"0x51", "dev_type":"psu_eeprom"},
"attr_list":
[
{ "attr_name":"psu_model_name", "attr_devaddr":"0x51", "attr_devtype":"eeprom", "attr_offset":"0x15", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"11" },
{ "attr_name":"psu_serial_num", "attr_devaddr":"0x51", "attr_devtype":"eeprom", "attr_offset":"0x2e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"17" }
]
}
},
"CPLD1":
{
"dev_info": { "device_type":"CPLD", "device_name":"CPLD1", "device_parent":"MUX3"},
@ -275,6 +303,7 @@
"TEMP1" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP1", "device_parent":"MUX2"},
"dev_attr": { "display_name":"MB_RearMAC_temp(0x48)"},
"i2c":
{
"topo_info": { "parent_bus":"0xf", "dev_addr":"0x48", "dev_type":"lm75"},
@ -288,7 +317,8 @@
},
"TEMP2" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP1", "device_parent":"MUX2"},
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP2", "device_parent":"MUX2"},
"dev_attr": { "display_name":"MB_FrontMAC_temp(0x49)"},
"i2c":
{
"topo_info": { "parent_bus":"0xf", "dev_addr":"0x49", "dev_type":"lm75"},
@ -302,7 +332,8 @@
},
"TEMP3" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP1", "device_parent":"MUX2"},
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP3", "device_parent":"MUX2"},
"dev_attr": { "display_name":"MB_LeftCenter_temp(0x4A)"},
"i2c":
{
"topo_info": { "parent_bus":"0xf", "dev_addr":"0x4A", "dev_type":"lm75"},
@ -316,7 +347,8 @@
},
"TEMP4" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP1", "device_parent":"MUX2"},
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP4", "device_parent":"MUX2"},
"dev_attr": { "display_name":"CB_temp(0x4B)"},
"i2c":
{
"topo_info": { "parent_bus":"0xf", "dev_addr":"0x4B", "dev_type":"lm75"},
@ -474,7 +506,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x21", "dev_addr":"0x71", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x29"},
"dev_attr": { "virt_bus":"0x29", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT2" },
@ -494,7 +526,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x22", "dev_addr":"0x72", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x31"},
"dev_attr": { "virt_bus":"0x31", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT10" },
@ -514,7 +546,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x23", "dev_addr":"0x73", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x39"},
"dev_attr": { "virt_bus":"0x39", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT18" },
@ -534,7 +566,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x24", "dev_addr":"0x74", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x41"},
"dev_attr": { "virt_bus":"0x41", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT27" },
@ -554,7 +586,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x25", "dev_addr":"0x75", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x49"},
"dev_attr": { "virt_bus":"0x49", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT34" },
@ -574,7 +606,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x26", "dev_addr":"0x76", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x51"},
"dev_attr": { "virt_bus":"0x51", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT41" },
@ -594,7 +626,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x18", "dev_addr":"0x72", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x19"},
"dev_attr": { "virt_bus":"0x19", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT49" },
@ -887,7 +919,7 @@
{ "attr_name":"xcvr_present", "attr_devaddr":"0x62", "attr_devtype":"cpld", "attr_devname":"CPLD2", "attr_offset":"0xF", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"xcvr_txfault", "attr_devaddr":"0x62", "attr_devtype":"cpld", "attr_devname":"CPLD2", "attr_offset":"0x3", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"},
{ "attr_name":"xcvr_txdisable", "attr_devaddr":"0x62", "attr_devtype":"cpld", "attr_devname":"CPLD2", "attr_offset":"0x7", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"},
{ "attr_name":"xcvr_rxlos", "attr_devaddr":"0x62", "attr_devtype":"cpld", "attr_offset":"0xB", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}
{ "attr_name":"xcvr_rxlos", "attr_devaddr":"0x62", "attr_devtype":"cpld", "attr_devname":"CPLD2","attr_offset":"0xB", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}
]
}
},
@ -927,7 +959,7 @@
{ "attr_name":"xcvr_present", "attr_devaddr":"0x62", "attr_devtype":"cpld", "attr_devname":"CPLD2", "attr_offset":"0x10", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"xcvr_txfault", "attr_devaddr":"0x62", "attr_devtype":"cpld", "attr_devname":"CPLD2", "attr_offset":"0x4", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"},
{ "attr_name":"xcvr_txdisable", "attr_devaddr":"0x62", "attr_devtype":"cpld","attr_devname":"CPLD2", "attr_offset":"0x8", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"},
{ "attr_name":"xcvr_rxlos", "attr_devaddr":"0x62", "attr_devtype":"cpld", "attr_offset":"0xC", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}
{ "attr_name":"xcvr_rxlos", "attr_devaddr":"0x62", "attr_devtype":"cpld", "attr_devname":"CPLD2", "attr_offset":"0xC", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}
]
}
},
@ -2381,10 +2413,10 @@
"topo_info": { "parent_bus":"0x54", "dev_addr":"0x53", "dev_type":"pddf_xcvr"},
"attr_list":
[
{ "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x11", "attr_devname":"CPLD1", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"xcvr_txfault", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x1B","attr_devname":"CPLD1", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"},
{ "attr_name":"xcvr_txdisable", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x15", "attr_devname":"CPLD1", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"},
{ "attr_name":"xcvr_rxlos", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x18", "attr_devname":"CPLD1","attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}
{ "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x11", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"xcvr_txfault", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x1B", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"},
{ "attr_name":"xcvr_txdisable", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x15", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"},
{ "attr_name":"xcvr_rxlos", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x18", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}
]
}
},
@ -2421,10 +2453,10 @@
"topo_info": { "parent_bus":"0x55", "dev_addr":"0x53", "dev_type":"pddf_xcvr"},
"attr_list":
[
{ "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_devname":"CPLD1", "attr_offset":"0x11", "attr_mask":"0x5", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"xcvr_txfault", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_devname":"CPLD1", "attr_offset":"0x1B", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"},
{ "attr_name":"xcvr_txdisable", "attr_devaddr":"0x60", "attr_devtype":"cpld","attr_devname":"CPLD1", "attr_devname":"CPLD1", "attr_offset":"0x15", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"},
{ "attr_name":"xcvr_rxlos", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_devname":"CPLD1", "attr_offset":"0x18", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"}
{ "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x11", "attr_mask":"0x5", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"xcvr_txfault", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x1B", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"},
{ "attr_name":"xcvr_txdisable", "attr_devaddr":"0x60", "attr_devtype":"cpld","attr_devname":"CPLD1","attr_offset":"0x15", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"},
{ "attr_name":"xcvr_rxlos", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x18", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"}
]
}
},
@ -2461,10 +2493,10 @@
"topo_info": { "parent_bus":"0x56", "dev_addr":"0x53", "dev_type":"pddf_xcvr"},
"attr_list":
[
{ "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld","attr_devname":"CPLD1", "attr_devname":"CPLD1", "attr_offset":"0x12", "attr_mask":"0x1", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"xcvr_txfault", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_devname":"CPLD1","attr_offset":"0x1C", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"},
{ "attr_name":"xcvr_txdisable", "attr_devaddr":"0x60", "attr_devtype":"cpld","attr_devname":"CPLD1", "attr_devname":"CPLD1", "attr_offset":"0x16", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"},
{ "attr_name":"xcvr_rxlos", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_devname":"CPLD1", "attr_offset":"0x19", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}
{ "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld","attr_devname":"CPLD1", "attr_offset":"0x12", "attr_mask":"0x1", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"xcvr_txfault", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x1C", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"},
{ "attr_name":"xcvr_txdisable", "attr_devaddr":"0x60", "attr_devtype":"cpld","attr_devname":"CPLD1", "attr_offset":"0x16", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"},
{ "attr_name":"xcvr_rxlos", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x19", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}
]
}
},

View File

@ -16,5 +16,10 @@ class board(eeprom_tlvinfo.TlvInfoDecoder):
_TLV_INFO_MAX_LEN = 256
def __init__(self, name, path, cpld_root, ro):
self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom"
exists = os.path.isfile('/sys/bus/i2c/devices/0-0056/eeprom')
if (exists is True):
self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom"
else:
self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom"
super(board, self).__init__(self.eeprom_path, 0, '', True)

View File

@ -1,5 +1,5 @@
{
"skip_ledd": true,
"skip_thermalctld": true
"skip_pcied": true
}

View File

@ -1,50 +1,46 @@
# libsensors configuration file for as7326-56x
# ------------------------------------------------
#
bus "i2c-11" "i2c-1-mux (chan_id 2)"
bus "i2c-13" "i2c-1-mux (chan_id 4)"
bus "i2c-15" "i2c-1-mux (chan_id 6)"
bus "i2c-17" "i2c-1-mux (chan_id 0)"
chip "ym2651-i2c-*-59"
chip "psu_pmbus-i2c-*-59"
label in3 "PSU 1 Voltage"
label fan1 "PSU 1 Fan"
label temp1 "PSU 1 Temperature"
label power2 "PSU 1 Power"
label curr2 "PSU 1 Current"
chip "ym2651-i2c-*-5b"
chip "psu_pmbus-i2c-*-5b"
label in3 "PSU 2 Voltage"
label fan1 "PSU 2 Fan"
label temp1 "PSU 2 Temperature"
label power2 "PSU 2 Power"
label curr2 "PSU 2 Current"
chip "as7326_56x_fan-*"
label fan1 "Fan 1 Front"
label fan2 "Fan 2 Front"
label fan3 "Fan 3 Front"
label fan4 "Fan 4 Front"
label fan5 "Fan 5 Front"
label fan6 "Fan 6 Front"
label fan11 "Fan 1 Rear"
label fan12 "Fan 2 Rear"
label fan13 "Fan 3 Rear"
label fan14 "Fan 4 Rear"
label fan15 "Fan 5 Rear"
label fan16 "Fan 6 Rear"
chip "fan_ctrl-*"
label fan1 "Fantray1 Front"
label fan2 "Fantray1 Rear"
label fan3 "Fantray2 Front"
label fan4 "Fantray2 Rear"
label fan5 "Fantray3 Front"
label fan6 "Fantray3 Rear"
label fan7 "Fantray4 Front"
label fan8 "Fantray4 Rear"
label fan9 "Fantray5 Front"
label fan10 "Fantray5 Rear"
label fan11 "Fantray6 Front"
label fan12 "Fantray6 Rear"
chip "lm75-i2c-*-48"
label temp1 "Main Board Temperature"
label temp1 "MB_RearMAC_temp"
chip "lm75-i2c-*-49"
label temp1 "Main Board Temperature"
label temp1 "MB_FrontMAC_temp"
chip "lm75-i2c-*-4a"
label temp1 "Main Board Temperature"
label temp1 "MB_LeftCenter_temp"
chip "lm75-i2c-*-4b"
label temp1 "CPU Board Temperature"
label temp1 "CB_temp"

View File

@ -0,0 +1,2 @@
__all__ = [ "platform", "chassis", "sfp", "eeprom", "component", "psu", "thermal", "fan", "fan_drawer" ]
from . import platform

View File

@ -0,0 +1,264 @@
#############################################################################
# Edgecore
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Chassis information which are available in the platform
#
#############################################################################
import os
import sys
try:
from sonic_platform_base.chassis_base import ChassisBase
from .event import SfpEvent
from sonic_py_common import device_info
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
NUM_FAN_TRAY = 6
NUM_PSU = 2
NUM_THERMAL = 4
NUM_PORT = 58
NUM_COMPONENT = 4
HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/"
PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/"
REBOOT_CAUSE_FILE = "reboot-cause.txt"
PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt"
HOST_CHK_CMD = "which systemctl > /dev/null 2>&1"
SYSLED_FNODE= "/sys/class/leds/accton_as7326_56x_led::diag/brightness"
SYSLED_MODES = {
"0" : "STATUS_LED_COLOR_OFF",
"1" : "STATUS_LED_COLOR_GREEN",
"3" : "STATUS_LED_COLOR_RED",
"5" : "STATUS_LED_COLOR_GREEN_BLINK"
}
class Chassis(ChassisBase):
"""Platform-specific Chassis class"""
def __init__(self):
ChassisBase.__init__(self)
self.config_data = {}
(self.platform, self.hwsku) = device_info.get_platform_and_hwsku()
self.__initialize_fan()
self.__initialize_psu()
self.__initialize_thermals()
self.__initialize_components()
self.__initialize_sfp()
self.__initialize_eeprom()
def __initialize_sfp(self):
from sonic_platform.sfp import Sfp
for index in range(NUM_PORT):
sfp = Sfp(index)
self._sfp_list.append(sfp)
self._sfpevent = SfpEvent(self._sfp_list)
self.sfp_module_initialized = True
def __initialize_fan(self):
from sonic_platform.fan_drawer import FanDrawer
for fant_index in range(NUM_FAN_TRAY):
fandrawer = FanDrawer(fant_index)
self._fan_drawer_list.append(fandrawer)
self._fan_list.extend(fandrawer._fan_list)
def __initialize_psu(self):
from sonic_platform.psu import Psu
for index in range(NUM_PSU):
psu = Psu(index)
self._psu_list.append(psu)
def __initialize_thermals(self):
from sonic_platform.thermal import Thermal
for index in range(NUM_THERMAL):
thermal = Thermal(index)
self._thermal_list.append(thermal)
def __initialize_eeprom(self):
from sonic_platform.eeprom import Tlv
self._eeprom = Tlv()
def __initialize_components(self):
from sonic_platform.component import Component
for index in range(NUM_COMPONENT):
component = Component(index)
self._component_list.append(component)
def __initialize_watchdog(self):
self._watchdog = Watchdog()
def __is_host(self):
return os.system(HOST_CHK_CMD) == 0
def __read_txt_file(self, file_path):
try:
with open(file_path, 'r') as fd:
return fd.read().strip()
except IOError:
pass
return None
def __write_txt_file(self, file_path, value):
try:
with open(file_path, 'w') as fd:
fd.write(str(value))
except Exception:
return False
return True
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
return self._eeprom.get_product_name()
def get_presence(self):
"""
Retrieves the presence of the Chassis
Returns:
bool: True if Chassis is present, False if not
"""
return True
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
return True
def get_base_mac(self):
"""
Retrieves the base MAC address for the chassis
Returns:
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
return self._eeprom.get_mac()
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return self._eeprom.get_pn()
def get_serial(self):
"""
Retrieves the hardware serial number for the chassis
Returns:
A string containing the hardware serial number for this chassis.
"""
return self._eeprom.get_serial()
def get_system_eeprom_info(self):
"""
Retrieves the full content of system EEPROM information for the chassis
Returns:
A dictionary where keys are the type code defined in
OCP ONIE TlvInfo EEPROM format and values are their corresponding
values.
"""
return self._eeprom.get_eeprom()
def get_reboot_cause(self):
"""
Retrieves the cause of the previous reboot
Returns:
A tuple (string, string) where the first element is a string
containing the cause of the previous reboot. This string must be
one of the predefined strings in this class. If the first string
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
to pass a description of the reboot cause.
"""
description = 'None'
reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) if self.__is_host(
) else (PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE)
prev_reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE) if self.__is_host(
) else (PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE)
sw_reboot_cause = self.__read_txt_file(reboot_cause_path) or "Unknown"
prev_sw_reboot_cause = self.__read_txt_file(prev_reboot_cause_path) or "Unknown"
if sw_reboot_cause != "Unknown":
reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
description = sw_reboot_cause
elif prev_reboot_cause_path != "Unknown":
reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
description = prev_sw_reboot_cause
return (reboot_cause, description)
def get_change_event(self, timeout=0):
# SFP event
if not self.sfp_module_initialized:
self.__initialize_sfp()
return self._sfpevent.get_sfp_event(timeout)
def get_sfp(self, index):
"""
Retrieves sfp represented by (1-based) index <index>
Args:
index: An integer, the index (1-based) of the sfp to retrieve.
The index should be the sequence of a physical port in a chassis,
starting from 1.
For example, 1 for Ethernet0, 2 for Ethernet4 and so on.
Returns:
An object dervied from SfpBase representing the specified sfp
"""
sfp = None
if not self.sfp_module_initialized:
self.__initialize_sfp()
try:
# The index will start from 1
sfp = self._sfp_list[index-1]
except IndexError:
sys.stderr.write("SFP index {} out of range (1-{})\n".format(
index, len(self._sfp_list)))
return sfp
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return -1
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return False
def initizalize_system_led(self):
return True
def get_status_led(self):
val = self.__read_txt_file(SYSLED_FNODE)
return SYSLED_MODES[val] if val in SYSLED_MODES else "UNKNOWN"
def set_status_led(self, color):
mode = None
for key, val in SYSLED_MODES.items():
if val == color:
mode = key
break
if mode is None:
return False
else:
return self.__write_txt_file(SYSLED_FNODE, mode)

View File

@ -0,0 +1,161 @@
#############################################################################
# Edgecore
#
# Component contains an implementation of SONiC Platform Base API and
# provides the components firmware management function
#
#############################################################################
try:
from sonic_platform_base.component_base import ComponentBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CPLD_ADDR_MAPPING = {
"CPLD-1": "18-0060",
"CPLD-2": "12-0062",
"CPLD-3": "19-0064",
}
SYSFS_PATH = "/sys/bus/i2c/devices/"
BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version"
COMPONENT_NAME_LIST = ["CPLD-1", "CPLD-2", "CPLD-3", "BIOS"]
COMPONENT_DES_LIST = [
"CPLD-1", "CPLD-2", "CPLD-3", "Basic Input/Output System"
]
class Component(ComponentBase):
"""Platform-specific Component class"""
DEVICE_TYPE = "component"
def __init__(self, component_index=0):
ComponentBase.__init__(self)
self.index = component_index
self.name = self.get_name()
def __get_bios_version(self):
# Retrieves the BIOS firmware version
try:
with open(BIOS_VERSION_PATH, 'r') as fd:
bios_version = fd.read()
return bios_version.strip()
except Exception as e:
return None
def __get_sysfs_value(self, addr, name):
# Retrieves the cpld register value
try:
with open(SYSFS_PATH + addr + '/' + name, 'r') as fd:
return fd.read().strip()
except Exception as e:
return None
def __get_cpld_version(self):
# Retrieves the CPLD firmware version
cpld_version = dict()
for cpld_name in CPLD_ADDR_MAPPING:
try:
cpld_addr = CPLD_ADDR_MAPPING[cpld_name]
cpld_version_raw = self.__get_sysfs_value(cpld_addr, "version")
cpld_version[cpld_name] = "{}".format(
int(cpld_version_raw, 16))
except Exception as e:
cpld_version[cpld_name] = 'None'
return cpld_version
def get_name(self):
"""
Retrieves the name of the component
Returns:
A string containing the name of the component
"""
return COMPONENT_NAME_LIST[self.index]
def get_description(self):
"""
Retrieves the description of the component
Returns:
A string containing the description of the component
"""
return COMPONENT_DES_LIST[self.index]
def get_firmware_version(self):
"""
Retrieves the firmware version of module
Returns:
string: The firmware versions of the module
"""
fw_version = None
if self.name == "BIOS":
fw_version = self.__get_bios_version()
elif "CPLD" in self.name:
cpld_version = self.__get_cpld_version()
fw_version = cpld_version.get(self.name)
return fw_version
def install_firmware(self, image_path):
"""
Install firmware to module
Args:
image_path: A string, path to firmware image
Returns:
A boolean, True if install successfully, False if not
"""
raise NotImplementedError
def get_presence(self):
"""
Retrieves the presence of the device
Returns:
bool: True if device is present, False if not
"""
return True
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return 'N/A'
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return 'N/A'
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
return True
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device.
If the agent cannot determine the parent-relative position
for some reason, or if the associated value of
entPhysicalContainedIn is'0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device
or -1 if cannot determine the position
"""
return -1
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return False

View File

@ -0,0 +1,139 @@
try:
import os
import sys
import re
from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo
if sys.version_info[0] >= 3:
from io import StringIO
else:
from cStringIO import StringIO
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CACHE_ROOT = '/var/cache/sonic/decode-syseeprom'
CACHE_FILE = 'syseeprom_cache'
NULL = 'N/A'
class Tlv(eeprom_tlvinfo.TlvInfoDecoder):
EEPROM_DECODE_HEADLINES = 6
def __init__(self):
#self._eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom"
exists = os.path.isfile('/sys/bus/i2c/devices/0-0056/eeprom')
if (exists is True):
self._eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom"
else:
self._eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom"
super(Tlv, self).__init__(self._eeprom_path, 0, '', True)
self._eeprom = self._load_eeprom()
def __parse_output(self, decode_output):
decode_output.replace('\0', '')
lines = decode_output.split('\n')
lines = lines[self.EEPROM_DECODE_HEADLINES:]
_eeprom_info_dict = dict()
for line in lines:
try:
match = re.search('(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+)',
line)
if match is not None:
idx = match.group(1)
value = match.group(3).rstrip('\0')
_eeprom_info_dict[idx] = value
except Exception:
pass
return _eeprom_info_dict
def _load_eeprom(self):
original_stdout = sys.stdout
sys.stdout = StringIO()
try:
self.read_eeprom_db()
except Exception:
decode_output = sys.stdout.getvalue()
sys.stdout = original_stdout
return self.__parse_output(decode_output)
status = self.check_status()
if 'ok' not in status:
return False
if not os.path.exists(CACHE_ROOT):
try:
os.makedirs(CACHE_ROOT)
except Exception:
pass
#
# only the eeprom classes that inherit from eeprom_base
# support caching. Others will work normally
#
try:
self.set_cache_name(os.path.join(CACHE_ROOT, CACHE_FILE))
except Exception:
pass
e = self.read_eeprom()
if e is None:
return 0
try:
self.update_cache(e)
except Exception:
pass
self.decode_eeprom(e)
decode_output = sys.stdout.getvalue()
sys.stdout = original_stdout
(is_valid, valid_crc) = self.is_checksum_valid(e)
if not is_valid:
return False
return self.__parse_output(decode_output)
def _valid_tlv(self, eeprom_data):
tlvinfo_type_codes_list = [
self._TLV_CODE_PRODUCT_NAME,
self._TLV_CODE_PART_NUMBER,
self._TLV_CODE_SERIAL_NUMBER,
self._TLV_CODE_MAC_BASE,
self._TLV_CODE_MANUF_DATE,
self._TLV_CODE_DEVICE_VERSION,
self._TLV_CODE_LABEL_REVISION,
self._TLV_CODE_PLATFORM_NAME,
self._TLV_CODE_ONIE_VERSION,
self._TLV_CODE_MAC_SIZE,
self._TLV_CODE_MANUF_NAME,
self._TLV_CODE_MANUF_COUNTRY,
self._TLV_CODE_VENDOR_NAME,
self._TLV_CODE_DIAG_VERSION,
self._TLV_CODE_SERVICE_TAG,
self._TLV_CODE_VENDOR_EXT,
self._TLV_CODE_CRC_32
]
for code in tlvinfo_type_codes_list:
code_str = "0x{:X}".format(code)
eeprom_data[code_str] = eeprom_data.get(code_str, NULL)
return eeprom_data
def get_eeprom(self):
return self._valid_tlv(self._eeprom)
def get_pn(self):
return self._eeprom.get('0x22', NULL)
def get_serial(self):
return self._eeprom.get('0x23', NULL)
def get_mac(self):
return self._eeprom.get('0x24', NULL)
def get_product_name(self):
return self._eeprom.get('0x21', NULL)

View File

@ -0,0 +1,60 @@
try:
import time
from sonic_py_common.logger import Logger
except ImportError as e:
raise ImportError(repr(e) + " - required module not found")
POLL_INTERVAL_IN_SEC = 1
class SfpEvent:
''' Listen to insert/remove sfp events '''
def __init__(self, sfp_list):
self._sfp_list = sfp_list
self._logger = Logger()
self._sfp_change_event_data = {'present': 0}
def get_presence_bitmap(self):
bitmap = 0
for sfp in self._sfp_list:
modpres = sfp.get_presence()
i=sfp.port_num-1
if modpres:
bitmap = bitmap | (1 << i)
return bitmap
def get_sfp_event(self, timeout=2000):
port_dict = {}
change_dict = {}
change_dict['sfp'] = port_dict
if timeout < 1000:
cd_ms = 1000
else:
cd_ms = timeout
while cd_ms > 0:
bitmap = self.get_presence_bitmap()
changed_ports = self._sfp_change_event_data['present'] ^ bitmap
if changed_ports != 0:
break
time.sleep(POLL_INTERVAL_IN_SEC)
# timeout=0 means wait for event forever
if timeout != 0:
cd_ms = cd_ms - POLL_INTERVAL_IN_SEC * 1000
if changed_ports != 0:
for sfp in self._sfp_list:
i=sfp.port_num-1
if (changed_ports & (1 << i)):
if (bitmap & (1 << i)) == 0:
port_dict[i+1] = '0'
else:
port_dict[i+1] = '1'
# Update the cache dict
self._sfp_change_event_data['present'] = bitmap
return True, change_dict
else:
return True, change_dict

View File

@ -0,0 +1,270 @@
#############################################################################
# Edgecore
#
# Module contains an implementation of SONiC Platform Base API and
# provides the fan status which are available in the platform
#
#############################################################################
try:
from sonic_platform_base.fan_base import FanBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
FAN_MAX_RPM = 25500
PSU_FAN_MAX_RPM = 25500
SPEED_TOLERANCE = 15
CPLD_I2C_PATH = "/sys/bus/i2c/devices/11-0066/fan"
PSU_I2C_PATH = "/sys/bus/i2c/devices/{}-00{}/"
PSU_HWMON_I2C_MAPPING = {
0: {
"bus": 17,
"addr": "59"
},
1: {
"bus": 13,
"addr": "5b"
},
}
PSU_CPLD_I2C_MAPPING = {
0: {
"bus": 17,
"addr": "51"
},
1: {
"bus": 13,
"addr": "53"
},
}
FAN_NAME_LIST = ["FAN-1F", "FAN-1R", "FAN-2F", "FAN-2R",
"FAN-3F", "FAN-3R", "FAN-4F", "FAN-4R",
"FAN-5F", "FAN-5R", "FAN-6F", "FAN-6R"]
class Fan(FanBase):
"""Platform-specific Fan class"""
def __init__(self,
fan_tray_index,
fan_index=0,
is_psu_fan=False,
psu_index=0):
self.fan_index = fan_index
self.fan_tray_index = fan_tray_index
self.is_psu_fan = is_psu_fan
self.psu_index = psu_index
if self.is_psu_fan:
psu_i2c_bus = PSU_HWMON_I2C_MAPPING[psu_index]["bus"]
psu_i2c_addr = PSU_HWMON_I2C_MAPPING[psu_index]["addr"]
self.psu_hwmon_path = PSU_I2C_PATH.format(psu_i2c_bus,
psu_i2c_addr)
psu_i2c_bus = PSU_CPLD_I2C_MAPPING[psu_index]["bus"]
psu_i2c_addr = PSU_CPLD_I2C_MAPPING[psu_index]["addr"]
self.cpld_path = PSU_I2C_PATH.format(psu_i2c_bus, psu_i2c_addr)
FanBase.__init__(self)
def __read_txt_file(self, file_path):
try:
with open(file_path, 'r') as fd:
return fd.read().strip()
except IOError:
pass
return ""
def __write_txt_file(self, file_path, value):
try:
with open(file_path, 'w') as fd:
fd.write(str(value))
except Exception:
return False
return True
def get_direction(self):
"""
Retrieves the direction of fan
Returns:
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
depending on fan direction
"""
if not self.is_psu_fan:
val = self.__read_txt_file(
CPLD_I2C_PATH + str(self.fan_tray_index+1) + "_direction")
direction = self.FAN_DIRECTION_EXHAUST if (
val == "0") else self.FAN_DIRECTION_INTAKE
else:
val = self.__read_txt_file(self.psu_hwmon_path + "psu_fan_dir")
direction = self.FAN_DIRECTION_EXHAUST if (
val == "F2B") else self.FAN_DIRECTION_INTAKE
return direction
def get_speed(self):
"""
Retrieves the speed of fan as a percentage of full speed
Returns:
An integer, the percentage of full fan speed, in the range 0 (off)
to 100 (full speed)
"""
speed = 0
if self.is_psu_fan:
speed = self.__read_txt_file(
self.psu_hwmon_path + "psu_fan1_speed_rpm")
speed = (int(speed, 10)) * 100 / PSU_FAN_MAX_RPM
speed = 100 if (speed > 100) else speed
elif self.get_presence():
speed = self.__read_txt_file(CPLD_I2C_PATH + str(
self.fan_index * 10 + self.fan_tray_index + 1) + "_input")
speed = (int(speed, 10)) * 100 / FAN_MAX_RPM
speed = 100 if (speed > 100) else speed
return int(speed)
def get_target_speed(self):
"""
Retrieves the target (expected) speed of the fan
Returns:
An integer, the percentage of full fan speed, in the range 0 (off)
to 100 (full speed)
Note:
speed_pc = pwm_target/255*100
0 : when PWM mode is use
pwm : when pwm mode is not use
"""
return self.get_speed()
def get_speed_tolerance(self):
"""
Retrieves the speed tolerance of the fan
Returns:
An integer, the percentage of variance from target speed which is
considered tolerable
"""
return SPEED_TOLERANCE
def set_speed(self, speed):
"""
Sets the fan speed
Args:
speed: An integer, the percentage of full fan speed to set fan to,
in the range 0 (off) to 100 (full speed)
Returns:
A boolean, True if speed is set successfully, False if not
"""
if not self.is_psu_fan and self.get_presence():
return self.__write_txt_file(
CPLD_I2C_PATH + "_duty_cycle_percentage", int(speed))
return False
def set_status_led(self, color):
"""
Sets the state of the fan module status LED
Args:
color: A string representing the color with which to set the
fan module status LED
Returns:
bool: True if status LED state is set successfully, False if not
"""
return False #Not supported
def get_status_led(self):
"""
Gets the state of the fan status LED
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings above
"""
status=self.get_presence()
if status is None:
return self.STATUS_LED_COLOR_OFF
return {
1: self.STATUS_LED_COLOR_GREEN,
0: self.STATUS_LED_COLOR_RED
}.get(status, self.STATUS_LED_COLOR_OFF)
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
fan_name = FAN_NAME_LIST[self.fan_tray_index*2 + self.fan_index] \
if not self.is_psu_fan \
else "PSU-{} FAN-{}".format(self.psu_index+1, self.fan_index+1)
return fan_name
def get_presence(self):
"""
Retrieves the presence of the PSU
Returns:
bool: True if PSU is present, False if not
"""
if self.is_psu_fan:
val = self.__read_txt_file(self.cpld_path + "psu_present")
return int(val, 10) == 1
val = self.__read_txt_file(
CPLD_I2C_PATH + str(self.fan_tray_index + 1) + "_present")
return int(val, 10)==1
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
if self.is_psu_fan:
psu_fan_path= "{}{}".format(self.psu_hwmon_path, 'psu_fan1_fault')
val=self.__read_txt_file(psu_fan_path)
if val is not None:
return int(val, 10)==0
else:
return False
else:
path = "{}{}{}".format(CPLD_I2C_PATH, self.fan_tray_index+1, '_fault')
val=self.__read_txt_file(path)
if val is not None:
return int(val, 10)==0
else:
return False
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return "N/A"
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return "N/A"
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device.
If the agent cannot determine the parent-relative position
for some reason, or if the associated value of
entPhysicalContainedIn is'0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device
or -1 if cannot determine the position
"""
return (self.fan_index+1) \
if not self.is_psu_fan else (self.psu_index+1)
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True if not self.is_psu_fan else False

View File

@ -0,0 +1,90 @@
########################################################################
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Fan-Drawers' information available in the platform.
#
########################################################################
try:
from sonic_platform_base.fan_drawer_base import FanDrawerBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
FANS_PER_FANTRAY = 2
class FanDrawer(FanDrawerBase):
"""Platform-specific Fan class"""
def __init__(self, fantray_index):
FanDrawerBase.__init__(self)
# FanTray is 0-based in platforms
self.fantrayindex = fantray_index
self.__initialize_fan_drawer()
def __initialize_fan_drawer(self):
from sonic_platform.fan import Fan
for i in range(FANS_PER_FANTRAY):
self._fan_list.append(Fan(self.fantrayindex, i))
def get_name(self):
"""
Retrieves the fan drawer name
Returns:
string: The name of the device
"""
return "FanTray{}".format(self.fantrayindex+1)
def get_presence(self):
"""
Retrieves the presence of the device
Returns:
bool: True if device is present, False if not
"""
return self._fan_list[0].get_presence()
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return self._fan_list[0].get_model()
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return self._fan_list[0].get_serial()
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
return self._fan_list[0].get_status()
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device.
If the agent cannot determine the parent-relative position
for some reason, or if the associated value of
entPhysicalContainedIn is'0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device
or -1 if cannot determine the position
"""
return (self.fantrayindex+1)
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True

View File

@ -0,0 +1,21 @@
#############################################################################
# Edgecore
#
# Module contains an implementation of SONiC Platform Base API and
# provides the platform information
#
#############################################################################
try:
from sonic_platform_base.platform_base import PlatformBase
from sonic_platform.chassis import Chassis
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Platform(PlatformBase):
"""Platform-specific Platform class"""
def __init__(self):
PlatformBase.__init__(self)
self._chassis = Chassis()

View File

@ -0,0 +1,264 @@
#############################################################################
# Edgecore
#
# Module contains an implementation of SONiC Platform Base API and
# provides the PSUs status which are available in the platform
#
#############################################################################
#import sonic_platform
try:
from sonic_platform_base.psu_base import PsuBase
from sonic_platform.thermal import Thermal
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
I2C_PATH = "/sys/bus/i2c/devices/{}-00{}/"
PSU_NAME_LIST = ["PSU-1", "PSU-2"]
PSU_NUM_FAN = [1, 1]
PSU_HWMON_I2C_MAPPING = {
0: {
"bus": 17,
"addr": "59"
},
1: {
"bus": 13,
"addr": "5b"
},
}
PSU_CPLD_I2C_MAPPING = {
0: {
"bus": 17,
"addr": "51"
},
1: {
"bus": 13,
"addr": "53"
},
}
NUM_FAN_TRAY = 6
class Psu(PsuBase):
"""Platform-specific Psu class"""
def __init__(self, psu_index=0):
PsuBase.__init__(self)
self.index = psu_index
bus = PSU_HWMON_I2C_MAPPING[self.index]["bus"]
addr = PSU_HWMON_I2C_MAPPING[self.index]["addr"]
self.hwmon_path = I2C_PATH.format(bus, addr)
bus = PSU_CPLD_I2C_MAPPING[self.index]["bus"]
addr = PSU_CPLD_I2C_MAPPING[self.index]["addr"]
self.cpld_path = I2C_PATH.format(bus, addr)
self.__initialize_fan()
def __initialize_fan(self):
from sonic_platform.fan import Fan
self._fan_list.append(
Fan(NUM_FAN_TRAY + self.index,
is_psu_fan=True,
psu_index=self.index))
self._thermal_list.append(Thermal(is_psu=True, psu_index=self.index))
def __read_txt_file(self, file_path):
try:
with open(file_path, 'r') as fd:
return fd.read().strip()
except IOError:
pass
return None
def get_voltage(self):
"""
Retrieves current PSU voltage output
Returns:
A float number, the output voltage in volts,
e.g. 12.1
"""
val = self.__read_txt_file(self.hwmon_path + "psu_v_out")
if val is not None:
return float(val)/ 1000
else:
return 0
def get_current(self):
"""
Retrieves present electric current supplied by PSU
Returns:
A float number, the electric current in amperes, e.g 15.4
"""
val = self.__read_txt_file(self.hwmon_path + "psu_i_out")
if val is not None:
return float(val)/1000
else:
return 0
def get_power(self):
"""
Retrieves current energy supplied by PSU
Returns:
A float number, the power in watts, e.g. 302.6
"""
val = self.__read_txt_file(self.hwmon_path + "psu_p_out")
if val is not None:
return float(val)/1000
else:
return 0
def get_powergood_status(self):
"""
Retrieves the powergood status of PSU
Returns:
A boolean, True if PSU has stablized its output voltages and passed all
its internal self-tests, False if not.
"""
return self.get_status()
def set_status_led(self, color):
"""
Sets the state of the PSU status LED
Args:
color: A string representing the color with which to set the PSU status LED
Note: Only support green and off
Returns:
bool: True if status LED state is set successfully, False if not
"""
return False #Controlled by HW
def get_status_led(self):
"""
Gets the state of the PSU status LED
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings above
"""
status=self.get_status()
if status is None:
return self.STATUS_LED_COLOR_OFF
return {
1: self.STATUS_LED_COLOR_GREEN,
0: self.STATUS_LED_COLOR_RED
}.get(status, self.STATUS_LED_COLOR_OFF)
def get_temperature(self):
"""
Retrieves current temperature reading from PSU
Returns:
A float number of current temperature in Celsius up to nearest thousandth
of one degree Celsius, e.g. 30.125
"""
return self._thermal_list[0].get_temperature()
def get_temperature_high_threshold(self):
"""
Retrieves the high threshold temperature of PSU
Returns:
A float number, the high threshold temperature of PSU in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125
"""
return False #Not supported
def get_voltage_high_threshold(self):
"""
Retrieves the high threshold PSU voltage output
Returns:
A float number, the high threshold output voltage in volts,
e.g. 12.1
"""
val = self.__read_txt_file(self.hwmon_path + "psu_mfr_vout_max")
if val is not None:
return float(val)/ 1000
else:
return 0
def get_voltage_low_threshold(self):
"""
Retrieves the low threshold PSU voltage output
Returns:
A float number, the low threshold output voltage in volts,
e.g. 12.1
"""
val = self.__read_txt_file(self.hwmon_path + "psu_mfr_vout_min")
if val is not None:
return float(val)/ 1000
else:
return 0
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
return PSU_NAME_LIST[self.index]
def get_presence(self):
"""
Retrieves the presence of the PSU
Returns:
bool: True if PSU is present, False if not
"""
val = self.__read_txt_file(self.cpld_path + "psu_present")
if val is not None:
return int(val, 10) == 1
else:
return 0
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
val = self.__read_txt_file(self.cpld_path + "psu_power_good")
if val is not None:
return int(val, 10) == 1
else:
return 0
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
model = self.__read_txt_file(self.cpld_path + "psu_model_name")
if model is None:
return "N/A"
return model
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
serial = self.__read_txt_file(self.cpld_path + "psu_serial_number")
if serial is None:
return "N/A"
return serial
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return self.index+1
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True

View File

@ -0,0 +1,626 @@
#############################################################################
# Edgecore
#
# Sfp contains an implementation of SONiC Platform Base API and
# provides the sfp device status which are available in the platform
#
#############################################################################
import os
import time
import sys
from ctypes import create_string_buffer
try:
from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase
from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CPLD_ADDR_MAPPING = {
0: {
"bus": 18,
"addr": "60"
}, # port 31-56
1: {
"bus": 12,
"addr": "62"
}, # port 1-30
}
CPLD_I2C_PATH = "/sys/bus/i2c/devices/{}-00{}/"
class Sfp(SfpOptoeBase):
"""Platform-specific Sfp class"""
# Port number
PORT_START = 1
PORT_END = 58
# Path to sysfs
PLATFORM_ROOT_PATH = "/usr/share/sonic/device"
PMON_HWSKU_PATH = "/usr/share/sonic/hwsku"
HOST_CHK_CMD = "which systemctl > /dev/null 2>&1"
PLATFORM = "x86_64-accton_as7326_56x-r0"
HWSKU = "Accton-AS7326-56X"
_port_to_i2c_mapping = {
1: [42],
2: [41],
3: [44],
4: [43],
5: [47],
6: [45],
7: [46],
8: [50],
9: [48],
10: [49],
11: [52],
12: [51],
13: [53],
14: [56],
15: [55],
16: [54],
17: [58],
18: [57],
19: [60],
20: [59],
21: [61],
22: [63],
23: [62],
24: [64],
25: [66],
26: [68],
27: [65],
28: [67],
29: [69],
30: [71],
31: [72],
32: [70],
33: [74],
34: [73],
35: [76],
36: [75],
37: [77],
38: [79],
39: [78],
40: [80],
41: [81],
42: [82],
43: [84],
44: [85],
45: [83],
46: [87],
47: [88],
48: [86],
49: [25],
50: [26],
51: [27],
52: [28],
53: [29],
54: [30],
55: [31],
56: [32],
57: [22],
58: [23]
}
def __init__(self, sfp_index=0):
SfpOptoeBase.__init__(self)
# Init index
self.index = sfp_index
self.port_num = self.index + 1
cpld_idx = 0 if self.port_num > 30 else 1
bus = CPLD_ADDR_MAPPING[cpld_idx]["bus"]
addr = CPLD_ADDR_MAPPING[cpld_idx]["addr"]
self.cpld_path = CPLD_I2C_PATH.format(bus, addr)
# Init eeprom path
eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom'
self.port_to_eeprom_mapping = {}
for x in range(self.PORT_START, self.PORT_END + 1):
self.port_to_eeprom_mapping[x] = eeprom_path.format(
self._port_to_i2c_mapping[x][0])
def get_eeprom_path(self):
return self.port_to_eeprom_mapping[self.port_num]
def __read_txt_file(self, file_path):
try:
with open(file_path, 'r') as fd:
return fd.read().strip()
except IOError:
pass
return ""
def __write_txt_file(self, file_path, value):
try:
with open(file_path, 'w') as fd:
fd.write(str(value))
except Exception:
return False
return True
def __is_host(self):
return os.system(self.HOST_CHK_CMD) == 0
def __get_path_to_port_config_file(self):
platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM])
hwsku_path = "/".join(
[platform_path,
self.HWSKU]) if self.__is_host() else self.PMON_HWSKU_PATH
return "/".join([hwsku_path, "port_config.ini"])
def __read_eeprom_specific_bytes(self, offset, num_bytes):
sysfsfile_eeprom = None
eeprom_raw = []
for i in range(0, num_bytes):
eeprom_raw.append("0x00")
sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[
self.port_num]
try:
sysfsfile_eeprom = open(
sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0)
sysfsfile_eeprom.seek(offset)
raw = sysfsfile_eeprom.read(num_bytes)
for n in range(0, num_bytes):
if sys.version_info[0] >= 3:
eeprom_raw[n] = hex(raw[n])[2:].zfill(2)
else:
eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2)
except Exception:
pass
finally:
if sysfsfile_eeprom:
sysfsfile_eeprom.close()
return eeprom_raw
def get_reset_status(self):
"""
Retrieves the reset status of SFP
Returns:
A Boolean, True if reset enabled, False if disabled
"""
if self.port_num <= 48 or self.port_num >=57:
return False # SPF port doesn't support this feature
val = self.__read_txt_file(
self.cpld_path + "module_reset_" + str(self.port_num))
return int(val, 10) == 1
def get_rx_los(self):
"""
Retrieves the RX LOS (lost-of-signal) status of SFP
Returns:
A Boolean, True if SFP has RX LOS, False if not.
Note : RX LOS status is latched until a call to get_rx_los or a reset.
"""
if self.port_num <= 48 or self.port_num >=57:
rx_los = self.__read_txt_file(
self.cpld_path + "module_rx_los_" + str(self.port_num))
if int(rx_los, 10) == 1:
return [True]
else:
return [False]
#status_control_raw = self.__read_eeprom_specific_bytes(
# SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH)
#if status_control_raw:
# data = int(status_control_raw[0], 16)
# rx_los = (sffbase().test_bit(data, 1) != 0)
else:
rx_los_list = []
dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(
QSFP_CHANNL_RX_LOS_STATUS_OFFSET,
QSFP_CHANNL_RX_LOS_STATUS_WIDTH) if self.get_presence(
) else None
if dom_channel_monitor_raw is not None:
rx_los_data = int(dom_channel_monitor_raw[0], 16)
rx_los_list.append(rx_los_data & 0x01 != 0)
rx_los_list.append(rx_los_data & 0x02 != 0)
rx_los_list.append(rx_los_data & 0x04 != 0)
rx_los_list.append(rx_los_data & 0x08 != 0)
return rx_los_list
else:
return [False]*4
def get_tx_fault(self):
"""
Retrieves the TX fault status of SFP
Returns:
A list of boolean values, representing the TX fault status
of each available channel, value is True if SFP channel
has TX fault, False if not.
E.g., for a tranceiver with four channels: [False, False, True, False]
Note : TX fault status is lached until a call to get_tx_fault or a reset.
"""
tx_fault = False
if self.port_num <= 48 or self.port_num >=57:
tx_fault = self.__read_txt_file(
self.cpld_path + "module_tx_fault_" + str(self.port_num))
if int(tx_fault, 10) == 1:
return [True]
else:
return [False]
#status_control_raw = self.__read_eeprom_specific_bytes(
# SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH)
#if status_control_raw:
# data = int(status_control_raw[0], 16)
# tx_fault = (sffbase().test_bit(data, 2) != 0)
else:
tx_fault_list = []
dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(
QSFP_CHANNL_TX_FAULT_STATUS_OFFSET,
QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) if self.get_presence(
) else None
if dom_channel_monitor_raw is not None:
tx_fault_data = int(dom_channel_monitor_raw[0], 16)
tx_fault_list.append(tx_fault_data & 0x01 != 0)
tx_fault_list.append(tx_fault_data & 0x02 != 0)
tx_fault_list.append(tx_fault_data & 0x04 != 0)
tx_fault_list.append(tx_fault_data & 0x08 != 0)
return tx_fault_list
else:
return [False]*4
def get_tx_disable(self):
"""
Retrieves the tx_disable status of this SFP
Returns:
A list of boolean values, representing the TX disable status
of each available channel, value is True if SFP channel
is TX disabled, False if not.
E.g., for a tranceiver with four channels: [False, False, True, False]
"""
if self.port_num <= 48 or self.port_num >=57:
tx_disable = False
status_control_raw = self.__read_eeprom_specific_bytes(
SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH)
if status_control_raw:
cpld_val = self.__read_txt_file(
self.cpld_path + "module_tx_disable_" + str(self.port_num))
tx_disable_hard = (int(cpld_val, 10) == 1)
data = int(status_control_raw[0], 16)
#tx_disable_hard = (sffbase().test_bit(
# data, SFP_TX_DISABLE_HARD_BIT) != 0)
tx_disable_soft = (sffbase().test_bit(
data, SFP_TX_DISABLE_SOFT_BIT) != 0)
tx_disable = tx_disable_hard | tx_disable_soft
if tx_disable==0:
return [False]
else:
return [True]
else:
return [False]
else:
tx_disable_list = []
sfpd_obj = sff8436Dom()
if sfpd_obj is None:
return [False]
dom_control_raw = self.__read_eeprom_specific_bytes(
QSFP_CONTROL_OFFSET,
QSFP_CONTROL_WIDTH) if self.get_presence() else None
if dom_control_raw is not None:
dom_control_data = sfpd_obj.parse_control_bytes(
dom_control_raw, 0)
tx_disable_list.append(
'On' == dom_control_data['data']['TX1Disable']['value'])
tx_disable_list.append(
'On' == dom_control_data['data']['TX2Disable']['value'])
tx_disable_list.append(
'On' == dom_control_data['data']['TX3Disable']['value'])
tx_disable_list.append(
'On' == dom_control_data['data']['TX4Disable']['value'])
return tx_disable_list
else:
return [False]*4
def get_tx_disable_channel(self):
"""
Retrieves the TX disabled channels in this SFP
Returns:
A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent
TX channels which have been disabled in this SFP.
As an example, a returned value of 0x5 indicates that channel 0
and channel 2 have been disabled.
"""
tx_disable_list = self.get_tx_disable()
if tx_disable_list is None:
return 0
tx_disabled = 0
for i in range(len(tx_disable_list)):
if tx_disable_list[i]:
tx_disabled |= 1 << i
return tx_disabled
def get_lpmode(self):
"""
Retrieves the lpmode (low power mode) status of this SFP
Returns:
A Boolean, True if lpmode is enabled, False if disabled
"""
if self.port_num <= 48 or self.port_num >= 57:
# SFP doesn't support this feature
return False
power_set = self.get_power_set()
power_override = self.get_power_override()
return power_set and power_override
def get_power_set(self):
if self.port_num <= 48 or self.port_num >= 57:
# SFP doesn't support this feature
return False
else:
power_set = False
sfpd_obj = sff8436Dom()
if sfpd_obj is None:
return False
dom_control_raw = self.__read_eeprom_specific_bytes(
QSFP_CONTROL_OFFSET,
QSFP_CONTROL_WIDTH) if self.get_presence() else None
if dom_control_raw is not None:
dom_control_data = sfpd_obj.parse_control_bytes(
dom_control_raw, 0)
power_set = (
'On' == dom_control_data['data']['PowerSet']['value'])
return power_set
def get_power_override(self):
"""
Retrieves the power-override status of this SFP
Returns:
A Boolean, True if power-override is enabled, False if disabled
"""
if self.port_num <= 48 or self.port_num >= 57:
return False # SFP doesn't support this feature
else:
power_override = False
sfpd_obj = sff8436Dom()
if sfpd_obj is None:
return False
dom_control_raw = self.__read_eeprom_specific_bytes(
QSFP_CONTROL_OFFSET,
QSFP_CONTROL_WIDTH) if self.get_presence() else None
if dom_control_raw is not None:
dom_control_data = sfpd_obj.parse_control_bytes(
dom_control_raw, 0)
power_override = (
'On' == dom_control_data['data']['PowerOverride']['value'])
return power_override
def reset(self):
"""
Reset SFP and return all user module settings to their default srate.
Returns:
A boolean, True if successful, False if not
"""
# Check for invalid port_num
if self.port_num <= 48 or self.port_num >=57:
return False # SFP doesn't support this feature
ret = self.__write_txt_file(
self.cpld_path + "module_reset_" + str(self.port_num), 1)
if ret is not True:
return ret
time.sleep(0.01)
ret = self.__write_txt_file(
self.cpld_path + "module_reset_" + str(self.port_num), 0)
time.sleep(0.2)
return ret
def tx_disable(self, tx_disable):
"""
Disable SFP TX for all channels
Args:
tx_disable : A Boolean, True to enable tx_disable mode, False to disable
tx_disable mode.
Returns:
A boolean, True if tx_disable is set successfully, False if not
"""
if self.port_num <= 48 or self.port_num >=57:
ret = self.__write_txt_file(
self.cpld_path + "module_tx_disable_" + str(self.port_num), 1
if tx_disable else 0)
time.sleep(0.01)
return ret
else:
if not self.get_presence():
return False
sysfsfile_eeprom = None
try:
tx_disable_ctl = 0xf if tx_disable else 0x0
buffer = create_string_buffer(1)
if sys.version_info[0] >= 3:
buffer[0] = tx_disable_ctl
else:
buffer[0] = chr(tx_disable_ctl)
# Write to eeprom
sysfsfile_eeprom = open(
self.port_to_eeprom_mapping[self.port_num], "r+b")
sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET)
sysfsfile_eeprom.write(buffer[0])
except IOError as e:
print("Error: unable to open file: %s" % str(e))
return False
finally:
if sysfsfile_eeprom is not None:
sysfsfile_eeprom.close()
time.sleep(0.01)
return True
def tx_disable_channel(self, channel, disable):
"""
Sets the tx_disable for specified SFP channels
Args:
channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3,
e.g. 0x5 for channel 0 and channel 2.
disable : A boolean, True to disable TX channels specified in channel,
False to enable
Returns:
A boolean, True if successful, False if not
"""
if self.port_num <= 48 or self.port_num >=57:
return False # SFP doesn't support this feature
else:
if not self.get_presence():
return False
sysfsfile_eeprom = None
try:
channel_state = self.get_tx_disable_channel()
for i in range(4):
channel_mask = (1 << i)
if not (channel & channel_mask):
continue
if disable:
channel_state |= channel_mask
else:
channel_state &= ~channel_mask
buffer = create_string_buffer(1)
if sys.version_info[0] >= 3:
buffer[0] = channel_state
else:
buffer[0] = chr(channel_state)
# Write to eeprom
sysfsfile_eeprom = open(
self.port_to_eeprom_mapping[self.port_num], "r+b")
sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET)
sysfsfile_eeprom.write(buffer[0])
except IOError as e:
print("Error: unable to open file: %s" % str(e))
return False
finally:
if sysfsfile_eeprom is not None:
sysfsfile_eeprom.close()
time.sleep(0.01)
return True
def set_lpmode(self, lpmode):
"""
Sets the lpmode (low power mode) of SFP
Args:
lpmode: A Boolean, True to enable lpmode, False to disable it
Note : lpmode can be overridden by set_power_override
Returns:
A boolean, True if lpmode is set successfully, False if not
"""
if self.port_num <= 48 or self.port_num >=57:
return False # SFP doesn't support this feature
if lpmode:
return self.set_power_override(True, True)
else:
return self.set_power_override(True, False)
def set_power_override(self, power_override, power_set):
"""
Sets SFP power level using power_override and power_set
Args:
power_override :
A Boolean, True to override set_lpmode and use power_set
to control SFP power, False to disable SFP power control
through power_override/power_set and use set_lpmode
to control SFP power.
power_set :
Only valid when power_override is True.
A Boolean, True to set SFP to low power mode, False to set
SFP to high power mode.
Returns:
A boolean, True if power-override and power_set are set successfully,
False if not
"""
if self.port_num <= 48 or self.port_num >=57:
return False # SFP doesn't support this feature
else:
if not self.get_presence():
return False
try:
power_override_bit = (1 << 0) if power_override else 0
power_set_bit = (1 << 1) if power_set else (1 << 3)
buffer = create_string_buffer(1)
if sys.version_info[0] >= 3:
buffer[0] = (power_override_bit | power_set_bit)
else:
buffer[0] = chr(power_override_bit | power_set_bit)
# Write to eeprom
with open(self.port_to_eeprom_mapping[self.port_num],
"r+b") as fd:
fd.seek(QSFP_POWEROVERRIDE_OFFSET)
fd.write(buffer[0])
time.sleep(0.01)
except Exception:
print("Error: unable to open file: %s" % str(e))
return False
return True
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
sfputil_helper = SfpUtilHelper()
sfputil_helper.read_porttab_mappings(
self.__get_path_to_port_config_file())
name = sfputil_helper.logical[self.index] or "Unknown"
return name
def get_presence(self):
"""
Retrieves the presence of the device
Returns:
bool: True if device is present, False if not
"""
val = self.__read_txt_file(
self.cpld_path + "module_present_" + str(self.port_num))
return val == '1'
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
return self.get_presence()
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return self.port_num
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True

View File

@ -0,0 +1,232 @@
#############################################################################
# Edgecore
#
# Thermal contains an implementation of SONiC Platform Base API and
# provides the thermal device status which are available in the platform
#
#############################################################################
import os
import os.path
import glob
try:
from sonic_platform_base.thermal_base import ThermalBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
PSU_I2C_PATH = "/sys/bus/i2c/devices/{}-00{}/"
PSU_HWMON_I2C_MAPPING = {
0: {
"bus": 17,
"addr": "59"
},
1: {
"bus": 13,
"addr": "5b"
},
}
PSU_CPLD_I2C_MAPPING = {
0: {
"bus": 17,
"addr": "51"
},
1: {
"bus": 13,
"addr": "53"
},
}
class Thermal(ThermalBase):
"""Platform-specific Thermal class"""
THERMAL_NAME_LIST = []
PSU_THERMAL_NAME_LIST = []
SYSFS_PATH = "/sys/bus/i2c/devices"
def __init__(self, thermal_index=0, is_psu=False, psu_index=0):
self.index = thermal_index
self.is_psu = is_psu
self.psu_index = psu_index
if self.is_psu:
psu_i2c_bus = PSU_HWMON_I2C_MAPPING[psu_index]["bus"]
psu_i2c_addr = PSU_HWMON_I2C_MAPPING[psu_index]["addr"]
self.psu_hwmon_path = PSU_I2C_PATH.format(psu_i2c_bus,
psu_i2c_addr)
psu_i2c_bus = PSU_CPLD_I2C_MAPPING[psu_index]["bus"]
psu_i2c_addr = PSU_CPLD_I2C_MAPPING[psu_index]["addr"]
self.cpld_path = PSU_I2C_PATH.format(psu_i2c_bus, psu_i2c_addr)
# Add thermal name
self.THERMAL_NAME_LIST.append("Temp sensor 1")
self.THERMAL_NAME_LIST.append("Temp sensor 2")
self.THERMAL_NAME_LIST.append("Temp sensor 3")
self.THERMAL_NAME_LIST.append("Temp sensor 4")
self.PSU_THERMAL_NAME_LIST.append("PSU-1 temp sensor 1")
self.PSU_THERMAL_NAME_LIST.append("PSU-2 temp sensor 1")
# Set hwmon path
i2c_path = {
0: "15-0048/hwmon/hwmon*/",
1: "15-0049/hwmon/hwmon*/",
2: "15-004a/hwmon/hwmon*/",
3: "15-004b/hwmon/hwmon*/"
}.get(self.index, None)
self.hwmon_path = "{}/{}".format(self.SYSFS_PATH, i2c_path)
self.ss_key = self.THERMAL_NAME_LIST[self.index]
self.ss_index = 1
def __read_txt_file(self, file_path):
for filename in glob.glob(file_path):
try:
with open(filename, 'r') as fd:
return fd.readline().rstrip()
except IOError as e:
pass
def __get_temp(self, temp_file):
if not self.is_psu:
temp_file_path = os.path.join(self.hwmon_path, temp_file)
else:
temp_file_path = temp_file
raw_temp = self.__read_txt_file(temp_file_path)
return float(raw_temp) / 1000
def __set_threshold(self, file_name, temperature):
if self.is_psu:
return True
temp_file_path = os.path.join(self.hwmon_path, file_name)
try:
with open(temp_file_path, 'w') as fd:
fd.write(str(temperature))
return True
except IOError:
return False
def get_temperature(self):
"""
Retrieves current temperature reading from thermal
Returns:
A float number of current temperature in Celsius up to nearest thousandth
of one degree Celsius, e.g. 30.125
"""
if not self.is_psu:
temp_file = "temp{}_input".format(self.ss_index)
else:
temp_file = self.psu_hwmon_path + "psu_temp1_input"
return self.__get_temp(temp_file)
def get_high_threshold(self):
"""
Retrieves the high threshold temperature of thermal
Returns:
A float number, the high threshold temperature of thermal in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125
"""
if self.is_psu:
return 0
temp_file = "temp{}_max".format(self.ss_index)
return self.__get_temp(temp_file)
def set_high_threshold(self, temperature):
"""
Sets the high threshold temperature of thermal
Args :
temperature: A float number up to nearest thousandth of one degree Celsius,
e.g. 30.125
Returns:
A boolean, True if threshold is set successfully, False if not
"""
temp_file = "temp{}_max".format(self.ss_index)
temperature = temperature *1000
self.__set_threshold(temp_file, temperature)
return True
def get_name(self):
"""
Retrieves the name of the thermal device
Returns:
string: The name of the thermal device
"""
if self.is_psu:
return self.PSU_THERMAL_NAME_LIST[self.psu_index]
else:
return self.THERMAL_NAME_LIST[self.index]
def get_presence(self):
"""
Retrieves the presence of the PSU
Returns:
bool: True if PSU is present, False if not
"""
if self.is_psu:
val = self.__read_txt_file(self.cpld_path + "psu_present")
return int(val, 10) == 1
temp_file = "temp{}_input".format(self.ss_index)
temp_file_path = os.path.join(self.hwmon_path, temp_file)
raw_txt = self.__read_txt_file(temp_file_path)
return raw_txt != None
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
if self.is_psu:
temp_file = self.psu_hwmon_path + "psu_temp_fault"
return self.get_presence() and (not int(
self.__read_txt_file(temp_file)))
file_str = "temp{}_input".format(self.ss_index)
file_path = os.path.join(self.hwmon_path, file_str)
raw_txt = self.__read_txt_file(file_path)
if raw_txt is None:
return False
else:
return int(raw_txt) != 0
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return "N/A"
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return "N/A"
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return self.index+1
def is_replaceable(self):
"""
Retrieves whether thermal module is replaceable
Returns:
A boolean value, True if replaceable, False if not
"""
return False

View File

@ -0,0 +1,15 @@
{
"services_to_ignore": [],
"devices_to_ignore": [
"asic",
"psu.temperature"
],
"user_defined_checkers": [],
"polling_interval": 60,
"led_color": {
"fault": "STATUS_LED_COLOR_RED",
"normal": "STATUS_LED_COLOR_GREEN",
"booting": "STATUS_LED_COLOR_GREEN_BLINK"
}
}

View File

@ -1,3 +1,4 @@
CONSOLE_PORT=0x2f8
CONSOLE_DEV=1
CONSOLE_SPEED=115200
ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="modprobe.blacklist=i2c-ismt,i2c_ismt,i2c-i801,i2c_i801"

View File

@ -48,7 +48,7 @@
"duty_cycle_to_pwm": "lambda dc: ((dc*100.0)/625 - 1)",
"pwm_to_duty_cycle": "lambda pwm: math.ceil(((pwm+1)*625.0)/100)"
"pwm_to_duty_cycle": "lambda pwm: (((pwm+1)*625.0)/100)"
}
}

View File

@ -34,7 +34,7 @@
"i2c-ismt",
"i2c-i801",
"i2c_dev",
"i2c_mux_pca954x force_deselect_on_exit=1",
"i2c_mux_pca954x",
"optoe"
],
"pddf_kos":
@ -116,7 +116,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x1", "dev_addr":"0x76", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x2"},
"dev_attr": { "virt_bus":"0x2", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"FAN-CTRL" },
@ -137,7 +137,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x0", "dev_addr":"0x71", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0xa"},
"dev_attr": { "virt_bus":"0xa", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PSU2" },
@ -402,7 +402,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x0", "dev_addr":"0x72", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x12"},
"dev_attr": { "virt_bus":"0x12", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT9" },
@ -423,7 +423,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x0", "dev_addr":"0x73", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x1a"},
"dev_attr": { "virt_bus":"0x1a", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT6" },
@ -444,7 +444,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x0", "dev_addr":"0x74", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x22"},
"dev_attr": { "virt_bus":"0x22", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT17" },
@ -465,7 +465,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x0", "dev_addr":"0x75", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x2a"},
"dev_attr": { "virt_bus":"0x2a", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT29" },

View File

@ -1,5 +1,5 @@
{
"skip_ledd": true,
"skip_thermalctld": true,
"skip_pcied": true
}

View File

@ -1789,6 +1789,7 @@
"TEMP1" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP1", "device_parent":"MUX7"},
"dev_attr": { "display_name":"FB_temp(0x4C)"},
"i2c":
{
"topo_info": { "parent_bus":"0x36", "dev_addr":"0x4c", "dev_type":"lm75"},
@ -1804,6 +1805,7 @@
"TEMP2" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP2", "device_parent":"MUX7"},
"dev_attr": { "display_name":"MB_RearMAC_temp(0x48)"},
"i2c":
{
"topo_info": { "parent_bus":"0x37", "dev_addr":"0x48", "dev_type":"lm75"},
@ -1819,6 +1821,7 @@
"TEMP3" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP3", "device_parent":"MUX7"},
"dev_attr": { "display_name":"MB_FrontMAC_temp(0x49)"},
"i2c":
{
"topo_info": { "parent_bus":"0x37", "dev_addr":"0x49", "dev_type":"lm75"},
@ -1834,6 +1837,7 @@
"TEMP4" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP4", "device_parent":"MUX7"},
"dev_attr": { "display_name":"MB_LeftCenter_temp(0x4A)"},
"i2c":
{
"topo_info": { "parent_bus":"0x37", "dev_addr":"0x4a", "dev_type":"lm75"},
@ -1849,6 +1853,7 @@
"TEMP5" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP5", "device_parent":"MUX7"},
"dev_attr": { "display_name":"CB_temp(0x4B)"},
"i2c":
{
"topo_info": { "parent_bus":"0x37", "dev_addr":"0x4b", "dev_type":"lm75"},

View File

@ -1,6 +1,5 @@
{
"skip_ledd": true,
"skip_pcied": true,
"skip_thermalctld": true
"skip_pcied": true
}

View File

@ -1,49 +1,49 @@
# libsensors configuration file for as7726-32x
# ------------------------------------------------
#
bus "i2c-49" "i2c-2-mux (chan_id 0)"
bus "i2c-50" "i2c-2-mux (chan_id 1)"
bus "i2c-54" "i2c-2-mux (chan_id 5)"
bus "i2c-55" "i2c-2-mux (chan_id 6)"
chip "ym2651-i2c-*-5b"
chip "psu_pmbus-i2c-*-5b"
label in3 "PSU 1 Voltage"
label fan1 "PSU 1 Fan"
label temp1 "PSU 1 Temperature"
label power1 "PSU 1 Power"
chip "ym2651-i2c-*-58"
label power2 "PSU 1 Power"
label curr2 "PSU 1 Current"
chip "psu_pmbus-i2c-*-58"
label in3 "PSU 2 Voltage"
label fan1 "PSU 2 Fan"
label temp1 "PSU 2 Temperature"
label power1 "PSU 2 Power"
chip "as7726_32x_fan-*"
label fan1 "Fan 1 Front"
label fan2 "Fan 2 Front"
label fan3 "Fan 3 Front"
label fan4 "Fan 4 Front"
label fan5 "Fan 5 Front"
label fan6 "Fan 6 Front"
label fan11 "Fan 1 Rear"
label fan12 "Fan 2 Rear"
label fan13 "Fan 3 Rear"
label fan14 "Fan 4 Rear"
label fan15 "Fan 5 Rear"
label fan16 "Fan 6 Rear"
label power2 "PSU 2 Power"
label curr2 "PSU 2 Current"
chip "fan_ctrl-*"
label fan1 "Fantray1 Front"
label fan2 "Fantray1 Rear"
label fan3 "Fantray2 Front"
label fan4 "Fantray2 Rear"
label fan5 "Fantray3 Front"
label fan6 "Fantray3 Rear"
label fan7 "Fantray4 Front"
label fan8 "Fantray4 Rear"
label fan9 "Fantray5 Front"
label fan10 "Fantray5 Rear"
label fan11 "Fantray6 Front"
label fan12 "Fantray6 Rear"
chip "lm75-i2c-*-48"
label temp1 "Main Board Temperature"
label temp1 "MB_RearMAC_temp"
chip "lm75-i2c-*-49"
label temp1 "Main Board Temperature"
label temp1 "MB_FrontMAC_temp"
chip "lm75-i2c-*-4a"
label temp1 "Main Board Temperature"
label temp1 "MB_LeftCenter_temp"
chip "lm75-i2c-*-4b"
label temp1 "CPU Board Temperature"
label temp1 "CB_temp"
chip "lm75-i2c-*-4c"
label temp1 "Fan Board Temperature"
label temp1 "FB_temp"

View File

@ -0,0 +1,260 @@
{
"interfaces": {
"Ethernet0": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet4": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet8": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet12": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet16": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet20": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet24": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet28": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet32": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet36": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet40": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet44": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet48": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet52": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet56": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet60": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet64": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet68": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet72": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet76": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet80": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet84": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet88": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet92": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet96": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet100": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet104": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet108": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet112": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet116": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet120": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet124": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet128": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet132": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet136": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet140": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet144": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet148": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet152": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet156": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet160": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet164": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet168": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet172": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet176": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet180": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet184": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet188": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet192": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet196": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet200": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet204": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet208": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet212": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet216": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet220": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet224": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet228": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet232": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet236": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet240": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet244": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet248": {
"default_brkout_mode": "1x100G[40G]"
},
"Ethernet252": {
"default_brkout_mode": "1x100G[40G]"
}
}
}

View File

@ -1,65 +1,65 @@
# name lanes alias index speed
Ethernet0 73,74,75,76 hundredGigE1 1 100000
Ethernet4 65,66,67,68 hundredGigE2 2 100000
Ethernet8 81,82,83,84 hundredGigE3 3 100000
Ethernet12 89,90,91,92 hundredGigE4 4 100000
Ethernet16 105,106,107,108 hundredGigE5 5 100000
Ethernet20 97,98,99,100 hundredGigE6 6 100000
Ethernet24 113,114,115,116 hundredGigE7 7 100000
Ethernet28 121,122,123,124 hundredGigE8 8 100000
Ethernet32 41,42,43,44 hundredGigE9 9 100000
Ethernet36 33,34,35,36 hundredGigE10 10 100000
Ethernet40 49,50,51,52 hundredGigE11 11 100000
Ethernet44 57,58,59,60 hundredGigE12 12 100000
Ethernet48 137,138,139,140 hundredGigE13 13 100000
Ethernet52 129,130,131,132 hundredGigE14 14 100000
Ethernet56 145,146,147,148 hundredGigE15 15 100000
Ethernet60 153,154,155,156 hundredGigE16 16 100000
Ethernet64 173,174,175,176 hundredGigE17 17 100000
Ethernet68 165,166,167,168 hundredGigE18 18 100000
Ethernet72 181,182,183,184 hundredGigE19 19 100000
Ethernet76 189,190,191,192 hundredGigE20 20 100000
Ethernet80 13,14,15,16 hundredGigE21 21 100000
Ethernet84 5,6,7,8 hundredGigE22 22 100000
Ethernet88 29,30,31,32 hundredGigE23 23 100000
Ethernet92 21,22,23,24 hundredGigE24 24 100000
Ethernet96 205,206,207,208 hundredGigE25 25 100000
Ethernet100 197,198,199,200 hundredGigE26 26 100000
Ethernet104 213,214,215,216 hundredGigE27 27 100000
Ethernet108 221,222,223,224 hundredGigE28 28 100000
Ethernet112 229,230,231,232 hundredGigE29 29 100000
Ethernet116 237,238,239,240 hundredGigE30 30 100000
Ethernet120 245,246,247,248 hundredGigE31 31 100000
Ethernet124 253,254,255,256 hundredGigE32 32 100000
Ethernet128 69,70,71,72 hundredGigE33 33 100000
Ethernet132 77,78,79,80 hundredGigE34 34 100000
Ethernet136 93,94,95,96 hundredGigE35 35 100000
Ethernet140 85,86,87,88 hundredGigE36 36 100000
Ethernet144 101,102,103,104 hundredGigE37 37 100000
Ethernet148 109,110,111,112 hundredGigE38 38 100000
Ethernet152 125,126,127,128 hundredGigE39 39 100000
Ethernet156 117,118,119,120 hundredGigE40 40 100000
Ethernet160 37,38,39,40 hundredGigE41 41 100000
Ethernet164 45,46,47,48 hundredGigE42 42 100000
Ethernet168 61,62,63,64 hundredGigE43 43 100000
Ethernet172 53,54,55,56 hundredGigE44 44 100000
Ethernet176 133,134,135,136 hundredGigE45 45 100000
Ethernet180 141,142,143,144 hundredGigE46 46 100000
Ethernet184 157,158,159,160 hundredGigE47 47 100000
Ethernet188 149,150,151,152 hundredGigE48 48 100000
Ethernet192 161,162,163,164 hundredGigE49 49 100000
Ethernet196 169,170,171,172 hundredGigE50 50 100000
Ethernet200 185,186,187,188 hundredGigE51 51 100000
Ethernet204 177,178,179,180 hundredGigE52 52 100000
Ethernet208 1,2,3,4 hundredGigE53 53 100000
Ethernet212 9,10,11,12 hundredGigE54 54 100000
Ethernet216 25,26,27,28 hundredGigE55 55 100000
Ethernet220 17,18,19,20 hundredGigE56 56 100000
Ethernet224 193,194,195,196 hundredGigE57 57 100000
Ethernet228 201,202,203,204 hundredGigE58 58 100000
Ethernet232 217,218,219,220 hundredGigE59 59 100000
Ethernet236 209,210,211,212 hundredGigE60 60 100000
Ethernet240 225,226,227,228 hundredGigE61 61 100000
Ethernet244 233,234,235,236 hundredGigE62 62 100000
Ethernet248 249,250,251,252 hundredGigE63 63 100000
Ethernet252 241,242,243,244 hundredGigE64 64 100000
Ethernet0 73,74,75,76 Eth1(Port1) 1 100000
Ethernet4 65,66,67,68 Eth2(Port2) 2 100000
Ethernet8 81,82,83,84 Eth3(Port3) 3 100000
Ethernet12 89,90,91,92 Eth4(Port4) 4 100000
Ethernet16 105,106,107,108 Eth5(Port5) 5 100000
Ethernet20 97,98,99,100 Eth6(Port6) 6 100000
Ethernet24 113,114,115,116 Eth7(Port7) 7 100000
Ethernet28 121,122,123,124 Eth8(Port8) 8 100000
Ethernet32 41,42,43,44 Eth9(Port9) 9 100000
Ethernet36 33,34,35,36 Eth10(Port10) 10 100000
Ethernet40 49,50,51,52 Eth11(Port11) 11 100000
Ethernet44 57,58,59,60 Eth12(Port12) 12 100000
Ethernet48 137,138,139,140 Eth13(Port13) 13 100000
Ethernet52 129,130,131,132 Eth14(Port14) 14 100000
Ethernet56 145,146,147,148 Eth15(Port15) 15 100000
Ethernet60 153,154,155,156 Eth16(Port16) 16 100000
Ethernet64 173,174,175,176 Eth17(Port17) 17 100000
Ethernet68 165,166,167,168 Eth18(Port18) 18 100000
Ethernet72 181,182,183,184 Eth19(Port19) 19 100000
Ethernet76 189,190,191,192 Eth20(Port20) 20 100000
Ethernet80 13,14,15,16 Eth21(Port21) 21 100000
Ethernet84 5,6,7,8 Eth22(Port22) 22 100000
Ethernet88 29,30,31,32 Eth23(Port23) 23 100000
Ethernet92 21,22,23,24 Eth24(Port24) 24 100000
Ethernet96 205,206,207,208 Eth25(Port25) 25 100000
Ethernet100 197,198,199,200 Eth26(Port26) 26 100000
Ethernet104 213,214,215,216 Eth27(Port27) 27 100000
Ethernet108 221,222,223,224 Eth28(Port28) 28 100000
Ethernet112 229,230,231,232 Eth29(Port29) 29 100000
Ethernet116 237,238,239,240 Eth30(Port30) 30 100000
Ethernet120 245,246,247,248 Eth31(Port31) 31 100000
Ethernet124 253,254,255,256 Eth32(Port32) 32 100000
Ethernet128 69,70,71,72 Eth33(Port33) 33 100000
Ethernet132 77,78,79,80 Eth34(Port34) 34 100000
Ethernet136 93,94,95,96 Eth35(Port35) 35 100000
Ethernet140 85,86,87,88 Eth36(Port36) 36 100000
Ethernet144 101,102,103,104 Eth37(Port37) 37 100000
Ethernet148 109,110,111,112 Eth38(Port38) 38 100000
Ethernet152 125,126,127,128 Eth39(Port39) 39 100000
Ethernet156 117,118,119,120 Eth40(Port40) 40 100000
Ethernet160 37,38,39,40 Eth41(Port41) 41 100000
Ethernet164 45,46,47,48 Eth42(Port42) 42 100000
Ethernet168 61,62,63,64 Eth43(Port43) 43 100000
Ethernet172 53,54,55,56 Eth44(Port44) 44 100000
Ethernet176 133,134,135,136 Eth45(Port45) 45 100000
Ethernet180 141,142,143,144 Eth46(Port46) 46 100000
Ethernet184 157,158,159,160 Eth47(Port47) 47 100000
Ethernet188 149,150,151,152 Eth48(Port48) 48 100000
Ethernet192 161,162,163,164 Eth49(Port49) 49 100000
Ethernet196 169,170,171,172 Eth50(Port50) 50 100000
Ethernet200 185,186,187,188 Eth51(Port51) 51 100000
Ethernet204 177,178,179,180 Eth52(Port52) 52 100000
Ethernet208 1,2,3,4 Eth53(Port53) 53 100000
Ethernet212 9,10,11,12 Eth54(Port54) 54 100000
Ethernet216 25,26,27,28 Eth55(Port55) 55 100000
Ethernet220 17,18,19,20 Eth56(Port56) 56 100000
Ethernet224 193,194,195,196 Eth57(Port57) 57 100000
Ethernet228 201,202,203,204 Eth58(Port58) 58 100000
Ethernet232 217,218,219,220 Eth59(Port59) 59 100000
Ethernet236 209,210,211,212 Eth60(Port60) 60 100000
Ethernet240 225,226,227,228 Eth61(Port61) 61 100000
Ethernet244 233,234,235,236 Eth62(Port62) 62 100000
Ethernet248 249,250,251,252 Eth63(Port63) 63 100000
Ethernet252 241,242,243,244 Eth64(Port64) 64 100000

View File

@ -1,2 +1,2 @@
CONSOLE_SPEED=115200
ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="tg3.short_preamble=1 tg3.bcm5718s_reset=1"
ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="tg3.short_preamble=1 tg3.bcm5718s_reset=1 pcie_aspm=off"

View File

@ -114,7 +114,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x0", "dev_addr":"0x77", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x1"},
"dev_attr": { "virt_bus":"0x1", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"MUX2" },
@ -137,7 +137,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x1", "dev_addr":"0x71", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x9"},
"dev_attr": { "virt_bus":"0x9", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PSU2"},
@ -249,7 +249,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x1", "dev_addr":"0x76", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x11"},
"dev_attr": { "virt_bus":"0x11", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"TEMP1" },
@ -319,7 +319,7 @@
"TEMP1" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP1", "device_parent":"MUX3"},
"dev_attr": { "display_name":"Temp_1"},
"dev_attr": { "display_name":"FB_1_temp(0x4D)"},
"i2c":
{
"topo_info": { "parent_bus":"0x11", "dev_addr":"0x4D", "dev_type":"lm75"},
@ -334,7 +334,7 @@
"TEMP2" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP2", "device_parent":"MUX3"},
"dev_attr": { "display_name":"Temp_2"},
"dev_attr": { "display_name":"FB_2_temp(0x4E)"},
"i2c":
{
"topo_info": { "parent_bus":"0x11", "dev_addr":"0x4E", "dev_type":"lm75"},
@ -349,7 +349,7 @@
"TEMP3" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP3", "device_parent":"MUX3"},
"dev_attr": { "display_name":"Temp_3"},
"dev_attr": { "display_name":"MB_MAC_temp(0x48)"},
"i2c":
{
"topo_info": { "parent_bus":"0x12", "dev_addr":"0x48", "dev_type":"lm75"},
@ -364,7 +364,7 @@
"TEMP4" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP4", "device_parent":"MUX3"},
"dev_attr": { "display_name":"Temp_4"},
"dev_attr": { "display_name":"MB_RearCenter_temp(0x49)"},
"i2c":
{
"topo_info": { "parent_bus":"0x12", "dev_addr":"0x49", "dev_type":"lm75"},
@ -379,7 +379,7 @@
"TEMP5" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP5", "device_parent":"MUX3"},
"dev_attr": { "display_name":"Temp_5"},
"dev_attr": { "display_name":"MB_RightCenter_temp(0x4A)"},
"i2c":
{
"topo_info": { "parent_bus":"0x12", "dev_addr":"0x4A", "dev_type":"lm75"},
@ -394,7 +394,7 @@
"TEMP6" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP6", "device_parent":"MUX3"},
"dev_attr": { "display_name":"Temp_6"},
"dev_attr": { "display_name":"CpuBoard_temp(0x4B)"},
"i2c":
{
"topo_info": { "parent_bus":"0x12", "dev_addr":"0x4B", "dev_type":"lm75"},
@ -464,7 +464,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x1", "dev_addr":"0x73", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x19"},
"dev_attr": { "virt_bus":"0x19", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT61" },
@ -484,7 +484,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x2", "dev_addr":"0x70", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x21"},
"dev_attr": { "virt_bus":"0x21", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT9" },
@ -504,7 +504,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x2", "dev_addr":"0x71", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x29"},
"dev_attr": { "virt_bus":"0x29", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT6" },
@ -524,7 +524,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x2", "dev_addr":"0x72", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x31"},
"dev_attr": { "virt_bus":"0x31", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT17" },
@ -544,7 +544,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x2", "dev_addr":"0x73", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x39"},
"dev_attr": { "virt_bus":"0x39", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT29" },
@ -564,7 +564,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x2", "dev_addr":"0x74", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x41"},
"dev_attr": { "virt_bus":"0x41", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT41" },
@ -584,7 +584,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x2", "dev_addr":"0x75", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x49"},
"dev_attr": { "virt_bus":"0x49", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT45" },
@ -604,7 +604,7 @@
"i2c":
{
"topo_info": { "parent_bus":"0x2", "dev_addr":"0x76", "dev_type":"pca9548"},
"dev_attr": { "virt_bus":"0x51"},
"dev_attr": { "virt_bus":"0x51", "idle_state":"-2"},
"channel":
[
{ "chn":"0", "dev":"PORT57" },

View File

@ -0,0 +1,902 @@
{
"chassis": {
"name": "7816-64X",
"components": [
{
"name": "CPLD1"
},
{
"name": "CPLD2"
},
{
"name": "CPLD3"
},
{
"name": "CPLD4"
},
{
"name": "BIOS"
}
],
"fans": [
{
"name": "FAN-1F"
},
{
"name": "FAN-1R"
},
{
"name": "FAN-2F"
},
{
"name": "FAN-2R"
},
{
"name": "FAN-3F"
},
{
"name": "FAN-3R"
},
{
"name": "FAN-4F"
},
{
"name": "FAN-4R"
}
],
"fan_drawers":[
{
"name": "FanTray1",
"num_fans" : 2,
"fans": [
{
"name": "FAN-1F"
},
{
"name": "FAN-1R"
}
]
},
{
"name": "FanTray2",
"num_fans" : 2,
"fans": [
{
"name": "FAN-2F"
},
{
"name": "FAN-2R"
}
]
},
{
"name": "FanTray3",
"num_fans" : 2,
"fans": [
{
"name": "FAN-3F"
},
{
"name": "FAN-3R"
}
]
},
{
"name": "FanTray4",
"num_fans" : 2,
"fans": [
{
"name": "FAN-4F"
},
{
"name": "FAN-4R"
}
]
}
],
"psus": [
{
"name": "PSU-1",
"fans": [
{
"name": "PSU-1 FAN-1"
}
],
"thermals": [
{
"name": "PSU-1 temp sensor 1"
}
]
},
{
"name": "PSU-2",
"fans": [
{
"name": "PSU-2 FAN-1"
}
],
"thermals": [
{
"name": "PSU-2 temp sensor 2"
}
]
}
],
"thermals": [
{
"name": "Temp sensor 1"
},
{
"name": "Temp sensor 2"
},
{
"name": "Temp sensor 3"
},
{
"name": "Temp sensor 4"
},
{
"name": "Temp sensor 5"
},
{
"name": "Temp sensor 6"
}
],
"sfps": [
{
"name": "Ethernet0"
},
{
"name": "Ethernet4"
},
{
"name": "Ethernet8"
},
{
"name": "Ethernet12"
},
{
"name": "Ethernet16"
},
{
"name": "Ethernet20"
},
{
"name": "Ethernet24"
},
{
"name": "Ethernet28"
},
{
"name": "Ethernet32"
},
{
"name": "Ethernet36"
},
{
"name": "Ethernet40"
},
{
"name": "Ethernet44"
},
{
"name": "Ethernet48"
},
{
"name": "Ethernet52"
},
{
"name": "Ethernet56"
},
{
"name": "Ethernet60"
},
{
"name": "Ethernet64"
},
{
"name": "Ethernet68"
},
{
"name": "Ethernet72"
},
{
"name": "Ethernet76"
},
{
"name": "Ethernet80"
},
{
"name": "Ethernet84"
},
{
"name": "Ethernet88"
},
{
"name": "Ethernet92"
},
{
"name": "Ethernet96"
},
{
"name": "Ethernet100"
},
{
"name": "Ethernet104"
},
{
"name": "Ethernet108"
},
{
"name": "Ethernet112"
},
{
"name": "Ethernet116"
},
{
"name": "Ethernet120"
},
{
"name": "Ethernet124"
},
{
"name": "Ethernet128"
},
{
"name": "Ethernet132"
},
{
"name": "Ethernet136"
},
{
"name": "Ethernet140"
},
{
"name": "Ethernet144"
},
{
"name": "Ethernet148"
},
{
"name": "Ethernet152"
},
{
"name": "Ethernet156"
},
{
"name": "Ethernet160"
},
{
"name": "Ethernet164"
},
{
"name": "Ethernet168"
},
{
"name": "Ethernet172"
},
{
"name": "Ethernet176"
},
{
"name": "Ethernet180"
},
{
"name": "Ethernet184"
},
{
"name": "Ethernet188"
},
{
"name": "Ethernet192"
},
{
"name": "Ethernet196"
},
{
"name": "Ethernet200"
},
{
"name": "Ethernet204"
},
{
"name": "Ethernet208"
},
{
"name": "Ethernet212"
},
{
"name": "Ethernet216"
},
{
"name": "Ethernet220"
},
{
"name": "Ethernet224"
},
{
"name": "Ethernet228"
},
{
"name": "Ethernet232"
},
{
"name": "Ethernet236"
},
{
"name": "Ethernet240"
},
{
"name": "Ethernet244"
},
{
"name": "Ethernet248"
},
{
"name": "Ethernet252"
}
]
},
"interfaces": {
"Ethernet0": {
"index": "1,1,1,1",
"lanes": "73,74,75,76",
"breakout_modes": {
"1x100G[40G]": ["Eth1(Port1)"],
"2x50G": ["Eth1/1(Port1)", "Eth1/2(Port1)"],
"4x25G": ["Eth1/1(Port1)", "Eth1/2(Port1)", "Eth1/3(Port1)", "Eth1/4(Port1)"],
"4x10G": ["Eth1/1(Port1)", "Eth1/2(Port1)", "Eth1/3(Port1)", "Eth1/4(Port1)"]
}
},
"Ethernet4": {
"index": "2,2,2,2",
"lanes": "65,66,67,68",
"breakout_modes": {
"1x100G[40G]": ["Eth2(Port2)"]
}
},
"Ethernet8": {
"index": "3,3,3,3",
"lanes": "81,82,83,84",
"breakout_modes": {
"1x100G[40G]": ["Eth3(Port3)"],
"2x50G": ["Eth3/1(Port3)", "Eth3/2(Port3)"],
"4x25G": ["Eth3/1(Port3)", "Eth3/2(Port3)", "Eth3/3(Port3)", "Eth3/4(Port3)"],
"4x10G": ["Eth3/1(Port3)", "Eth3/2(Port3)", "Eth3/3(Port3)", "Eth3/4(Port3)"]
}
},
"Ethernet12": {
"index": "4,4,4,4",
"lanes": "89,90,91,92",
"breakout_modes": {
"1x100G[40G]": ["Eth4(Port4)"]
}
},
"Ethernet16": {
"index": "5,5,5,5",
"lanes": "105,106,107,108",
"breakout_modes": {
"1x100G[40G]": ["Eth5(Port5)"],
"2x50G": ["Eth5/1(Port5)", "Eth5/2(Port5)"],
"4x25G": ["Eth5/1(Port5)", "Eth5/2(Port5)", "Eth5/3(Port5)", "Eth5/4(Port5)"],
"4x10G": ["Eth5/1(Port5)", "Eth5/2(Port5)", "Eth5/3(Port5)", "Eth5/4(Port5)"]
}
},
"Ethernet20": {
"index": "6,6,6,6",
"lanes": "97,98,99,100",
"breakout_modes": {
"1x100G[40G]": ["Eth6(Port6)"]
}
},
"Ethernet24": {
"index": "7,7,7,7",
"lanes": "113,114,115,116",
"breakout_modes": {
"1x100G[40G]": ["Eth7(Port7)"],
"2x50G": ["Eth7/1(Port7)", "Eth7/2(Port7)"],
"4x25G": ["Eth7/1(Port7)", "Eth7/2(Port7)", "Eth7/3(Port7)", "Eth7/4(Port7)"],
"4x10G": ["Eth7/1(Port7)", "Eth7/2(Port7)", "Eth7/3(Port7)", "Eth7/4(Port7)"]
}
},
"Ethernet28": {
"index": "8,8,8,8",
"lanes": "121,122,123,124",
"breakout_modes": {
"1x100G[40G]": ["Eth8(Port8)"]
}
},
"Ethernet32": {
"index": "9,9,9,9",
"lanes": "41,42,43,44",
"breakout_modes": {
"1x100G[40G]": ["Eth9(Port9)"],
"2x50G": ["Eth9/1(Port9)", "Eth9/2(Port9)"],
"4x25G": ["Eth9/1(Port9)", "Eth9/2(Port9)", "Eth9/3(Port9)", "Eth9/4(Port9)"],
"4x10G": ["Eth9/1(Port9)", "Eth9/2(Port9)", "Eth9/3(Port9)", "Eth9/4(Port9)"]
}
},
"Ethernet36": {
"index": "10,10,10,10",
"lanes": "33,34,35,36",
"breakout_modes": {
"1x100G[40G]": ["Eth10(Port10)"]
}
},
"Ethernet40": {
"index": "11,11,11,11",
"lanes": "49,50,51,52",
"breakout_modes": {
"1x100G[40G]": ["Eth11(Port11)"],
"2x50G": ["Eth11/1(Port11)", "Eth11/2(Port11)"],
"4x25G": ["Eth11/1(Port11)", "Eth11/2(Port11)", "Eth11/3(Port11)", "Eth11/4(Port11)"],
"4x10G": ["Eth11/1(Port11)", "Eth11/2(Port11)", "Eth11/3(Port11)", "Eth11/4(Port11)"]
}
},
"Ethernet44": {
"index": "12,12,12,12",
"lanes": "57,58,59,60",
"breakout_modes": {
"1x100G[40G]": ["Eth12(Port12)"]
}
},
"Ethernet48": {
"index": "13,13,13,13",
"lanes": "137,138,139,140",
"breakout_modes": {
"1x100G[40G]": ["Eth13(Port13)"],
"2x50G": ["Eth13/1(Port13)", "Eth13/2(Port13)"],
"4x25G": ["Eth13/1(Port13)", "Eth13/2(Port13)", "Eth13/3(Port13)", "Eth13/4(Port13)"],
"4x10G": ["Eth13/1(Port13)", "Eth13/2(Port13)", "Eth13/3(Port13)", "Eth13/4(Port13)"]
}
},
"Ethernet52": {
"index": "14,14,14,14",
"lanes": "129,130,131,132",
"breakout_modes": {
"1x100G[40G]": ["Eth14(Port14)"]
}
},
"Ethernet56": {
"index": "15,15,15,15",
"lanes": "145,146,147,148",
"breakout_modes": {
"1x100G[40G]": ["Eth15(Port15)"],
"2x50G": ["Eth15/1(Port15)", "Eth15/2(Port15)"],
"4x25G": ["Eth15/1(Port15)", "Eth15/2(Port15)", "Eth15/3(Port15)", "Eth15/4(Port15)"],
"4x10G": ["Eth15/1(Port15)", "Eth15/2(Port15)", "Eth15/3(Port15)", "Eth15/4(Port15)"]
}
},
"Ethernet60": {
"index": "16,16,16,16",
"lanes": "153,154,155,156",
"breakout_modes": {
"1x100G[40G]": ["Eth16(Port16)"]
}
},
"Ethernet64": {
"index": "17,17,17,17",
"lanes": "173,174,175,176",
"breakout_modes": {
"1x100G[40G]": ["Eth17(Port17)"],
"2x50G": ["Eth17/1(Port17)", "Eth17/2(Port17)"],
"4x25G": ["Eth17/1(Port17)", "Eth17/2(Port17)", "Eth17/3(Port17)", "Eth17/4(Port17)"],
"4x10G": ["Eth17/1(Port17)", "Eth17/2(Port17)", "Eth17/3(Port17)", "Eth17/4(Port17)"]
}
},
"Ethernet68": {
"index": "18,18,18,18",
"lanes": "165,166,167,168",
"breakout_modes": {
"1x100G[40G]": ["Eth18(Port18)"]
}
},
"Ethernet72": {
"index": "19,19,19,19",
"lanes": "181,182,183,184",
"breakout_modes": {
"1x100G[40G]": ["Eth19(Port19)"],
"2x50G": ["Eth19/1(Port19)", "Eth19/2(Port19)"],
"4x25G": ["Eth19/1(Port19)", "Eth19/2(Port19)", "Eth19/3(Port19)", "Eth19/4(Port19)"],
"4x10G": ["Eth19/1(Port19)", "Eth19/2(Port19)", "Eth19/3(Port19)", "Eth19/4(Port19)"]
}
},
"Ethernet76": {
"index": "20,20,20,20",
"lanes": "189,190,191,192",
"breakout_modes": {
"1x100G[40G]": ["Eth20(Port20)"]
}
},
"Ethernet80": {
"index": "21,21,21,21",
"lanes": "13,14,15,16",
"breakout_modes": {
"1x100G[40G]": ["Eth21(Port21)"],
"2x50G": ["Eth21/1(Port21)", "Eth21/2(Port21)"],
"4x25G": ["Eth21/1(Port21)", "Eth21/2(Port21)", "Eth21/3(Port21)", "Eth21/4(Port21)"],
"4x10G": ["Eth21/1(Port21)", "Eth21/2(Port21)", "Eth21/3(Port21)", "Eth21/4(Port21)"]
}
},
"Ethernet84": {
"index": "22,22,22,22",
"lanes": "5,6,7,8",
"breakout_modes": {
"1x100G[40G]": ["Eth22(Port22)"]
}
},
"Ethernet88": {
"index": "23,23,23,23",
"lanes": "29,30,31,32",
"breakout_modes": {
"1x100G[40G]": ["Eth23(Port23)"],
"2x50G": ["Eth23/1(Port23)", "Eth23/2(Port23)"],
"4x25G": ["Eth23/1(Port23)", "Eth23/2(Port23)", "Eth23/3(Port23)", "Eth23/4(Port23)"],
"4x10G": ["Eth23/1(Port23)", "Eth23/2(Port23)", "Eth23/3(Port23)", "Eth23/4(Port23)"]
}
},
"Ethernet92": {
"index": "24,24,24,24",
"lanes": "21,22,23,24",
"breakout_modes": {
"1x100G[40G]": ["Eth24(Port24)"]
}
},
"Ethernet96": {
"index": "25,25,25,25",
"lanes": "205,206,207,208",
"breakout_modes": {
"1x100G[40G]": ["Eth25(Port25)"],
"2x50G": ["Eth25/1(Port25)", "Eth25/2(Port25)"],
"4x25G": ["Eth25/1(Port25)", "Eth25/2(Port25)", "Eth25/3(Port25)", "Eth25/4(Port25)"],
"4x10G": ["Eth25/1(Port25)", "Eth25/2(Port25)", "Eth25/3(Port25)", "Eth25/4(Port25)"]
}
},
"Ethernet100": {
"index": "26,26,26,26",
"lanes": "197,198,199,200",
"breakout_modes": {
"1x100G[40G]": ["Eth26(Port26)"]
}
},
"Ethernet104": {
"index": "27,27,27,27",
"lanes": "213,214,215,216",
"breakout_modes": {
"1x100G[40G]": ["Eth27(Port27)"],
"2x50G": ["Eth27/1(Port27)", "Eth27/2(Port27)"],
"4x25G": ["Eth27/1(Port27)", "Eth27/2(Port27)", "Eth27/3(Port27)", "Eth27/4(Port27)"],
"4x10G": ["Eth27/1(Port27)", "Eth27/2(Port27)", "Eth27/3(Port27)", "Eth27/4(Port27)"]
}
},
"Ethernet108": {
"index": "28,28,28,28",
"lanes": "221,222,223,224",
"breakout_modes": {
"1x100G[40G]": ["Eth28(Port28)"]
}
},
"Ethernet112": {
"index": "29,29,29,29",
"lanes": "229,230,231,232",
"breakout_modes": {
"1x100G[40G]": ["Eth29(Port29)"],
"2x50G": ["Eth29/1(Port29)", "Eth29/2(Port29)"],
"4x25G": ["Eth29/1(Port29)", "Eth29/2(Port29)", "Eth29/3(Port29)", "Eth29/4(Port29)"],
"4x10G": ["Eth29/1(Port29)", "Eth29/2(Port29)", "Eth29/3(Port29)", "Eth29/4(Port29)"]
}
},
"Ethernet116": {
"index": "30,30,30,30",
"lanes": "237,238,239,240",
"breakout_modes": {
"1x100G[40G]": ["Eth30(Port30)"]
}
},
"Ethernet120": {
"index": "31,31,31,31",
"lanes": "245,246,247,248",
"breakout_modes": {
"1x100G[40G]": ["Eth31(Port31)"],
"2x50G": ["Eth31/1(Port31)", "Eth31/2(Port31)"],
"4x25G": ["Eth31/1(Port31)", "Eth31/2(Port31)", "Eth31/3(Port31)", "Eth31/4(Port31)"],
"4x10G": ["Eth31/1(Port31)", "Eth31/2(Port31)", "Eth31/3(Port31)", "Eth31/4(Port31)"]
}
},
"Ethernet124": {
"index": "32,32,32,32",
"lanes": "253,254,255,256",
"breakout_modes": {
"1x100G[40G]": ["Eth32(Port32)"]
}
},
"Ethernet128": {
"index": "33,33,33,33",
"lanes": "69,70,71,72",
"breakout_modes": {
"1x100G[40G]": ["Eth33(Port33)"]
}
},
"Ethernet132": {
"index": "34,34,34,34",
"lanes": "77,78,79,80",
"breakout_modes": {
"1x100G[40G]": ["Eth34(Port34)"]
}
},
"Ethernet136": {
"index": "35,35,35,35",
"lanes": "93,94,95,96",
"breakout_modes": {
"1x100G[40G]": ["Eth35(Port35)"]
}
},
"Ethernet140": {
"index": "36,36,36,36",
"lanes": "85,86,87,88",
"breakout_modes": {
"1x100G[40G]": ["Eth36(Port36)"]
}
},
"Ethernet144": {
"index": "37,37,37,37",
"lanes": "101,102,103,104",
"breakout_modes": {
"1x100G[40G]": ["Eth37(Port37)"]
}
},
"Ethernet148": {
"index": "38,38,38,38",
"lanes": "109,110,111,112",
"breakout_modes": {
"1x100G[40G]": ["Eth38(Port38)"]
}
},
"Ethernet152": {
"index": "39,39,39,39",
"lanes": "125,126,127,128",
"breakout_modes": {
"1x100G[40G]": ["Eth39(Port39)"]
}
},
"Ethernet156": {
"index": "40,40,40,40",
"lanes": "117,118,119,120",
"breakout_modes": {
"1x100G[40G]": ["Eth40(Port40)"]
}
},
"Ethernet160": {
"index": "41,41,41,41",
"lanes": "37,38,39,40",
"breakout_modes": {
"1x100G[40G]": ["Eth41(Port41)"]
}
},
"Ethernet164": {
"index": "42,42,42,42",
"lanes": "45,46,47,48",
"breakout_modes": {
"1x100G[40G]": ["Eth42(Port42)"]
}
},
"Ethernet168": {
"index": "43,43,43,43",
"lanes": "61,62,63,64",
"breakout_modes": {
"1x100G[40G]": ["Eth43(Port43)"]
}
},
"Ethernet172": {
"index": "44,44,44,44",
"lanes": "53,54,55,56",
"breakout_modes": {
"1x100G[40G]": ["Eth44(Port44)"]
}
},
"Ethernet176": {
"index": "45,45,45,45",
"lanes": "133,134,135,136",
"breakout_modes": {
"1x100G[40G]": ["Eth45(Port45)"]
}
},
"Ethernet180": {
"index": "46,46,46,46",
"lanes": "141,142,143,144",
"breakout_modes": {
"1x100G[40G]": ["Eth46(Port46)"]
}
},
"Ethernet184": {
"index": "47,47,47,47",
"lanes": "157,158,159,160",
"breakout_modes": {
"1x100G[40G]": ["Eth47(Port47)"]
}
},
"Ethernet188": {
"index": "48,48,48,48",
"lanes": "149,150,151,152",
"breakout_modes": {
"1x100G[40G]": ["Eth48(Port48)"]
}
},
"Ethernet192": {
"index": "49,49,49,49",
"lanes": "161,162,163,164",
"breakout_modes": {
"1x100G[40G]": ["Eth49(Port49)"]
}
},
"Ethernet196": {
"index": "50,50,50,50",
"lanes": "169,170,171,172",
"breakout_modes": {
"1x100G[40G]": ["Eth50(Port50)"]
}
},
"Ethernet200": {
"index": "51,51,51,51",
"lanes": "185,186,187,188",
"breakout_modes": {
"1x100G[40G]": ["Eth51(Port51)"]
}
},
"Ethernet204": {
"index": "52,52,52,52",
"lanes": "177,178,179,180",
"breakout_modes": {
"1x100G[40G]": ["Eth52(Port52)"]
}
},
"Ethernet208": {
"index": "53,53,53,53",
"lanes": "1,2,3,4",
"breakout_modes": {
"1x100G[40G]": ["Eth53(Port53)"]
}
},
"Ethernet212": {
"index": "54,54,54,54",
"lanes": "9,10,11,12",
"breakout_modes": {
"1x100G[40G]": ["Eth54(Port54)"]
}
},
"Ethernet216": {
"index": "55,55,55,55",
"lanes": "25,26,27,28",
"breakout_modes": {
"1x100G[40G]": ["Eth55(Port55)"]
}
},
"Ethernet220": {
"index": "56,56,56,56",
"lanes": "17,18,19,20",
"breakout_modes": {
"1x100G[40G]": ["Eth56(Port56)"]
}
},
"Ethernet224": {
"index": "57,57,57,57",
"lanes": "193,194,195,196",
"breakout_modes": {
"1x100G[40G]": ["Eth57(Port57)"]
}
},
"Ethernet228": {
"index": "58,58,58,58",
"lanes": "201,202,203,204",
"breakout_modes": {
"1x100G[40G]": ["Eth58(Port58)"]
}
},
"Ethernet232": {
"index": "59,59,59,59",
"lanes": "217,218,219,220",
"breakout_modes": {
"1x100G[40G]": ["Eth59(Port59)"]
}
},
"Ethernet236": {
"index": "60,60,60,60",
"lanes": "209,210,211,212",
"breakout_modes": {
"1x100G[40G]": ["Eth60(Port60)"]
}
},
"Ethernet240": {
"index": "61,61,61,61",
"lanes": "225,226,227,228",
"breakout_modes": {
"1x100G[40G]": ["Eth61(Port61)"]
}
},
"Ethernet244": {
"index": "62,62,62,62",
"lanes": "233,234,235,236",
"breakout_modes": {
"1x100G[40G]": ["Eth62(Port62)"]
}
},
"Ethernet248": {
"index": "63,63,63,63",
"lanes": "249,250,251,252",
"breakout_modes": {
"1x100G[40G]": ["Eth63(Port63)"]
}
},
"Ethernet252": {
"index": "64,64,64,64",
"lanes": "241,242,243,244",
"breakout_modes": {
"1x100G[40G]": ["Eth64(Port64)"]
}
}
}
}

View File

@ -1,6 +1,5 @@
{
"skip_ledd": true,
"skip_pcied": true,
"skip_thermalctld": true
"skip_pcied": true
}

View File

@ -1,51 +1,46 @@
# libsensors configuration file for as7816-64x
# ------------------------------------------------
#
bus "i2c-9" "i2c-1-mux (chan_id 0)"
bus "i2c-10" "i2c-1-mux (chan_id 1)"
bus "i2c-17" "i2c-1-mux (chan_id 0)"
bus "i2c-18" "i2c-1-mux (chan_id 1)"
chip "ym2851-i2c-*-5b"
chip "psu_pmbus-i2c-*-5b"
label in3 "PSU 1 Voltage"
label fan1 "PSU 1 Fan"
label temp1 "PSU 1 Temperature"
label power2 "PSU 1 Power"
label curr2 "PSU 1 Current"
chip "ym2851-i2c-*-58"
chip "psu_pmbus-i2c-*-58"
label in3 "PSU 2 Voltage"
label fan1 "PSU 2 Fan"
label temp1 "PSU 2 Temperature"
label power2 "PSU 2 Power"
label curr2 "PSU 2 Current"
chip "as7816_64x_fan-*"
label fan1 "Fan 1 Front"
label fan2 "Fan 2 Front"
label fan3 "Fan 3 Front"
label fan4 "Fan 4 Front"
label fan11 "Fan 1 Rear"
label fan12 "Fan 2 Rear"
label fan13 "Fan 3 Rear"
label fan14 "Fan 4 Rear"
chip "fan_ctrl-*"
label fan1 "Fantray1 Front"
label fan2 "Fantray1 Rear"
label fan3 "Fantray2 Front"
label fan4 "Fantray2 Rear"
label fan5 "Fantray3 Front"
label fan6 "Fantray3 Rear"
label fan7 "Fantray4 Front"
label fan8 "Fantray4 Rear"
chip "lm75-i2c-*-48"
label temp1 "Main Board Temperature"
label temp1 "MB_MAC_temp"
chip "lm75-i2c-*-49"
label temp1 "Main Board Temperature"
label temp1 "MB_RearCenter_temp"
chip "lm75-i2c-*-4a"
label temp1 "Main Board Temperature"
label temp1 "MB_RightCenter_temp"
chip "lm75-i2c-*-4b"
label temp1 "CPU Board Temperature"
label temp1 "CpuBoard_temp"
chip "lm75-i2c-*-4d"
label temp1 "Fan Board Temperature"
label temp1 "FB_1_temp"
chip "lm75-i2c-*-4e"
label temp1 "Fan Board Temperature"
label temp1 "FB_2_temp"

View File

@ -0,0 +1,2 @@
__all__ = [ "platform", "chassis", "sfp", "eeprom", "component", "psu", "thermal", "fan", "fan_drawer" ]
from . import platform

View File

@ -0,0 +1,250 @@
#############################################################################
# Edgecore
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Chassis information which are available in the platform
#
#############################################################################
import os
import sys
try:
from sonic_platform_base.chassis_base import ChassisBase
from .helper import APIHelper
from .event import SfpEvent
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
NUM_FAN_TRAY = 4
NUM_FAN = 2
NUM_PSU = 2
NUM_THERMAL = 6
NUM_PORT = 64
NUM_COMPONENT = 5
HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/"
PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/"
REBOOT_CAUSE_FILE = "reboot-cause.txt"
PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt"
HOST_CHK_CMD = "which systemctl > /dev/null 2>&1"
SYSLED_FNODE = "/sys/class/leds/as7816_64x_led::diag/brightness"
SYSLED_MODES = {
"0" : "STATUS_LED_COLOR_OFF",
"16" : "STATUS_LED_COLOR_GREEN",
"10" : "STATUS_LED_COLOR_RED"
}
class Chassis(ChassisBase):
"""Platform-specific Chassis class"""
def __init__(self):
ChassisBase.__init__(self)
self._api_helper = APIHelper()
self.is_host = self._api_helper.is_host()
self.config_data = {}
self.__initialize_fan()
self.__initialize_psu()
self.__initialize_thermals()
self.__initialize_components()
self.__initialize_sfp()
self.__initialize_eeprom()
def __initialize_sfp(self):
from sonic_platform.sfp import Sfp
for index in range(0, NUM_PORT):
sfp = Sfp(index)
self._sfp_list.append(sfp)
self._sfpevent = SfpEvent(self._sfp_list)
self.sfp_module_initialized = True
def __initialize_fan(self):
from sonic_platform.fan_drawer import FanDrawer
for fant_index in range(NUM_FAN_TRAY):
fandrawer = FanDrawer(fant_index)
self._fan_drawer_list.append(fandrawer)
self._fan_list.extend(fandrawer._fan_list)
def __initialize_psu(self):
from sonic_platform.psu import Psu
for index in range(0, NUM_PSU):
psu = Psu(index)
self._psu_list.append(psu)
def __initialize_thermals(self):
from sonic_platform.thermal import Thermal
for index in range(0, NUM_THERMAL):
thermal = Thermal(index)
self._thermal_list.append(thermal)
def __initialize_eeprom(self):
from sonic_platform.eeprom import Tlv
self._eeprom = Tlv()
def __initialize_components(self):
from sonic_platform.component import Component
for index in range(0, NUM_COMPONENT):
component = Component(index)
self._component_list.append(component)
def __initialize_watchdog(self):
from sonic_platform.watchdog import Watchdog
self._watchdog = Watchdog()
def __is_host(self):
return os.system(HOST_CHK_CMD) == 0
def __read_txt_file(self, file_path):
try:
with open(file_path, 'r') as fd:
data = fd.read()
return data.strip()
except IOError:
pass
return None
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
return self._eeprom.get_product_name()
def get_presence(self):
"""
Retrieves the presence of the Chassis
Returns:
bool: True if Chassis is present, False if not
"""
return True
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
return True
def get_base_mac(self):
"""
Retrieves the base MAC address for the chassis
Returns:
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
return self._eeprom.get_mac()
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return self._eeprom.get_pn()
def get_serial(self):
"""
Retrieves the hardware serial number for the chassis
Returns:
A string containing the hardware serial number for this chassis.
"""
return self._eeprom.get_serial()
def get_system_eeprom_info(self):
"""
Retrieves the full content of system EEPROM information for the chassis
Returns:
A dictionary where keys are the type code defined in
OCP ONIE TlvInfo EEPROM format and values are their corresponding
values.
"""
return self._eeprom.get_eeprom()
def get_reboot_cause(self):
"""
Retrieves the cause of the previous reboot
Returns:
A tuple (string, string) where the first element is a string
containing the cause of the previous reboot. This string must be
one of the predefined strings in this class. If the first string
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
to pass a description of the reboot cause.
"""
reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE)
sw_reboot_cause = self._api_helper.read_txt_file(
reboot_cause_path) or "Unknown"
return ('REBOOT_CAUSE_NON_HARDWARE', sw_reboot_cause)
def get_change_event(self, timeout=0):
# SFP event
if not self.sfp_module_initialized:
self.__initialize_sfp()
return self._sfpevent.get_sfp_event(timeout)
def get_sfp(self, index):
"""
Retrieves sfp represented by (1-based) index <index>
Args:
index: An integer, the index (1-based) of the sfp to retrieve.
The index should be the sequence of a physical port in a chassis,
starting from 1.
For example, 1 for Ethernet0, 2 for Ethernet4 and so on.
Returns:
An object dervied from SfpBase representing the specified sfp
"""
sfp = None
if not self.sfp_module_initialized:
self.__initialize_sfp()
try:
# The index will start from 1
sfp = self._sfp_list[index-1]
except IndexError:
sys.stderr.write("SFP index {} out of range (1-{})\n".format(
index, len(self._sfp_list)))
return sfp
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return -1
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return False
def initizalize_system_led(self):
return True
def get_status_led(self):
val = self._api_helper.read_txt_file(SYSLED_FNODE)
return SYSLED_MODES[val] if val in SYSLED_MODES else "UNKNOWN"
def set_status_led(self, color):
mode = None
for key, val in SYSLED_MODES.items():
if val == color:
mode = key
break
if mode is None:
return False
else:
return self._api_helper.write_txt_file(SYSLED_FNODE, mode)

Some files were not shown because too many files have changed in this diff Show More