Allow enforcement of minimum item count. Improve logging output.

This commit is contained in:
hoth 2022-02-01 07:08:30 +05:30
parent 5d2e93ca41
commit effa940e69

View File

@ -135,34 +135,56 @@ class BackupRotator:
assert os.path.isdir(path), "Path should be a directory: {}".format(path) assert os.path.isdir(path), "Path should be a directory: {}".format(path)
self.log("Rotating path for maximum items: {}".format(path)) self.log("Rotating path for a maximum of {} items: {}".format(
max_items, path
))
children = self._gather_rotation_candidates(config, path) children = self._gather_rotation_candidates(config, path)
minimum_items = self._determine_minimum_items(config)
# Do we need to rotate anything out? # Do we need to rotate anything out?
if len(children) <= max_items: if len(children) < minimum_items:
self.log( self.log("Path only has {} items, which does not meet the minimum threshold of {} items. Won't rotate this path.".format(
"Path only has {} items, but needs more than {} for rotation; Won't rotate this path.".format( len(children), minimum_items
len(children), max_items ))
) elif len(children) <= max_items:
) self.log("Path only has {} items, but needs more than {} for rotation; Won't rotate this path.".format(
len(children), max_items
))
return return
self.log("Found {} items to examine".format(len(children)))
# #
maximum_purge_count = len(children) - minimum_items
purge_count = len(children) - max_items purge_count = len(children) - max_items
self.log("Need to purge {} items".format(purge_count)) self.log("Want to purge {} items".format(purge_count))
if purge_count > maximum_purge_count:
self.log("Reducing purge count from {} to {} items to respect minimum items setting ({})".format(
purge_count, maximum_purge_count, minimum_items
))
purge_count = maximum_purge_count
children_to_purge = []
for purge_index in range(purge_count): for purge_index in range(purge_count):
# #
item_to_purge, item_ctime = self._pick_oldest_item(config, children) item_to_purge, item_ctime, item_age_seconds, item_age = self._pick_oldest_item(config, children)
children.remove(item_to_purge) children.remove(item_to_purge)
self.log("Found next item to purge: ({}) {} (ctime: {})".format( self.log("Found next item to purge: ({}) {} ({})".format(
purge_index + 1, purge_index + 1,
os.path.basename(item_to_purge), item_ctime os.path.basename(item_to_purge),
item_age
)) ))
# #
children_to_purge.append(item_to_purge)
#
self.log("Removing items")
for child_to_purge in children_to_purge:
child_basename = os.path.basename(child_to_purge)
self._remove_item(config, item_to_purge) self._remove_item(config, item_to_purge)
def _rotate_path_for_maximum_age(self, config, path: str, max_age_days: int): def _rotate_path_for_maximum_age(self, config, path: str, max_age_days: int):
@ -173,7 +195,7 @@ class BackupRotator:
children = self._gather_rotation_candidates(config, path) children = self._gather_rotation_candidates(config, path)
self.log("Examining {} items for deletion") self.log("Examining {} items for deletion".format(len(children)))
children_to_delete = [] children_to_delete = []
for child in children: for child in children:
@ -183,20 +205,22 @@ class BackupRotator:
child_basename = os.path.basename(child) child_basename = os.path.basename(child)
if age_days > max_age_days: if age_days > max_age_days:
self.log("Old enough to delete: {} ({})".format( self.log("[Old enough ] {} ({})".format(
child_basename, age_formatted child_basename, age_formatted
)) ))
children_to_delete.append(child) children_to_delete.append(child)
else: else:
self.log("Not old enough to delete: {} ({})".format( self.log("[Not Old enough] {} ({})".format(
child_basename, age_formatted child_basename, age_formatted
)) ))
self.log("Removing old items ...") if len(children_to_delete) > 0:
for child_to_delete in children_to_delete: self.log("Removing old items ...")
basename = os.path.basename(child_to_delete) for child_to_delete in children_to_delete:
self.log("> {}".format(basename)) basename = os.path.basename(child_to_delete)
self._remove_item(config, child_to_delete) self._remove_item(config, child_to_delete)
else:
self.log("No old items to remove")
@staticmethod @staticmethod
@ -235,7 +259,10 @@ class BackupRotator:
best_ctime = ctime best_ctime = ctime
best_item = item best_item = item
return best_item, best_ctime age_seconds = self._detect_item_age_seconds(config, best_item)
age_string = self.seconds_to_time_string(age_seconds)
return best_item, best_ctime, age_seconds, age_string
@staticmethod @staticmethod
def _detect_item_date(config, item): def _detect_item_date(config, item):
@ -336,3 +363,16 @@ class BackupRotator:
else: else:
self.log("Purging directory:", dir_path) self.log("Purging directory:", dir_path)
shutil.rmtree(dir_path) shutil.rmtree(dir_path)
def _determine_minimum_items(self, config):
minimum_items = 0
if "minimum-items" in config.keys():
minimum_items = config["minimum-items"]
self.log("Won't delete anything unless a minimum of {} items were found".format(minimum_items))
else:
self.log("No value found for \"minimum-items\"; Will not enforce minimum item constraint.")
return minimum_items