def testDestroyExpiredZFSSnapshots_errorCaseIsFalse_destroysSnapshots( self, mock_find_snapshots_older_than, mock_get_current_datetime): FLAGS.ssh_path = '/fake/ssh' FLAGS.ssh_port = 1234 FLAGS.remote_user = '******' mock_find_snapshots_older_than.return_value = [ 'zfs/homedirs@fake-prefix-2014-01-05--0630', 'zfs/homedirs@fake-prefix-2014-01-06--0648' ] mock_get_current_datetime.return_value = datetime.datetime(2014, 4, 1) mock_command_runner = test_lib.GetMockCommandRunner() backup = zfs.ZFSLVMBackup(label='unused_label', source_hostname='unused', rsync_dst='unused_dst_host:/unused_dst', zfs_hostname='fake_zfs_host', dataset_name='unused_pool/unused_dataset', snapshot_expiration_days=30, settings_path=None, command_runner=mock_command_runner) expected_call1 = mock.call([ '/fake/ssh', '-p', '1234', 'fake_user@fake_zfs_host', 'zfs', 'destroy', 'zfs/homedirs@fake-prefix-2014-01-05--0630' ], False) expected_call2 = mock.call([ '/fake/ssh', '-p', '1234', 'fake_user@fake_zfs_host', 'zfs', 'destroy', 'zfs/homedirs@fake-prefix-2014-01-06--0648' ], False) backup._destroy_expired_zfs_snapshots(30, error_case=False) self.assertEqual(mock_command_runner.run.mock_calls, [expected_call1, expected_call2])
def testCreateSnapshots_multipleSnapshots_createsSnapshots(self): FLAGS.snapshot_suffix = '-fake_backup' mock_command_runner = test_lib.GetMockCommandRunner() # Note that setting source_hostname to 'localhost' prevents the command # that is run from being prefixed with an ssh command. backup = FakeBackup(source_hostname='localhost', label='unused', settings_path=None, command_runner=mock_command_runner) expected_call_fakevolume1 = mock.call([ 'lvcreate', '-s', '-L', '1G', 'fake_volume_group/fake_volume1', '-n', 'fake_volume1-fake_backup' ], False) expected_call_fakevolume2 = mock.call([ 'lvcreate', '-s', '-L', '1G', 'fake_volume_group/fake_volume2', '-n', 'fake_volume2-fake_backup' ], False) backup.add_volume('fake_volume_group/fake_volume1', '/etc') backup.add_volume('fake_volume_group/fake_volume2', '/var') backup.run() mock_command_runner.run.assert_has_calls( [expected_call_fakevolume1, expected_call_fakevolume2], any_order=True)
def testFindSnapshotsOlderThan_returnsOnlySnapshotsOlderThanX( self, mock_get_snapshot_creation_time, mock_get_current_datetime): FLAGS.zfs_snapshot_prefix = 'fake-prefix-' FLAGS.zfs_snapshot_timestamp_format = '%Y-%m-%d--%H%M' mock_get_snapshot_creation_time.side_effect = ([ datetime.datetime(2014, 1, 5), datetime.datetime(2014, 3, 6) ]) mock_get_current_datetime.return_value = datetime.datetime(2014, 4, 1) fake_stdout = ('zfs/homedirs\tfilesystem\n' 'zfs/homedirs@fake-prefix-2014-01-05--0630\tsnapshot\n' 'zfs/homedirs@fake-prefix-2014-03-06--0648\tsnapshot\n') mock_command_runner = test_lib.GetMockCommandRunner() mock_command_runner.run.return_value = (fake_stdout, str(), 0) backup = zfs.ZFSLVMBackup(label='unused_label', source_hostname='unused', rsync_dst='unused_dst_host:/unused_dst', zfs_hostname='unused_zfs_host', dataset_name='unused_pool/unused_dataset', snapshot_expiration_days=30, settings_path=None, command_runner=mock_command_runner) snapshots = backup._find_snapshots_older_than(30) self.assertEqual(snapshots, ['zfs/homedirs@fake-prefix-2014-01-05--0630'])
def testCreateSnapshots_multipleSnapshots_addsSnapshotsToTracker(self): FLAGS.snapshot_mount_root = '/fake_root' FLAGS.snapshot_suffix = '-fake_backup' mock_command_runner = test_lib.GetMockCommandRunner() backup = FakeBackup(source_hostname='localhost', label='fake_backup', settings_path=None, command_runner=mock_command_runner) expected_value = [ { 'lv_path': 'fake_volume_group/fake_volume1-fake_backup', 'mount_path': '/fake_root/fake_backup/etc', 'mount_options': None, 'created': True, 'mount_point_created': False, 'mounted': False, }, { 'lv_path': 'fake_volume_group/fake_volume2-fake_backup', 'mount_path': '/fake_root/fake_backup/var', 'mount_options': None, 'created': True, 'mount_point_created': False, 'mounted': False, }, ] backup.add_volume('fake_volume_group/fake_volume1', '/etc') backup.add_volume('fake_volume_group/fake_volume2', '/var') backup._create_snapshots() self.assertListEqual(expected_value, backup._lv_snapshots)
def testMountSnapshots_withoutMountOptions_mountsWithoutMountOptions(self): FLAGS.snapshot_mount_root = '/fake_root' FLAGS.snapshot_suffix = '-fake_backup' mock_command_runner = test_lib.GetMockCommandRunner() # Note that setting source_hostname to 'localhost' prevents the command # that is run from being prefixed with an ssh command. backup = FakeBackup(source_hostname='localhost', label='fake_backup', settings_path=None, command_runner=mock_command_runner) expected_call_fakevolume1 = mock.call([ 'mount', '/dev/fake_volume_group/fake_volume1-fake_backup', '/fake_root/fake_backup/etc' ], False) expected_call_fakevolume2 = mock.call([ 'mount', '/dev/fake_volume_group/fake_volume2-fake_backup', '/fake_root/fake_backup/var' ], False) backup.add_volume('fake_volume_group/fake_volume1', '/etc') backup.add_volume('fake_volume_group/fake_volume2', '/var') backup.run() mock_command_runner.AssertCallsInOrder( [expected_call_fakevolume1, expected_call_fakevolume2])
def testWorkflowRunsInCorrectOrder(self, mock_create_snapshots, mock_mount_snapshots, mock_umount_snapshots, mock_delete_snapshots, mock_run_custom_workflow): mock_command_runner = test_lib.GetMockCommandRunner() backup = FakeBackup(source_hostname='unused', label='unused', settings_path=None, command_runner=mock_command_runner) # Attach mocks to manager mock so we can track their call order. manager_mock = mock.MagicMock() manager_mock.attach_mock(mock_create_snapshots, '_create_snapshots') manager_mock.attach_mock(mock_mount_snapshots, '_mount_snapshots') manager_mock.attach_mock(mock_umount_snapshots, '_umount_snapshots') manager_mock.attach_mock(mock_delete_snapshots, '_delete_snapshots') manager_mock.attach_mock(mock_run_custom_workflow, '_run_custom_workflow') # Create mock.call objects and defined their expected call order. create_snapshots_call = mock.call._create_snapshots() mount_snapshots_call = mock.call._mount_snapshots() umount_snapshots_call = mock.call._umount_snapshots(error_case=False) delete_snapshots_call = mock.call._delete_snapshots(error_case=False) run_custom_workflow_call = mock.call._run_custom_workflow() expected_calls = [ create_snapshots_call, mount_snapshots_call, run_custom_workflow_call, umount_snapshots_call, delete_snapshots_call ] backup.add_volume('fake_volume_group/fake_volume1', '/unused') backup.run() test_lib.AssertCallsInOrder(manager_mock, expected_calls)
def testCreateZFSSnapshot_errorCaseIsFalse_createsSnapshot( self, mock_get_current_datetime): FLAGS.zfs_snapshot_timestamp_format = '%Y-%m-%d--%H%M' FLAGS.zfs_snapshot_prefix = 'fake-prefix-' FLAGS.remote_user = '******' FLAGS.ssh_path = '/fake/ssh' FLAGS.ssh_port = 1234 mock_get_current_datetime.return_value = datetime.datetime( 2015, 1, 2, 3, 4) mock_command_runner = test_lib.GetMockCommandRunner() # Note that setting source_hostname to 'localhost' prevents the command # that is run from being prefixed with an ssh command. backup = zfs.ZFSLVMBackup(label='unused_label', source_hostname='localhost', rsync_dst='unused_dst_host:/unused_dst', zfs_hostname='fake_zfs_host', dataset_name='fake_pool/fake_dataset', snapshot_expiration_days=30, settings_path=None, command_runner=mock_command_runner) backup._create_zfs_snapshot(error_case=False) mock_command_runner.run.assert_called_once_with([ '/fake/ssh', '-p', '1234', 'fake_user@fake_zfs_host', 'zfs', 'snapshot', 'fake_pool/fake_dataset@fake-prefix-2015-01-02--0304' ], False)
def testRunCommand_commandIsNotStringOrList_raisesException(self): mock_command_runner = test_lib.GetMockCommandRunner() test_workflow = workflow.BaseWorkflow( label='unused', settings_path=None, command_runner=mock_command_runner) with self.assertRaises(TypeError): test_workflow.run_command(None)
def testRunCommand_commandHasNonZeroExitCode_rasiesException(self): mock_command_runner = test_lib.GetMockCommandRunner() # Return empty strings for stdout and stderr and 1 for the exit code. mock_command_runner.run.return_value = (str(), str(), 1) test_workflow = workflow.BaseWorkflow( label='unused', settings_path=None, command_runner=mock_command_runner) with self.assertRaises(workflow.NonZeroExitCode): test_workflow.run_command('test_command')
def testRunCommand_commandIsList_commandIsRunWithoutShell(self): mock_command_runner = test_lib.GetMockCommandRunner() test_workflow = workflow.BaseWorkflow( label='unused', settings_path=None, command_runner=mock_command_runner) test_workflow.run_command( ['test_command', '--test_flag', 'test_arg'], host='localhost') mock_command_runner.run.assert_called_once_with( ['test_command', '--test_flag', 'test_arg'], False)
def testRunCommand_commandIsString_commandIsRunInShell(self): mock_command_runner = test_lib.GetMockCommandRunner() test_workflow = workflow.BaseWorkflow( label='unused', settings_path=None, command_runner=mock_command_runner) test_workflow.run_command( 'test_command --test_flag test_arg', host='localhost') mock_command_runner.run.assert_called_once_with( 'test_command --test_flag test_arg', True)
def testMountSnapshots_mountPointAlreadyExists_backupFails( self, mock_ismount): mock_ismount.return_value = True mock_command_runner = test_lib.GetMockCommandRunner() backup = FakeBackup(source_hostname='unused', label='unused', settings_path=None, command_runner=mock_command_runner) backup.add_volume('fake_volume_group/fake_volume1', '/unused') self.assertFalse(backup.run())
def testRemoveOlderThan_errorCaseIsTrue_doesNotTrimBackups(self): mock_command_runner = test_lib.GetMockCommandRunner() backup = rdiff_backup_wrapper.RdiffBackup( label='unused', source_hostname='unused', settings_path=None, command_runner=mock_command_runner) backup._remove_older_than('60D', error_case=True) self.assertFalse(mock_command_runner.run.called)
def testDeleteSnapshots_multipleSnapshots_marksSnapshotsAsDeleted(self): mock_command_runner = test_lib.GetMockCommandRunner() backup = FakeBackup(source_hostname='unused', label='unused', settings_path=None, command_runner=mock_command_runner) backup.add_volume('fake_volume_group/fake_volume1', '/unused1') backup.add_volume('fake_volume_group/fake_volume2', '/unused2') backup.run() self.assertFalse(backup._lv_snapshots[0]['created']) self.assertFalse(backup._lv_snapshots[1]['created'])
def testRunCustomWorkflow_updatesTopLevelSrcDir2SnapshotMountPointBasePath( self): FLAGS.snapshot_mount_root = '/fake_root' mock_command_runner = test_lib.GetMockCommandRunner() backup = lvm.RdiffLVMBackup(source_hostname='unused', label='fake_backup', settings_path=None, command_runner=mock_command_runner) backup.run() self.assertEqual(backup.top_level_src_dir, '/fake_root/fake_backup')
def testRunCommand_returnsStdoutAndStdErr(self): mock_command_runner = test_lib.GetMockCommandRunner() # Return fake strings for stdout and stderr and 0 for the exit code. mock_command_runner.run.return_value = ('fake_stdout', 'fake_stderr', 0) test_workflow = workflow.BaseWorkflow( label='unused', settings_path=None, command_runner=mock_command_runner) stdout, stderr = test_workflow.run_command('test_command') self.assertEqual(stdout, 'fake_stdout') self.assertEqual(stderr, 'fake_stderr')
def testRunCommandWithRetries_firstTrySucceeds_commandNotRetried( self, unused_mock_sleep): mock_command_runner = test_lib.GetMockCommandRunner() # Return empty strings for stdout and stderr and 0 (success) for the # exit code. mock_command_runner.run.return_value = (str(), str(), 0) test_workflow = workflow.BaseWorkflow( label='unused', settings_path=None, command_runner=mock_command_runner) test_workflow.run_command_with_retries('test_command') self.assertEqual(mock_command_runner.run.call_count, 1)
def testRunCustomWorkflow_prefixesIncludeDirs(self): FLAGS.snapshot_mount_root = '/fake_root' mock_command_runner = test_lib.GetMockCommandRunner() backup = lvm.RdiffLVMBackup(source_hostname='unused', label='fake_backup', settings_path=None, command_runner=mock_command_runner) backup.add_volume('fake_volume_group/fake_volume', '/var') backup.include('/var') backup.run() self.assertEqual(backup._includes, ['/fake_root/fake_backup/var'])
def testDestroyExpiredZFSSnapshots_errorCaseIsTrue_doesNothing(self): mock_command_runner = test_lib.GetMockCommandRunner() backup = zfs.ZFSLVMBackup(label='unused_label', source_hostname='unused', rsync_dst='unused_dst_host:/unused_dst', zfs_hostname='unused_zfs_host', dataset_name='unused_pool/unused_dataset', snapshot_expiration_days=30, settings_path=None, command_runner=mock_command_runner) backup._destroy_expired_zfs_snapshots(30, error_case=True) self.assertFalse(mock_command_runner.run.called)
def testMountSnapshots_multipleSnapshots_marksMountPointAsCreated(self): mock_command_runner = test_lib.GetMockCommandRunner() backup = FakeBackup(source_hostname='unused', label='unused', settings_path=None, command_runner=mock_command_runner) backup.add_volume('fake_volume_group/fake_volume1', '/unused1') backup.add_volume('fake_volume_group/fake_volume2', '/unused2') backup._create_snapshots() backup._mount_snapshots() self.assertTrue(backup._lv_snapshots[0]['mount_point_created']) self.assertTrue(backup._lv_snapshots[1]['mount_point_created'])
def testRunCommandWithRetries_maxRetriesReached_raisesException( self, unused_mock_sleep): FLAGS.max_retries = 1 mock_command_runner = test_lib.GetMockCommandRunner() return1 = (str(), str(), 1) # command failed return2 = (str(), str(), 1) # command failed return3 = (str(), str(), 0) # command succeeded mock_command_runner.run.side_effect = [return1, return2, return3] test_workflow = workflow.BaseWorkflow( label='unused', settings_path=None, command_runner=mock_command_runner) with self.assertRaises(workflow.NonZeroExitCode): test_workflow.run_command_with_retries('test_command')
def testRunCommandWithRetries_firstTryFails_commandRetried( self, unused_mock_sleep): FLAGS.max_retries = 1 mock_command_runner = test_lib.GetMockCommandRunner() return1 = (str(), str(), 1) # command failed return2 = (str(), str(), 0) # command succeeded mock_command_runner.run.side_effect = [return1, return2] test_workflow = workflow.BaseWorkflow( label='unused', settings_path=None, command_runner=mock_command_runner) test_workflow.run_command_with_retries('test_command') self.assertEqual(mock_command_runner.run.call_count, 2)
def testRemoveOlderThan_timespecIsNone_backupsNotTrimmed( self, mock_remove_older_than): FLAGS.remove_older_than_timespec = None mock_command_runner = test_lib.GetMockCommandRunner() backup = rdiff_backup_wrapper.RdiffBackup( remove_older_than_timespec=None, label='unused', source_hostname='unused', settings_path=None, command_runner=mock_command_runner) backup.include('/unused') backup.run() self.assertFalse(mock_remove_older_than.called)
def testRunCommand_hostIsNotLocalhost_sshArgumentsAdded(self): FLAGS.remote_user = '******' FLAGS.ssh_path = '/fake/ssh' FLAGS.ssh_port = 1234 mock_command_runner = test_lib.GetMockCommandRunner() test_workflow = workflow.BaseWorkflow( label='unused', settings_path=None, command_runner=mock_command_runner) test_workflow.run_command( 'test_command --test_flag test_arg', host='fake_host') mock_command_runner.run.assert_called_once_with( ['/fake/ssh', '-p', '1234', 'test_user@fake_host', 'test_command', '--test_flag', 'test_arg'], False)
def testRunCommandWithRetries_firstTryFails_sleepsBetweenRetries( self, mock_sleep): FLAGS.max_retries = 1 FLAGS.retry_interval = 7 mock_command_runner = test_lib.GetMockCommandRunner() return1 = (str(), str(), 1) # command failed return2 = (str(), str(), 0) # command succeeded mock_command_runner.run.side_effect = [return1, return2] test_workflow = workflow.BaseWorkflow( label='unused', settings_path=None, command_runner=mock_command_runner) test_workflow.run_command_with_retries('test_command') mock_sleep.assert_called_once_with(7)
def testRemoveOlderThan_errorCaseIsFalse_trimsBackups(self): FLAGS.rdiff_backup_path = '/fake/rdiff-backup' FLAGS.backup_store_path = '/fake/backup-store' mock_command_runner = test_lib.GetMockCommandRunner() backup = rdiff_backup_wrapper.RdiffBackup( label='fake_backup', source_hostname='unused', settings_path=None, command_runner=mock_command_runner) backup._remove_older_than('60D', error_case=False) mock_command_runner.run.assert_called_once_with([ '/fake/rdiff-backup', '--force', '--remove-older-than', '60D', '/fake/backup-store/fake_backup' ], False)
def testRemoveOlderThan_timespecArgIsNone_timespecFlagUsed( self, mock_remove_older_than): FLAGS.remove_older_than_timespec = '13D' mock_command_runner = test_lib.GetMockCommandRunner() backup = rdiff_backup_wrapper.RdiffBackup( remove_older_than_timespec=None, label='unused', source_hostname='unused', settings_path=None, command_runner=mock_command_runner) backup.include('/unused') backup.run() mock_remove_older_than.assert_called_once_with(timespec='13D', error_case=False)
def testRunCustomWorkflow_sourceHostnameIsLocalhost_sourceIsPath(self): FLAGS.rdiff_backup_path = '/fake/rdiff-backup' FLAGS.backup_store_path = '/fake/backup-store' FLAGS.top_level_src_dir = '/' mock_command_runner = test_lib.GetMockCommandRunner() backup = rdiff_backup_wrapper.RdiffBackup( label='fake_backup', source_hostname='localhost', settings_path=None, command_runner=mock_command_runner) backup.include('/fake_dir') backup.run() mock_command_runner.run.assert_called_once_with([ '/fake/rdiff-backup', '--include', '/fake_dir', '--exclude', '**', '/', '/fake/backup-store/fake_backup' ], False)
def testRemoveOlderThan_timespecIsNotNone_backupsTrimmed(self): FLAGS.rdiff_backup_path = '/fake/rdiff-backup' FLAGS.backup_store_path = '/fake/backup-store' mock_command_runner = test_lib.GetMockCommandRunner() backup = rdiff_backup_wrapper.RdiffBackup( remove_older_than_timespec='60D', label='fake_backup', source_hostname='unused', settings_path=None, command_runner=mock_command_runner) backup.include('/unused') backup.run() mock_command_runner.run.assert_called_with([ '/fake/rdiff-backup', '--force', '--remove-older-than', '60D', '/fake/backup-store/fake_backup' ], False)
def testGetSnapshotCreationTime_parsesCreationTime(self): mock_command_runner = test_lib.GetMockCommandRunner() mock_command_runner.run.return_value = ('Sat Jan 3 6:48 2015', str(), 0) backup = zfs.ZFSLVMBackup(label='unused_label', source_hostname='unused', rsync_dst='unused_dst_host:/unused_dst', zfs_hostname='fake_zfs_host', dataset_name='unused_pool/unused_dataset', snapshot_expiration_days=30, settings_path=None, command_runner=mock_command_runner) expected_creation_time = datetime.datetime(2015, 1, 3, 6, 48) creation_time = backup._get_snapshot_creation_time( 'unused_pool/unused_snapshot') self.assertEqual(creation_time, expected_creation_time)