Skip to content

Commit 8cc2f48

Browse files
committed
Merge branch 'master' of https://github.com/Azure/LinuxPatchExtension into feature/pkg_failed_retry_set_status_warning
pull master changes
2 parents e025e1f + 1e997cc commit 8cc2f48

File tree

7 files changed

+60
-34
lines changed

7 files changed

+60
-34
lines changed

src/core/src/bootstrap/Constants.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ class StatusTruncationConfig(EnumBackport):
197197
RED_HAT = 'Red Hat'
198198
SUSE = 'SUSE'
199199
CENTOS = 'CentOS'
200-
AZURE_LINUX = 'Microsoft Azure Linux'
200+
AZURE_LINUX = ['Microsoft Azure Linux', 'Common Base Linux Mariner']
201201

202202
# Package Managers
203203
APT = 'apt'
@@ -379,7 +379,7 @@ class EnvLayer(EnumBackport):
379379
class UbuntuProClientSettings(EnumBackport):
380380
FEATURE_ENABLED = True
381381
MINIMUM_PYTHON_VERSION_REQUIRED = (3, 5) # using tuple as we can compare this with sys.version_info. The comparison will happen in the same order. Major version checked first. Followed by Minor version.
382-
MAX_OS_MAJOR_VERSION_SUPPORTED = 20
382+
MAX_OS_MAJOR_VERSION_SUPPORTED = 24
383383
MINIMUM_CLIENT_VERSION = "27.14.4"
384384

385385
class BufferMessage(EnumBackport):

src/core/src/bootstrap/EnvLayer.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,15 @@ def __init__(self, real_record_path=None, recorder_enabled=False, emulator_enabl
6060
# Constant paths
6161
self.etc_environment_file_path = "/etc/environment"
6262

63+
@staticmethod
64+
def is_distro_azure_linux(distro_name):
65+
return any(x in distro_name for x in Constants.AZURE_LINUX)
66+
6367
def get_package_manager(self):
6468
""" Detects package manager type """
6569
ret = None
6670

67-
if self.platform.linux_distribution()[0] == Constants.AZURE_LINUX:
71+
if self.is_distro_azure_linux(str(self.platform.linux_distribution())):
6872
code, out = self.run_command_output('which tdnf', False, False)
6973
if code == 0:
7074
ret = Constants.TDNF

src/core/src/package_managers/AptitudePackageManager.py

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,9 @@ def get_all_updates(self, cached=False):
333333
self.composite_logger.log_debug("[APM-Pro] Get all updates : [DefaultAllPackagesCount={0}][UbuntuProClientQuerySuccess={1}][UbuntuProClientAllPackagesCount={2}]"
334334
.format(len(self.all_updates_cached), ubuntu_pro_client_all_updates_query_success, len(self.ubuntu_pro_client_all_updates_cached)))
335335
if len(pro_client_missed_updates) > 0: # not good, needs investigation
336-
self.composite_logger.log_debug("[APM-Pro][!] Pro client missed updates found. [Count={0}][Updates={1}]".format(len(pro_client_missed_updates), pro_client_missed_updates))
336+
self.composite_logger.log_debug("[APM-Pro][!] Pro Client missed updates found. [Count={0}][Updates={1}]".format(len(pro_client_missed_updates), pro_client_missed_updates))
337337
if len(all_updates_missed_updates) > 0: # interesting, for review
338-
self.composite_logger.log_debug("[APM-Pro] Pro client only updates found. [Count={0}][Updates={1}]".format(len(all_updates_missed_updates), all_updates_missed_updates))
338+
self.composite_logger.log_debug("[APM-Pro][*] Pro Client only updates found. [Count={0}][Updates={1}]".format(len(all_updates_missed_updates), all_updates_missed_updates))
339339

340340
if ubuntu_pro_client_all_updates_query_success: # this needs to be revisited based on logs above
341341
return self.ubuntu_pro_client_all_updates_cached, self.ubuntu_pro_client_all_updates_versions_cached
@@ -348,28 +348,46 @@ def get_security_updates(self):
348348
ubuntu_pro_client_security_packages = []
349349
ubuntu_pro_client_security_package_versions = []
350350

351-
self.composite_logger.log_verbose("[APM] Discovering 'security' packages...")
351+
# regular security updates check
352+
self.composite_logger.log_verbose("[APM] Discovering 'security' packages (default)...")
352353
source_parts, source_list = self.__get_custom_sources_to_spec(self.max_patch_publish_date, base_classification=Constants.PackageClassification.SECURITY)
353354
cmd = self.__generate_command_with_custom_sources(self.cmd_dist_upgrade_simulation_template, source_parts=source_parts, source_list=source_list)
354355
out = self.invoke_package_manager(cmd)
355356
security_packages, security_package_versions = self.extract_packages_and_versions(out)
356-
self.composite_logger.log_debug("[APM] Discovered 'security' packages. [Count={0}]".format(len(security_packages)))
357+
self.composite_logger.log_debug("[APM] Discovered 'security' packages (default). [Count={0}]".format(len(security_packages)))
357358

359+
# Query pro client if prerequisites are met
358360
if self.__pro_client_prereq_met:
361+
self.refresh_repo()
362+
self.composite_logger.log_verbose("[APM-Pro][Sec] Discovering 'security' packages (pro client)...")
359363
ubuntu_pro_client_security_updates_query_success, ubuntu_pro_client_security_packages, ubuntu_pro_client_security_package_versions = self.ubuntu_pro_client.get_security_updates()
360-
pro_client_missed_updates = list(set(security_packages) - set(ubuntu_pro_client_security_packages))
361-
sec_updates_missed_updates = list(set(ubuntu_pro_client_security_packages) - set(security_packages))
362-
self.composite_logger.log_debug("[APM-Pro][Sec] Get Security Updates : [DefaultSecurityPackagesCount={0}][UbuntuProClientQuerySuccess={1}][UbuntuProClientSecurityPackagesCount={2}]".format(len(security_packages), ubuntu_pro_client_security_updates_query_success, len(ubuntu_pro_client_security_packages)))
363-
if len(pro_client_missed_updates) > 0: # not good, needs investigation
364-
self.composite_logger.log_debug("[APM-Pro][Sec][!] Pro client missed updates found. [Count={0}][Updates={1}]".format(len(pro_client_missed_updates), pro_client_missed_updates))
365-
if len(sec_updates_missed_updates) > 0: # interesting, for review
366-
self.composite_logger.log_debug("[APM-Pro][Sec] Pro client only updates found. [Count={0}][Updates={1}]".format(len(sec_updates_missed_updates), sec_updates_missed_updates))
367364

368-
if ubuntu_pro_client_security_updates_query_success: # this needs to be revisited based on logs above
369-
return ubuntu_pro_client_security_packages, ubuntu_pro_client_security_package_versions
370-
else:
365+
# Only use non-pro client results if either pre-reqs are not met or if the query fails
366+
if not ubuntu_pro_client_security_updates_query_success:
367+
self.composite_logger.log_debug("[APM-Pro][Sec] Using non-Pro Client results only. [ProClientPreReq={0}][ProClientQuerySuccess={1}]".format(str(self.__pro_client_prereq_met), str(ubuntu_pro_client_security_updates_query_success)))
371368
return security_packages, security_package_versions
372369

370+
# Pro-client works - Cross-examine the results of queries
371+
pro_client_missed_updates = list(set(security_packages) - set(ubuntu_pro_client_security_packages))
372+
sec_updates_missed_updates = list(set(ubuntu_pro_client_security_packages) - set(security_packages))
373+
self.composite_logger.log_verbose("[APM-Pro][Sec] Pro Client to default package count comparison. [DefaultSecurityPackagesCount={0}][UbuntuProClientSecurityPackagesCount={1}]".format(len(security_packages), len(ubuntu_pro_client_security_packages)))
374+
if len(pro_client_missed_updates) > 0: # not good, needs investigation - incl. several pro client differences that are now known
375+
self.composite_logger.log_debug("[APM-Pro][Sec][!] Pro Client missed updates found. [Count={0}][Updates={1}]".format(len(pro_client_missed_updates), pro_client_missed_updates))
376+
if len(sec_updates_missed_updates) > 0: # interesting, for review
377+
self.composite_logger.log_debug("[APM-Pro][Sec][*] Pro Client-only updates found. [Count={0}][Updates={1}]".format(len(sec_updates_missed_updates), sec_updates_missed_updates))
378+
379+
# Use default security update list & versions as base, and adding pro client specific items on top
380+
complete_list = security_packages
381+
complete_version_list = security_package_versions # default security update list (incl. versions) supersedes due to reliability
382+
if len(sec_updates_missed_updates) > 0:
383+
for index in range(len(ubuntu_pro_client_security_packages)):
384+
if ubuntu_pro_client_security_packages[index] in sec_updates_missed_updates:
385+
complete_list.append(ubuntu_pro_client_security_packages[index])
386+
complete_version_list.append(ubuntu_pro_client_security_package_versions[index])
387+
self.composite_logger.log_debug("[APM-Pro][Sec][!] Added Pro Client-only packages to full security package list. [CombinedCount={0}][ProClientOnlyCount={1}][DefaultSecOnlyCount={2}]".format(len(complete_list),len(sec_updates_missed_updates),len(pro_client_missed_updates)))
388+
389+
return complete_list, complete_version_list
390+
373391
def get_security_esm_updates(self):
374392
"""Get missing security-esm updates."""
375393
ubuntu_pro_client_security_esm_updates_query_success = False

src/core/src/package_managers/TdnfPackageManager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def __init__(self, env_layer, execution_config, composite_logger, telemetry_writ
7777
# if an Auto Patching request comes in on a Azure Linux machine with Security and/or Critical classifications selected, we need to install all patches, since classifications aren't available in Azure Linux repository
7878
installation_included_classifications = [] if execution_config.included_classifications_list is None else execution_config.included_classifications_list
7979
if execution_config.health_store_id is not str() and execution_config.operation.lower() == Constants.INSTALLATION.lower() \
80-
and Constants.AZURE_LINUX in str(env_layer.platform.linux_distribution()) \
80+
and (env_layer.is_distro_azure_linux(str(env_layer.platform.linux_distribution()))) \
8181
and 'Critical' in installation_included_classifications and 'Security' in installation_included_classifications:
8282
self.composite_logger.log_debug("Updating classifications list to install all patches for the Auto Patching request since classification based patching is not available on Azure Linux machines")
8383
execution_config.included_classifications_list = [Constants.PackageClassification.CRITICAL, Constants.PackageClassification.SECURITY, Constants.PackageClassification.OTHER]

src/core/src/package_managers/UbuntuProClient.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def install_or_update_pro(self):
4242
run_command_success = True
4343
except Exception as error:
4444
run_command_exception = repr(error)
45-
self.composite_logger.log_debug("Ubuntu Pro Client installation: [InstallationSuccess={0}][Error={1}]".format(run_command_success, run_command_exception))
45+
self.composite_logger.log_debug("[APM][Pro] Ubuntu Pro Client installation: [InstallationSuccess={0}][Error={1}]".format(run_command_success, run_command_exception))
4646
return run_command_success
4747

4848
def is_pro_working(self):
@@ -59,7 +59,7 @@ def is_pro_working(self):
5959
# extract version from pro_client_verison 27.13.4~18.04.1 -> 27.13.4
6060
extracted_ubuntu_pro_client_version = self.version_comparator.extract_version_from_os_version_nums(ubuntu_pro_client_version)
6161

62-
self.composite_logger.log_debug("Ubuntu Pro Client current version: [ClientVersion={0}]".format(str(extracted_ubuntu_pro_client_version)))
62+
self.composite_logger.log_verbose("[APM][Pro] Ubuntu Pro Client current version: [ClientVersion={0}]".format(str(extracted_ubuntu_pro_client_version)))
6363

6464
# use custom comparator output 0 (equal), -1 (less), +1 (greater)
6565
is_minimum_ubuntu_pro_version_installed = self.version_comparator.compare_versions(extracted_ubuntu_pro_client_version, Constants.UbuntuProClientSettings.MINIMUM_CLIENT_VERSION) >= 0
@@ -70,7 +70,7 @@ def is_pro_working(self):
7070
except Exception as error:
7171
ubuntu_pro_client_exception = repr(error)
7272

73-
self.composite_logger.log_debug("Is Ubuntu Pro Client working debug flags: [Success={0}][UbuntuProClientVersion={1}][UbuntuProClientMinimumVersionInstalled={2}][IsAttached={3}][Error={4}]".format(is_ubuntu_pro_client_working, ubuntu_pro_client_version, is_minimum_ubuntu_pro_version_installed, self.is_ubuntu_pro_client_attached, ubuntu_pro_client_exception))
73+
self.composite_logger.log_debug("[APM][Pro] Is Ubuntu Pro Client working debug flags: [Success={0}][UbuntuProClientVersion={1}][UbuntuProClientMinimumVersionInstalled={2}][IsAttached={3}][Error={4}]".format(is_ubuntu_pro_client_working, ubuntu_pro_client_version, is_minimum_ubuntu_pro_version_installed, self.is_ubuntu_pro_client_attached, ubuntu_pro_client_exception))
7474
return is_ubuntu_pro_client_working
7575

7676
def log_ubuntu_pro_client_attached(self):
@@ -82,7 +82,7 @@ def log_ubuntu_pro_client_attached(self):
8282
is_ubuntu_pro_client_attached = json.loads(output)['summary']['ua']['attached']
8383
except Exception as error:
8484
ubuntu_pro_client_exception = repr(error)
85-
self.composite_logger.log_debug("Ubuntu Pro Client Attached Exception: [Exception={0}]".format(ubuntu_pro_client_exception))
85+
self.composite_logger.log_debug("[APM][Pro] Ubuntu Pro Client Attached Exception: [Exception={0}]".format(ubuntu_pro_client_exception))
8686
return is_ubuntu_pro_client_attached
8787

8888
def extract_packages_and_versions(self, updates):
@@ -121,22 +121,22 @@ def get_security_updates(self):
121121
security_criteria = ["standard-security"]
122122
security_updates_query_success, security_updates_exception, security_updates, security_updates_versions = self.get_filtered_updates(security_criteria)
123123

124-
self.composite_logger.log_debug("Ubuntu Pro Client get security updates : [SecurityUpdatesCount={0}][error={1}]".format(len(security_updates), security_updates_exception))
124+
self.composite_logger.log_debug("[APM][Pro] Ubuntu Pro Client get standard security updates : [SecurityUpdatesCount={0}][error={1}]".format(len(security_updates), security_updates_exception))
125125
return security_updates_query_success, security_updates, security_updates_versions
126126

127127
def get_security_esm_updates(self):
128128
"""query Ubuntu Pro Client to get security-esm updates."""
129129
security_esm_updates_query_success, security_esm_updates_exception, security_esm_updates, security_esm_updates_versions = self.get_filtered_updates(self.security_esm_criteria_strings)
130130

131-
self.composite_logger.log_debug("Ubuntu Pro Client get security-esm updates : [SecurityEsmUpdatesCount={0}][error={1}]".format(len(security_esm_updates),security_esm_updates_exception))
131+
self.composite_logger.log_debug("[APM][Pro] Ubuntu Pro Client get security-esm updates : [SecurityEsmUpdatesCount={0}][error={1}]".format(len(security_esm_updates),security_esm_updates_exception))
132132
return security_esm_updates_query_success, security_esm_updates, security_esm_updates_versions
133133

134134
def get_all_updates(self):
135135
"""query Ubuntu Pro Client to get all updates."""
136136
filter_criteria = []
137137
all_updates_query_success, all_updates_exception, all_updates, all_updates_versions = self.get_filtered_updates(filter_criteria)
138138

139-
self.composite_logger.log_debug("Ubuntu Pro Client get all updates: [AllUpdatesCount={0}][error={1}]".format(len(all_updates), all_updates_exception))
139+
self.composite_logger.log_debug("[APM][Pro] Ubuntu Pro Client get all updates: [AllUpdatesCount={0}][error={1}]".format(len(all_updates), all_updates_exception))
140140
return all_updates_query_success, all_updates, all_updates_versions
141141

142142
def get_ubuntu_pro_client_updates(self):
@@ -148,7 +148,7 @@ def get_other_updates(self):
148148
other_criteria = ["standard-updates"]
149149
other_updates_query_success, other_update_exception, other_updates, other_updates_versions = self.get_filtered_updates(other_criteria)
150150

151-
self.composite_logger.log_debug("Ubuntu Pro Client get other updates: [OtherUpdatesCount={0}][error = {1}]".format(len(other_updates), other_update_exception))
151+
self.composite_logger.log_debug("[APM][Pro] Ubuntu Pro Client get other updates: [OtherUpdatesCount={0}][error = {1}]".format(len(other_updates), other_update_exception))
152152
return other_updates_query_success, other_updates, other_updates_versions
153153

154154
def is_reboot_pending(self):
@@ -170,5 +170,5 @@ def is_reboot_pending(self):
170170
ubuntu_pro_client_api_success = False
171171
ubuntu_pro_client_exception = repr(error)
172172

173-
self.composite_logger.log_debug("Ubuntu Pro Client Reboot Required: [UbuntuProClientSuccess={0}][RebootRequiredFlag={1}][Error={2}]".format(ubuntu_pro_client_api_success, ubuntu_pro_client_reboot_required, ubuntu_pro_client_exception))
173+
self.composite_logger.log_debug("[APM][Pro] Ubuntu Pro Client Reboot Required: [UbuntuProClientSuccess={0}][RebootRequiredFlag={1}][Error={2}]".format(ubuntu_pro_client_api_success, ubuntu_pro_client_reboot_required, ubuntu_pro_client_exception))
174174
return ubuntu_pro_client_api_success, ubuntu_pro_client_reboot_required

src/core/tests/Test_AptitudePackageManager.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ def mock_read_with_retry_raise_exception(self):
4141
def mock_write_with_retry_raise_exception(self, file_path_or_handle, data, mode='a+'):
4242
raise Exception
4343

44-
def mock_linux_distribution_to_return_ubuntu_focal(self):
45-
return ['Ubuntu', '24.04', 'focal']
44+
def mock_linux_distribution_to_return_ubuntu_oracular(self):
45+
return ['Ubuntu', '26.04', 'oracular']
4646

4747
def mock_is_pro_working_return_true(self):
4848
return True
@@ -427,7 +427,7 @@ def test_is_pro_client_prereq_met_should_return_false_for_unsupported_os_version
427427
package_manager = self.container.get('package_manager')
428428
backup_envlayer_platform_linux_distribution = LegacyEnvLayerExtensions.LegacyPlatform.linux_distribution
429429
backup_package_manager_ubuntu_pro_client_is_pro_working = package_manager.ubuntu_pro_client.is_pro_working
430-
LegacyEnvLayerExtensions.LegacyPlatform.linux_distribution = self.mock_linux_distribution_to_return_ubuntu_focal
430+
LegacyEnvLayerExtensions.LegacyPlatform.linux_distribution = self.mock_linux_distribution_to_return_ubuntu_oracular
431431
package_manager.ubuntu_pro_client.is_pro_working = self.mock_is_pro_working_return_true
432432

433433
self.assertFalse(package_manager.check_pro_client_prerequisites())
@@ -563,7 +563,7 @@ def test_is_reboot_pending_test_raises_exception(self):
563563
def test_check_pro_client_prerequisites_should_return_false(self):
564564
package_manager = self.container.get('package_manager')
565565
backup_envlayer_platform_linux_distribution = LegacyEnvLayerExtensions.LegacyPlatform.linux_distribution
566-
LegacyEnvLayerExtensions.LegacyPlatform.linux_distribution = self.mock_linux_distribution_to_return_ubuntu_focal
566+
LegacyEnvLayerExtensions.LegacyPlatform.linux_distribution = self.mock_linux_distribution_to_return_ubuntu_oracular
567567
backup_ubuntu_pro_client_is_pro_working = package_manager.ubuntu_pro_client.is_pro_working
568568
package_manager.ubuntu_pro_client.is_pro_working = self.mock_is_pro_working_return_true
569569

0 commit comments

Comments
 (0)