From 83a3c99438aaf9509f3aea27a696a0ff408813dd Mon Sep 17 00:00:00 2001 From: tomerlf1 Date: Mon, 29 May 2023 17:01:23 +0300 Subject: [PATCH 1/2] Created argument --skip-snapshot and added relevent funcs in Instance class --- gce_rescue/bin/rescue.py | 5 +++-- gce_rescue/config.py | 5 ++++- gce_rescue/gce.py | 11 +++++++++-- gce_rescue/messages.py | 9 +++++++-- gce_rescue/tasks/actions.py | 17 ++++++++++++++--- gce_rescue/tasks/backup.py | 5 ----- gce_rescue/tasks/backup_test.py | 2 +- gce_rescue/tasks/disks.py | 22 +++++++++++++++++++--- gce_rescue/tasks/disks_test.py | 2 +- 9 files changed, 58 insertions(+), 20 deletions(-) diff --git a/gce_rescue/bin/rescue.py b/gce_rescue/bin/rescue.py index 0535b6b..bce2ef9 100755 --- a/gce_rescue/bin/rescue.py +++ b/gce_rescue/bin/rescue.py @@ -68,11 +68,12 @@ def main(): print('Restoring VM...') action = 'reset_rescue_mode' - msg = messages.tip_restore_disk(vm) + has_snapshot = vm.snapshot + msg = messages.tip_restore_disk(vm, snapshot=has_snapshot) call_tasks(vm=vm, action=action) print(msg) if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/gce_rescue/config.py b/gce_rescue/config.py index aa8ac82..7b32788 100644 --- a/gce_rescue/config.py +++ b/gce_rescue/config.py @@ -24,6 +24,7 @@ config = { 'version': VERSION, 'debug': False, + 'skip-snapshot': False, 'startup-script-file': os.path.join(dirname, 'startup-script.txt'), 'source_guests': { 'x86_64':[ @@ -56,9 +57,11 @@ def process_args(): help='Print to the log file in debug leve') parser.add_argument('-f', '--force', action='store_true', help='Don\'t ask for confirmation.') - + parser.add_argument('-s', '--skip-snapshot', action='store_true', + help='Skip backing up the disk using a snapshot.') return parser def set_configs(user_args): config['debug'] = getattr(user_args, 'debug') + config['skip-snapshot'] = getattr(user_args, 'skip_snapshot') \ No newline at end of file diff --git a/gce_rescue/gce.py b/gce_rescue/gce.py index bf43b56..0884a1a 100644 --- a/gce_rescue/gce.py +++ b/gce_rescue/gce.py @@ -20,7 +20,7 @@ from typing import Dict, List, Union from time import time from gce_rescue.tasks.backup import backup_metadata_items -from gce_rescue.tasks.disks import list_disk +from gce_rescue.tasks.disks import list_disk, list_snapshot from gce_rescue.tasks.pre_validations import Validations from gce_rescue.config import get_config @@ -70,7 +70,7 @@ def validate_instance_mode(data: Dict) -> Dict: 'rescue-mode': False, 'ts': generate_ts() } - if 'metadata' in data and 'items' in data['metadata']: + if 'metadata' in data and 'items' in data['metadata']: metadata = data['metadata'] for item in metadata['items']: if item['key'] == 'rescue-mode': @@ -216,3 +216,10 @@ def backup_items(self, v: List[str]) -> None: @property def disks(self) -> List[str]: return self._disks + + @property + def snapshot(self) -> str: + if not self.rescue_mode_status['rescue-mode']: + return f"{self.disks['disk_name']}-{self.ts}" + return list_snapshot(self) + diff --git a/gce_rescue/messages.py b/gce_rescue/messages.py index c46a33d..02a5f13 100644 --- a/gce_rescue/messages.py +++ b/gce_rescue/messages.py @@ -26,9 +26,14 @@ def tip_connect_ssh(vm: Instance) -> str: f'{vm.zone}/instances/{vm.name}?authuser=0&hl=en_US&useAdminProxy=true&' f'troubleshoot4005Enabled=true\n') -def tip_restore_disk(vm: Instance) -> str: - return (f'└── The instance {vm.name} was restored! Use the snapshot below ' +def tip_restore_disk(vm: Instance, snapshot=False) -> str: + if not snapshot: + snapshot_restore_msg = '' + else: + snapshot_restore_msg = (f' Use the snapshot below ' f'if you need to restore the modification made while the instance was ' f'in rescue mode.\n Snapshot name: {vm.disks["disk_name"]}-{vm.ts}\n' f' More information: ' f'https://cloud.google.com/compute/docs/disks/restore-snapshot\n') + + return (f'└── The instance {vm.name} was restored!' + snapshot_restore_msg) diff --git a/gce_rescue/tasks/actions.py b/gce_rescue/tasks/actions.py index 610a78c..a4c18cd 100644 --- a/gce_rescue/tasks/actions.py +++ b/gce_rescue/tasks/actions.py @@ -19,7 +19,8 @@ from gce_rescue.gce import Instance from gce_rescue.tasks.disks import ( - config_rescue_disks, + take_snapshot, + create_rescue_disk, restore_original_disk, attach_disk ) @@ -32,7 +33,7 @@ restore_metadata_items ) from gce_rescue.utils import Tracker - +from gce_rescue.config import get_config _logger = logging.getLogger(__name__) def _list_tasks(vm: Instance, action: str) -> List: @@ -50,7 +51,13 @@ def _list_tasks(vm: Instance, action: str) -> List: }] }, { - 'name': config_rescue_disks, + 'name': take_snapshot, + 'args': [{ + 'vm': vm + }] + }, + { + 'name': create_rescue_disk, 'args': [{ 'vm': vm }] @@ -126,6 +133,10 @@ def call_tasks(vm: Instance, action: str) -> None: tracker.start() for task in tasks: + if task['name'].__name__ == "take_snapshot": + if get_config('skip-snapshot'): + _logger.info(f'Skipping snapshot backup.') + continue execute = task['name'] args = task['args'][0] diff --git a/gce_rescue/tasks/backup.py b/gce_rescue/tasks/backup.py index e08ee23..a69db90 100644 --- a/gce_rescue/tasks/backup.py +++ b/gce_rescue/tasks/backup.py @@ -51,8 +51,3 @@ def _create_snapshot(vm) -> Dict: result = wait_for_operation(vm, oper=operation) return result -def backup(vm) -> None: - """ - List of methods to backup data and information from the orignal instance - """ - _create_snapshot(vm) diff --git a/gce_rescue/tasks/backup_test.py b/gce_rescue/tasks/backup_test.py index 8f886d8..1ec6626 100644 --- a/gce_rescue/tasks/backup_test.py +++ b/gce_rescue/tasks/backup_test.py @@ -39,7 +39,7 @@ def test_backup_metadata_items(self): def test_backup(self): """Test backup task.""" - backup.backup(self.vm) + backup._create_snapshot(self.vm) if __name__ == '__main__': diff --git a/gce_rescue/tasks/disks.py b/gce_rescue/tasks/disks.py index bc19a84..0bcaa2c 100644 --- a/gce_rescue/tasks/disks.py +++ b/gce_rescue/tasks/disks.py @@ -20,8 +20,9 @@ import googleapiclient.errors from gce_rescue.tasks.keeper import wait_for_operation -from gce_rescue.tasks.backup import backup +from gce_rescue.tasks.backup import _create_snapshot from gce_rescue.utils import ThreadHandler as Handler +from googleapiclient.errors import HttpError _logger = logging.getLogger(__name__) @@ -177,9 +178,12 @@ def _detach_disk(vm, disk: str) -> Dict: return result -def config_rescue_disks(vm) -> None: +def take_snapshot(vm) -> None: + _create_snapshot(vm) + + +def create_rescue_disk(vm) -> None: device_name = vm.disks['device_name'] - backup(vm) # task1 = multitasks.Handler( # target = backup, # kwargs={'vm' : vm} @@ -199,6 +203,18 @@ def config_rescue_disks(vm) -> None: boot=True ) +def list_snapshot(vm) -> str: + lookup_filter = f"{vm.disks['disk_name']}-{vm.ts}" + try: + result = vm.compute.snapshots().get( + snapshot=lookup_filter, + project=vm.project + ).execute() + except HttpError as e: + _logger.info('Snapshot was not found for VM in active rescue mode') + return '' + return 'ok' + def restore_original_disk(vm) -> None: """ Restore tasks to the original disk """ device_name = vm.disks['device_name'] diff --git a/gce_rescue/tasks/disks_test.py b/gce_rescue/tasks/disks_test.py index 940e7a4..568b3e6 100644 --- a/gce_rescue/tasks/disks_test.py +++ b/gce_rescue/tasks/disks_test.py @@ -73,7 +73,7 @@ def test_config_rescue_disks(self): 'operations', 'disks', ]) - disks.config_rescue_disks(self.vm) + disks.create_rescue_disk(self.vm) def test_restore_original_disk(self): From d73f8c4e7dccd7c7403283e9cdba47dc7e7bcad4 Mon Sep 17 00:00:00 2001 From: tomerlf1 Date: Mon, 29 May 2023 17:01:23 +0300 Subject: [PATCH 2/2] Created argument --skip-snapshot and added relevent funcs in Instance class --- gce_rescue/bin/rescue.py | 5 +++-- gce_rescue/config.py | 5 ++++- gce_rescue/gce.py | 11 +++++++++-- gce_rescue/messages.py | 9 +++++++-- gce_rescue/tasks/actions.py | 17 ++++++++++++++--- gce_rescue/tasks/backup.py | 5 ----- gce_rescue/tasks/backup_test.py | 2 +- gce_rescue/tasks/disks.py | 22 +++++++++++++++++++--- gce_rescue/tasks/disks_test.py | 2 +- 9 files changed, 58 insertions(+), 20 deletions(-) diff --git a/gce_rescue/bin/rescue.py b/gce_rescue/bin/rescue.py index 0535b6b..bce2ef9 100755 --- a/gce_rescue/bin/rescue.py +++ b/gce_rescue/bin/rescue.py @@ -68,11 +68,12 @@ def main(): print('Restoring VM...') action = 'reset_rescue_mode' - msg = messages.tip_restore_disk(vm) + has_snapshot = vm.snapshot + msg = messages.tip_restore_disk(vm, snapshot=has_snapshot) call_tasks(vm=vm, action=action) print(msg) if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/gce_rescue/config.py b/gce_rescue/config.py index aa8ac82..7b32788 100644 --- a/gce_rescue/config.py +++ b/gce_rescue/config.py @@ -24,6 +24,7 @@ config = { 'version': VERSION, 'debug': False, + 'skip-snapshot': False, 'startup-script-file': os.path.join(dirname, 'startup-script.txt'), 'source_guests': { 'x86_64':[ @@ -56,9 +57,11 @@ def process_args(): help='Print to the log file in debug leve') parser.add_argument('-f', '--force', action='store_true', help='Don\'t ask for confirmation.') - + parser.add_argument('-s', '--skip-snapshot', action='store_true', + help='Skip backing up the disk using a snapshot.') return parser def set_configs(user_args): config['debug'] = getattr(user_args, 'debug') + config['skip-snapshot'] = getattr(user_args, 'skip_snapshot') \ No newline at end of file diff --git a/gce_rescue/gce.py b/gce_rescue/gce.py index bf43b56..0884a1a 100644 --- a/gce_rescue/gce.py +++ b/gce_rescue/gce.py @@ -20,7 +20,7 @@ from typing import Dict, List, Union from time import time from gce_rescue.tasks.backup import backup_metadata_items -from gce_rescue.tasks.disks import list_disk +from gce_rescue.tasks.disks import list_disk, list_snapshot from gce_rescue.tasks.pre_validations import Validations from gce_rescue.config import get_config @@ -70,7 +70,7 @@ def validate_instance_mode(data: Dict) -> Dict: 'rescue-mode': False, 'ts': generate_ts() } - if 'metadata' in data and 'items' in data['metadata']: + if 'metadata' in data and 'items' in data['metadata']: metadata = data['metadata'] for item in metadata['items']: if item['key'] == 'rescue-mode': @@ -216,3 +216,10 @@ def backup_items(self, v: List[str]) -> None: @property def disks(self) -> List[str]: return self._disks + + @property + def snapshot(self) -> str: + if not self.rescue_mode_status['rescue-mode']: + return f"{self.disks['disk_name']}-{self.ts}" + return list_snapshot(self) + diff --git a/gce_rescue/messages.py b/gce_rescue/messages.py index c46a33d..26d070a 100644 --- a/gce_rescue/messages.py +++ b/gce_rescue/messages.py @@ -26,9 +26,14 @@ def tip_connect_ssh(vm: Instance) -> str: f'{vm.zone}/instances/{vm.name}?authuser=0&hl=en_US&useAdminProxy=true&' f'troubleshoot4005Enabled=true\n') -def tip_restore_disk(vm: Instance) -> str: - return (f'└── The instance {vm.name} was restored! Use the snapshot below ' +def tip_restore_disk(vm: Instance, snapshot=False) -> str: + if not snapshot: + snapshot_restore_msg = '' + else: + snapshot_restore_msg = (f' Use the snapshot below ' f'if you need to restore the modification made while the instance was ' f'in rescue mode.\n Snapshot name: {vm.disks["disk_name"]}-{vm.ts}\n' f' More information: ' f'https://cloud.google.com/compute/docs/disks/restore-snapshot\n') + + return f'└── The instance {vm.name} was restored!' + snapshot_restore_msg diff --git a/gce_rescue/tasks/actions.py b/gce_rescue/tasks/actions.py index 610a78c..1caf8a1 100644 --- a/gce_rescue/tasks/actions.py +++ b/gce_rescue/tasks/actions.py @@ -19,7 +19,8 @@ from gce_rescue.gce import Instance from gce_rescue.tasks.disks import ( - config_rescue_disks, + take_snapshot, + create_rescue_disk, restore_original_disk, attach_disk ) @@ -32,7 +33,7 @@ restore_metadata_items ) from gce_rescue.utils import Tracker - +from gce_rescue.config import get_config _logger = logging.getLogger(__name__) def _list_tasks(vm: Instance, action: str) -> List: @@ -50,7 +51,13 @@ def _list_tasks(vm: Instance, action: str) -> List: }] }, { - 'name': config_rescue_disks, + 'name': take_snapshot, + 'args': [{ + 'vm': vm + }] + }, + { + 'name': create_rescue_disk, 'args': [{ 'vm': vm }] @@ -126,6 +133,10 @@ def call_tasks(vm: Instance, action: str) -> None: tracker.start() for task in tasks: + if task['name'].__name__ == 'take_snapshot': + if get_config('skip-snapshot'): + _logger.info(f'Skipping snapshot backup.') + continue execute = task['name'] args = task['args'][0] diff --git a/gce_rescue/tasks/backup.py b/gce_rescue/tasks/backup.py index e08ee23..a69db90 100644 --- a/gce_rescue/tasks/backup.py +++ b/gce_rescue/tasks/backup.py @@ -51,8 +51,3 @@ def _create_snapshot(vm) -> Dict: result = wait_for_operation(vm, oper=operation) return result -def backup(vm) -> None: - """ - List of methods to backup data and information from the orignal instance - """ - _create_snapshot(vm) diff --git a/gce_rescue/tasks/backup_test.py b/gce_rescue/tasks/backup_test.py index 8f886d8..1ec6626 100644 --- a/gce_rescue/tasks/backup_test.py +++ b/gce_rescue/tasks/backup_test.py @@ -39,7 +39,7 @@ def test_backup_metadata_items(self): def test_backup(self): """Test backup task.""" - backup.backup(self.vm) + backup._create_snapshot(self.vm) if __name__ == '__main__': diff --git a/gce_rescue/tasks/disks.py b/gce_rescue/tasks/disks.py index bc19a84..0bcaa2c 100644 --- a/gce_rescue/tasks/disks.py +++ b/gce_rescue/tasks/disks.py @@ -20,8 +20,9 @@ import googleapiclient.errors from gce_rescue.tasks.keeper import wait_for_operation -from gce_rescue.tasks.backup import backup +from gce_rescue.tasks.backup import _create_snapshot from gce_rescue.utils import ThreadHandler as Handler +from googleapiclient.errors import HttpError _logger = logging.getLogger(__name__) @@ -177,9 +178,12 @@ def _detach_disk(vm, disk: str) -> Dict: return result -def config_rescue_disks(vm) -> None: +def take_snapshot(vm) -> None: + _create_snapshot(vm) + + +def create_rescue_disk(vm) -> None: device_name = vm.disks['device_name'] - backup(vm) # task1 = multitasks.Handler( # target = backup, # kwargs={'vm' : vm} @@ -199,6 +203,18 @@ def config_rescue_disks(vm) -> None: boot=True ) +def list_snapshot(vm) -> str: + lookup_filter = f"{vm.disks['disk_name']}-{vm.ts}" + try: + result = vm.compute.snapshots().get( + snapshot=lookup_filter, + project=vm.project + ).execute() + except HttpError as e: + _logger.info('Snapshot was not found for VM in active rescue mode') + return '' + return 'ok' + def restore_original_disk(vm) -> None: """ Restore tasks to the original disk """ device_name = vm.disks['device_name'] diff --git a/gce_rescue/tasks/disks_test.py b/gce_rescue/tasks/disks_test.py index 940e7a4..568b3e6 100644 --- a/gce_rescue/tasks/disks_test.py +++ b/gce_rescue/tasks/disks_test.py @@ -73,7 +73,7 @@ def test_config_rescue_disks(self): 'operations', 'disks', ]) - disks.config_rescue_disks(self.vm) + disks.create_rescue_disk(self.vm) def test_restore_original_disk(self):