diff options
author | Daniel Watkins <daniel.watkins@canonical.com> | 2016-09-13 16:11:47 +0100 |
---|---|---|
committer | usd-importer <ubuntu-server@lists.ubuntu.com> | 2016-09-14 10:39:12 +0000 |
commit | 5009a9d0f3606fc08a80ec0d59076d8dc48d2f25 (patch) | |
tree | ad67eef74c5208178950db6ee28195e2137fa713 /azurelinuxagent/pa/rdma | |
parent | 0f7cef5b52162d1ebb31a738bd8fc9febe1fbda6 (diff) | |
download | vyos-walinuxagent-5009a9d0f3606fc08a80ec0d59076d8dc48d2f25.tar.gz vyos-walinuxagent-5009a9d0f3606fc08a80ec0d59076d8dc48d2f25.zip |
Import patches-unapplied version 2.1.5-0ubuntu1 to ubuntu/yakkety-proposed
Imported using git-ubuntu import.
Changelog parent: 0f7cef5b52162d1ebb31a738bd8fc9febe1fbda6
New changelog entries:
* New upstream release (LP: #1603581)
- d/patches/disable-auto-update.patch:
- The new version introduces auto-updating of the agent to its latest
version via an internal mechanism; disable this
- d/patches/fix_shebangs.patch:
- Dropped in favour of the dh_python3 --shebang option.
- Refreshed d/patches/disable_udev_overrides.patch
Diffstat (limited to 'azurelinuxagent/pa/rdma')
-rw-r--r-- | azurelinuxagent/pa/rdma/__init__.py | 18 | ||||
-rw-r--r-- | azurelinuxagent/pa/rdma/centos.py | 203 | ||||
-rw-r--r-- | azurelinuxagent/pa/rdma/factory.py | 41 | ||||
-rw-r--r-- | azurelinuxagent/pa/rdma/suse.py | 130 |
4 files changed, 392 insertions, 0 deletions
diff --git a/azurelinuxagent/pa/rdma/__init__.py b/azurelinuxagent/pa/rdma/__init__.py new file mode 100644 index 0000000..dff0ba4 --- /dev/null +++ b/azurelinuxagent/pa/rdma/__init__.py @@ -0,0 +1,18 @@ +# Copyright 2016 Microsoft Corporation +# +# 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. +# +# Requires Python 2.4+ and Openssl 1.0+ +# + +from azurelinuxagent.pa.rdma.factory import get_rdma_handler diff --git a/azurelinuxagent/pa/rdma/centos.py b/azurelinuxagent/pa/rdma/centos.py new file mode 100644 index 0000000..c527e1b --- /dev/null +++ b/azurelinuxagent/pa/rdma/centos.py @@ -0,0 +1,203 @@ +# Microsoft Azure Linux Agent +# +# Copyright 2014 Microsoft Corporation +# +# 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. +# +# Requires Python 2.4+ and Openssl 1.0+ +# + +import glob +import os +import re +import azurelinuxagent.common.logger as logger +import azurelinuxagent.common.utils.shellutil as shellutil +from azurelinuxagent.common.rdma import RDMAHandler + + +class CentOSRDMAHandler(RDMAHandler): + rdma_user_mode_package_name = 'microsoft-hyper-v-rdma' + rdma_kernel_mode_package_name = 'kmod-microsoft-hyper-v-rdma' + rdma_wrapper_package_name = 'msft-rdma-drivers' + + hyper_v_package_name = "hypervkvpd" + hyper_v_package_name_new = "microsoft-hyper-v" + + version_major = None + version_minor = None + + def __init__(self, distro_version): + v = distro_version.split('.') + if len(v) < 2: + raise Exception('Unexpected centos version: %s' % distro_version) + self.version_major, self.version_minor = v[0], v[1] + + def install_driver(self): + """ + Install the KVP daemon and the appropriate RDMA driver package for the + RDMA firmware. + """ + fw_version = RDMAHandler.get_rdma_version() + if not fw_version: + raise Exception('Cannot determine RDMA firmware version') + logger.info("RDMA: found firmware version: {0}".format(fw_version)) + fw_version = self.get_int_rdma_version(fw_version) + installed_pkg = self.get_rdma_package_info() + if installed_pkg: + logger.info( + 'RDMA: driver package present: {0}'.format(installed_pkg)) + if self.is_rdma_package_up_to_date(installed_pkg, fw_version): + logger.info('RDMA: driver package is up-to-date') + return + else: + logger.info('RDMA: driver package needs updating') + self.update_rdma_package(fw_version) + else: + logger.info('RDMA: driver package is NOT installed') + self.update_rdma_package(fw_version) + + def is_rdma_package_up_to_date(self, pkg, fw_version): + # Example match (pkg name, -, followed by 3 segments, fw_version and -): + # - pkg=microsoft-hyper-v-rdma-4.1.0.142-20160323.x86_64 + # - fw_version=142 + pattern = '{0}-\d\.\d\.\d\.({1})-'.format( + self.rdma_user_mode_package_name, fw_version) + return re.match(pattern, pkg) + + @staticmethod + def get_int_rdma_version(version): + s = version.split('.') + if len(s) == 0: + raise Exception('Unexpected RDMA firmware version: "%s"' % version) + return s[0] + + def get_rdma_package_info(self): + """ + Returns the installed rdma package name or None + """ + ret, output = shellutil.run_get_output( + 'rpm -q %s' % self.rdma_user_mode_package_name, chk_err=False) + if ret != 0: + return None + return output + + def update_rdma_package(self, fw_version): + logger.info("RDMA: updating RDMA packages") + self.refresh_repos() + self.force_install_package(self.rdma_wrapper_package_name) + self.install_rdma_drivers(fw_version) + + def force_install_package(self, pkg_name): + """ + Attempts to remove existing package and installs the package + """ + logger.info('RDMA: Force installing package: %s' % pkg_name) + if self.uninstall_package(pkg_name) != 0: + logger.info('RDMA: Erasing package failed but will continue') + if self.install_package(pkg_name) != 0: + raise Exception('Failed to install package "{0}"'.format(pkg_name)) + logger.info('RDMA: installation completed: %s' % pkg_name) + + @staticmethod + def uninstall_package(pkg_name): + return shellutil.run('yum erase -y -q {0}'.format(pkg_name)) + + @staticmethod + def install_package(pkg_name): + return shellutil.run('yum install -y -q {0}'.format(pkg_name)) + + def refresh_repos(self): + logger.info("RDMA: refreshing yum repos") + if shellutil.run('yum clean all') != 0: + raise Exception('Cleaning yum repositories failed') + if shellutil.run('yum updateinfo') != 0: + raise Exception('Failed to act on yum repo update information') + logger.info("RDMA: repositories refreshed") + + def install_rdma_drivers(self, fw_version): + """ + Installs the drivers from /opt/rdma/rhel[Major][Minor] directory, + particularly the microsoft-hyper-v-rdma-* kmod-* and (no debuginfo or + src). Tries to uninstall them first. + """ + pkg_dir = '/opt/microsoft/rdma/rhel{0}{1}'.format( + self.version_major, self.version_minor) + logger.info('RDMA: pkgs dir: {0}'.format(pkg_dir)) + if not os.path.isdir(pkg_dir): + raise Exception('RDMA packages directory %s is missing' % pkg_dir) + + pkgs = os.listdir(pkg_dir) + logger.info('RDMA: found %d files in package directory' % len(pkgs)) + + # Uninstal KVP daemon first (if exists) + self.uninstall_kvp_driver_package_if_exists() + + # Install kernel mode driver (kmod-microsoft-hyper-v-rdma-*) + kmod_pkg = self.get_file_by_pattern( + pkgs, "%s-\d\.\d\.\d\.+(%s)-\d{8}\.x86_64.rpm" % (self.rdma_kernel_mode_package_name, fw_version)) + if not kmod_pkg: + raise Exception("RDMA kernel mode package not found") + kmod_pkg_path = os.path.join(pkg_dir, kmod_pkg) + self.uninstall_pkg_and_install_from( + 'kernel mode', self.rdma_kernel_mode_package_name, kmod_pkg_path) + + # Install user mode driver (microsoft-hyper-v-rdma-*) + umod_pkg = self.get_file_by_pattern( + pkgs, "%s-\d\.\d\.\d\.+(%s)-\d{8}\.x86_64.rpm" % (self.rdma_user_mode_package_name, fw_version)) + if not umod_pkg: + raise Exception("RDMA user mode package not found") + umod_pkg_path = os.path.join(pkg_dir, umod_pkg) + self.uninstall_pkg_and_install_from( + 'user mode', self.rdma_user_mode_package_name, umod_pkg_path) + + logger.info("RDMA: driver packages installed") + self.load_driver_module() + if not self.is_driver_loaded(): + logger.info("RDMA: driver module is not loaded; reboot required") + self.reboot_system() + else: + logger.info("RDMA: kernel module is loaded") + + @staticmethod + def get_file_by_pattern(list, pattern): + for l in list: + if re.match(pattern, l): + return l + return None + + def uninstall_pkg_and_install_from(self, pkg_type, pkg_name, pkg_path): + logger.info( + "RDMA: Processing {0} driver: {1}".format(pkg_type, pkg_path)) + logger.info("RDMA: Try to uninstall existing version: %s" % pkg_name) + if self.uninstall_package(pkg_name) == 0: + logger.info("RDMA: Successfully uninstaled %s" % pkg_name) + logger.info( + "RDMA: Installing {0} package from {1}".format(pkg_type, pkg_path)) + if self.install_package(pkg_path) != 0: + raise Exception( + "Failed to install RDMA {0} package".format(pkg_type)) + + def uninstall_kvp_driver_package_if_exists(self): + kvp_pkgs = [self.hyper_v_package_name, + self.hyper_v_package_name_new] + + for kvp_pkg in kvp_pkgs: + if shellutil.run("rpm -q %s" % kvp_pkg, chk_err=False) != 0: + logger.info( + "RDMA: kvp package %s does not exist, skipping" % kvp_pkg) + else: + logger.info('RDMA: erasing kvp package "%s"' % kvp_pkg) + if shellutil.run("yum erase -q -y %s" % kvp_pkg, chk_err=False) == 0: + logger.info("RDMA: successfully erased package") + else: + logger.error("RDMA: failed to erase package") diff --git a/azurelinuxagent/pa/rdma/factory.py b/azurelinuxagent/pa/rdma/factory.py new file mode 100644 index 0000000..535b3d3 --- /dev/null +++ b/azurelinuxagent/pa/rdma/factory.py @@ -0,0 +1,41 @@ +# Copyright 2016 Microsoft Corporation +# +# 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. +# +# Requires Python 2.4+ and Openssl 1.0+ +# + +import azurelinuxagent.common.logger as logger + +from azurelinuxagent.common.version import DISTRO_FULL_NAME, DISTRO_VERSION +from azurelinuxagent.common.rdma import RDMAHandler +from .suse import SUSERDMAHandler +from .centos import CentOSRDMAHandler + + +def get_rdma_handler( + distro_full_name=DISTRO_FULL_NAME, + distro_version=DISTRO_VERSION +): + """Return the handler object for RDMA driver handling""" + if ( + distro_full_name == 'SUSE Linux Enterprise Server' and + int(distro_version) > 11 + ): + return SUSERDMAHandler() + + if distro_full_name == 'CentOS Linux' or distro_full_name == 'CentOS': + return CentOSRDMAHandler(distro_version) + + logger.info("No RDMA handler exists for distro='{0}' version='{1}'", distro_full_name, distro_version) + return RDMAHandler() diff --git a/azurelinuxagent/pa/rdma/suse.py b/azurelinuxagent/pa/rdma/suse.py new file mode 100644 index 0000000..f0d8d0f --- /dev/null +++ b/azurelinuxagent/pa/rdma/suse.py @@ -0,0 +1,130 @@ +# Microsoft Azure Linux Agent +# +# Copyright 2014 Microsoft Corporation +# +# 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. +# +# Requires Python 2.4+ and Openssl 1.0+ +# + +import glob +import os +import azurelinuxagent.common.logger as logger +import azurelinuxagent.common.utils.shellutil as shellutil +from azurelinuxagent.common.rdma import RDMAHandler + + +class SUSERDMAHandler(RDMAHandler): + + def install_driver(self): + """Install the appropriate driver package for the RDMA firmware""" + + fw_version = RDMAHandler.get_rdma_version() + if not fw_version: + error_msg = 'RDMA: Could not determine firmware version. ' + error_msg += 'Therefore, no driver will be installed.' + logger.error(error_msg) + return + zypper_install = 'zypper -n in %s' + zypper_remove = 'zypper -n rm %s' + zypper_search = 'zypper se -s %s' + package_name = 'msft-rdma-kmp-default' + cmd = zypper_search % package_name + status, repo_package_info = shellutil.run_get_output(cmd) + driver_package_versions = [] + driver_package_installed = False + for entry in repo_package_info.split('\n'): + if package_name in entry: + sections = entry.split('|') + if len(sections) < 4: + error_msg = 'RDMA: Unexpected output from"%s": "%s"' + logger.error(error_msg % (cmd, entry)) + continue + installed = sections[0].strip() + version = sections[3].strip() + driver_package_versions.append(version) + if fw_version in version and installed == 'i': + info_msg = 'RDMA: Matching driver package "%s-%s" ' + info_msg += 'is already installed, nothing to do.' + logger.info(info_msg % (package_name, version)) + return True + if installed == 'i': + driver_package_installed = True + + # If we get here the driver package is installed but the + # version doesn't match or no package is installed + requires_reboot = False + if driver_package_installed: + # Unloading the particular driver with rmmod does not work + # We have to reboot after the new driver is installed + if self.is_driver_loaded(): + info_msg = 'RDMA: Currently loaded driver does not match the ' + info_msg += 'firmware implementation, reboot will be required.' + logger.info(info_msg) + requires_reboot = True + logger.info("RDMA: removing package %s" % package_name) + cmd = zypper_remove % package_name + shellutil.run(cmd) + logger.info("RDMA: removed package %s" % package_name) + + logger.info("RDMA: looking for fw version %s in packages" % fw_version) + for entry in driver_package_versions: + if not fw_version in version: + logger.info("Package '%s' is not a match." % entry) + else: + logger.info("Package '%s' is a match. Installing." % entry) + complete_name = '%s-%s' % (package_name, version) + cmd = zypper_install % complete_name + result = shellutil.run(cmd) + if result: + error_msg = 'RDMA: Failed install of package "%s" ' + error_msg += 'from available repositories.' + logger.error(error_msg % complete_name) + msg = 'RDMA: Successfully installed "%s" from ' + msg += 'configured repositories' + logger.info(msg % complete_name) + self.load_driver_module() + if requires_reboot: + self.reboot_system() + return True + else: + logger.info("RDMA: No suitable match in repos. Trying local.") + local_packages = glob.glob('/opt/microsoft/rdma/*.rpm') + for local_package in local_packages: + logger.info("Examining: %s" % local_package) + if local_package.endswith('.src.rpm'): + continue + if ( + package_name in local_package and + fw_version in local_package + ): + logger.info("RDMA: Installing: %s" % local_package) + cmd = zypper_install % local_package + result = shellutil.run(cmd) + if result: + error_msg = 'RDMA: Failed install of package "%s" ' + error_msg += 'from local package cache' + logger.error(error_msg % local_package) + break + msg = 'RDMA: Successfully installed "%s" from ' + msg += 'local package cache' + logger.info(msg % (local_package)) + self.load_driver_module() + if requires_reboot: + self.reboot_system() + return True + else: + error_msg = 'Unable to find driver package that matches ' + error_msg += 'RDMA firmware version "%s"' % fw_version + logger.error(error_msg) + return |