def test_download_archive(self): dummy_profile = { u'host_ip': u'10.0.0.20', u'ftp_user': u'dummy', u'ftp_password': u'dummypass', u'backups_archive_dir': u'/mnt/backups/ESXi-archives', u'backup_vms': { u'DummyVM-1': {}, }, } with nested( patch('__builtin__.open', create=True), patch(__name__ + '.backup.FTP', return_value=Mock()), ) as (mock_open, mock_ftp): mock_open.return_value = MagicMock(spec=file) with backup.BackupProfile(dummy_profile) as bp: self.assertIsInstance( bp._download_archive(u'/vmfs/volumes/Backup-LUN/BackupsDir/DummyVM-1/DummyVM-1-2013-12-04_08-03-34.tar.gz'), float) mock_open.assert_called_once_with( os.path.join(u'/mnt/backups/ESXi-archives', u'DummyVM-1-2013-12-04_08-03-34.tar.gz'), 'wb') mock_file = mock_open.return_value.__enter__.return_value mock_ftp.assert_called_once_with(u'10.0.0.20') mock_ftp.return_value.login.assert_called_once_with( u'dummy', u'dummypass') mock_ftp.return_value.retrbinary.assert_called_once_with( u'RETR /vmfs/volumes/Backup-LUN/BackupsDir/DummyVM-1/DummyVM-1-2013-12-04_08-03-34.tar.gz', mock_file.write)
def test_run_remote_backup(self): dummy_profile = { u'ghettovcb_script_template': u'/local/vmware/ghettovcb.sh.tmpl', u'remote_workdir': u'/tmp', u'remote_backup_dir': u'/vmfs/volumes/Backup-LUN/BackupsDir', u'backup_vms': { u'DummyVM-1': {}, }, } with backup.BackupProfile(dummy_profile) as bp: bp._apply_template = Mock(return_value=u'/local/tmp/rndBla') bp._upload_file = Mock() bp._set_remote_chmod = Mock() bp._remove_local_file = Mock() bp._run_ssh_command = Mock(return_value=u'ghettovcb') bp._remove_remote_file = Mock() bp._parse_ghettovcb_output = Mock(return_value={u'OK': u'OK'}) self.assertDictEqual({u'OK': u'OK'}, bp._run_remote_backup(u'DummyVM-1')) bp._apply_template.assert_called_once_with( u'/local/vmware/ghettovcb.sh.tmpl', {u'RemoteBackupDir': u'/vmfs/volumes/Backup-LUN/BackupsDir'} ) bp._upload_file.assert_called_once_with(u'/local/tmp/rndBla', u'/tmp/ghettovcb.sh') bp._set_remote_chmod.assert_called_once_with(u'/tmp/ghettovcb.sh') bp._remove_local_file.assert_called_once_with(u'/local/tmp/rndBla') bp._run_ssh_command.assert_called_once_with( u'/tmp/ghettovcb.sh -m DummyVM-1') bp._parse_ghettovcb_output.assert_called_once_with(u'ghettovcb')
def test_backup_vm(self): dummy_profile = { u'ghettovcb_script_template': u'/local/vmware/ghettovcb.sh.tmpl', u'remote_workdir': u'/tmp', u'remote_backup_dir': u'/vmfs/volumes/Backup-LUN/BackupsDir', u'backups_archive_dir': u'/mnt/backups/ESXi-archives', u'backup_vms': { u'DummyVM-1': {}, }, } with backup.BackupProfile(dummy_profile) as bp: bp._run_remote_backup = Mock(return_value={ u'FINAL_STATUS': True, u'VM_BACKUP_DIR_NAMING_CONVENTION': u'2013-12-04_08-03-34', }) bp._archive_remote_backup = Mock(return_value= u'/vmfs/volumes/Backup-LUN/BackupsDir/DummyVM-1/DummyVM-1-2013-12-04_08-03-34.tar.gz') bp._download_archive = Mock(return_value=1.0) bp._remove_remote_file = Mock() bp.backup_vm(u'DummyVM-1') bp._run_remote_backup.assert_called_once_with(u'DummyVM-1') bp._archive_remote_backup.assert_called_once_with(u'DummyVM-1', u'DummyVM-1-2013-12-04_08-03-34') bp._download_archive.assert_called_once_with( u'/vmfs/volumes/Backup-LUN/BackupsDir/DummyVM-1/DummyVM-1-2013-12-04_08-03-34.tar.gz') bp._remove_remote_file.assert_called_once_with( u'/vmfs/volumes/Backup-LUN/BackupsDir/DummyVM-1/DummyVM-1-2013-12-04_08-03-34.tar.gz')
def test_parse_ghettovcb_output_no_vm(self): dummy_profile = {} with backup.BackupProfile(dummy_profile) as bp: self.assertDictContainsSubset( {u'FINAL_STATUS': False, u'WARNINGS': [],}, bp._parse_ghettovcb_output(ghettovcb_output_no_vm) )
def test_get_next_vm_to_backup_with_new_archives(self): "Check that next VM to backup is as expected when there are only new backups" dummy_profile = { u'backup_vms': { u'DummyVM-1': { u'period': timedelta(7), }, u'DummyVM-2': { u'period': timedelta(7), }, }, } with backup.BackupProfile(dummy_profile) as bp: from datetime import datetime bp._get_current_time = Mock(return_value = datetime(2013,12,11,10,9,8)) bp._list_backup_archives_for_vm = Mock(return_value=[ u'C:\\Backups\\DummyVM-1-2013-12-01_01-23-45.tar.gz', u'C:\\Backups\\DummyVM-2-2013-12-01_01-23-45.tar.gz', ]) bp._list_backup_archives = Mock(return_value=[ u'C:\\Backups\\DummyVM-1-2013-12-08_01-23-45.tar.gz', u'/mnt/backups/DummyVM-2-2013-12-09_23-59-59.tar.gz', ]) self.assertEqual(bp.get_next_vm_to_backup(), None) bp._list_backup_archives_for_vm.assert_has_calls( [call(u'DummyVM-1'), call(u'DummyVM-2')])
def test_remove_remote_file(self): dummy_profile = {} with backup.BackupProfile(dummy_profile) as bp: bp._run_ssh_command = Mock() bp._remove_remote_file(u'/file/to/remove/me.tar.gz') bp._run_ssh_command.assert_called_once_with( u'rm /file/to/remove/me.tar.gz')
def test_get_next_vm_to_backup_with_old_archive(self): "Check that next VM to backup is as expected when the last backup is old" dummy_profile = { u'backup_vms': { u'DummyVM-1': { u'period': timedelta(7), }, }, } with backup.BackupProfile(dummy_profile) as bp: from datetime import datetime bp._get_current_time = Mock(return_value = datetime(2013,12,11,10,9,8)) bp._list_backup_archives_for_vm = Mock(return_value=[ u'C:\\Backups\\DummyVM-1-2013-12-01_01-23-45.tar.gz', ]) bp._list_backup_archives = Mock(return_value=[ u'C:\\Backups\\DummyVM-1-2013-01-01_01-23-45.tar.gz', u'/mnt/backups/DummyVM-2-2013-12-11_23-59-59.tar.gz', ]) self.assertEqual(bp.get_next_vm_to_backup(), u'DummyVM-1') bp._list_backup_archives_for_vm.assert_called_once_with( u'DummyVM-1') backup.logger.warning.assert_called_once_with( u'VM "DummyVM-2" not in profile, but archive found')
def test_get_next_vm_to_backup_no_existing_archives(self): "Check that next VM to backup is as expected when there are no archives" dummy_profile = { u'backup_vms': { u'DummyVM-1': { u'period': timedelta(7), }, }, } with backup.BackupProfile(dummy_profile) as bp: bp._list_backup_archives_for_vm = Mock(return_value=[]) self.assertEqual(bp.get_next_vm_to_backup(), u'DummyVM-1') bp._list_backup_archives_for_vm.assert_called_once_with( u'DummyVM-1')
def test_get_latest_backup_archives(self): "Check that BackupProfile.get_latest_archives behaves correctly" dummy_profile = {} with backup.BackupProfile(dummy_profile) as bp: bp._list_backup_archives = Mock(return_value=[ u'C:\\Backups\\DummyVM-1-2013-01-01_01-23-45.tar.gz', u'C:\\Backups\\DummyVM-1-2013-02-28_21-23-45.tar.gz', u'C:\\Backups\\DummyVM-1-2013-03-31_11-23-45.tar.gz', u'/mnt/backups/DummyVM-2-2013-12-11_23-59-59.tar.gz', ]) from datetime import datetime self.assertDictEqual(bp.get_latest_archives(), { u'DummyVM-1': datetime(2013,03,31,11,23,45), u'DummyVM-2': datetime(2013,12,11,23,59,59), })
def test_archive_remote_backup(self): dummy_profile = { u'remote_backup_dir': u'/vmfs/volumes/Backup-LUN/BackupsDir', u'backup_vms': { u'DummyVM-1': {}, }, } with backup.BackupProfile(dummy_profile) as bp: bp._run_ssh_command = Mock(return_value=u'') self.assertEqual(u'/vmfs/volumes/Backup-LUN/BackupsDir/DummyVM-1/DummyVM-1-2013-12-04_08-03-34.tar.gz', bp._archive_remote_backup(u'DummyVM-1', u'DummyVM-1-2013-12-04_08-03-34')) bp._run_ssh_command.assert_called_once_with( u'cd "/vmfs/volumes/Backup-LUN/BackupsDir/DummyVM-1"; ' u'tar -cz -f "DummyVM-1-2013-12-04_08-03-34.tar.gz" ' u'"DummyVM-1-2013-12-04_08-03-34"')
def test_trim_archives_nothing_to_trim(self): "Check that archive trimming works as expected when there's nothing to trim" dummy_profile = { u'backup_vms': { u'DummyVM-1': { u'rotation_count': 3, }, }, } with backup.BackupProfile(dummy_profile) as bp: bp._list_backup_archives_for_vm = Mock(return_value=[ u'C:\\Backups\\DummyVM-1-2013-12-01_01-23-45.tar.gz', u'C:\\Backups\\DummyVM-1-2013-10-01_01-23-45.tar.gz', u'C:\\Backups\\DummyVM-1-2013-11-01_01-23-45.tar.gz', ]) bp._remove_local_file = Mock() bp.trim_backup_archives() self.assertFalse(bp._remove_local_file.called)
def test_archive_remote_backup_error(self): dummy_profile = { u'remote_backup_dir': u'/vmfs/volumes/Backup-LUN/BackupsDir', u'backup_vms': { u'DummyVM-1': {}, }, } with backup.BackupProfile(dummy_profile) as bp: bp._run_ssh_command = Mock(return_value=u'No such file or directory') with self.assertRaises(RuntimeError) as cm: self.assertEqual(u'/vmfs/volumes/Backup-LUN/BackupsDir/DummyVM-1/DummyVM-1-2013-12-04_08-03-34.tar.gz', bp._archive_remote_backup(u'DummyVM-1', u'DummyVM-1-2013-12-04_08-03-34')) self.assertEqual(cm.exception.message, u'Tar command failed:\nNo such file or directory') bp._run_ssh_command.assert_called_once_with( u'cd "/vmfs/volumes/Backup-LUN/BackupsDir/DummyVM-1"; ' u'tar -cz -f "DummyVM-1-2013-12-04_08-03-34.tar.gz" ' u'"DummyVM-1-2013-12-04_08-03-34"')
def test_trim_archives_one_deletion(self): "Check that archive trimming works as expected with one archive to delete" dummy_profile = { u'backup_vms': { u'DummyVM-1': { u'rotation_count': 2, }, }, } with backup.BackupProfile(dummy_profile) as bp: bp._list_backup_archives_for_vm = Mock(return_value=[ u'C:\\Backups\\DummyVM-1-2013-12-01_01-23-45.tar.gz', u'C:\\Backups\\DummyVM-1-2013-10-01_01-23-45.tar.gz', u'C:\\Backups\\DummyVM-1-2013-11-01_01-23-45.tar.gz', ]) bp._remove_local_file = Mock() bp.trim_backup_archives() bp._remove_local_file.assert_called_once_with( u'C:\\Backups\\DummyVM-1-2013-10-01_01-23-45.tar.gz')
def test_parse_ghettovcb_output_vm_with_two_vmdk(self): dummy_profile = {} with backup.BackupProfile(dummy_profile) as bp: self.assertDictContainsSubset( {u'FINAL_STATUS': True, u'VERSION': u'2013_01_11_0', u'VM_BACKUP_VOLUME': u'/vmfs/volumes/Backup-LUN/BackupsDir', u'VM_BACKUP_ROTATION_COUNT': u'2', u'VM_BACKUP_DIR_NAMING_CONVENTION': u'2013-12-04_08-03-34', u'DISK_BACKUP_FORMAT': u'thin', u'ITER_TO_WAIT_SHUTDOWN': u'3', u'POWER_VM_DOWN_BEFORE_BACKUP': u'0', u'SNAPSHOT_TIMEOUT': u'15', u'ENABLE_HARD_POWER_OFF': '0', u'POWER_DOWN_TIMEOUT': u'5', u'LOG_LEVEL': u'info', u'ENABLE_COMPRESSION': u'0', u'BACKUP_LOG_OUTPUT': u'/tmp/ghettoVCB-2013-12-04_08-03-34-$.log', u'VM_SNAPSHOT_MEMORY': u'0', u'VM_SNAPSHOT_QUIESCE': u'0', u'ALLOW_VMS_WITH_SNAPSHOTS_TO_BE_BACKEDUP': u'0', u'VMDK_FILES_TO_BACKUP': u'all', u'EMAIL_LOG': u'0', u'BACKUP_DURATION': u'19.22 Minutes', u'WARNINGS': [], }, bp._parse_ghettovcb_output(ghettovcb_output_vm_two_vmdk_poweron) )
def test_is_vm_backup_overdue(self): "" dummy_profile = { u'backup_vms': { u'DummyVM-1': { u'period': timedelta(7), }, }, } with backup.BackupProfile(dummy_profile) as bp: from datetime import datetime bp._get_current_time = Mock(return_value = datetime(2013,12,11,10,9,8)) self.assertTrue(bp.is_vm_backup_overdue(u'DummyVM-1', datetime(2013,12,1,11,11,11))) self.assertTrue(bp.is_vm_backup_overdue(u'DummyVM-1', datetime(2013,12,4,10,9,8))) self.assertFalse(bp.is_vm_backup_overdue(u'DummyVM-1', datetime(2013,12,4,10,9,9))) self.assertFalse(bp.is_vm_backup_overdue(u'DummyVM-1', datetime(2013,12,11,10,9,7))) self.assertFalse(bp.is_vm_backup_overdue(u'DummyVM-1', datetime(2013,12,12,12,12,12)))
def test_set_remote_chmod(self): dummy_profile = {} with backup.BackupProfile(dummy_profile) as bp: bp._run_ssh_command = Mock() bp._set_remote_chmod(u'script.sh') bp._run_ssh_command.assert_called_once_with(u'chmod +x script.sh')