sonic-buildimage/platform/mellanox/integration-scripts/sdk_kernel_patches.py

227 lines
8.5 KiB
Python
Raw Normal View History

[Mellanox] Facilitate automatic integration of sdk kernel patches (#14652) #### Why I did it Facilitate Automatic integration of sdk kernel patches into SONiC. **Inputs to the Script:** 1) `MLNX_SDK_VERSION` Eg: `4.5.4206` 2) `MLNX_SDK_ISSU_VERSION` Eg: `101` **Note: If nothing is provided the one already present in the sdk.mk file is used** 3) `MLNX_SDK_SOURCE_BASE_URL:` **Note: If nothing is provided the upstream sdk drivers url is used** 4) `CREATE_BRANCH: (y|n)` Creates a branch instead of a commit (optional, default: n) 5) `BRANCH_SONIC`: Only relevant when CREATE_BRANCH is y. `Default: master`. Note: These should be provided through `SONIC_OVERRIDE_BUILD_VARS ` parameter **Output:** 1) Script creates a commit in sonic-linux-kernel with any updates to sdk-kernel patches in sonic in accordance with the version provided by `MLNX_SDK_VERSION` **Note: Script Doesn't commit anything to linux-kernel when there aren't any changes required..** #### How I did it 1) Added a new make target which can be invoked by calling `make integrate-mlnx-sdk` ``` user@server:/sonic-buildimage/src/sonic-linux-kernel$ git rev-parse --abbrev-ref HEAD master_6f38dca_integrate_4.5.4206 user@server:/sonic-buildimage/src/sonic-linux-kernel$ git log --oneline -n 1 d64d1e7 (HEAD -> master_6f38dca_integrate_4.5.4206) Intgerate MLNX SDK 4.5.4206 Kernel Patches ``` Changes made will be summarized under `sonic-buildimage/integrate-mlnx-sdk_user.out` file. Debugging and troubleshooting output is written to `sonic-buildimage/integrate-mlnx-sdk.log` files [log_files.zip](https://github.com/sonic-net/sonic-buildimage/files/11226441/log_files.zip) #### Limitations: 1) Assumes that the sdk kernel patches are always upstreamed #### How to verify it Build the Kernel and test
2023-05-30 00:24:06 -05:00
#!/usr/bin/env python
#
# Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES.
# Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import os
import sys
import shutil
import argparse
import copy
from helper import *
COMMIT_TITLE = "Integrate SDK {} Kernel Patches"
DELIMITTER = "========================"
class Data:
# old sonic-linux-kernel series file
old_series = list()
# updated sonic-linux-kernel series file
new_series = list()
# list of any new SDK patches to add
new_patches = list()
# list of current patch list in sonic-linux-kernel
old_patches = list()
# index of the mlnx_hw_mgmt patches start marker in old_series
i_sdk_start = -1
# index of the mlnx_hw_mgmt patches end marker in old_series
i_sdk_end = -1
# kernel directory to consider the patches
k_dir = ""
class SDKAction(Action):
def __init__(self, args):
super().__init__(args)
def check(self):
if not (self.args.patches and os.path.exists(self.args.patches)):
print("-> ERR: patch directory is missing ")
return False
if not (self.args.build_root and os.path.exists(self.args.build_root)):
print("-> ERR: build_root is missing")
return False
return True
def read_data(self):
Data.old_series = FileHandler.read_raw(os.path.join(self.args.build_root, SLK_SERIES))
def find_sdk_patches(self):
for index in range(Data.i_sdk_start+1, Data.i_sdk_end):
patch = Data.old_series[index].strip()
if patch:
Data.old_patches.append(Data.old_series[index].strip())
print("-> INFO Current mellanox sdk upstream patches. \n{}".format("\n".join(Data.old_patches)))
def get_kernel_dir(self):
# Get the kernel dir name to get the patches
try:
(kernel, major, minor) = self.args.sonic_kernel_ver.split(".")
minor_int = int(minor)
except Exception as e:
print("-> FATAL Kernel version formatting error: " + str(e))
sys.exit(1)
major_kernel_path = os.path.join(KERNEL_BACKPORTS, "{}.{}".format(kernel, major))
# if the k_dir with actual minor doesn't exit, use the closest minor version
for minor_i in range(minor_int, -1, -1):
[Mellanox] Facilitate automatic integration of sdk kernel patches (#14652) #### Why I did it Facilitate Automatic integration of sdk kernel patches into SONiC. **Inputs to the Script:** 1) `MLNX_SDK_VERSION` Eg: `4.5.4206` 2) `MLNX_SDK_ISSU_VERSION` Eg: `101` **Note: If nothing is provided the one already present in the sdk.mk file is used** 3) `MLNX_SDK_SOURCE_BASE_URL:` **Note: If nothing is provided the upstream sdk drivers url is used** 4) `CREATE_BRANCH: (y|n)` Creates a branch instead of a commit (optional, default: n) 5) `BRANCH_SONIC`: Only relevant when CREATE_BRANCH is y. `Default: master`. Note: These should be provided through `SONIC_OVERRIDE_BUILD_VARS ` parameter **Output:** 1) Script creates a commit in sonic-linux-kernel with any updates to sdk-kernel patches in sonic in accordance with the version provided by `MLNX_SDK_VERSION` **Note: Script Doesn't commit anything to linux-kernel when there aren't any changes required..** #### How I did it 1) Added a new make target which can be invoked by calling `make integrate-mlnx-sdk` ``` user@server:/sonic-buildimage/src/sonic-linux-kernel$ git rev-parse --abbrev-ref HEAD master_6f38dca_integrate_4.5.4206 user@server:/sonic-buildimage/src/sonic-linux-kernel$ git log --oneline -n 1 d64d1e7 (HEAD -> master_6f38dca_integrate_4.5.4206) Intgerate MLNX SDK 4.5.4206 Kernel Patches ``` Changes made will be summarized under `sonic-buildimage/integrate-mlnx-sdk_user.out` file. Debugging and troubleshooting output is written to `sonic-buildimage/integrate-mlnx-sdk.log` files [log_files.zip](https://github.com/sonic-net/sonic-buildimage/files/11226441/log_files.zip) #### Limitations: 1) Assumes that the sdk kernel patches are always upstreamed #### How to verify it Build the Kernel and test
2023-05-30 00:24:06 -05:00
path = os.path.join(major_kernel_path, "{}.{}.{}".format(kernel, major, minor_i))
if os.path.exists(os.path.join(self.args.patches, path)):
minor = str(minor_i)
Data.k_dir = path
print(f"-> INFO Kernel minor version dir {Data.k_dir} found ")
break
if not Data.k_dir:
print("-> Couldn't find the relevant kernel directory")
sys.exit(1)
path_to_check = os.path.join(self.args.patches, Data.k_dir)
if not os.path.exists(path_to_check):
print("-> FATAL Kernel dir with patches doesn't exist: {}".format(path_to_check))
sys.exit(1)
def update_series(self):
# Remove patches if they are already present in existing series file
patch_ids_remove = set()
for id in range(0, len(Data.old_series)):
for patch in Data.new_patches:
if patch in Data.old_series[id]:
patch_ids_remove.add(id)
# Modify the series files
temp_series = copy.deepcopy(Data.old_series)
Data.old_series.clear()
for id in range(0, len(temp_series)):
if id not in patch_ids_remove:
Data.old_series.append(temp_series[id])
else:
print("-> INFO Patch {} will be removed from the existing series".format(temp_series[id]))
print("-> INFO Updated Series file after removing SDK patches: \n{}".format("".join(Data.old_series)))
def add_new_patch_series(self):
new_patches = [patch + "\n" for patch in Data.new_patches]
Data.new_series = Data.old_series[0:Data.i_sdk_start+1] + new_patches + Data.old_series[Data.i_sdk_end:]
def process_update(self):
src_path = os.path.join(self.args.patches, Data.k_dir)
dst_path = os.path.join(self.args.build_root, SLK_PATCH_LOC)
for patch in Data.new_patches:
print(f"-> Moving patch: {patch}")
shutil.copy(os.path.join(src_path, patch), dst_path)
FileHandler.write_lines(os.path.join(self.args.build_root, SLK_SERIES), Data.new_series, True)
print("-> INFO Written sonic-linux-kernel series file \n{}".format("".join(Data.new_series)))
def get_new_patches(self):
patches_path = os.path.join(self.args.patches, Data.k_dir)
Data.new_patches = FileHandler.read_dir(patches_path, "*.patch")
Data.new_patches.sort()
def cleanup_old_patches(self):
patches_del = copy.deepcopy(Data.old_patches)
for patch in Data.new_patches:
if patch in Data.old_patches:
patches_del.remove(patch)
print(f" -> Patches to be removed are : {patches_del}")
for patch in patches_del:
file_n = os.path.join(self.args.build_root, os.path.join(SLK_PATCH_LOC, patch))
if os.path.exists(file_n):
print(f"{file_n} is deleted")
os.remove(file_n)
[Mellanox] Facilitate automatic integration of sdk kernel patches (#14652) #### Why I did it Facilitate Automatic integration of sdk kernel patches into SONiC. **Inputs to the Script:** 1) `MLNX_SDK_VERSION` Eg: `4.5.4206` 2) `MLNX_SDK_ISSU_VERSION` Eg: `101` **Note: If nothing is provided the one already present in the sdk.mk file is used** 3) `MLNX_SDK_SOURCE_BASE_URL:` **Note: If nothing is provided the upstream sdk drivers url is used** 4) `CREATE_BRANCH: (y|n)` Creates a branch instead of a commit (optional, default: n) 5) `BRANCH_SONIC`: Only relevant when CREATE_BRANCH is y. `Default: master`. Note: These should be provided through `SONIC_OVERRIDE_BUILD_VARS ` parameter **Output:** 1) Script creates a commit in sonic-linux-kernel with any updates to sdk-kernel patches in sonic in accordance with the version provided by `MLNX_SDK_VERSION` **Note: Script Doesn't commit anything to linux-kernel when there aren't any changes required..** #### How I did it 1) Added a new make target which can be invoked by calling `make integrate-mlnx-sdk` ``` user@server:/sonic-buildimage/src/sonic-linux-kernel$ git rev-parse --abbrev-ref HEAD master_6f38dca_integrate_4.5.4206 user@server:/sonic-buildimage/src/sonic-linux-kernel$ git log --oneline -n 1 d64d1e7 (HEAD -> master_6f38dca_integrate_4.5.4206) Intgerate MLNX SDK 4.5.4206 Kernel Patches ``` Changes made will be summarized under `sonic-buildimage/integrate-mlnx-sdk_user.out` file. Debugging and troubleshooting output is written to `sonic-buildimage/integrate-mlnx-sdk.log` files [log_files.zip](https://github.com/sonic-net/sonic-buildimage/files/11226441/log_files.zip) #### Limitations: 1) Assumes that the sdk kernel patches are always upstreamed #### How to verify it Build the Kernel and test
2023-05-30 00:24:06 -05:00
def refresh_markers(self):
print("-> INFO Refreshing Markers ")
(Data.i_sdk_start, Data.i_sdk_end) = FileHandler.find_marker_indices(Data.old_series, SDK_MARKER)
if Data.i_sdk_start < 0 or Data.i_sdk_end > len(Data.old_series):
print("-> FATAL mellanox_sdk marker not found. Couldn't continue.. exiting")
sys.exit(1)
print("-> INFO mellanox_sdk markers found. start: {}, end: {}".format(Data.i_sdk_start, Data.i_sdk_end))
def fetch_patch_table(self, root_dir):
lines = FileHandler.read_strip(os.path.join(root_dir, "README"))
delim_id = 0
for id in range(0, len(lines)):
if DELIMITTER in lines[id]:
delim_id = id
break
table = dict()
for id in range(delim_id+1, len(lines)):
tokens = lines[id].split()
if len(tokens) != 3:
print("-> INFO Error Formatted line, {}".format(" ".join(lines[id])))
continue
patch, commit = tokens[0], tokens[1]
if ".patch" not in patch:
print(f"-> INFO Unexpected Patch name {patch}")
continue
table[patch.strip()] = commit.strip()
print(f"-> INFO Final Patch Table: {table}")
return table
def create_commit_msg(self, patch_table):
changes = {}
for patch in Data.new_patches:
if patch not in Data.old_patches:
changes[patch] = parse_id(patch_table.get(patch.strip(), ""))
slk_commit_msg = COMMIT_TITLE.format(self.args.sdk_ver) + "\n" + build_commit_description(changes)
print(f"-> INFO Commit Message: {slk_commit_msg}")
return slk_commit_msg
def perform(self):
self.read_data()
self.refresh_markers()
self.find_sdk_patches()
self.get_kernel_dir()
self.get_new_patches()
self.update_series()
self.refresh_markers()
self.add_new_patch_series()
self.process_update()
self.cleanup_old_patches()
[Mellanox] Facilitate automatic integration of sdk kernel patches (#14652) #### Why I did it Facilitate Automatic integration of sdk kernel patches into SONiC. **Inputs to the Script:** 1) `MLNX_SDK_VERSION` Eg: `4.5.4206` 2) `MLNX_SDK_ISSU_VERSION` Eg: `101` **Note: If nothing is provided the one already present in the sdk.mk file is used** 3) `MLNX_SDK_SOURCE_BASE_URL:` **Note: If nothing is provided the upstream sdk drivers url is used** 4) `CREATE_BRANCH: (y|n)` Creates a branch instead of a commit (optional, default: n) 5) `BRANCH_SONIC`: Only relevant when CREATE_BRANCH is y. `Default: master`. Note: These should be provided through `SONIC_OVERRIDE_BUILD_VARS ` parameter **Output:** 1) Script creates a commit in sonic-linux-kernel with any updates to sdk-kernel patches in sonic in accordance with the version provided by `MLNX_SDK_VERSION` **Note: Script Doesn't commit anything to linux-kernel when there aren't any changes required..** #### How I did it 1) Added a new make target which can be invoked by calling `make integrate-mlnx-sdk` ``` user@server:/sonic-buildimage/src/sonic-linux-kernel$ git rev-parse --abbrev-ref HEAD master_6f38dca_integrate_4.5.4206 user@server:/sonic-buildimage/src/sonic-linux-kernel$ git log --oneline -n 1 d64d1e7 (HEAD -> master_6f38dca_integrate_4.5.4206) Intgerate MLNX SDK 4.5.4206 Kernel Patches ``` Changes made will be summarized under `sonic-buildimage/integrate-mlnx-sdk_user.out` file. Debugging and troubleshooting output is written to `sonic-buildimage/integrate-mlnx-sdk.log` files [log_files.zip](https://github.com/sonic-net/sonic-buildimage/files/11226441/log_files.zip) #### Limitations: 1) Assumes that the sdk kernel patches are always upstreamed #### How to verify it Build the Kernel and test
2023-05-30 00:24:06 -05:00
patch_table = self.fetch_patch_table(os.path.join(self.args.patches, Data.k_dir))
slk_msg = self.create_commit_msg(patch_table)
if self.args.slk_msg:
with open(self.args.slk_msg, 'w') as f:
f.write(slk_msg)
def create_parser():
# Create argument parser
parser = argparse.ArgumentParser()
# Optional arguments
parser.add_argument("--sonic_kernel_ver", type=str)
parser.add_argument("--patches", type=str)
parser.add_argument("--slk_msg", type=str)
parser.add_argument("--sdk_ver", type=str)
parser.add_argument("--build_root", type=str)
return parser
if __name__ == '__main__':
parser = create_parser()
action = SDKAction(parser.parse_args())
action.check()
action.perform()