diff --git a/azurelinuxagent/common/conf.py b/azurelinuxagent/common/conf.py index 0e0eb7f18e..167d520d09 100644 --- a/azurelinuxagent/common/conf.py +++ b/azurelinuxagent/common/conf.py @@ -643,7 +643,7 @@ def get_enable_ga_versioning(conf=__conf__): If True, the agent looks for rsm updates(checking requested version in GS) otherwise it will fall back to self-update and finds the highest version from PIR. NOTE: This option is experimental and may be removed in later versions of the Agent. """ - return conf.get_switch("Debug.EnableGAVersioning", True) + return conf.get_switch("Debug.EnableGAVersioning", False) def get_firewall_rules_log_period(conf=__conf__): diff --git a/azurelinuxagent/ga/agent_update_handler.py b/azurelinuxagent/ga/agent_update_handler.py index 212ca1f945..6c93e092ca 100644 --- a/azurelinuxagent/ga/agent_update_handler.py +++ b/azurelinuxagent/ga/agent_update_handler.py @@ -58,12 +58,7 @@ def __should_update_agent(self, requested_version): largest version update(self-update): update is allowed once per (as specified in the conf.get_hotfix_upgrade_frequency() or conf.get_normal_upgrade_frequency()) return false when we don't allow updates. - Note: Downgrades are not allowed for self-update. """ - - if not self.__check_if_downgrade_is_requested_and_allowed(requested_version): - return False - now = datetime.datetime.now() if self._is_requested_version_update: @@ -329,6 +324,11 @@ def run(self, goal_state): self.__log_event(LogLevel.WARNING, warn_msg) try: + # Downgrades are not allowed for self-update version + # Added it in try block after agent update timewindow check so that we don't log it too frequently + if not self.__check_if_downgrade_is_requested_and_allowed(requested_version): + return + daemon_version = get_daemon_version() if requested_version < daemon_version: # Don't process the update if the requested version is less than daemon version, diff --git a/tests/ga/test_agent_update_handler.py b/tests/ga/test_agent_update_handler.py index a78471df08..d387164147 100644 --- a/tests/ga/test_agent_update_handler.py +++ b/tests/ga/test_agent_update_handler.py @@ -57,10 +57,11 @@ def put_handler(url, *args, **_): with patch("azurelinuxagent.common.conf.get_autoupdate_enabled", return_value=autoupdate_enabled): with patch("azurelinuxagent.common.conf.get_autoupdate_frequency", return_value=autoupdate_frequency): with patch("azurelinuxagent.common.conf.get_autoupdate_gafamily", return_value="Prod"): - with patch("azurelinuxagent.ga.agent_update_handler.add_event") as mock_telemetry: - agent_update_handler = get_agent_update_handler(protocol) - agent_update_handler._protocol = protocol - yield agent_update_handler, mock_telemetry + with patch("azurelinuxagent.common.conf.get_enable_ga_versioning", return_value=True): + with patch("azurelinuxagent.ga.agent_update_handler.add_event") as mock_telemetry: + agent_update_handler = get_agent_update_handler(protocol) + agent_update_handler._protocol = protocol + yield agent_update_handler, mock_telemetry def __assert_agent_directories_available(self, versions): diff --git a/tests/ga/test_update.py b/tests/ga/test_update.py index 129ce3cad7..b3cf721580 100644 --- a/tests/ga/test_update.py +++ b/tests/ga/test_update.py @@ -1250,68 +1250,69 @@ def test_it_should_recreate_extension_event_directories_for_existing_extensions_ def test_it_should_report_update_status_in_status_blob(self): with mock_wire_protocol(DATA_FILE) as protocol: with patch.object(conf, "get_autoupdate_gafamily", return_value="Prod"): - with patch("azurelinuxagent.common.logger.warn") as patch_warn: - - protocol.aggregate_status = None - protocol.incarnation = 1 - - def get_handler(url, **kwargs): - if HttpRequestPredicates.is_agent_package_request(url): - return MockHttpResponse(status=httpclient.SERVICE_UNAVAILABLE) - return protocol.mock_wire_data.mock_http_get(url, **kwargs) - - def put_handler(url, *args, **_): - if HttpRequestPredicates.is_host_plugin_status_request(url): - # Skip reading the HostGA request data as its encoded - return MockHttpResponse(status=500) - protocol.aggregate_status = json.loads(args[0]) - return MockHttpResponse(status=201) - - def update_goal_state_and_run_handler(autoupdate_enabled = True): - protocol.incarnation += 1 - protocol.mock_wire_data.set_incarnation(protocol.incarnation) - self._add_write_permission_to_goal_state_files() - with _get_update_handler(iterations=1, protocol=protocol, autoupdate_enabled=autoupdate_enabled) as (update_handler, _): - GAUpdateReportState.report_error_msg = "" - update_handler.run(debug=True) - self.assertEqual(0, update_handler.get_exit_code(), - "Exit code should be 0; List of all warnings logged by the agent: {0}".format( - patch_warn.call_args_list)) - - protocol.set_http_handlers(http_get_handler=get_handler, http_put_handler=put_handler) - - # Case 1: Requested version removed in GS; report missing requested version errr - protocol.mock_wire_data.set_extension_config("wire/ext_conf.xml") - protocol.mock_wire_data.reload() - update_goal_state_and_run_handler() - self.assertTrue("updateStatus" in protocol.aggregate_status['aggregateStatus']['guestAgentStatus'], - "updateStatus should be reported") - update_status = protocol.aggregate_status['aggregateStatus']['guestAgentStatus']["updateStatus"] - self.assertEqual(VMAgentUpdateStatuses.Error, update_status['status'], "Status should be an error") - self.assertEqual(update_status['code'], 1, "incorrect code reported") - self.assertIn("Missing requested version", update_status['formattedMessage']['message'], "incorrect message reported") - - # Case 2: Requested version in GS == Current Version; updateStatus should be Success - protocol.mock_wire_data.set_extension_config("wire/ext_conf_requested_version.xml") - protocol.mock_wire_data.set_extension_config_requested_version(str(CURRENT_VERSION)) - update_goal_state_and_run_handler() - self.assertTrue("updateStatus" in protocol.aggregate_status['aggregateStatus']['guestAgentStatus'], - "updateStatus should be reported if asked in GS") - update_status = protocol.aggregate_status['aggregateStatus']['guestAgentStatus']["updateStatus"] - self.assertEqual(VMAgentUpdateStatuses.Success, update_status['status'], "Status should be successful") - self.assertEqual(update_status['expectedVersion'], str(CURRENT_VERSION), "incorrect version reported") - self.assertEqual(update_status['code'], 0, "incorrect code reported") - - # Case 3: Requested version in GS != Current Version; update fail and report error - protocol.mock_wire_data.set_extension_config("wire/ext_conf_requested_version.xml") - protocol.mock_wire_data.set_extension_config_requested_version("5.2.0.1") - update_goal_state_and_run_handler() - self.assertTrue("updateStatus" in protocol.aggregate_status['aggregateStatus']['guestAgentStatus'], - "updateStatus should be in status blob. Warns: {0}".format(patch_warn.call_args_list)) - update_status = protocol.aggregate_status['aggregateStatus']['guestAgentStatus']["updateStatus"] - self.assertEqual(VMAgentUpdateStatuses.Error, update_status['status'], "Status should be an error") - self.assertEqual(update_status['expectedVersion'], "5.2.0.1", "incorrect version reported") - self.assertEqual(update_status['code'], 1, "incorrect code reported") + with patch("azurelinuxagent.common.conf.get_enable_ga_versioning", return_value=True): + with patch("azurelinuxagent.common.logger.warn") as patch_warn: + + protocol.aggregate_status = None + protocol.incarnation = 1 + + def get_handler(url, **kwargs): + if HttpRequestPredicates.is_agent_package_request(url): + return MockHttpResponse(status=httpclient.SERVICE_UNAVAILABLE) + return protocol.mock_wire_data.mock_http_get(url, **kwargs) + + def put_handler(url, *args, **_): + if HttpRequestPredicates.is_host_plugin_status_request(url): + # Skip reading the HostGA request data as its encoded + return MockHttpResponse(status=500) + protocol.aggregate_status = json.loads(args[0]) + return MockHttpResponse(status=201) + + def update_goal_state_and_run_handler(autoupdate_enabled = True): + protocol.incarnation += 1 + protocol.mock_wire_data.set_incarnation(protocol.incarnation) + self._add_write_permission_to_goal_state_files() + with _get_update_handler(iterations=1, protocol=protocol, autoupdate_enabled=autoupdate_enabled) as (update_handler, _): + GAUpdateReportState.report_error_msg = "" + update_handler.run(debug=True) + self.assertEqual(0, update_handler.get_exit_code(), + "Exit code should be 0; List of all warnings logged by the agent: {0}".format( + patch_warn.call_args_list)) + + protocol.set_http_handlers(http_get_handler=get_handler, http_put_handler=put_handler) + + # Case 1: Requested version removed in GS; report missing requested version errr + protocol.mock_wire_data.set_extension_config("wire/ext_conf.xml") + protocol.mock_wire_data.reload() + update_goal_state_and_run_handler() + self.assertTrue("updateStatus" in protocol.aggregate_status['aggregateStatus']['guestAgentStatus'], + "updateStatus should be reported") + update_status = protocol.aggregate_status['aggregateStatus']['guestAgentStatus']["updateStatus"] + self.assertEqual(VMAgentUpdateStatuses.Error, update_status['status'], "Status should be an error") + self.assertEqual(update_status['code'], 1, "incorrect code reported") + self.assertIn("Missing requested version", update_status['formattedMessage']['message'], "incorrect message reported") + + # Case 2: Requested version in GS == Current Version; updateStatus should be Success + protocol.mock_wire_data.set_extension_config("wire/ext_conf_requested_version.xml") + protocol.mock_wire_data.set_extension_config_requested_version(str(CURRENT_VERSION)) + update_goal_state_and_run_handler() + self.assertTrue("updateStatus" in protocol.aggregate_status['aggregateStatus']['guestAgentStatus'], + "updateStatus should be reported if asked in GS") + update_status = protocol.aggregate_status['aggregateStatus']['guestAgentStatus']["updateStatus"] + self.assertEqual(VMAgentUpdateStatuses.Success, update_status['status'], "Status should be successful") + self.assertEqual(update_status['expectedVersion'], str(CURRENT_VERSION), "incorrect version reported") + self.assertEqual(update_status['code'], 0, "incorrect code reported") + + # Case 3: Requested version in GS != Current Version; update fail and report error + protocol.mock_wire_data.set_extension_config("wire/ext_conf_requested_version.xml") + protocol.mock_wire_data.set_extension_config_requested_version("5.2.0.1") + update_goal_state_and_run_handler() + self.assertTrue("updateStatus" in protocol.aggregate_status['aggregateStatus']['guestAgentStatus'], + "updateStatus should be in status blob. Warns: {0}".format(patch_warn.call_args_list)) + update_status = protocol.aggregate_status['aggregateStatus']['guestAgentStatus']["updateStatus"] + self.assertEqual(VMAgentUpdateStatuses.Error, update_status['status'], "Status should be an error") + self.assertEqual(update_status['expectedVersion'], "5.2.0.1", "incorrect version reported") + self.assertEqual(update_status['code'], 1, "incorrect code reported") def test_it_should_wait_to_fetch_first_goal_state(self): with _get_update_handler() as (update_handler, protocol): @@ -1438,7 +1439,8 @@ def create_conf_mocks(self, autoupdate_frequency, hotfix_frequency, normal_frequ with patch("azurelinuxagent.common.conf.get_hotfix_upgrade_frequency", return_value=hotfix_frequency): with patch("azurelinuxagent.common.conf.get_normal_upgrade_frequency", return_value=normal_frequency): with patch("azurelinuxagent.common.conf.get_autoupdate_gafamily", return_value="Prod"): - yield + with patch("azurelinuxagent.common.conf.get_enable_ga_versioning", return_value=True): + yield @contextlib.contextmanager def __get_update_handler(self, iterations=1, test_data=None, diff --git a/tests_e2e/orchestrator/scripts/install-agent b/tests_e2e/orchestrator/scripts/install-agent index 7c80f6caf6..0496784766 100755 --- a/tests_e2e/orchestrator/scripts/install-agent +++ b/tests_e2e/orchestrator/scripts/install-agent @@ -115,7 +115,7 @@ echo "Agent's conf path: $waagent_conf_path" sed -i 's/AutoUpdate.Enabled=n/AutoUpdate.Enabled=y/g' "$waagent_conf_path" # By default GAUpdates flag set to True, so that agent go through update logic to look for new agents. # But in e2e tests this flag needs to be off in test version 9.9.9.9 to stop the agent updates, so that our scenarios run on 9.9.9.9. -sed -i '$a Debug.DownloadNewAgents=n' "$waagent_conf_path" +# sed -i '$a Debug.DownloadNewAgents=n' "$waagent_conf_path" # Logging and exiting tests if Extensions.Enabled flag is disabled for other distros than debian if grep -q "Extensions.Enabled=n" $waagent_conf_path; then pypy_get_distro=$(pypy3 -c 'from azurelinuxagent.common.version import get_distro; print(get_distro())') diff --git a/tests_e2e/tests/agent_update/rsm_update.py b/tests_e2e/tests/agent_update/rsm_update.py index bb6dcc6a7a..8d2ac149c1 100644 --- a/tests_e2e/tests/agent_update/rsm_update.py +++ b/tests_e2e/tests/agent_update/rsm_update.py @@ -139,7 +139,7 @@ def _prepare_agent(self, daemon_version="1.0.0.0", update_config=True) -> None: log.info('Successfully updated agent installed version') if update_config: log.info('Executing update-waagent-conf remote script to update agent update config flags to allow and download test versions') - self._run_remote_test("update-waagent-conf Debug.DownloadNewAgents=y AutoUpdate.GAFamily=Test", use_sudo=True) + self._run_remote_test("update-waagent-conf Debug.EnableGAVersioning=y AutoUpdate.GAFamily=Test", use_sudo=True) log.info('Successfully updated agent update config') @staticmethod