Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

DPDK MANA CentOS 7 changes #3373

Open
wants to merge 9 commits into
base: mcgov/dpdk-mana-merge
Choose a base branch
from
7 changes: 5 additions & 2 deletions lisa/base_tools/mv.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Licensed under the MIT license.

from lisa.executable import Tool
from typing import Union


class Mv(Tool):
Expand All @@ -14,13 +15,15 @@ def can_install(self) -> bool:
return False

def move(
self, src_path: str, dest_path: str, overwrite: bool = False, sudo: bool = False
self, src_path: str, dest_path: str, overwrite: bool = False,
sudo: bool = False, ignore_error: bool = False
) -> None:
args = "-f" if overwrite else ""
expected_exit_code = None if ignore_error else 0
self.run(
f"{args} {src_path} {dest_path}",
sudo=sudo,
shell=True,
force_run=True,
expected_exit_code=0,
expected_exit_code=expected_exit_code,
)
49 changes: 34 additions & 15 deletions lisa/transformers/kernel_source_installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ class SourceInstallerSchema(BaseInstallerSchema):
),
)

# Additional build dependencies
build_deps: List[str] = field(default_factory=list)


class SourceInstaller(BaseInstaller):
_code_path: PurePath
Expand Down Expand Up @@ -143,7 +146,7 @@ def install(self) -> str:
runbook: SourceInstallerSchema = self.runbook
assert runbook.location, "the repo must be defined."

self._install_build_tools(node)
self._install_build_tools(node, runbook.build_deps)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the build_deps be added into this class, instead of configurable? It makes repro harder from others.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please elaborate?

Currently it is added as a configurable because different kernel versions might need different build dependencies.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can add checks for kernel versions, if it's some version, add the deps. If the deps are maintained out of code, it's hard to others to make the build tools works without the right configuration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but we fetch the kernel version after installation of the build tools (otherwise make kernelrelease might fail). Should I add a second call to install_build_tools after kernel version is known?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you can call installation again, after know kernel version. Please add comments to explain the dependencies.


factory = subclasses.Factory[BaseLocation](BaseLocation)
source = factory.create_by_runbook(
Expand Down Expand Up @@ -286,33 +289,49 @@ def _build_code(self, node: Node, code_path: PurePath, kconfig_file: str) -> Non
)
result.assert_exit_code()

# the gcc version of Redhat 7.x is too old. Upgrade it.
if isinstance(node.os, Redhat) and node.os.information.version < "8.0.0":
node.os.install_packages(["devtoolset-8"])
node.tools[Mv].move("/bin/gcc", "/bin/gcc_back", overwrite=True, sudo=True)
result.assert_exit_code()
result = node.execute(
"ln -s /opt/rh/devtoolset-8/root/usr/bin/gcc /bin/gcc", sudo=True
)
result.assert_exit_code()

make = node.tools[Make]
make.make(arguments="olddefconfig", cwd=code_path)

# set timeout to 2 hours
make.make(arguments="", cwd=code_path, timeout=60 * 60 * 2)

def _install_build_tools(self, node: Node) -> None:
def _fix_mirrorlist_to_vault(self, node: Node) -> None:
node.execute("sed -i '\
s/^mirrorlist=/#mirrorlist=/;\
s/^#baseurl=/baseurl=/;\
/^baseurl=/ s/mirror/vault/\
' /etc/yum.repos.d/CentOS-*.repo", shell=True, sudo=True)

def _install_build_tools(self, node: Node, build_deps: list[str]) -> None:
os = node.os
self._log.info("installing build tools")
if isinstance(node.os, Redhat) and node.os.information.version < "8.0.0":
self._fix_mirrorlist_to_vault(node)
if isinstance(os, Redhat):
for package in list(
["elfutils-libelf-devel", "openssl-devel", "dwarves", "bc"]
["elfutils-libelf-devel", "openssl-devel", "dwarves", "bc"] + build_deps
):
if os.is_package_in_repo(package):
os.install_packages(package)
os.group_install_packages("Development Tools")

# if the kernel requires devtoolset, install its gcc
devtoolsets = [
pkg
for pkg in build_deps
if pkg.startswith("devtoolset")
]
if devtoolsets:
assert len(devtoolsets) == 1, f"only one devtoolset can be given, instead of {devtoolsets}"
devtoolset = devtoolsets[0]
node.os.install_packages(devtoolset)
node.tools[Mv].move("/bin/gcc", "/bin/gcc_back", overwrite=True, sudo=True)
result.assert_exit_code()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add message, so once the assertion failed, the error message give more details.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please take care all assert_exit_code, add error message.

result = node.execute(
f"ln -s /opt/rh/{devtoolset}/root/usr/bin/gcc /bin/gcc", sudo=True
)
result.assert_exit_code(f"can not link {devtoolset} to gcc")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use named arguments, so it won't be broken, if the interface changed in future.


if os.information.version < "8.0.0":
# git from default CentOS/RedHat 7.x does not support git tag format
# syntax temporarily use a community repo, then remove it
Expand All @@ -336,7 +355,7 @@ def _install_build_tools(self, node: Node) -> None:
"libssl-dev",
"bc",
"ccache",
]
] + build_deps
)
elif isinstance(os, CBLMariner):
os.install_packages(
Expand All @@ -355,7 +374,7 @@ def _install_build_tools(self, node: Node) -> None:
"xz-libs",
"openssl-libs",
"openssl-devel",
]
] + build_deps
)
else:
raise LisaException(
Expand Down
93 changes: 72 additions & 21 deletions microsoft/testsuites/dpdk/dpdktestpmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
from lisa.executable import ExecutableResult, Tool
from lisa.features import Disk
from lisa.nic import NicInfo
from lisa.operating_system import Debian, Fedora, Suse, Ubuntu
from lisa.operating_system import Debian, Fedora, Suse, Ubuntu, Redhat
from lisa.tools import (
Cat,
Chmod,
Dmesg,
Echo,
Expand Down Expand Up @@ -325,6 +326,7 @@ def generate_testpmd_command(
).is_greater_than(0)

return (
f"env LD_LIBRARY_PATH=/usr/local/lib64 "
f"{self._testpmd_install_path} {core_list} "
f"{nic_include_info} {log_level_args}"
f" -- --forward-mode={mode} "
Expand Down Expand Up @@ -488,6 +490,8 @@ def get_dpdk_portmask(self, ports: List[int]) -> str:

def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
# do not update kernel on backporting
self.update_kernel = kwargs.pop("update_kernel", True)
# set source args for builds if needed, first for dpdk
self.dpdk_build_path: Optional[PurePath] = None
self._dpdk_source: str = kwargs.pop("dpdk_source", PACKAGE_MANAGER_SOURCE)
Expand All @@ -499,6 +503,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
node=self.node,
rdma_core_source=rdma_core_source,
rdma_core_ref=rdma_core_ref,
update_kernel=self.update_kernel,
)
self._sample_apps_to_build = kwargs.pop("sample_apps", list())
self._dpdk_version_info = VersionInfo(0, 0)
Expand Down Expand Up @@ -531,7 +536,8 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
)

# if dpdk is already installed, find the binary and check the version
if self.find_testpmd_binary(assert_on_fail=False):
if self.find_testpmd_binary(assert_on_fail=False) or \
self.find_testpmd_binary(check_path='/usr/local/bin', assert_on_fail=False):
pkgconfig = self.node.tools[Pkgconfig]
if pkgconfig.package_info_exists(
self._dpdk_lib_name,
Expand Down Expand Up @@ -592,6 +598,13 @@ def _set_backport_repo_args(self) -> None:
else:
self._backport_repo_args = []

def _fix_mirrorlist_to_vault(self, node) -> None:
node.execute("""sed -i '
s/^mirrorlist=/#mirrorlist=/;
s/^#[ ]*baseurl=/baseurl=/;
/^baseurl=/ s/mirror/vault/;
' /etc/yum.repos.d/CentOS-*.repo""", shell=True, sudo=True)

def _install(self) -> bool:
self._testpmd_output_after_reenable = ""
self._testpmd_output_before_rescind = ""
Expand All @@ -610,6 +623,33 @@ def _install(self) -> bool:
)
)

if isinstance(node.os, Redhat) and node.os.information.version < "8.0.0":
self._fix_mirrorlist_to_vault(node)
squirrelsc marked this conversation as resolved.
Show resolved Hide resolved
node.os.install_packages(["centos-release-scl"])

# Fix CentOS-SCL's paths to mirrorlist
self._fix_mirrorlist_to_vault(node)
devtoolset_version = 8
devtoolset_pkg = f"devtoolset-{devtoolset_version}"
node.os.install_packages([devtoolset_pkg])
links = {
"gcc": ("gcc", "cc"),
"g++": ("g++", "c++"),
}
for binary in [alias
for aliases in links.values()
for alias in aliases
]:
node.tools[Mv].move(f"/bin/{binary}", f"/bin/{binary}_back",
overwrite=True, sudo=True, ignore_error=None)
devtoolset_binpath = f"/opt/rh/{devtoolset_pkg}/root/bin"
for binary, aliases in links.items():
for alias in aliases:
result = node.execute(
f"ln -s {devtoolset_binpath}/{binary} /bin/{alias}", sudo=True
)
result.assert_exit_code()

# before doing anything: determine if backport repo needs to be enabled
self._set_backport_repo_args()

Expand Down Expand Up @@ -672,11 +712,11 @@ def _install(self) -> bool:
if (
isinstance(distro, Debian)
or isinstance(distro, (Fedora, Suse))
and distro.package_exists("dpdk")
):
# if not using package manager and dpdk is already installed, uninstall it
# in preperation for source build
distro.uninstall_packages("dpdk")
if distro.package_exists("dpdk"):
distro.uninstall_packages("dpdk")
else:
raise NotImplementedError(
"Dpdk package names are missing in dpdktestpmd.install"
Expand Down Expand Up @@ -756,11 +796,20 @@ def _install(self) -> bool:
# add mana driver to build if needed
if self.vf_helper.is_mana():
drivers_to_build += ",net/mana"
# shrink build
build_flags += [
f"-Denable_drivers={drivers_to_build}",
"-Denable_apps=app/test-pmd",
]

# shrink build, if supported
cat = node.tools[Cat]
meson_options_content = cat.run("meson_options.txt",
cwd=self.dpdk_path, shell=True).stdout
if "enable_drivers" in meson_options_content:
build_flags += [
f"-Denable_drivers={drivers_to_build}"
]

if "enable_apps" in meson_options_content:
build_flags += [
"-Denable_apps=app/test-pmd"
]

node.execute(
f"meson setup {' '.join(build_flags)} build",
Expand Down Expand Up @@ -861,7 +910,7 @@ def _load_drivers_for_dpdk(self) -> None:
if isinstance(self.node.os, (Ubuntu, Suse)):
# Ubuntu shouldn't need any special casing, skip to loading rdma/ib
pass
elif isinstance(self.node.os, Debian):
elif self.update_kernel and isinstance(self.node.os, Debian):
# NOTE: debian buster doesn't include rdma and ib drivers
# on 5.4 specifically for linux-image-cloud:
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1012639
Expand Down Expand Up @@ -960,8 +1009,9 @@ def _install_ubuntu_dependencies(self) -> None:
return # appease the type checker

# apply update to latest first
ubuntu.update_packages("linux-azure")
node.reboot()
if self.update_kernel:
ubuntu.update_packages("linux-azure")
node.reboot()
if ubuntu.information.version < "18.4.0":
raise SkippedException(
f"Ubuntu {str(ubuntu.information.version)} is not supported. "
Expand All @@ -980,9 +1030,8 @@ def _install_ubuntu_dependencies(self) -> None:
extra_args=self._backport_repo_args,
)
# MANA tests use linux-modules-extra-azure, install if it's available.
if self.vf_helper.is_mana() and ubuntu.is_package_in_repo(
"linux-modules-extra-azure"
):
if self.update_kernel and self.vf_helper.is_mana() and \
ubuntu.is_package_in_repo("linux-modules-extra-azure"):
ubuntu.install_packages("linux-modules-extra-azure")

def _install_fedora_dependencies(self) -> None:
Expand All @@ -997,12 +1046,13 @@ def _install_fedora_dependencies(self) -> None:

# DPDK is very sensitive to rdma-core/kernel mismatches
# update to latest kernel before installing dependencies
rhel.install_packages(["kernel", "kernel-modules-extra", "kernel-headers"])
node.reboot()
try:
rhel.install_packages("kernel-devel")
except MissingPackagesException:
node.log.debug("Fedora: kernel-devel not found, attempting to continue")
if self.update_kernel:
rhel.install_packages(["kernel", "kernel-modules-extra", "kernel-headers"])
node.reboot()
try:
rhel.install_packages("kernel-devel")
except MissingPackagesException:
node.log.debug("Fedora: kernel-devel not found, attempting to continue")

if rhel.information.version.major == 7:
# Add packages for rhel7
Expand All @@ -1015,6 +1065,7 @@ def _install_fedora_dependencies(self) -> None:

rhel.group_install_packages("Development Tools")
rhel.install_packages(self._fedora_packages)
rhel.uninstall_packages(["doxygen"])

# ensure RDMA service is started if present.

Expand Down
15 changes: 12 additions & 3 deletions microsoft/testsuites/dpdk/dpdkutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from lisa.base_tools.uname import Uname
from lisa.features import NetworkInterface
from lisa.nic import NicInfo
from lisa.operating_system import Fedora, OperatingSystem, Ubuntu
from lisa.operating_system import Fedora, OperatingSystem, Ubuntu, CentOs
from lisa.tools import (
Dmesg,
Echo,
Expand Down Expand Up @@ -178,8 +178,15 @@ def _set_forced_source_by_distro(
# Default to 20.11 unless another version is provided by the
# user. 20.11 is the latest dpdk version for 18.04.
if (
isinstance(node.os, Ubuntu)
and node.os.information.version < "20.4.0"
(
isinstance(node.os, Ubuntu)
and node.os.information.version < "20.4.0"
)
or
(
isinstance(node.os, CentOs)
and node.os.information.version < "8.0.0"
)
or examples != None
):
variables["dpdk_source"] = variables.get("dpdk_source", DPDK_STABLE_GIT_REPO)
Expand Down Expand Up @@ -333,6 +340,7 @@ def initialize_node_resources(
dpdk_branch = variables.get("dpdk_branch", "")
rdma_core_source = variables.get("rdma_core_source", "")
rdma_core_ref = variables.get("rdma_core_git_ref", "")
update_kernel = variables.get("dpdk_update_kernel", True)
force_net_failsafe_pmd = variables.get("dpdk_force_net_failsafe_pmd", False)
enforce_strict_threshold = variables.get("dpdk_enforce_strict_threshold", False)
log.info(
Expand Down Expand Up @@ -374,6 +382,7 @@ def initialize_node_resources(
rdma_core_ref=rdma_core_ref,
enforce_strict_threshold=enforce_strict_threshold,
build_release=build_release,
update_kernel=update_kernel,
)

# init and enable hugepages (required by dpdk)
Expand Down
Loading