Skip to content

Commit

Permalink
Fix bug with dependent extensions with no settings (#2285) (#2349)
Browse files Browse the repository at this point in the history
Co-authored-by: Laveesh Rohra <larohra@microsoft.com>
  • Loading branch information
nagworld9 and larohra authored Sep 2, 2021
1 parent 8bd66bf commit 0eeed5a
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 2 deletions.
10 changes: 8 additions & 2 deletions azurelinuxagent/ga/exthandlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -563,9 +563,13 @@ def wait_for_handler_completion(handler_i, wait_until, extension=None):
Check the status of the extension being handled. Wait until it has a terminal state or times out.
:raises: Exception if it is not handled successfully.
"""

extension_name = handler_i.get_extension_full_name(extension)

# If the handler had no settings, we should not wait at all for handler to report status.
if extension is None:
logger.info("No settings found for {0}, not waiting for it's status".format(extension_name))
return

try:
ext_completed, status = False, None

Expand Down Expand Up @@ -1652,7 +1656,9 @@ def get_status_file_path(self, extension=None):
def collect_ext_status(self, ext):
self.logger.verbose("Collect extension status for {0}".format(self.get_extension_full_name(ext)))
seq_no, ext_status_file = self.get_status_file_path(ext)
if seq_no == -1:

# We should never try to read any status file if the handler has no settings, returning None in that case
if seq_no == -1 or ext is None:
return None

data = None
Expand Down
32 changes: 32 additions & 0 deletions tests/data/wire/ext_conf_dependencies_with_empty_settings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<Extensions version="1.0.0.0" goalStateIncarnation="9">
<GuestAgentExtension
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<GAFamilies>
<GAFamily>
<Name>Prod</Name>
<Uris>
<Uri>http://mock-goal-state/manifest_of_ga.xml</Uri>
</Uris>
</GAFamily>
<GAFamily>
<Name>Test</Name>
<Uris>
<Uri>http://mock-goal-state/manifest_of_ga.xml</Uri>
</Uris>
</GAFamily>
</GAFamilies>
</GuestAgentExtension>
<Plugins>
<Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.0.0" location="http://mock-goal-state/rdfepirv2hknprdstr03.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_ExampleHandlerLinux_asiaeast_manifest.xml" config="" state="enabled" autoUpgrade="false" failoverlocation="http://mock-goal-state/rdfepirv2hknprdstr04.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_ExampleHandlerLinux_asiaeast_manifest.xml" runAsStartupTask="false" isJson="true" />
<Plugin name="OSTCExtensions.OtherExampleHandlerLinux" version="1.0.0" location="http://mock-goal-state/rdfepirv2hknprdstr03.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_OtherExampleHandlerLinux_asiaeast_manifest.xml" config="" state="enabled" autoUpgrade="false" failoverlocation="http://mock-goal-state/rdfepirv2hknprdstr04.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_OtherExampleHandlerLinux_asiaeast_manifest.xml" runAsStartupTask="false" isJson="true" />
</Plugins>
<PluginSettings>
<Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.0.0">
<DependsOn dependencyLevel="1">
<DependsOnExtension handler="OSTCExtensions.OtherExampleHandlerLinux" />
</DependsOn>
<RuntimeSettings seqNo="0">{"runtimeSettings":[{"handlerSettings":{"protectedSettingsCertThumbprint":"4037FBF5F1F3014F99B5D6C7799E9B20E6871CB3","protectedSettings":"MIICWgYJK","publicSettings":{"foo":"bar"}}}]}</RuntimeSettings>
</Plugin>
</PluginSettings>
<StatusUploadBlob statusBlobType="BlockBlob">https://test.blob.core.windows.net/vhds/test-cs12.test-cs12.test-cs12.status?sr=b&amp;sp=rw&amp;se=9999-01-01&amp;sk=key1&amp;sv=2014-02-14&amp;sig=hfRh7gzUE7sUtYwke78IOlZOrTRCYvkec4hGZ9zZzXo</StatusUploadBlob>
</Extensions>
32 changes: 32 additions & 0 deletions tests/ga/test_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,38 @@ def test_ext_handler_sequencing(self, *args):
(dep_ext_level_5, ExtensionCommandNames.UNINSTALL)
)

def test_it_should_process_sequencing_properly_even_if_no_settings_for_dependent_extension(
self, mock_get, mock_crypt, *args):
test_data_file = DATA_FILE.copy()
test_data_file["ext_conf"] = "wire/ext_conf_dependencies_with_empty_settings.xml"
test_data = mockwiredata.WireProtocolData(test_data_file)
exthandlers_handler, protocol = self._create_mock(test_data, mock_get, mock_crypt, *args)

ext_1 = extension_emulator(name="OSTCExtensions.ExampleHandlerLinux")
ext_2 = extension_emulator(name="OSTCExtensions.OtherExampleHandlerLinux")

with enable_invocations(ext_1, ext_2) as invocation_record:
exthandlers_handler.run()
exthandlers_handler.report_ext_handlers_status()

# Ensure no extension status was reported for OtherExampleHandlerLinux as no settings provided for it
self._assert_handler_status(protocol.report_vm_status, "Ready", 0, "1.0.0",
expected_handler_name="OSTCExtensions.OtherExampleHandlerLinux")

# Ensure correct status reported back for the other extension with settings
self._assert_handler_status(protocol.report_vm_status, "Ready", 1, "1.0.0",
expected_handler_name="OSTCExtensions.ExampleHandlerLinux")
self._assert_ext_status(protocol.report_vm_status, "success", 0,
expected_handler_name="OSTCExtensions.ExampleHandlerLinux")

# Ensure the invocation order follows the dependency levels
invocation_record.compare(
(ext_2, ExtensionCommandNames.INSTALL),
(ext_2, ExtensionCommandNames.ENABLE),
(ext_1, ExtensionCommandNames.INSTALL),
(ext_1, ExtensionCommandNames.ENABLE)
)

def test_ext_handler_sequencing_should_fail_if_handler_failed(self, mock_get, mock_crypt, *args):
test_data = mockwiredata.WireProtocolData(mockwiredata.DATA_FILE_EXT_SEQUENCING)
exthandlers_handler, protocol = self._create_mock(test_data, mock_get, mock_crypt, *args)
Expand Down

0 comments on commit 0eeed5a

Please sign in to comment.