brendandixon: LGTM
diff --git a/azurelinuxagent/common/protocol/hostplugin.py b/azurelinuxagent/common/protocol/hostplugin.py
index 4c4c2290..bdae56e2 100644
--- a/azurelinuxagent/common/protocol/hostplugin.py
+++ b/azurelinuxagent/common/protocol/hostplugin.py
@@ -80,10 +80,10 @@ class HostPluginProtocol(object):
     def get_artifact_request(self, artifact_url, artifact_manifest_url=None):
         if not self.ensure_initialized():
             logger.error("host plugin channel is not available")
-            return
+            return None, None
         if textutil.is_str_none_or_whitespace(artifact_url):
             logger.error("no extension artifact url was provided")
-            return
+            return None, None
 
         url = URI_FORMAT_GET_EXTENSION_ARTIFACT.format(self.endpoint,
                                                        HOST_PLUGIN_PORT)
diff --git a/azurelinuxagent/common/rdma.py b/azurelinuxagent/common/rdma.py
index ba9a0294..226482d3 100644
--- a/azurelinuxagent/common/rdma.py
+++ b/azurelinuxagent/common/rdma.py
@@ -133,14 +133,14 @@ class RDMAHandler(object):
         """Load the kernel driver, this depends on the proper driver
            to be installed with the install_driver() method"""
         logger.info("RDMA: probing module '%s'" % self.driver_module_name)
-        result = shellutil.run('modprobe %s' % self.driver_module_name)
+        result = shellutil.run('modprobe --first-time %s' % self.driver_module_name)
         if result != 0:
             error_msg = 'Could not load "%s" kernel module. '
-            error_msg += 'Run "modprobe %s" as root for more details'
+            error_msg += 'Run "modprobe --first-time %s" as root for more details'
             logger.error(
                 error_msg % (self.driver_module_name, self.driver_module_name)
             )
-            return
+            return False
         logger.info('RDMA: Loaded the kernel driver successfully.')
         return True
 
@@ -158,6 +158,7 @@ class RDMAHandler(object):
             logger.info('RDMA: module loaded.')
             return True
         logger.info('RDMA: module not loaded.')
+        return False
 
     def reboot_system(self):
         """Reboot the system. This is required as the kernel module for
diff --git a/azurelinuxagent/ga/exthandlers.py b/azurelinuxagent/ga/exthandlers.py
index c563cc85..9b99d041 100644
--- a/azurelinuxagent/ga/exthandlers.py
+++ b/azurelinuxagent/ga/exthandlers.py
@@ -341,7 +341,7 @@ class ExtHandlerInstance(object):
         self.logger = logger.Logger(logger.DEFAULT_LOGGER, prefix)
         
         try:
-            fileutil.mkdir(self.get_log_dir(), mode=0o744)
+            fileutil.mkdir(self.get_log_dir(), mode=0o755)
         except IOError as e:
             self.logger.error(u"Failed to create extension log dir: {0}", e)
 
diff --git a/azurelinuxagent/ga/update.py b/azurelinuxagent/ga/update.py
index ed05135c..59bc70c5 100644
--- a/azurelinuxagent/ga/update.py
+++ b/azurelinuxagent/ga/update.py
@@ -701,11 +701,15 @@ class GuestAgent(object):
             if self._fetch(uri.uri):
                 break
             else:
-                if self.host is not None:
+                if self.host is not None and self.host.ensure_initialized():
                     logger.warn("Download unsuccessful, falling back to host plugin")
                     uri, headers = self.host.get_artifact_request(uri.uri, self.host.manifest_uri)
-                    if self._fetch(uri, headers=headers):
+                    if uri is not None \
+                            and headers is not None \
+                            and self._fetch(uri, headers=headers):
                         break
+                else:
+                    logger.warn("Download unsuccessful, host plugin not available")
 
         if not os.path.isfile(self.get_agent_pkg_path()):
             msg = u"Unable to download Agent {0} from any URI".format(self.name)
diff --git a/azurelinuxagent/pa/rdma/centos.py b/azurelinuxagent/pa/rdma/centos.py
index 8ad09c54..214f9ead 100644
--- a/azurelinuxagent/pa/rdma/centos.py
+++ b/azurelinuxagent/pa/rdma/centos.py
@@ -173,8 +173,7 @@ class CentOSRDMAHandler(RDMAHandler):
             '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():
+        if not self.load_driver_module() or not self.is_driver_loaded():
             logger.info("RDMA: driver module is not loaded; reboot required")
             self.reboot_system()
         else:
diff --git a/azurelinuxagent/pa/rdma/suse.py b/azurelinuxagent/pa/rdma/suse.py
index f0d8d0f5..d31b2b08 100644
--- a/azurelinuxagent/pa/rdma/suse.py
+++ b/azurelinuxagent/pa/rdma/suse.py
@@ -93,8 +93,7 @@ class SUSERDMAHandler(RDMAHandler):
                 msg = 'RDMA: Successfully installed "%s" from '
                 msg += 'configured repositories'
                 logger.info(msg % complete_name)
-                self.load_driver_module()
-                if requires_reboot:
+                if not self.load_driver_module() or requires_reboot:
                     self.reboot_system()
                 return True
         else:
@@ -119,8 +118,7 @@ class SUSERDMAHandler(RDMAHandler):
                     msg = 'RDMA: Successfully installed "%s" from '
                     msg += 'local package cache'
                     logger.info(msg % (local_package))
-                    self.load_driver_module()
-                    if requires_reboot:
+                    if not self.load_driver_module() or requires_reboot:
                         self.reboot_system()
                     return True
             else:

Unhandled error
```
2017/02/06 19:09:15.537324 ERROR get API versions failed with [(000009)HTTP GET failed]
2017/02/06 19:09:15.537516 ERROR Event: name=WALA, op=InitializeHostPlugin, message=
2017/02/06 19:09:15.538399 ERROR host plugin channel is not available
2017/02/06 19:09:15.545516 WARNING Agent WALinuxAgent-2.2.4 failed with exception: 'NoneType' object is not iterable
2017/02/06 19:10:14.026838 WARNING Agent WALinuxAgent-2.2.4 launched with command 'python -u bin/WALinuxAgent-2.2.4-py2.7.egg -run-exthandlers' failed with return code: 1
```

We need to handle this failure more gracefully
diff --git a/tests/ga/test_update.py b/tests/ga/test_update.py
index a431a9b6..5277e594 100644
--- a/tests/ga/test_update.py
+++ b/tests/ga/test_update.py
@@ -17,30 +17,10 @@
 
 from __future__ import print_function
 
-import copy
-import glob
-import json
-import os
-import platform
-import random
-import re
-import subprocess
-import sys
-import tempfile
-import zipfile
-
-from tests.protocol.mockwiredata import *
-from tests.tools import *
-
-import azurelinuxagent.common.logger as logger
-import azurelinuxagent.common.utils.fileutil as fileutil
-
-from azurelinuxagent.common.exception import UpdateError
-from azurelinuxagent.common.protocol.restapi import *
+from azurelinuxagent.common.protocol.hostplugin import *
 from azurelinuxagent.common.protocol.wire import *
-from azurelinuxagent.common.utils.flexible_version import FlexibleVersion
-from azurelinuxagent.common.version import AGENT_NAME, AGENT_VERSION
 from azurelinuxagent.ga.update import *
+from tests.tools import *
 
 NO_ERROR = {
     "last_failure" : 0.0,
@@ -194,7 +174,7 @@ class UpdateTestCase(AgentTestCase):
             self.copy_agents(get_agent_pkgs()[0])
             self.expand_agents()
             count -= 1
-        
+
         # Determine the most recent agent version
         versions = self.agent_versions()
         src_v = FlexibleVersion(str(versions[0]))
@@ -290,11 +270,11 @@ class TestGuestAgentError(UpdateTestCase):
 
         for i in range(0, MAX_FAILURE):
             err.mark_failure()
-        
+
         # Agent failed >= MAX_FAILURE, it should be blacklisted
         self.assertTrue(err.is_blacklisted)
         self.assertEqual(MAX_FAILURE, err.failure_count)
-        
+
         # Clear old failure does not clear recent failure
         err.clear_old_failure()
         self.assertTrue(err.is_blacklisted)
@@ -396,7 +376,7 @@ class TestGuestAgent(UpdateTestCase):
         self.assertFalse(agent.is_available)
         agent._unpack()
         self.assertTrue(agent.is_available)
-        
+
         agent.mark_failure(is_fatal=True)
         self.assertFalse(agent.is_available)
         return
@@ -409,7 +389,7 @@ class TestGuestAgent(UpdateTestCase):
         agent._unpack()
         self.assertFalse(agent.is_blacklisted)
         self.assertEqual(agent.is_blacklisted, agent.error.is_blacklisted)
-        
+
         agent.mark_failure(is_fatal=True)
         self.assertTrue(agent.is_blacklisted)
         self.assertEqual(agent.is_blacklisted, agent.error.is_blacklisted)
@@ -525,7 +505,7 @@ class TestGuestAgent(UpdateTestCase):
         self.assertFalse(os.path.isdir(self.agent_path))
 
         mock_http_get.return_value= ResponseMock(status=restutil.httpclient.SERVICE_UNAVAILABLE)
-        
+
         pkg = ExtHandlerPackage(version=str(get_agent_version()))
         pkg.uris.append(ExtHandlerPackageUri())
         agent = GuestAgent(pkg=pkg)
@@ -546,6 +526,8 @@ class TestGuestAgent(UpdateTestCase):
 
         ext_uri = 'ext_uri'
         host_uri = 'host_uri'
+        api_uri = URI_FORMAT_GET_API_VERSIONS.format(host_uri, HOST_PLUGIN_PORT)
+        art_uri = URI_FORMAT_GET_EXTENSION_ARTIFACT.format(host_uri, HOST_PLUGIN_PORT)
         mock_host = HostPluginProtocol(host_uri,
                                        'container_id',
                                        'role_config')
@@ -555,13 +537,29 @@ class TestGuestAgent(UpdateTestCase):
         agent = GuestAgent(pkg=pkg)
         agent.host = mock_host
 
+        # ensure fallback fails gracefully, no http
+        self.assertRaises(UpdateError, agent._download)
+        self.assertEqual(mock_http_get.call_count, 2)
+        self.assertEqual(mock_http_get.call_args_list[0][0][0], ext_uri)
+        self.assertEqual(mock_http_get.call_args_list[1][0][0], api_uri)
+
+        # ensure fallback fails gracefully, artifact api failure
         with patch.object(HostPluginProtocol,
-                          "get_artifact_request",
-                          return_value=[host_uri, {}]):
+                          "ensure_initialized",
+                          return_value=True):
             self.assertRaises(UpdateError, agent._download)
-            self.assertEqual(mock_http_get.call_count, 2)
-            self.assertEqual(mock_http_get.call_args_list[0][0][0], ext_uri)
-            self.assertEqual(mock_http_get.call_args_list[1][0][0], host_uri)
+            self.assertEqual(mock_http_get.call_count, 4)
+            self.assertEqual(mock_http_get.call_args_list[2][0][0], ext_uri)
+            self.assertEqual(mock_http_get.call_args_list[3][0][0], art_uri)
+
+            # ensure fallback works as expected
+            with patch.object(HostPluginProtocol,
+                              "get_artifact_request",
+                              return_value=[art_uri, {}]):
+                self.assertRaises(UpdateError, agent._download)
+                self.assertEqual(mock_http_get.call_count, 6)
+                self.assertEqual(mock_http_get.call_args_list[4][0][0], ext_uri)
+                self.assertEqual(mock_http_get.call_args_list[5][0][0], art_uri)
 
     @patch("azurelinuxagent.ga.update.restutil.http_get")
     def test_ensure_downloaded(self, mock_http_get):
@@ -688,7 +686,7 @@ class TestUpdate(UpdateTestCase):
             protocol=None,
             versions=None,
             count=5):
-        
+
         latest_version = self.prepare_agents(count=count)
         if versions is None or len(versions) <= 0:
             versions = [latest_version]
@@ -741,7 +739,7 @@ class TestUpdate(UpdateTestCase):
         self.prepare_agents()
         agent_count = self.agent_count()
         self.assertEqual(5, agent_count)
-        
+
         agent_versions = self.agent_versions()[:3]
         self.assertTrue(self._test_upgrade_available(versions=agent_versions))
         self.assertEqual(len(agent_versions), len(self.update_handler.agents))
@@ -793,7 +791,7 @@ class TestUpdate(UpdateTestCase):
                 return iterations[0] < invocations
 
             mock_util.check_pid_alive = Mock(side_effect=iterator)
-            
+
             with patch('os.getpid', return_value=42):
                 with patch('time.sleep', return_value=None) as mock_sleep:
                     self.update_handler._ensure_no_orphans(orphan_wait_interval=interval)
@@ -1178,7 +1176,7 @@ class TestUpdate(UpdateTestCase):
         #   reference. Incrementing an item of a list changes an item to
         #   which the code has a reference.
         #   See http://stackoverflow.com/questions/26408941/python-nested-functions-and-variable-scope
-        iterations = [0] 
+        iterations = [0]
         def iterator(*args, **kwargs):
             iterations[0] += 1
             if iterations[0] >= invocations:

pip install -e .
parse_log_pytest
pytest
pyasn1 nose pytest
apt-get update apt-get install -y gcc
3.4
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///opt/conda/conda-bld/attrs_1642510447205/work
certifi==2021.5.30
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1631916693255/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
more-itertools @ file:///tmp/build/80754af9/more-itertools_1637733554872/work
nose==1.3.7
packaging @ file:///tmp/build/80754af9/packaging_1637314298585/work
pluggy @ file:///tmp/build/80754af9/pluggy_1615976315926/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pyasn1==0.5.1
pyparsing @ file:///tmp/build/80754af9/pyparsing_1635766073266/work
pytest==6.2.4
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
typing_extensions @ file:///opt/conda/conda-bld/typing_extensions_1647553014482/work
-e git+https://github.com/Azure/WALinuxAgent.git@d3a25f6cba37f8f18330d1a55500a4648d22dc49#egg=WALinuxAgent
zipp @ file:///tmp/build/80754af9/zipp_1633618647012/work

name: WALinuxAgent
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=21.4.0=pyhd3eb1b0_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - importlib-metadata=4.8.1=py36h06a4308_0
  - importlib_metadata=4.8.1=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - more-itertools=8.12.0=pyhd3eb1b0_0
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=21.3=pyhd3eb1b0_0
  - pip=21.2.2=py36h06a4308_0
  - pluggy=0.13.1=py36h06a4308_0
  - py=1.11.0=pyhd3eb1b0_0
  - pyparsing=3.0.4=pyhd3eb1b0_0
  - pytest=6.2.4=py36h06a4308_2
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd3eb1b0_0
  - typing_extensions=4.1.1=pyh06a4308_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.6.0=pyhd3eb1b0_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - nose==1.3.7
      - pyasn1==0.5.1
prefix: /opt/conda/envs/WALinuxAgent

tests/ga/test_update.py::TestGuestAgent::test_download_fallback
tests/ga/test_update.py::TestGuestAgentError::test_clear tests/ga/test_update.py::TestGuestAgentError::test_creation tests/ga/test_update.py::TestGuestAgentError::test_load_preserves_error_state tests/ga/test_update.py::TestGuestAgentError::test_mark_failure tests/ga/test_update.py::TestGuestAgentError::test_mark_failure_permanent tests/ga/test_update.py::TestGuestAgentError::test_save tests/ga/test_update.py::TestGuestAgentError::test_str tests/ga/test_update.py::TestGuestAgent::test_clear_error tests/ga/test_update.py::TestGuestAgent::test_creation tests/ga/test_update.py::TestGuestAgent::test_download tests/ga/test_update.py::TestGuestAgent::test_download_fail tests/ga/test_update.py::TestGuestAgent::test_ensure_download_skips_blacklisted tests/ga/test_update.py::TestGuestAgent::test_ensure_downloaded tests/ga/test_update.py::TestGuestAgent::test_ensure_downloaded_download_fails tests/ga/test_update.py::TestGuestAgent::test_ensure_downloaded_load_manifest_fails tests/ga/test_update.py::TestGuestAgent::test_ensure_downloaded_unpack_fails tests/ga/test_update.py::TestGuestAgent::test_is_available tests/ga/test_update.py::TestGuestAgent::test_is_blacklisted tests/ga/test_update.py::TestGuestAgent::test_is_downloaded tests/ga/test_update.py::TestGuestAgent::test_load_error tests/ga/test_update.py::TestGuestAgent::test_load_manifest tests/ga/test_update.py::TestGuestAgent::test_load_manifest_is_empty tests/ga/test_update.py::TestGuestAgent::test_load_manifest_is_malformed tests/ga/test_update.py::TestGuestAgent::test_load_manifest_missing tests/ga/test_update.py::TestGuestAgent::test_mark_failure tests/ga/test_update.py::TestGuestAgent::test_unpack tests/ga/test_update.py::TestGuestAgent::test_unpack_fail tests/ga/test_update.py::TestUpdate::test_creation tests/ga/test_update.py::TestUpdate::test_emit_restart_event_emits_event_if_not_clean_start tests/ga/test_update.py::TestUpdate::test_emit_restart_event_writes_sentinal_file tests/ga/test_update.py::TestUpdate::test_ensure_no_orphans tests/ga/test_update.py::TestUpdate::test_ensure_no_orphans_ignores_exceptions tests/ga/test_update.py::TestUpdate::test_ensure_no_orphans_kills_after_interval tests/ga/test_update.py::TestUpdate::test_ensure_no_orphans_skips_if_no_orphans tests/ga/test_update.py::TestUpdate::test_evaluate_agent_health_ignores_installed_agent tests/ga/test_update.py::TestUpdate::test_evaluate_agent_health_raises_exception_for_restarting_agent tests/ga/test_update.py::TestUpdate::test_evaluate_agent_health_resets_with_new_agent tests/ga/test_update.py::TestUpdate::test_evaluate_agent_health_will_not_raise_exception_for_long_restarts tests/ga/test_update.py::TestUpdate::test_evaluate_agent_health_will_not_raise_exception_too_few_restarts tests/ga/test_update.py::TestUpdate::test_filter_blacklisted_agents tests/ga/test_update.py::TestUpdate::test_get_latest_agent tests/ga/test_update.py::TestUpdate::test_get_latest_agent_excluded tests/ga/test_update.py::TestUpdate::test_get_latest_agent_no_updates tests/ga/test_update.py::TestUpdate::test_get_latest_agent_skip_updates tests/ga/test_update.py::TestUpdate::test_get_latest_agent_skips_unavailable tests/ga/test_update.py::TestUpdate::test_get_pid_files tests/ga/test_update.py::TestUpdate::test_get_pid_files_returns_previous tests/ga/test_update.py::TestUpdate::test_is_clean_start_returns_false_for_current_agent tests/ga/test_update.py::TestUpdate::test_is_clean_start_returns_false_for_exceptions tests/ga/test_update.py::TestUpdate::test_is_clean_start_returns_true_sentinal_agent_is_not_current tests/ga/test_update.py::TestUpdate::test_is_clean_start_returns_true_when_no_sentinal tests/ga/test_update.py::TestUpdate::test_is_orphaned_returns_false_if_parent_exists tests/ga/test_update.py::TestUpdate::test_is_orphaned_returns_true_if_parent_does_not_exist tests/ga/test_update.py::TestUpdate::test_is_orphaned_returns_true_if_parent_is_init tests/ga/test_update.py::TestUpdate::test_load_agents tests/ga/test_update.py::TestUpdate::test_load_agents_does_reload tests/ga/test_update.py::TestUpdate::test_load_agents_sorts tests/ga/test_update.py::TestUpdate::test_purge_agents tests/ga/test_update.py::TestUpdate::test_run tests/ga/test_update.py::TestUpdate::test_run_clears_sentinal_on_successful_exit tests/ga/test_update.py::TestUpdate::test_run_emits_restart_event tests/ga/test_update.py::TestUpdate::test_run_keeps_running tests/ga/test_update.py::TestUpdate::test_run_latest tests/ga/test_update.py::TestUpdate::test_run_latest_captures_signals tests/ga/test_update.py::TestUpdate::test_run_latest_creates_only_one_signal_handler tests/ga/test_update.py::TestUpdate::test_run_latest_defaults_to_current tests/ga/test_update.py::TestUpdate::test_run_latest_exception_blacklists tests/ga/test_update.py::TestUpdate::test_run_latest_forwards_output tests/ga/test_update.py::TestUpdate::test_run_latest_nonzero_code_marks_failures tests/ga/test_update.py::TestUpdate::test_run_latest_polling_stops_at_failure tests/ga/test_update.py::TestUpdate::test_run_latest_polling_stops_at_success tests/ga/test_update.py::TestUpdate::test_run_latest_polls_and_waits_for_success tests/ga/test_update.py::TestUpdate::test_run_leaves_sentinal_on_unsuccessful_exit tests/ga/test_update.py::TestUpdate::test_run_stops_if_orphaned tests/ga/test_update.py::TestUpdate::test_run_stops_if_update_available tests/ga/test_update.py::TestUpdate::test_set_agents_sets_agents tests/ga/test_update.py::TestUpdate::test_set_agents_sorts_agents tests/ga/test_update.py::TestUpdate::test_set_sentinal tests/ga/test_update.py::TestUpdate::test_set_sentinal_writes_current_agent tests/ga/test_update.py::TestUpdate::test_shutdown tests/ga/test_update.py::TestUpdate::test_shutdown_ignores_exceptions tests/ga/test_update.py::TestUpdate::test_shutdown_ignores_missing_sentinal_file tests/ga/test_update.py::TestUpdate::test_upgrade_available_handles_missing_family tests/ga/test_update.py::TestUpdate::test_upgrade_available_includes_old_agents tests/ga/test_update.py::TestUpdate::test_upgrade_available_purges_old_agents tests/ga/test_update.py::TestUpdate::test_upgrade_available_returns_true_on_first_use tests/ga/test_update.py::TestUpdate::test_upgrade_available_skips_if_too_frequent tests/ga/test_update.py::TestUpdate::test_upgrade_available_skips_if_when_no_new_versions tests/ga/test_update.py::TestUpdate::test_upgrade_available_skips_when_no_versions tests/ga/test_update.py::TestUpdate::test_upgrade_available_skips_when_updates_are_disabled tests/ga/test_update.py::TestUpdate::test_upgrade_available_sorts tests/ga/test_update.py::TestUpdate::test_write_pid_file tests/ga/test_update.py::TestUpdate::test_write_pid_file_ignores_exceptions
azurelinuxagent/ga/update.py azurelinuxagent/pa/rdma/centos.py azurelinuxagent/common/protocol/hostplugin.py azurelinuxagent/common/rdma.py azurelinuxagent/ga/exthandlers.py azurelinuxagent/pa/rdma/suse.py
azurelinuxagent/ga/update.py azurelinuxagent/pa/rdma/centos.py azurelinuxagent/common/protocol/hostplugin.py azurelinuxagent/common/rdma.py azurelinuxagent/ga/exthandlers.py azurelinuxagent/pa/rdma/suse.py