Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consume IsVersionFromRSM Property #2934

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,12 @@ def _parse_extensions_config(self, xml_text, wire_client):
for ga_family in ga_families:
name = findtext(ga_family, "Name")
version = findtext(ga_family, "Version")
is_version_from_rsm = findtext(ga_family, "IsVersionFromRSM")
uris_list = find(ga_family, "Uris")
uris = findall(uris_list, "Uri")
family = VMAgentFamily(name, version)
if is_version_from_rsm is not None:
family.is_version_from_rsm = is_version_from_rsm.lower() == "true"
for uri in uris:
family.uris.append(gettext(uri))
self._agent_families.append(family)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ def _parse_agent_manifests(self, vm_settings):
# {
# "name": "Prod",
# "version": "9.9.9.9",
# "isVersionFromRSM": true,
# "uris": [
# "https://zrdfepirv2cdm03prdstr01a.blob.core.windows.net/7d89d439b79f4452950452399add2c90/Microsoft.OSTCLinuxAgent_Prod_uscentraleuap_manifest.xml",
# "https://ardfepirv2cdm03prdstr01a.blob.core.windows.net/7d89d439b79f4452950452399add2c90/Microsoft.OSTCLinuxAgent_Prod_uscentraleuap_manifest.xml"
Expand All @@ -266,10 +267,13 @@ def _parse_agent_manifests(self, vm_settings):
for family in families:
name = family["name"]
version = family.get("version")
is_version_from_rsm = family.get("isVersionFromRSM")
uris = family.get("uris")
if uris is None:
uris = []
agent_family = VMAgentFamily(name, version)
if is_version_from_rsm is not None:
agent_family.is_version_from_rsm = is_version_from_rsm
for u in uris:
agent_family.uris.append(u)
self._agent_families.append(agent_family)
Expand Down
2 changes: 2 additions & 0 deletions azurelinuxagent/common/protocol/restapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ def __init__(self, name, version=None):
self.name = name
# This is the Requested version as specified by the Goal State, it defaults to 0.0.0.0 if not specified in GS
self.requested_version_string = VERSION_0 if version is None else version
# Set to False if the version from rsm property is not specified in the GS
self.is_version_from_rsm = False
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having is_version_from_rsm and is_requested_version_specified seems redundant/overcomplicated. can we simplify that?

self.uris = []

@property
Expand Down
22 changes: 11 additions & 11 deletions azurelinuxagent/ga/agent_update_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,23 +295,23 @@ def run(self, goal_state):
requested_version = self.__get_requested_version(agent_family)
agent_manifest = None # This is to make sure fetch agent manifest once per update
warn_msg = ""
if requested_version is None:
if requested_version is not None and agent_family.is_version_from_rsm:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this even possible? if RSM is not requesting an update then we would simply get the version from the manifest, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition exactly for that to go to else for doing manifest call. The requested version could None if GS itself don't have it or when we disable the GA versioning.

self._is_requested_version_update = True
# Save the requested version to report back
GAUpdateReportState.report_expected_version = requested_version
# Remove the missing requested version warning once requested version becomes available
if "Missing requested version" in GAUpdateReportState.report_error_msg:
GAUpdateReportState.report_error_msg = ""
else:
# Do not proceed with update if self-update needs to download the manifest again with in an hour
if not self.__should_agent_attempt_manifest_download():
return
if conf.get_enable_ga_versioning(): # log the warning only when ga versioning is enabled
if conf.get_enable_ga_versioning() and not agent_family.is_version_from_rsm: # log the warning only when ga versioning is enabled
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but aren't you planning on enabling ga versioning? (and hence this warning would always be there until RSM updates are enabled?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yet, I'll do it in separate PR. We only log the warning when RSM updates are enabled and still missing requested version

warn_msg = "Missing requested version in agent family: {0} for incarnation: {1}, fallback to largest version update".format(self._ga_family, self._gs_id)
GAUpdateReportState.report_error_msg = warn_msg
agent_manifest = goal_state.fetch_agent_manifest(agent_family.name, agent_family.uris)
requested_version = self.__get_largest_version(agent_manifest)
self._is_requested_version_update = False
else:
self._is_requested_version_update = True
# Save the requested version to report back
GAUpdateReportState.report_expected_version = requested_version
# Remove the missing requested version warning once requested version becomes available
if "Missing requested version" in GAUpdateReportState.report_error_msg:
GAUpdateReportState.report_error_msg = ""

if requested_version == CURRENT_VERSION:
return
Expand All @@ -338,8 +338,8 @@ def run(self, goal_state):
raise AgentUpdateError("The Agent received a request to downgrade to version {0}, but downgrading to a version less than "
"the Agent installed on the image ({1}) is not supported. Skipping downgrade.".format(requested_version, daemon_version))

msg = "Goal state {0} is requesting a new agent version {1}, will update the agent before processing the goal state.".format(
self._gs_id, str(requested_version))
msg = "Goal state {0} is requesting a new agent version {1} [VersionFromRSM:{2}], will update the agent before processing the goal state.".format(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change "VersionFromRSM" to something like "Is RSM update"?

self._gs_id, str(requested_version), agent_family.is_version_from_rsm)
self.__log_event(LogLevel.INFO, msg)

agent = self.__download_and_get_agent(goal_state, agent_family, agent_manifest, requested_version)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,16 @@ def test_its_source_channel_should_be_wire_server(self):
extensions_goal_state = protocol.get_goal_state().extensions_goal_state

self.assertEqual(GoalStateChannel.WireServer, extensions_goal_state.channel, "The channel is incorrect")

def test_it_should_parse_is_version_from_rsm_properly(self):
with mock_wire_protocol(wire_protocol_data.DATA_FILE) as protocol:
agent_families = protocol.get_goal_state().extensions_goal_state.agent_families
for family in agent_families:
self.assertEqual(family.is_version_from_rsm, False, "is_version_from_rsm should be False")

data_file = wire_protocol_data.DATA_FILE.copy()
data_file["ext_conf"] = "hostgaplugin/ext_conf-requested_version.xml"
with mock_wire_protocol(data_file) as protocol:
agent_families = protocol.get_goal_state().extensions_goal_state.agent_families
for family in agent_families:
self.assertEqual(family.is_version_from_rsm, True, "is_version_from_rsm should be True")
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,22 @@ def test_it_should_parse_requested_version_properly(self):
for family in families:
self.assertEqual(family.requested_version_string, "9.9.9.9", "Version should be 9.9.9.9")

def test_it_should_parse_is_version_from_rsm_properly(self):
with mock_wire_protocol(wire_protocol_data.DATA_FILE_VM_SETTINGS) as protocol:
goal_state = GoalState(protocol.client)
families = goal_state.extensions_goal_state.agent_families
for family in families:
self.assertEqual(family.is_version_from_rsm, False, "is_version_from_rsm should be False")

data_file = wire_protocol_data.DATA_FILE_VM_SETTINGS.copy()
data_file["vm_settings"] = "hostgaplugin/vm_settings-requested_version.json"
with mock_wire_protocol(data_file) as protocol:
protocol.mock_wire_data.set_etag(888)
goal_state = GoalState(protocol.client)
families = goal_state.extensions_goal_state.agent_families
for family in families:
self.assertEqual(family.is_version_from_rsm, True, "is_version_from_rsm should be True")

def test_it_should_parse_missing_status_upload_blob_as_none(self):
data_file = wire_protocol_data.DATA_FILE_VM_SETTINGS.copy()
data_file["vm_settings"] = "hostgaplugin/vm_settings-no_status_upload_blob.json"
Expand Down
2 changes: 2 additions & 0 deletions tests/data/hostgaplugin/ext_conf-requested_version.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<GAFamily>
<Name>Prod</Name>
<Version>9.9.9.10</Version>
<IsVersionFromRSM>true</IsVersionFromRSM>
<Uris>
<Uri>https://zrdfepirv2cdm03prdstr01a.blob.core.windows.net/7d89d439b79f4452950452399add2c90/Microsoft.OSTCLinuxAgent_Prod_uscentraleuap_manifest.xml</Uri>
<Uri>https://ardfepirv2cdm03prdstr01a.blob.core.windows.net/7d89d439b79f4452950452399add2c90/Microsoft.OSTCLinuxAgent_Prod_uscentraleuap_manifest.xml</Uri>
Expand All @@ -12,6 +13,7 @@
<GAFamily>
<Name>Test</Name>
<Version>9.9.9.10</Version>
<IsVersionFromRSM>true</IsVersionFromRSM>
<Uris>
<Uri>https://zrdfepirv2cdm03prdstr01a.blob.core.windows.net/7d89d439b79f4452950452399add2c90/Microsoft.OSTCLinuxAgent_Test_uscentraleuap_manifest.xml</Uri>
<Uri>https://ardfepirv2cdm03prdstr01a.blob.core.windows.net/7d89d439b79f4452950452399add2c90/Microsoft.OSTCLinuxAgent_Test_uscentraleuap_manifest.xml</Uri>
Expand Down
2 changes: 2 additions & 0 deletions tests/data/hostgaplugin/vm_settings-requested_version.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
{
"name": "Prod",
"version": "9.9.9.9",
"isVersionFromRSM": true,
"uris": [
"https://zrdfepirv2cdm03prdstr01a.blob.core.windows.net/7d89d439b79f4452950452399add2c90/Microsoft.OSTCLinuxAgent_Prod_uscentraleuap_manifest.xml",
"https://ardfepirv2cdm03prdstr01a.blob.core.windows.net/7d89d439b79f4452950452399add2c90/Microsoft.OSTCLinuxAgent_Prod_uscentraleuap_manifest.xml"
Expand All @@ -37,6 +38,7 @@
{
"name": "Test",
"version": "9.9.9.9",
"isVersionFromRSM": true,
"uris": [
"https://zrdfepirv2cdm03prdstr01a.blob.core.windows.net/7d89d439b79f4452950452399add2c90/Microsoft.OSTCLinuxAgent_Test_uscentraleuap_manifest.xml",
"https://ardfepirv2cdm03prdstr01a.blob.core.windows.net/7d89d439b79f4452950452399add2c90/Microsoft.OSTCLinuxAgent_Test_uscentraleuap_manifest.xml"
Expand Down
2 changes: 2 additions & 0 deletions tests/data/wire/ext_conf_requested_version.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
<GAFamily>
<Name>Prod</Name>
<Version>9.9.9.10</Version>
<IsVersionFromRSM>true</IsVersionFromRSM>
<Uris>
<Uri>http://mock-goal-state/manifest_of_ga.xml</Uri>
</Uris>
</GAFamily>
<GAFamily>
<Name>Test</Name>
<Version>9.9.9.10</Version>
<IsVersionFromRSM>true</IsVersionFromRSM>
<Uris>
<Uri>http://mock-goal-state/manifest_of_ga.xml</Uri>
</Uris>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
<GAFamily>
<Name>Prod</Name>
<Version>5.2.1.0</Version>
<IsVersionFromRSM>true</IsVersionFromRSM>
<Uris>
<Uri>http://mock-goal-state/manifest_of_ga.xml</Uri>
</Uris>
</GAFamily>
<GAFamily>
<Name>Test</Name>
<Version>5.2.1.0</Version>
<IsVersionFromRSM>true</IsVersionFromRSM>
<Uris>
<Uri>http://mock-goal-state/manifest_of_ga.xml</Uri>
</Uris>
Expand Down
31 changes: 31 additions & 0 deletions tests/data/wire/ext_conf_requested_version_not_from_rsm.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<Extensions version="1.0.0.0" goalStateIncarnation="9"><GuestAgentExtension xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<GAFamilies>
<GAFamily>
<Name>Prod</Name>
<Version>9.9.9.10</Version>
<IsVersionFromRSM>false</IsVersionFromRSM>
<Uris>
<Uri>http://mock-goal-state/manifest_of_ga.xml</Uri>
</Uris>
</GAFamily>
<GAFamily>
<Name>Test</Name>
<Version>9.9.9.10</Version>
<IsVersionFromRSM>false</IsVersionFromRSM>
<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" />
</Plugins>
<PluginSettings>
<Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.0.0">
<RuntimeSettings seqNo="0">{"runtimeSettings":[{"handlerSettings":{"protectedSettingsCertThumbprint":"BD447EF71C3ADDF7C837E84D630F3FAC22CCD22F","protectedSettings":"MIICWgYJK","publicSettings":{"foo":"bar"}}}]}</RuntimeSettings>
</Plugin>
</PluginSettings>
<InVMGoalStateMetaData inSvdSeqNo="10" createdOnTicks="637726657706205217" activityId="a33f6f53-43d6-4625-b322-1a39651a00c9" correlationId="9a47a2a2-e740-4bfc-b11b-4f2f7cfe7d2e" />
<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>

13 changes: 13 additions & 0 deletions tests/ga/test_agent_update_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,19 @@ def test_it_should_update_to_largest_version_if_requested_version_not_available(
self.__assert_agent_directories_exist_and_others_dont_exist(versions=[str(CURRENT_VERSION), "99999.0.0.0"])
self.assertIn("Agent update found, exiting current process", ustr(context.exception.reason))

def test_it_should_update_to_largest_version_if_requested_version_not_from_rsm(self):
self.prepare_agents(count=1)

data_file = DATA_FILE.copy()
data_file['ext_conf'] = "wire/ext_conf_requested_version_not_from_rsm.xml"
with self.__get_agent_update_handler(test_data=data_file) as (agent_update_handler, mock_telemetry):
with self.assertRaises(AgentUpgradeExitException) as context:
agent_update_handler.run(agent_update_handler._protocol.get_goal_state())
self.__assert_agent_requested_version_in_goal_state(mock_telemetry, inc=2, version="99999.0.0.0")
self.__assert_agent_directories_exist_and_others_dont_exist(versions=[str(CURRENT_VERSION), "99999.0.0.0"])
self.assertIn("Agent update found, exiting current process", ustr(context.exception.reason))


def test_it_should_not_download_manifest_again_if_last_attempted_download_time_not_elapsed(self):
self.prepare_agents(count=1)
data_file = DATA_FILE.copy()
Expand Down
2 changes: 1 addition & 1 deletion tests/ga/test_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -1593,7 +1593,7 @@ def test_it_should_not_update_if_requested_version_not_found_in_manifest(self):
kwarg['op'] in (WALAEventOperation.AgentUpgrade, WALAEventOperation.Download)]
# This will throw if corresponding message not found so not asserting on that
requested_version_found = next(kwarg for kwarg in agent_msgs if
"Goal state incarnation_1 is requesting a new agent version 5.2.1.0, will update the agent before processing the goal state" in kwarg['message'])
"Goal state incarnation_1 is requesting a new agent version 5.2.1.0 [VersionFromRSM:True], will update the agent before processing the goal state" in kwarg['message'])
self.assertTrue(requested_version_found['is_success'],
"The requested version found op should be reported as a success")

Expand Down