Skip to content

Commit

Permalink
refactor(physical-restore): Always run cleanup on failure
Browse files Browse the repository at this point in the history
  • Loading branch information
tanmoysrt committed Jan 20, 2025
1 parent 6114420 commit e26c7f4
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ frappe.ui.form.on('Physical Backup Restoration', {
[
[__('Start'), 'execute', frm.doc.status === 'Pending'],
[__('Force Continue'), 'force_continue', frm.doc.status === 'Failure'],
[__('Cleanup'), 'cleanup', frm.doc.status === 'Failure'],
[__('Force Fail'), 'force_fail', frm.doc.status === 'Running'],
].forEach(([label, method, condition]) => {
if (condition) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from press.press.doctype.virtual_disk_snapshot.virtual_disk_snapshot import VirtualDiskSnapshot
from press.press.doctype.virtual_machine.virtual_machine import VirtualMachine

StepStatus = Enum("StepStatus", ["Pending", "Running", "Success", "Failure"])
StepStatus = Enum("StepStatus", ["Pending", "Running", "Skipped", "Success", "Failure"])


class PhysicalBackupRestoration(Document):
Expand Down Expand Up @@ -68,32 +68,35 @@ def migration_steps(self):
NoWait = False
SyncStep = False
AsyncStep = True
GeneralStep = False
CleanupStep = True
methods = [

Check warning on line 73 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L67-L73

Added lines #L67 - L73 were not covered by tests
(self.wait_for_pending_snapshot_to_be_completed, Wait, SyncStep),
(self.create_volume_from_snapshot, NoWait, SyncStep),
(self.wait_for_volume_to_be_available, Wait, SyncStep),
(self.attach_volume_to_instance, NoWait, SyncStep),
(self.create_mount_point, NoWait, SyncStep),
(self.mount_volume_to_instance, NoWait, SyncStep),
(self.change_permission_of_backup_directory, NoWait, SyncStep),
(self.change_permission_of_database_directory, NoWait, SyncStep),
(self.restore_database, Wait, AsyncStep),
(self.rollback_permission_change_of_database_directory, NoWait, SyncStep),
(self.unmount_volume_from_instance, NoWait, SyncStep),
(self.delete_mount_point, NoWait, SyncStep),
(self.detach_volume_from_instance, NoWait, SyncStep),
(self.wait_for_volume_to_be_detached, Wait, SyncStep),
(self.delete_volume, NoWait, SyncStep),
(self.wait_for_pending_snapshot_to_be_completed, Wait, SyncStep, GeneralStep),
(self.create_volume_from_snapshot, NoWait, SyncStep, GeneralStep),
(self.wait_for_volume_to_be_available, Wait, SyncStep, GeneralStep),
(self.attach_volume_to_instance, NoWait, SyncStep, GeneralStep),
(self.create_mount_point, NoWait, SyncStep, GeneralStep),
(self.mount_volume_to_instance, NoWait, SyncStep, GeneralStep),
(self.change_permission_of_backup_directory, NoWait, SyncStep, GeneralStep),
(self.change_permission_of_database_directory, NoWait, SyncStep, GeneralStep),
(self.restore_database, Wait, AsyncStep, GeneralStep),
(self.rollback_permission_of_database_directory, NoWait, SyncStep, CleanupStep),
(self.unmount_volume_from_instance, NoWait, SyncStep, CleanupStep),
(self.delete_mount_point, NoWait, SyncStep, CleanupStep),
(self.detach_volume_from_instance, NoWait, SyncStep, CleanupStep),
(self.wait_for_volume_to_be_detached, Wait, SyncStep, CleanupStep),
(self.delete_volume, NoWait, SyncStep, CleanupStep),
]

steps = []
for method, wait_for_completion, is_async in methods:
for method, wait_for_completion, is_async, is_cleanup_step in methods:
steps.append(

Check warning on line 93 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L91-L93

Added lines #L91 - L93 were not covered by tests
{
"step": method.__doc__,
"method": method.__name__,
"wait_for_completion": wait_for_completion,
"is_async": is_async,
"is_cleanup_step": is_cleanup_step,
}
)
return steps

Check warning on line 102 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L102

Added line #L102 was not covered by tests
Expand Down Expand Up @@ -294,7 +297,7 @@ def restore_database(self) -> StepStatus:
return StepStatus.Success
return StepStatus.Failure

Check warning on line 298 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L288-L298

Added lines #L288 - L298 were not covered by tests

def rollback_permission_change_of_database_directory(self) -> StepStatus:
def rollback_permission_of_database_directory(self) -> StepStatus:
"""Rollback permission of database directory"""

# Docs > https://mariadb.com/kb/en/specifying-permissions-for-schema-data-directories-and-tables/
Expand All @@ -309,7 +312,7 @@ def rollback_permission_change_of_database_directory(self) -> StepStatus:

def unmount_volume_from_instance(self) -> StepStatus:
"""Unmount volume from instance"""
if self.get_step_status(self.mount_volume_to_instance) != StepStatus.Success:
if self.get_step_status(self.mount_volume_to_instance) != StepStatus.Success.name:
return StepStatus.Success
response = self.ansible_run(f"umount {self.mount_point}")
if response["status"] != "Success":
Expand Down Expand Up @@ -353,7 +356,10 @@ def wait_for_volume_to_be_detached(self) -> StepStatus:

def delete_volume(self) -> StepStatus:
"""Delete volume"""
if not self.volume or self.get_step_status(self.create_volume_from_snapshot) != StepStatus.Success:
if (

Check warning on line 359 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L359

Added line #L359 was not covered by tests
not self.volume
or self.get_step_status(self.create_volume_from_snapshot) != StepStatus.Success.name
):
return StepStatus.Success
state = self.virtual_machine.get_state_of_volume(self.volume)
if state in ["deleting", "deleted"]:
Expand Down Expand Up @@ -385,9 +391,14 @@ def fail(self) -> None:
self.end = frappe.utils.now_datetime()
self.duration = (self.end - self.start).total_seconds()
self.save()
self.cleanup()

Check warning on line 394 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L387-L394

Added lines #L387 - L394 were not covered by tests

def succeed(self) -> None:
def finish(self) -> None:
self.status = "Success"

Check warning on line 397 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L397

Added line #L397 was not covered by tests
# If any step is failed, then mark the job as failed
for step in self.steps:
if step.status == "Failure":
self.status = "Failure"
self.end = frappe.utils.now_datetime()
self.duration = (self.end - self.start).total_seconds()
self.save()

Check warning on line 404 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L399-L404

Added lines #L399 - L404 were not covered by tests
Expand All @@ -400,7 +411,7 @@ def next(self, ignore_version=False) -> None:

if not next_step:

Check warning on line 412 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L412

Added line #L412 was not covered by tests
# We've executed everything
self.succeed()
self.finish()
return

Check warning on line 415 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L414-L415

Added lines #L414 - L415 were not covered by tests

frappe.enqueue_doc(

Check warning on line 417 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L417

Added line #L417 was not covered by tests
Expand All @@ -412,6 +423,22 @@ def next(self, ignore_version=False) -> None:
at_front=True,
)

@frappe.whitelist()
def cleanup(self):
is_cleanup_required = False
for step in self.steps:

Check warning on line 429 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L428-L429

Added lines #L428 - L429 were not covered by tests
# Mark the pending non-cleanup steps as skipped
if not step.is_cleanup_step and step.status == "Pending":
step.status = "Skipped"

Check warning on line 432 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L431-L432

Added lines #L431 - L432 were not covered by tests

# Mark the cleanup steps with non-failure status as pending
if step.is_cleanup_step and step.status != "Failure":
step.status = "Pending"
is_cleanup_required = True

Check warning on line 437 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L435-L437

Added lines #L435 - L437 were not covered by tests

if is_cleanup_required:
self.next()

Check warning on line 440 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L439-L440

Added lines #L439 - L440 were not covered by tests

@frappe.whitelist()
def force_continue(self) -> None:
first_failed_step: PhysicalBackupRestorationStep = None

Check warning on line 444 in press/press/doctype/physical_backup_restoration/physical_backup_restoration.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/physical_backup_restoration/physical_backup_restoration.py#L444

Added line #L444 was not covered by tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"wait_for_completion",
"is_async",
"attempts",
"is_cleanup_step",
"section_break_vyao",
"traceback"
],
Expand Down Expand Up @@ -90,12 +91,18 @@
"fieldname": "is_async",
"fieldtype": "Check",
"label": "Is Async"
},
{
"default": "0",
"fieldname": "is_cleanup_step",
"fieldtype": "Check",
"label": "Is Cleanup Step"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2025-01-20 15:38:21.354247",
"modified": "2025-01-20 16:48:34.338658",
"modified_by": "Administrator",
"module": "Press",
"name": "Physical Backup Restoration Step",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class PhysicalBackupRestorationStep(Document):
duration: DF.Duration | None
end: DF.Datetime | None
is_async: DF.Check
is_cleanup_step: DF.Check
method: DF.Data
parent: DF.Data
parentfield: DF.Data
Expand Down

0 comments on commit e26c7f4

Please sign in to comment.