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

Calculate maximum batch size in batch patching as per time remaining in maintenance window #250

Merged
merged 19 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
b3282e2
Increasing batch size from 3 to 6
GAURAVRAMRAKHYANI Nov 16, 2023
7e0d995
Merge branch 'master' of https://github.com/Azure/LinuxPatchExtension
GAURAVRAMRAKHYANI Mar 6, 2024
61bbdfd
Merge branch 'master' of https://github.com/Azure/LinuxPatchExtension
GAURAVRAMRAKHYANI Mar 12, 2024
2a9a47d
Added function signatures and callers from the code
GAURAVRAMRAKHYANI Mar 13, 2024
01ebd9d
Some indentation changes
GAURAVRAMRAKHYANI Mar 13, 2024
a67d6f4
Incorporate PR comments
GAURAVRAMRAKHYANI Mar 21, 2024
4b1f79d
Implemented the function get_max_batch_size
GAURAVRAMRAKHYANI Mar 25, 2024
eae056f
Addressing some comments in the PR. The comments addressed are:
GAURAVRAMRAKHYANI Apr 1, 2024
f49ab63
Added test case for get_max_batch_size
GAURAVRAMRAKHYANI Apr 3, 2024
92b5160
Addressed PR comments
GAURAVRAMRAKHYANI Apr 5, 2024
b5a5f6e
added package_manager in the callers for the method is_package_instal…
GAURAVRAMRAKHYANI Apr 7, 2024
1ec9401
Removed mentioning specific package manager in test_get_max_batch_size
GAURAVRAMRAKHYANI Apr 7, 2024
be7b562
Add runtime.stop() at the end of the test test_get_max_batch_size
GAURAVRAMRAKHYANI Apr 7, 2024
37173c2
Merge branch 'master' of https://github.com/Azure/LinuxPatchExtension…
GAURAVRAMRAKHYANI Apr 7, 2024
510f4ec
Addressing PR comments and one fix.
GAURAVRAMRAKHYANI Apr 24, 2024
acd64d2
Merge branch 'master' into garamrak-multiPhase
kjohn-msft May 1, 2024
a8ad80a
Update unit tests to increase code coverage
GAURAVRAMRAKHYANI May 3, 2024
a122a55
Update test cases as per the product code changes done.
GAURAVRAMRAKHYANI May 3, 2024
4de68b4
update test case to increase % coverage
GAURAVRAMRAKHYANI May 3, 2024
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
28 changes: 13 additions & 15 deletions src/core/src/bootstrap/Constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,21 @@ class StatusTruncationConfig(EnumBackport):
MAX_INSTALLATION_RETRY_COUNT = 3
MAX_IMDS_CONNECTION_RETRY_COUNT = 5
MAX_ZYPPER_REPO_REFRESH_RETRY_COUNT = 5
MAX_BATCH_SIZE_FOR_PACKAGES = 6
NUMBER_OF_PACKAGES_IN_BATCH_COULD_TAKE_MAX_TIME_TO_INSTALL = 3
MAX_COMPLETE_STATUS_FILES_TO_RETAIN = 10

# Batch Patching Parameters
MAX_BATCH_SIZE_FOR_PACKAGES = 300
MAX_PHASES_FOR_BATCH_PATCHING = 2

# Batch size decay factor is factor to which batch size is decreased in batch patching to install remaining packages in case there
# are some package install failures with original batch size.
BATCH_SIZE_DECAY_FACTOR = 10

# We need to keep some buffer time between calculation of batch size and starting batch patching because after calculating the batch size,
# there would be little time taken before the batch patching is started. The function is_package_install_time_available is called before installing a batch.
# If we do not keep buffer then is_package_install_time_available would return false.
BUFFER_TIME_FOR_BATCH_PATCHING_START_IN_MINUTES = 5
GAURAVRAMRAKHYANI marked this conversation as resolved.
Show resolved Hide resolved

class PackageClassification(EnumBackport):
UNCLASSIFIED = 'Unclassified'
CRITICAL = 'Critical'
Expand Down Expand Up @@ -269,19 +280,6 @@ class PatchAssessmentSummaryStartedBy(EnumBackport):

# Maintenance Window
PACKAGE_INSTALL_EXPECTED_MAX_TIME_IN_MINUTES = 5

# As per telemetry data, when batch size is 3, the average time taken per package installation for different package managers is as follow:
# apt: 43 seconds
# yum: 71 seconds
# zypper: 142 seconds
# Overall, including all package managers, the average time is 51 seconds.
# The average time taken per package installation is average of (total time taken to install the packages) / (total number of packages installed).
# The expected average time should be kept as max of average time taken by different packages managers. The max of average time is taken in zypper i.e. 142 seconds when batch size is 3.
# But as the batch size increases, the time taken to install package will decrease. Also, the average time is taken in consideration in calculating maintenance window cutoff only if the
# batch size is greater than or equal to 4. So, keeping the expected average time as 2 minutes i.e. 120 seconds. It should be fine to keep expected time little lower than actual average time
# observed in telemetry because there is PACKAGE_INSTALL_EXPECTED_MAX_TIME_IN_MINUTES also in the calucalation of maintenance window cut off which will make the overall cutoff time enough to
# install the batch of packages.
PACKAGE_INSTALL_EXPECTED_AVG_TIME_IN_MINUTES = 2

# Package Manager Setting
PACKAGE_MGR_SETTING_REPEAT_PATCH_OPERATION = "RepeatUpdateRun"
Expand Down
31 changes: 8 additions & 23 deletions src/core/src/core_logic/MaintenanceWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,32 +59,16 @@ def get_remaining_time_in_minutes(self, current_time=None, log_to_stdout=False):

return remaining_time_in_minutes

def is_package_install_time_available(self, remaining_time_in_minutes=None, number_of_packages_in_batch=1):
def is_package_install_time_available(self, package_manager, remaining_time_in_minutes=None, number_of_packages_in_batch=1):
"""Check if time still available for package installation"""
cutoff_time_in_minutes = 0

# In the extreme case, all the package installations in the batch might take the maximum time.
# But calculating cutoff time based on max time to install packages for all the packages will make cutoff time very huge
# as it is very unlikely that all the package installations take maximum time.
# Also, as the batch size increases, the expected time taken per package installation decreases due to batch patching.
# So, for batch size less than or equal to 3, calculating cutoff time expecting all packages might take max time to install.
# For larger batch size i.e. 4 or higher, expecting 3 package installations can take max time and rest can take average time to install.
# It is safe assumption that only 3 packages will take max time to install. Even if more number of packages take max time to install then
# due to batch patching in large batch size, the time taken to install a package decreases substantially and hence cutoff time should be enough
# to install the batch of packages.
# PACKAGE_INSTALL_EXPECTED_MAX_TIME is 5 minutes, PACKAGE_INSTALL_EXPECTED_AVG_TIME is 2 minutes
# For different batch size, following would be cutoff:
# Batch Size = 1, Cutoff = 5 * 1 = 5 minutes
# Batch Size = 2, Cutoff = 5 * 2 = 10 minutes
# Batch Size = 3, Cutoff = 5 * 3 = 15 minutes
# Batch Size = 4, Cutoff = (5 * 3) + (2 * 1) = 17 minutes
# Batch Size = 5, Cutoff = (5 * 3) + (2 * 2) = 19 minutes
# Batch Size = 6, Cutoff = (5 * 3) + (2 * 3) = 21 minutes
if number_of_packages_in_batch <= Constants.NUMBER_OF_PACKAGES_IN_BATCH_COULD_TAKE_MAX_TIME_TO_INSTALL:
cutoff_time_in_minutes = Constants.PACKAGE_INSTALL_EXPECTED_MAX_TIME_IN_MINUTES * number_of_packages_in_batch
else:
cutoff_time_in_minutes = Constants.PACKAGE_INSTALL_EXPECTED_MAX_TIME_IN_MINUTES * Constants.NUMBER_OF_PACKAGES_IN_BATCH_COULD_TAKE_MAX_TIME_TO_INSTALL
cutoff_time_in_minutes += Constants.PACKAGE_INSTALL_EXPECTED_AVG_TIME_IN_MINUTES * (number_of_packages_in_batch - Constants.NUMBER_OF_PACKAGES_IN_BATCH_COULD_TAKE_MAX_TIME_TO_INSTALL)
# Assuming that one of the packages in the batch could take maximum time to install and rest of the packages take average time.
cutoff_time_in_minutes = Constants.PACKAGE_INSTALL_EXPECTED_MAX_TIME_IN_MINUTES
if number_of_packages_in_batch > 1:
package_install_expected_avg_time = package_manager.get_package_install_expected_avg_time_in_minutes()
cutoff_time_in_minutes += package_install_expected_avg_time * (number_of_packages_in_batch - 1)

if Constants.REBOOT_SETTINGS[self.execution_config.reboot_setting] != Constants.REBOOT_NEVER:
cutoff_time_in_minutes = cutoff_time_in_minutes + Constants.REBOOT_BUFFER_IN_MINUTES
Expand Down Expand Up @@ -121,4 +105,5 @@ def get_percentage_maintenance_window_used(self):

# Rounding off to one digit after decimal e.g. 14.514372666666667 will become 14.5
percent_maintenance_window_used = round(percent_maintenance_window_used, 1)
return percent_maintenance_window_used
return percent_maintenance_window_used

Loading
Loading