Merge branch 'sonic-net:master' into config
This commit is contained in:
commit
6d4196fcc7
@ -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"
|
||||
|
@ -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
|
||||
|
33
.azure-pipelines/azure-pipelines-download-certificate.yml
Normal file
33
.azure-pipelines/azure-pipelines-download-certificate.yml
Normal 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"
|
@ -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 }}
|
||||
|
@ -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: ''
|
||||
|
19
.azure-pipelines/build-commonlib.yml
Normal file
19
.azure-pipelines/build-commonlib.yml
Normal 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
|
16
.azure-pipelines/check-dirty-version.yml
Normal file
16
.azure-pipelines/check-dirty-version.yml
Normal 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"
|
@ -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 }}
|
@ -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 }}
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -37,7 +37,7 @@ stages:
|
||||
|
||||
jobs:
|
||||
- job:
|
||||
pool: sonictest
|
||||
pool: sonictest-ma
|
||||
displayName: "kvmtest-multi-asic-t1-lag"
|
||||
timeoutInMinutes: 240
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
10
.azure-pipelines/template-clean-sonic-slave.yml
Normal file
10
.azure-pipelines/template-clean-sonic-slave.yml
Normal 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'
|
53
.azure-pipelines/template-commonlib.yml
Normal file
53
.azure-pipelines/template-commonlib.yml
Normal 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 }}
|
12
.azure-pipelines/template-skipvstest.yml
Normal file
12
.azure-pipelines/template-skipvstest.yml
Normal 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."
|
4
.azure-pipelines/template-variables.yml
Normal file
4
.azure-pipelines/template-variables.yml
Normal file
@ -0,0 +1,4 @@
|
||||
variables:
|
||||
DEFAULT_CONTAINER_REGISTRY: 'publicmirror.azurecr.io'
|
||||
COMMON_LIB_BUILD_ENVS: 'bullseye'
|
||||
SONIC_SLAVE_DOCKER_DRIVER: 'overlay2'
|
62
.azure-pipelines/trigger-publish-artifacts-build.yml
Normal file
62
.azure-pipelines/trigger-publish-artifacts-build.yml
Normal 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)"}
|
4
.azure-pipelines/vstest-exclude
Normal file
4
.azure-pipelines/vstest-exclude
Normal file
@ -0,0 +1,4 @@
|
||||
^platform
|
||||
^.azure-pipelines
|
||||
^files/build/versions
|
||||
^sonic-slave-
|
2
.azure-pipelines/vstest-include
Normal file
2
.azure-pipelines/vstest-include
Normal file
@ -0,0 +1,2 @@
|
||||
^platform/vs
|
||||
^.azure-pipelines/run-test-template.yml
|
74
.github/CODEOWNERS
vendored
74
.github/CODEOWNERS
vendored
@ -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
|
||||
|
5
.github/pull_request_template.md
vendored
5
.github/pull_request_template.md
vendored
@ -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)
|
||||
|
2
.github/workflows/automerge.yml
vendored
2
.github/workflows/automerge.yml
vendored
@ -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
21
.github/workflows/semgrep.yml
vendored
Normal 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
3
.gitignore
vendored
@ -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
63
.gitmodules
vendored
@ -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
|
||||
|
35
Makefile
35
Makefile
@ -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
|
||||
|
@ -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 := $$? )
|
||||
|
333
Makefile.work
333
Makefile.work
@ -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
|
||||
|
75
README.md
75
README.md
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
170
build_debian.sh
170
build_debian.sh
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
stable_size=71303168
|
||||
stable_size=76303168
|
||||
|
||||
#polarity/lanemap is using TH2 style.
|
||||
core_clock_frequency=893
|
||||
|
@ -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"
|
||||
|
@ -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" },
|
||||
|
@ -0,0 +1,2 @@
|
||||
__all__ = [ "platform", "chassis", "sfp", "eeprom", "component", "psu", "thermal", "fan", "fan_drawer" ]
|
||||
from . import platform
|
@ -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)
|
||||
|
@ -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
|
@ -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)
|
@ -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
|
284
device/accton/x86_64-accton_as4630_54pe-r0/sonic_platform/fan.py
Normal file
284
device/accton/x86_64-accton_as4630_54pe-r0/sonic_platform/fan.py
Normal 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
|
||||
|
@ -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
|
@ -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
|
@ -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()
|
269
device/accton/x86_64-accton_as4630_54pe-r0/sonic_platform/psu.py
Normal file
269
device/accton/x86_64-accton_as4630_54pe-r0/sonic_platform/psu.py
Normal 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
|
484
device/accton/x86_64-accton_as4630_54pe-r0/sonic_platform/sfp.py
Normal file
484
device/accton/x86_64-accton_as4630_54pe-r0/sonic_platform/sfp.py
Normal 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
|
@ -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
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"skip_ledd": true,
|
||||
"skip_thermalctld": true
|
||||
"skip_pcied": true
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"skip_ledd": true,
|
||||
"skip_thermalctld": true
|
||||
"skip_pcied": true
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
@ -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"}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@ -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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"skip_ledd": true,
|
||||
"skip_thermalctld": true
|
||||
"skip_pcied": true
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -0,0 +1,2 @@
|
||||
__all__ = [ "platform", "chassis", "sfp", "eeprom", "component", "psu", "thermal", "fan", "fan_drawer" ]
|
||||
from . import platform
|
@ -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)
|
@ -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
|
||||
|
@ -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)
|
@ -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
|
270
device/accton/x86_64-accton_as7326_56x-r0/sonic_platform/fan.py
Normal file
270
device/accton/x86_64-accton_as7326_56x-r0/sonic_platform/fan.py
Normal 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
|
@ -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
|
@ -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()
|
264
device/accton/x86_64-accton_as7326_56x-r0/sonic_platform/psu.py
Normal file
264
device/accton/x86_64-accton_as7326_56x-r0/sonic_platform/psu.py
Normal 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
|
626
device/accton/x86_64-accton_as7326_56x-r0/sonic_platform/sfp.py
Normal file
626
device/accton/x86_64-accton_as7326_56x-r0/sonic_platform/sfp.py
Normal 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
|
@ -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
|
@ -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"
|
||||
}
|
||||
}
|
@ -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"
|
||||
|
@ -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)"
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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" },
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"skip_ledd": true,
|
||||
"skip_thermalctld": true,
|
||||
"skip_pcied": true
|
||||
}
|
||||
|
||||
|
@ -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"},
|
||||
|
@ -1,6 +1,5 @@
|
||||
{
|
||||
"skip_ledd": true,
|
||||
"skip_pcied": true,
|
||||
"skip_thermalctld": true
|
||||
"skip_pcied": true
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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]"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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" },
|
||||
|
902
device/accton/x86_64-accton_as7816_64x-r0/platform.json
Executable file
902
device/accton/x86_64-accton_as7816_64x-r0/platform.json
Executable 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)"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
{
|
||||
"skip_ledd": true,
|
||||
"skip_pcied": true,
|
||||
"skip_thermalctld": true
|
||||
"skip_pcied": true
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -0,0 +1,2 @@
|
||||
__all__ = [ "platform", "chassis", "sfp", "eeprom", "component", "psu", "thermal", "fan", "fan_drawer" ]
|
||||
from . import platform
|
@ -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
Loading…
Reference in New Issue
Block a user