Repository: Azure/WALinuxAgent
Pull request #1078 (2018-03-28 16:19:40)

Merge hotfix/2.2.25 


Patch:
diff --git a/azurelinuxagent/common/exception.py b/azurelinuxagent/common/exception.py
index bb8ab109..5960e6a7 100644
--- a/azurelinuxagent/common/exception.py
+++ b/azurelinuxagent/common/exception.py
@@ -114,15 +114,6 @@ class ProtocolNotFoundError(ProtocolError):
         super(ProtocolNotFoundError, self).__init__(msg, inner)
 
 
-class RestartError(ProtocolError):
-    """
-    Variant of ProtocolError used to restart processing if the GoalState
-    becomes stale.
-    """
-
-    pass
-
-
 class HttpError(AgentError):
     """
     Http request failure
diff --git a/azurelinuxagent/common/protocol/metadata.py b/azurelinuxagent/common/protocol/metadata.py
index 0cfa5ede..ed4fff98 100644
--- a/azurelinuxagent/common/protocol/metadata.py
+++ b/azurelinuxagent/common/protocol/metadata.py
@@ -240,7 +240,7 @@ class MetadataProtocol(Protocol):
             set_properties("extensionHandlers", ext_list.extHandlers, data)
         return ext_list, etag
 
-    def get_ext_handler_pkgs(self, ext_handler, etag):
+    def get_ext_handler_pkgs(self, ext_handler):
         logger.verbose("Get extension handler packages")
         pkg_list = ExtHandlerPackageList()
 
diff --git a/azurelinuxagent/common/protocol/restapi.py b/azurelinuxagent/common/protocol/restapi.py
index f3eeff8b..3e6d510b 100644
--- a/azurelinuxagent/common/protocol/restapi.py
+++ b/azurelinuxagent/common/protocol/restapi.py
@@ -326,7 +326,7 @@ class Protocol(DataContract):
     def get_ext_handlers(self):
         raise NotImplementedError()
 
-    def get_ext_handler_pkgs(self, extension, etag):
+    def get_ext_handler_pkgs(self, extension):
         raise NotImplementedError()
 
     def get_artifacts_profile(self):
diff --git a/azurelinuxagent/common/protocol/wire.py b/azurelinuxagent/common/protocol/wire.py
index 850dfedc..d79cc146 100644
--- a/azurelinuxagent/common/protocol/wire.py
+++ b/azurelinuxagent/common/protocol/wire.py
@@ -28,7 +28,7 @@ import azurelinuxagent.common.utils.fileutil as fileutil
 import azurelinuxagent.common.utils.textutil as textutil
 
 from azurelinuxagent.common.exception import ProtocolNotFoundError, \
-                                            ResourceGoneError, RestartError
+                                            ResourceGoneError
 from azurelinuxagent.common.future import httpclient, bytebuffer
 from azurelinuxagent.common.protocol.hostplugin import HostPluginProtocol
 from azurelinuxagent.common.protocol.restapi import *
@@ -145,9 +145,10 @@ class WireProtocol(Protocol):
         # In wire protocol, incarnation is equivalent to ETag
         return ext_conf.ext_handlers, goal_state.incarnation
 
-    def get_ext_handler_pkgs(self, ext_handler, etag):
+    def get_ext_handler_pkgs(self, ext_handler):
         logger.verbose("Get extension handler package")
-        man = self.client.get_ext_manifest(ext_handler, etag)
+        goal_state = self.client.get_goal_state()
+        man = self.client.get_ext_manifest(ext_handler, goal_state)
         return man.pkg_list
 
     def get_artifacts_profile(self):
@@ -799,35 +800,25 @@ class WireClient(object):
                 self.ext_conf = ExtensionsConfig(xml_text)
         return self.ext_conf
 
-    def get_ext_manifest(self, ext_handler, incarnation):
-
+    def get_ext_manifest(self, ext_handler, goal_state):
         for update_goal_state in [False, True]:
             try:
                 if update_goal_state:
                     self.update_goal_state(forced=True)
-                    incarnation = self.get_goal_state().incarnation
+                    goal_state = self.get_goal_state()
 
                 local_file = MANIFEST_FILE_NAME.format(
                                 ext_handler.name,
-                                incarnation)
+                                goal_state.incarnation)
                 local_file = os.path.join(conf.get_lib_dir(), local_file)
-
-                xml_text = None
-                if not update_goal_state:
-                    try:
-                        xml_text = self.fetch_cache(local_file)
-                    except ProtocolError:
-                        pass
-
-                if xml_text is None:
-                    xml_text = self.fetch_manifest(ext_handler.versionUris)
-                    self.save_cache(local_file, xml_text)
+                xml_text = self.fetch_manifest(ext_handler.versionUris)
+                self.save_cache(local_file, xml_text)
                 return ExtensionManifest(xml_text)
 
             except ResourceGoneError:
                 continue
 
-        raise RestartError("Failed to retrieve extension manifest")
+        raise ProtocolError("Failed to retrieve extension manifest")
 
     def filter_package_list(self, family, ga_manifest, goal_state):
         complete_list = ga_manifest.pkg_list
diff --git a/azurelinuxagent/common/version.py b/azurelinuxagent/common/version.py
index 98e7c8e4..417142cc 100644
--- a/azurelinuxagent/common/version.py
+++ b/azurelinuxagent/common/version.py
@@ -113,7 +113,7 @@ def get_distro():
 
 AGENT_NAME = "WALinuxAgent"
 AGENT_LONG_NAME = "Azure Linux Agent"
-AGENT_VERSION = '2.2.21'
+AGENT_VERSION = '2.2.25'
 AGENT_LONG_VERSION = "{0}-{1}".format(AGENT_NAME, AGENT_VERSION)
 AGENT_DESCRIPTION = """
 The Azure Linux Agent supports the provisioning and running of Linux
diff --git a/azurelinuxagent/ga/exthandlers.py b/azurelinuxagent/ga/exthandlers.py
index 0743c82d..6c7357ed 100644
--- a/azurelinuxagent/ga/exthandlers.py
+++ b/azurelinuxagent/ga/exthandlers.py
@@ -38,7 +38,7 @@ import azurelinuxagent.common.version as version
 from azurelinuxagent.common.errorstate import ErrorState, ERROR_STATE_DELTA
 
 from azurelinuxagent.common.event import add_event, WALAEventOperation, elapsed_milliseconds
-from azurelinuxagent.common.exception import ExtensionError, ProtocolError, RestartError
+from azurelinuxagent.common.exception import ExtensionError, ProtocolError
 from azurelinuxagent.common.future import ustr
 from azurelinuxagent.common.protocol.restapi import ExtHandlerStatus, \
                                                     ExtensionStatus, \
@@ -208,8 +208,6 @@ class ExtHandlersHandler(object):
 
             self.report_ext_handlers_status()
             self.cleanup_outdated_handlers()
-        except RestartError:
-            raise
         except Exception as e:
             msg = u"Exception processing extension handlers: {0}".format(
                 ustr(e))
@@ -348,7 +346,7 @@ class ExtHandlersHandler(object):
                 return
 
             self.set_log_upgrade_guid(ext_handler, True)
-            ext_handler_i.decide_version(etag=etag, target_state=state)
+            ext_handler_i.decide_version(target_state=state)
             if not ext_handler_i.is_upgrade and self.last_etag == etag:
                 if self.log_etag:
                     ext_handler_i.logger.verbose("Version {0} is current for etag {1}",
@@ -376,11 +374,6 @@ class ExtHandlersHandler(object):
             else:
                 message = u"Unknown ext handler state:{0}".format(state)
                 raise ExtensionError(message)
-        except RestartError:
-            ext_handler_i.logger.info("GoalState became stale during "
-                                      "processing. Restarting with new "
-                                      "GoalState")
-            raise
         except Exception as e:
             ext_handler_i.set_handler_status(message=ustr(e), code=-1)
             ext_handler_i.report_event(message=ustr(e), is_success=False)
@@ -525,9 +518,12 @@ class ExtHandlerInstance(object):
         self.logger.add_appender(logger.AppenderType.FILE,
                                  logger.LogLevel.INFO, log_file)
 
-    def decide_version(self, etag, target_state=None):
+    def decide_version(self, target_state=None):
         self.logger.verbose("Decide which version to use")
-        pkg_list = self.protocol.get_ext_handler_pkgs(self.ext_handler, etag)
+        try:
+            pkg_list = self.protocol.get_ext_handler_pkgs(self.ext_handler)
+        except ProtocolError as e:
+            raise ExtensionError("Failed to get ext handler pkgs", e)
 
         # Determine the desired and installed versions
         requested_version = FlexibleVersion(
diff --git a/azurelinuxagent/ga/update.py b/azurelinuxagent/ga/update.py
index dcd2955d..68570549 100644
--- a/azurelinuxagent/ga/update.py
+++ b/azurelinuxagent/ga/update.py
@@ -45,7 +45,6 @@ from azurelinuxagent.common.event import add_event, add_periodic, \
                                     WALAEventOperation
 from azurelinuxagent.common.exception import ProtocolError, \
                                             ResourceGoneError, \
-                                            RestartError, \
                                             UpdateError
 from azurelinuxagent.common.future import ustr
 from azurelinuxagent.common.osutil import get_osutil


Test patch:
diff --git a/tests/ga/test_extension.py b/tests/ga/test_extension.py
index 82667857..d922a263 100644
--- a/tests/ga/test_extension.py
+++ b/tests/ga/test_extension.py
@@ -645,12 +645,12 @@ class TestExtension(AgentTestCase):
                         decision_version = '1.0.0'
 
                 _, protocol = self._create_mock(WireProtocolData(datafile), *args)
-                ext_handlers, etag = protocol.get_ext_handlers()
+                ext_handlers, _ = protocol.get_ext_handlers()
                 self.assertEqual(1, len(ext_handlers.extHandlers))
                 ext_handler = ext_handlers.extHandlers[0]
                 self.assertEqual('OSTCExtensions.ExampleHandlerLinux', ext_handler.name)
                 self.assertEqual(config_version, ext_handler.properties.version, "config version.")
-                ExtHandlerInstance(ext_handler, protocol).decide_version(etag)
+                ExtHandlerInstance(ext_handler, protocol).decide_version()
                 self.assertEqual(decision_version, ext_handler.properties.version, "decision version.")
 
     def test_ext_handler_version_decide_between_minor_versions(self, *args):
@@ -677,7 +677,6 @@ class TestExtension(AgentTestCase):
         _, protocol = self._create_mock(WireProtocolData(DATA_FILE), *args)
         version_uri = Mock()
         version_uri.uri = 'http://some/Microsoft.OSTCExtensions_ExampleHandlerLinux_asiaeast_manifest.xml'
-        incarnation = 1
 
         for (installed_version, config_version, expected_version, autoupgrade_expected_version) in cases:
             ext_handler = Mock()
@@ -689,9 +688,8 @@ class TestExtension(AgentTestCase):
             ext_handler_instance = ExtHandlerInstance(ext_handler, protocol)
             ext_handler_instance.get_installed_version = Mock(return_value=installed_version)
 
-            ext_handler_instance.decide_version(incarnation)
+            ext_handler_instance.decide_version()
             self.assertEqual(expected_version, ext_handler.properties.version)
-            incarnation += 1
 
             ext_handler.properties.version = config_version
             ext_handler.properties.upgradePolicy = 'auto'
@@ -699,9 +697,8 @@ class TestExtension(AgentTestCase):
             ext_handler_instance = ExtHandlerInstance(ext_handler, protocol)
             ext_handler_instance.get_installed_version = Mock(return_value=installed_version)
 
-            ext_handler_instance.decide_version(incarnation)
+            ext_handler_instance.decide_version()
             self.assertEqual(autoupgrade_expected_version, ext_handler.properties.version)
-            incarnation += 1
 
 
 if __name__ == '__main__':
diff --git a/tests/ga/test_update.py b/tests/ga/test_update.py
index 0726d4c2..e03b3245 100644
--- a/tests/ga/test_update.py
+++ b/tests/ga/test_update.py
@@ -176,7 +176,7 @@ class UpdateTestCase(AgentTestCase):
         return
 
     def prepare_agents(self,
-                       count=5,
+                       count=20,
                        is_available=True):
 
         # Ensure the test data is copied over
@@ -699,7 +699,7 @@ class TestUpdate(UpdateTestCase):
             pass
         self.event_patch.stop()
 
-    def _create_protocol(self, count=5, versions=None):
+    def _create_protocol(self, count=20, versions=None):
         latest_version = self.prepare_agents(count=count)
         if versions is None or len(versions) <= 0:
             versions = [latest_version]
@@ -861,8 +861,8 @@ class TestUpdate(UpdateTestCase):
         self.update_handler._set_agents([GuestAgent(path=path) for path in self.agent_dirs()])
         self.assertEqual(len(self.agent_dirs()), len(self.update_handler.agents))
 
-        kept_agents = self.update_handler.agents[1::2]
-        blacklisted_agents = self.update_handler.agents[::2]
+        kept_agents = self.update_handler.agents[::2]
+        blacklisted_agents = self.update_handler.agents[1::2]
         for agent in blacklisted_agents:
             agent.mark_failure(is_fatal=True)
         self.update_handler._filter_blacklisted_agents()
@@ -898,6 +898,7 @@ class TestUpdate(UpdateTestCase):
         protocol = WireProtocol('12.34.56.78')
         mock_get_host.return_value = "faux host"
         host = self.update_handler._get_host_plugin(protocol=protocol)
+        print("mock_get_host call cound={0}".format(mock_get_host.call_count))
         mock_get_host.assert_called_once()
         self.assertEqual("faux host", host)
 
@@ -1018,8 +1019,8 @@ class TestUpdate(UpdateTestCase):
         self.assertTrue(2 < len(self.update_handler.agents))
 
         # Purge every other agent
-        purged_agents = self.update_handler.agents[1::2]
-        kept_agents = self.update_handler.agents[::2]
+        kept_agents = self.update_handler.agents[1::2]
+        purged_agents = self.update_handler.agents[::2]
 
         # Reload and assert only the kept agents remain on disk
         self.update_handler.agents = kept_agents
@@ -1330,7 +1331,7 @@ class TestUpdate(UpdateTestCase):
             base_version=FlexibleVersion(AGENT_VERSION),
             protocol=None,
             versions=None,
-            count=5):
+            count=20):
 
         if protocol is None:
             protocol = self._create_protocol(count=count, versions=versions)
@@ -1378,7 +1379,7 @@ class TestUpdate(UpdateTestCase):
     def test_upgrade_available_purges_old_agents(self):
         self.prepare_agents()
         agent_count = self.agent_count()
-        self.assertEqual(5, agent_count)
+        self.assertEqual(20, agent_count)
 
         agent_versions = self.agent_versions()[:3]
         self.assertTrue(self._test_upgrade_available(versions=agent_versions))
diff --git a/tests/protocol/test_metadata.py b/tests/protocol/test_metadata.py
index 5f90f128..5047b86e 100644
--- a/tests/protocol/test_metadata.py
+++ b/tests/protocol/test_metadata.py
@@ -39,7 +39,7 @@ class TestMetadataProtocolGetters(AgentTestCase):
             protocol.get_certs()
             ext_handlers, etag = protocol.get_ext_handlers()
             for ext_handler in ext_handlers.extHandlers:
-                protocol.get_ext_handler_pkgs(ext_handler, etag)
+                protocol.get_ext_handler_pkgs(ext_handler)
 
     def test_getters(self, *args):
         test_data = MetadataProtocolData(DATA_FILE)
diff --git a/tests/protocol/test_wire.py b/tests/protocol/test_wire.py
index 9e475ec1..77a08821 100644
--- a/tests/protocol/test_wire.py
+++ b/tests/protocol/test_wire.py
@@ -43,9 +43,8 @@ class TestWireProtocol(AgentTestCase):
             protocol.get_vminfo()
             protocol.get_certs()
             ext_handlers, etag = protocol.get_ext_handlers()
-            self.assertEqual("1", etag)
             for ext_handler in ext_handlers.extHandlers:
-                protocol.get_ext_handler_pkgs(ext_handler, etag)
+                protocol.get_ext_handler_pkgs(ext_handler)
 
             crt1 = os.path.join(self.tmp_dir,
                                 '33B0ABCE4673538650971C10F7D7397E71561F35.crt')
@@ -94,7 +93,6 @@ class TestWireProtocol(AgentTestCase):
         #    HostingEnvironmentConfig, will be retrieved the expected number
         self.assertEqual(2, test_data.call_counts["hostingenvuri"])
 
-
     def test_call_storage_kwargs(self,
                                  mock_cryptutil,
                                  mock_sleep):