Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
5af4306
Add UbuntuProClient.py and initial skeleton code.
SathishMSFT Feb 6, 2023
23716de
Change pre_req property name. Change log_warning to log_debug.
SathishMSFT Feb 8, 2023
9aa02c8
Add comment
SathishMSFT Feb 8, 2023
168a05a
update comment
SathishMSFT Feb 8, 2023
8ed7268
Merge branch 'master' into satimpro
SathishMSFT Feb 8, 2023
4ee8beb
Add UT. Address review comments.
SathishMSFT Feb 15, 2023
8276292
Added more test to fix codecov.
SathishMSFT Feb 15, 2023
cf6dabc
Merge branch 'master' into satimpro
SathishMSFT Feb 15, 2023
e2db84c
update mock method
SathishMSFT Feb 15, 2023
88c3f96
Merge branch 'satimpro' of https://github.com/Azure/LinuxPatchExtensi…
SathishMSFT Feb 15, 2023
8d5cd0d
implement reboot_required
SathishMSFT Feb 20, 2023
7ec4157
Add more unit tests to address codecov issues
SathishMSFT Feb 22, 2023
fcef184
Remove comments
SathishMSFT Feb 22, 2023
4a8099b
Addressing review comments
SathishMSFT Feb 24, 2023
d8e640b
Remove extra line
SathishMSFT Feb 24, 2023
7133c01
Finxing the unit test
SathishMSFT Mar 1, 2023
1839709
Moving reboot_pending method to package_manager and updated review co…
SathishMSFT Mar 1, 2023
4b49f21
Updating comments and removing commented code.
SathishMSFT Mar 1, 2023
639dd4d
updating unittests
SathishMSFT Mar 1, 2023
1833169
adding more unittests
SathishMSFT Mar 1, 2023
8c5d622
adding review comments
SathishMSFT Mar 2, 2023
adf3fe3
adding more unit test
SathishMSFT Mar 2, 2023
b35c300
addressing review comment.
SathishMSFT Mar 3, 2023
2fc1955
addressing review comment.
SathishMSFT Mar 3, 2023
ca1ca08
addressing review comment.
SathishMSFT Mar 3, 2023
27fa81d
addressing review comment.
SathishMSFT Mar 3, 2023
e810f49
updating the unit test.
SathishMSFT Mar 6, 2023
bfc6091
updating comments as per review.
SathishMSFT Mar 8, 2023
4a7eb0b
updating comments as per review.
SathishMSFT Mar 8, 2023
be9793b
updating comments as per review.
SathishMSFT Mar 10, 2023
0231afc
updating comments as per review.
SathishMSFT Mar 10, 2023
4f2e38b
re-arranging mock code.
SathishMSFT Mar 10, 2023
3869145
re-arranging mock code.
SathishMSFT Mar 15, 2023
72bb9ab
reverting unwanted changes
SathishMSFT Mar 15, 2023
f79e039
updating unit tests
SathishMSFT Mar 15, 2023
acb869b
updating unit tests
SathishMSFT Mar 15, 2023
6b1df49
updating unit tests
SathishMSFT Mar 15, 2023
c532298
Merge branch 'master' into satimpro
SathishMSFT Mar 16, 2023
76c9aca
Merge latest from master
SathishMSFT Mar 16, 2023
f1d2c25
revert comments
SathishMSFT Mar 16, 2023
02fb6bc
Adding back tests missed in merge
SathishMSFT Mar 16, 2023
3bcbcd4
Initial code for get_all_updates without unit tests
SathishMSFT Mar 27, 2023
49671da
Merge branch 'satimpro' of https://github.com/Azure/LinuxPatchExtensi…
SathishMSFT Mar 27, 2023
63d11ba
merge
SathishMSFT Mar 27, 2023
9527c75
Merge branch 'master' into satimpro
SathishMSFT Mar 31, 2023
1e1baa9
Merge branch 'master' into satimpro
SathishMSFT Apr 4, 2023
5047b1b
Add Security updates and esm updates changes
SathishMSFT Apr 6, 2023
d62438e
Merge branch 'satimpro' of https://github.com/Azure/LinuxPatchExtensi…
SathishMSFT Apr 6, 2023
a79d78d
Add SecurityESM to constants
SathishMSFT Apr 6, 2023
435351c
change the updates method to use api.
SathishMSFT Apr 25, 2023
4be8387
Add other_updates. Patch operation sucess.
SathishMSFT Apr 27, 2023
54ef688
Handle esm packages during patch operations
SathishMSFT May 2, 2023
f8303fb
Address review comments.
SathishMSFT May 2, 2023
38748e4
Add Error for assessment and some refactor
SathishMSFT May 3, 2023
8b4d5be
Adding unit tests for UbuntuProClient.py
SathishMSFT May 17, 2023
117e79c
Adding unit tests for UbuntuProClient.py
SathishMSFT May 17, 2023
ae260fc
merge latest code
SathishMSFT May 17, 2023
dafc0fa
fix code missed during merge
SathishMSFT May 18, 2023
4425b7e
merge latest change
SathishMSFT May 18, 2023
82ce4a9
merge latest change
SathishMSFT May 18, 2023
532d5e2
Handle patching esm packages in un-attached VM scenario.
SathishMSFT May 29, 2023
d90cf84
Fix the attach issue.
SathishMSFT May 29, 2023
432cdce
Fix the unit test issue.
SathishMSFT May 29, 2023
d7938de
Branding changes and more unit tests
SathishMSFT May 30, 2023
1bf37b8
Adding mock outputs
SathishMSFT May 30, 2023
daba01b
Removing ESM package checks that are not needed.
SathishMSFT May 30, 2023
d31e9aa
Updating comment
SathishMSFT May 30, 2023
c80c811
Removing un-used code. Add more test
SathishMSFT May 30, 2023
fee6795
Removing un-used code.
SathishMSFT May 30, 2023
a71f305
ADding unit tests
SathishMSFT May 31, 2023
bfdf2c1
ADding unit tests
SathishMSFT May 31, 2023
ef1b75d
Adding some fix.
SathishMSFT Jun 4, 2023
42692b0
Fixing the bad merge.
SathishMSFT Jun 6, 2023
ae655e8
fix classification count and remove extra line.
SathishMSFT Jun 7, 2023
b23518a
Addressing review comments.
SathishMSFT Jun 8, 2023
675e19e
Refactoring the updates code.
SathishMSFT Jun 8, 2023
c261e99
Adding more to unittest
SathishMSFT Jun 14, 2023
87bd66d
Addressing review comments missed before.
SathishMSFT Jun 14, 2023
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
8 changes: 6 additions & 2 deletions src/core/src/bootstrap/Constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ class PackageClassification(EnumBackport):
UNCLASSIFIED = 'Unclassified'
CRITICAL = 'Critical'
SECURITY = 'Security'
SECURITY_ESM = 'Security-ESM'
OTHER = 'Other'

PKG_MGR_SETTING_FILTER_CRITSEC_ONLY = 'FilterCritSecOnly'
Expand Down Expand Up @@ -264,6 +265,7 @@ class PatchOperationErrorCodes(EnumBackport):
OPERATION_FAILED = "OPERATION_FAILED"
PACKAGE_MANAGER_FAILURE = "PACKAGE_MANAGER_FAILURE"
NEWER_OPERATION_SUPERSEDED = "NEWER_OPERATION_SUPERSEDED"
UA_ESM_REQUIRED = "UA_ESM_REQUIRED"

ERROR_ADDED_TO_STATUS = "Error_added_to_status"

Expand Down Expand Up @@ -312,8 +314,9 @@ class EnvLayer(EnumBackport):
PackageClassificationOrderInStatusReporting = {
PackageClassification.CRITICAL: 1,
PackageClassification.SECURITY: 2,
PackageClassification.OTHER: 3,
PackageClassification.UNCLASSIFIED: 4
PackageClassification.SECURITY_ESM: 3,
PackageClassification.OTHER: 4,
PackageClassification.UNCLASSIFIED: 5
}

PatchStateOrderInStatusReporting = {
Expand All @@ -330,4 +333,5 @@ class UbuntuProClientSettings(EnumBackport):
FEATURE_ENABLED = True
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.
MAX_OS_MAJOR_VERSION_SUPPORTED = 18
MINIMUM_CLIENT_VERSION = "27.14.4"

2 changes: 1 addition & 1 deletion src/core/src/core_logic/PackageFilter.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def is_msft_other_classification_only(self):
def is_msft_all_classification_included(self):
"""Returns true if all classifications were individually selected *OR* (nothing was selected AND no inclusion list is present) -- business logic"""
all_classifications = [key for key in Constants.PackageClassification.__dict__.keys() if not key.startswith('__')]
all_classifications_explicitly_selected = bool(len(self.installation_included_classifications) == (len(all_classifications) - 1))
all_classifications_explicitly_selected = bool(len(self.installation_included_classifications) == (len(all_classifications) - 2)) # all_classifications has "UNCLASSIFIED" and "SECURITY-ESM" that should be ignored. Hence -2
no_classifications_selected = bool(len(self.installation_included_classifications) == 0)
only_unclassified_selected = bool('Unclassified' in self.installation_included_classifications and len(self.installation_included_classifications) == 1)
return all_classifications_explicitly_selected or ((no_classifications_selected or only_unclassified_selected) and not self.is_inclusion_list_present())
Expand Down
5 changes: 4 additions & 1 deletion src/core/src/core_logic/PatchAssessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,10 @@ def start_assessment(self):

# Tag security updates
self.telemetry_writer.write_event("Security assessment: " + str(sec_packages), Constants.TelemetryEventLevel.Verbose)
self.status_handler.set_package_assessment_status(sec_packages, sec_package_versions, "Security")
self.status_handler.set_package_assessment_status(sec_packages, sec_package_versions, Constants.PackageClassification.SECURITY)

# Set the security-esm packages in status.
self.package_manager.set_security_esm_package_status(Constants.ASSESSMENT)

# ensure reboot status is set
reboot_pending = self.package_manager.is_reboot_pending()
Expand Down
40 changes: 25 additions & 15 deletions src/core/src/core_logic/PatchInstaller.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ def __init__(self, env_layer, execution_config, composite_logger, telemetry_writ
self.attempted_parent_package_install_count = 0
self.successful_parent_package_install_count = 0
self.failed_parent_package_install_count = 0
self.skipped_esm_packages = []
self.skipped_esm_package_versions = []
self.esm_packages_found_without_attach = False # Flag used to record if esm packages excluded as ubuntu vm not attached.

self.stopwatch = Stopwatch(self.env_layer, self.telemetry_writer, self.composite_logger)

def start_installation(self, simulate=False):
Expand Down Expand Up @@ -150,20 +154,31 @@ def install_updates(self, maintenance_window, package_manager, simulate=False):
excluded_packages, excluded_package_versions = self.get_excluded_updates(package_manager, packages, package_versions)
self.telemetry_writer.write_event("Excluded package list: " + str(excluded_packages), Constants.TelemetryEventLevel.Verbose)

packages, package_versions = self.filter_out_excluded_updates(packages, package_versions, excluded_packages) # Final, honoring exclusions
packages, package_versions = self.filter_out_excluded_updates(packages, package_versions, excluded_packages) # honoring exclusions

# For ubuntu VMs, filter out esm_packages, if the VM is not attached.
# These packages will already be marked with version as 'UA_ESM_REQUIRED'.
# Esm packages will not be dependent packages to non-esm packages. This is confirmed by Canonical. So, once these are removed from processing, we need not worry about handling it in our batch / sequential patch processing logic.
# Adding this after filtering excluded packages, so we don`t un-intentionally mark excluded esm-package status as failed.
packages, package_versions, self.skipped_esm_packages, self.skipped_esm_package_versions, self.esm_packages_found_without_attach = package_manager.filter_out_esm_packages(packages, package_versions)

self.telemetry_writer.write_event("Final package list: " + str(packages), Constants.TelemetryEventLevel.Verbose)

# Set initial statuses
if not package_manager.get_package_manager_setting(Constants.PACKAGE_MGR_SETTING_REPEAT_PATCH_OPERATION, False): # 'Not included' list is not accurate when a repeat is required
self.status_handler.set_package_install_status(not_included_packages, not_included_package_versions, Constants.NOT_SELECTED)
self.status_handler.set_package_install_status(excluded_packages, excluded_package_versions, Constants.EXCLUDED)
self.status_handler.set_package_install_status(packages, package_versions, Constants.PENDING)
self.status_handler.set_package_install_status(self.skipped_esm_packages, self.skipped_esm_package_versions, Constants.FAILED)
self.composite_logger.log("\nList of packages to be updated: \n" + str(packages))

sec_packages, sec_package_versions = self.package_manager.get_security_updates()
self.telemetry_writer.write_event("Security packages out of the final package list: " + str(sec_packages), Constants.TelemetryEventLevel.Verbose)
self.status_handler.set_package_install_status_classification(sec_packages, sec_package_versions, classification="Security")

# Set the security-esm package status.
package_manager.set_security_esm_package_status(Constants.INSTALLATION)

self.composite_logger.log("\nNote: Packages that are neither included nor excluded may still be installed if an included package has a dependency on it.")
# We will see this as packages going from NotSelected --> Installed. We could remove them preemptively from not_included_packages, but we're explicitly choosing not to.

Expand Down Expand Up @@ -237,15 +252,11 @@ def install_updates(self, maintenance_window, package_manager, simulate=False):
# point in time status
progress_status = self.progress_template.format(str(datetime.timedelta(minutes=remaining_time)), str(self.attempted_parent_package_install_count), str(self.successful_parent_package_install_count), str(self.failed_parent_package_install_count), str(installed_update_count - self.successful_parent_package_install_count),
"Processing package: " + str(package) + " (" + str(version) + ")")
if version == Constants.UA_ESM_REQUIRED:
progress_status += "[Skipping - requires Ubuntu Advantage for Infrastructure with Extended Security Maintenance]"
self.composite_logger.log(progress_status)
self.status_handler.set_package_install_status(package_manager.get_product_name(package), str(version), Constants.NOT_SELECTED) # may be changed to Failed in the future
continue

self.composite_logger.log(progress_status)

# include all dependencies (with specified versions) explicitly
# package_and_dependencies initially conains only one package. The dependencies are added in the list by method include_dependencies
# package_and_dependencies initially contains only one package. The dependencies are added in the list by method include_dependencies
package_and_dependencies = [package]
package_and_dependency_versions = [version]

Expand Down Expand Up @@ -435,14 +446,10 @@ def install_packages_in_batches(self, all_packages, all_package_versions, packag

packages_in_batch = []
package_versions_in_batch = []
skip_packages = []
already_installed_packages = []

for index in range(begin_index, end_index + 1):
if package_versions[index] == Constants.UA_ESM_REQUIRED:
skip_packages.append(packages[index])
self.status_handler.set_package_install_status(package_manager.get_product_name(packages[index]), str(package_versions[index]), Constants.NOT_SELECTED)
elif packages[index] not in self.last_still_needed_packages:
if packages[index] not in self.last_still_needed_packages:
# Could have got installed as dependent package of some other package. Package installation status could also have been set.
already_installed_packages.append(packages[index])
self.attempted_parent_package_install_count += 1
Expand All @@ -454,9 +461,6 @@ def install_packages_in_batches(self, all_packages, all_package_versions, packag
if len(already_installed_packages) > 0:
self.composite_logger.log("Following packages are already installed. Could have got installed as dependent package of some other package " + str(already_installed_packages))

if len(skip_packages) > 0:
self.composite_logger.log("[Skipping packages " + str(skip_packages) + " - requires Ubuntu Advantage for Infrastructure with Extended Security Maintenance]")

if len(packages_in_batch) == 0:
continue

Expand Down Expand Up @@ -553,10 +557,16 @@ def mark_installation_completed(self):

# RebootNever is selected and pending, set status warning else success
if self.reboot_manager.reboot_setting == Constants.REBOOT_NEVER and self.reboot_manager.is_reboot_pending():
# Set error details inline with windows extension when setting warning status. This message will be shown in portal.
self.status_handler.add_error_to_status("Machine is Required to reboot. However, the customer-specified reboot setting doesn't allow reboots.", Constants.PatchOperationErrorCodes.DEFAULT_ERROR)
self.status_handler.set_installation_substatus_json(status=Constants.STATUS_WARNING)
else:
self.status_handler.set_installation_substatus_json(status=Constants.STATUS_SUCCESS)

# If esm packages are found, set the status as warning. This will show up in portal along with the error message we already set.
if self.esm_packages_found_without_attach:
self.status_handler.set_installation_substatus_json(status=Constants.STATUS_WARNING)

# Update patch metadata in status for auto patching request, to be reported to healthStore
# When available, HealthStoreId always takes precedence over the 'overriden' Maintenance Run Id that is being re-purposed for other reasons
# In the future, maintenance run id will be completely deprecated for health store reporting.
Expand Down
Loading