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/provision/ubuntu.py b/azurelinuxagent/pa/provision/ubuntu.py
index 60b9a89a..a71df374 100644
--- a/azurelinuxagent/pa/provision/ubuntu.py
+++ b/azurelinuxagent/pa/provision/ubuntu.py
@@ -89,8 +89,14 @@ class UbuntuProvisionHandler(ProvisionHandler):
         path = '/etc/ssh/ssh_host_{0}_key.pub'.format(keypair_type)
         for retry in range(0, max_retry):
             if os.path.isfile(path):
-                return self.get_ssh_host_key_thumbprint(keypair_type)
+                logger.info("ssh host key found at: {0}".format(path))
+                try:
+                    thumbprint = self.get_ssh_host_key_thumbprint(keypair_type)
+                    logger.info("Thumbprint obtained from : {0}".format(path))
+                    return thumbprint
+                except ProvisionError:
+                    logger.warn("Could not get thumbprint from {0}".format(path))
             if retry < max_retry - 1:
-                logger.info("Wait for ssh host key be generated: {0}", path)
+                logger.info("Wait for ssh host key be generated: {0}".format(path))
                 time.sleep(5)
         raise ProvisionError("ssh host key is not generated.")
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:

Timing Issue with cloud-init and host keys
Under some circumstances, provisioning can fail waiting for cloud-init to regenerate SSH host keys:
```
2017/02/08 23:03:23.712479 INFO Wait for ssh host key to be generated.
2017/02/08 23:03:23.756726 ERROR run cmd 'ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub' failed
2017/02/08 23:03:23.762243 ERROR Error Code:255
2017/02/08 23:03:23.766393 ERROR Result:ssh-keygen: /etc/ssh/ssh_host_rsa_key.pub: No such file or directory
 
2017/02/08 23:03:23.775621 ERROR Provision failed: (000004)**Failed to generate ssh host key: ret=255, out= ssh-keygen: /etc/ssh/ssh_host_rsa_key.pub: No such file or directory**
```
Waagent checks the thumbprint of the host rsa pub file to validate that the key is regenerated. If the file doesn't exist, it waits up to 5 minutes for it to be generated. Based on the logs, the sequence of events seems to be

1. Waagent confirms existence of the file
2. Cloud-init deletes the file and begins generating a new file
3. Waagent tries and fails to get the thumbprint because the file doesn't exist

One or both of the following should be implemented:
1. Use more caution when exiting from this function with error. If the thumbprint operation finds that the file doesn't exist (when it was just confirmed to exist by other means), we should try again.
2. If the expectation is that the SSH host keys are deleted before provisioning, then waagent -deprovision should delete them.

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
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
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
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/pa/provision/ubuntu.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/pa/provision/ubuntu.py azurelinuxagent/ga/exthandlers.py azurelinuxagent/pa/rdma/suse.py