def test_failed_delete_checkpoint(): error_msg = "Internal delete error" dom = FakeDomainAdapter() checkpoint_2 = FakeCheckpoint(CHECKPOINT_2_XML, CHECKPOINT_2_ID, dom=dom) # simulating an error that raised when calling the delete method # of a specific checkpoint checkpoint_2.errors["delete"] = fake.libvirt_error( [libvirt.VIR_ERR_INTERNAL_ERROR, '', error_msg], "Fake libvirt error") dom.output_checkpoints = [ FakeCheckpoint(CHECKPOINT_1_XML, CHECKPOINT_1_ID, dom=dom), checkpoint_2 ] vm = FakeVm() res = backup.delete_checkpoints(vm, dom, [CHECKPOINT_1_ID, CHECKPOINT_2_ID]) expected_result = { 'checkpoint_ids': [CHECKPOINT_1_ID], 'error': { 'code': 1, 'message': error_msg } } assert res["result"] == expected_result res = backup.list_checkpoints(vm, dom) assert res["result"] == [CHECKPOINT_2_ID]
def test_stop_backup_failed(tmp_backupdir, tmp_basedir): vm = FakeVm() dom = FakeDomainAdapter() dom.errors["abortJob"] = fake.libvirt_error( [libvirt.VIR_ERR_INTERNAL_ERROR], "Fake libvirt error") fake_disks = create_fake_disks() config = {'backup_id': BACKUP_ID, 'disks': fake_disks} res = backup.start_backup(vm, dom, config) verify_scratch_disks_exists(vm) result_disks = res['result']['disks'] verify_backup_urls(BACKUP_ID, result_disks) with pytest.raises(exception.BackupError): backup.stop_backup(vm, dom, BACKUP_ID) # Failed to stop, backup still alive assert dom.backing_up # verify scratch disks weren't removed verify_scratch_disks_exists(vm)
def test_incremental_backup_with_backup_mode(tmp_dirs): vm = FakeVm() dom = FakeDomainAdapter() fake_disks = create_fake_disks(vm, backup_mode=backup.MODE_FULL) # start full backup config = { 'backup_id': BACKUP_1_ID, 'disks': fake_disks, 'to_checkpoint_id': CHECKPOINT_1_ID } backup.start_backup(vm, dom, config) backup.stop_backup(vm, dom, BACKUP_1_ID) # start incremental backup socket = backup.socket_path(BACKUP_2_ID) scratch1 = scratch_disk_path(vm, BACKUP_2_ID, "sda") scratch2 = scratch_disk_path(vm, BACKUP_2_ID, "vda") dom.output_checkpoints = [CHECKPOINT_1] # Set vda disk backup_mode to 'incremental' for disk in fake_disks: if disk["imageID"] == IMAGE_2_UUID: disk["backup_mode"] = backup.MODE_INCREMENTAL config = { 'backup_id': BACKUP_2_ID, 'disks': fake_disks, 'from_checkpoint_id': CHECKPOINT_1_ID, 'to_checkpoint_id': CHECKPOINT_2_ID, } backup.start_backup(vm, dom, config) backup_xml = f""" <domainbackup mode='pull'> <incremental>{CHECKPOINT_1_ID}</incremental> <server transport='unix' socket='{socket}'/> <disks> <disk name='sda' backup='yes' type='file' backupmode='full' exportname='sda' index='9'> <driver type='qcow2'/> <scratch file='{scratch1}'> <seclabel model='dac' relabel='no'/> </scratch> </disk> <disk name='vda' backup='yes' type='file' backupmode='incremental' incremental='{CHECKPOINT_1_ID}' exportname='vda' index='10'> <driver type='qcow2'/> <scratch file='{scratch2}'> <seclabel model="dac" relabel="no"/> </scratch> </disk> </disks> </domainbackup> """ assert normalized(dom.backupGetXMLDesc()) == normalized(backup_xml)
def test_start_backup_failed_get_checkpoint(tmp_backupdir, tmp_basedir): vm = FakeVm() dom = FakeDomainAdapter() dom.errors["checkpointLookupByName"] = fake.libvirt_error( [libvirt.VIR_ERR_INTERNAL_ERROR], "Fake libvirt error") fake_disks = create_fake_disks() config = { 'backup_id': BACKUP_1_ID, 'disks': fake_disks, 'to_checkpoint_id': CHECKPOINT_1_ID } res = backup.start_backup(vm, dom, config) assert dom.backing_up verify_scratch_disks_exists(vm) # verify that the vm froze and thawed during the backup assert vm.froze assert vm.thawed assert 'checkpoint' not in res['result'] result_disks = res['result']['disks'] verify_backup_urls(BACKUP_1_ID, result_disks) backup.stop_backup(vm, dom, BACKUP_1_ID) assert not dom.backing_up verify_scratch_disks_removed(vm)
def test_dump_missing_checkpoint(): dom = FakeDomainAdapter() dom.output_checkpoints = [ FakeCheckpoint(CHECKPOINT_1_XML, CHECKPOINT_1_ID), ] with pytest.raises(exception.NoSuchCheckpointError): backup.dump_checkpoint(dom, CHECKPOINT_2_ID)
def test_stop_non_existing_backup(): vm = FakeVm() dom = FakeDomainAdapter() dom.errors["backupGetXMLDesc"] = fake.libvirt_error( [libvirt.VIR_ERR_NO_DOMAIN_BACKUP], "Fake libvirt error") # test that nothing is raised when stopping non-existing backup backup.stop_backup(vm, dom, BACKUP_ID)
def test_backup_info_no_backup_running(): vm = FakeVm() dom = FakeDomainAdapter() dom.errors["backupGetXMLDesc"] = fake.libvirt_error( [libvirt.VIR_ERR_NO_DOMAIN_BACKUP], "Fake libvirt error") with pytest.raises(exception.NoSuchBackupError): backup.backup_info(vm, dom, BACKUP_ID)
def test_backup_info_get_xml_desc_failed(): vm = FakeVm() dom = FakeDomainAdapter() dom.errors["backupGetXMLDesc"] = fake.libvirt_error( [libvirt.VIR_ERR_INTERNAL_ERROR], "Fakse libvirt error") with pytest.raises(exception.BackupError): backup.backup_info(vm, dom, BACKUP_ID)
def test_incremental_backup_with_backup_mode(tmp_backupdir, tmp_basedir): vm = FakeVm() dom = FakeDomainAdapter() fake_disks = create_fake_disks(backup_mode=backup.MODE_FULL) # start full backup config = { 'backup_id': BACKUP_1_ID, 'disks': fake_disks, 'to_checkpoint_id': CHECKPOINT_1_ID } backup.start_backup(vm, dom, config) backup.stop_backup(vm, dom, BACKUP_1_ID) # start incremental backup socket_path = backup.socket_path(BACKUP_2_ID) scratch_disk_paths = _get_scratch_disks_path(BACKUP_2_ID) expected_xml = """ <domainbackup mode='pull'> <incremental>{}</incremental> <server transport='unix' socket='{}'/> <disks> <disk backupmode="full" name='sda' type='file'> <scratch file='{}'> <seclabel model="dac" relabel="no"/> </scratch> </disk> <disk backupmode="incremental" incremental='{}' name='vda' type='file'> <scratch file='{}'> <seclabel model="dac" relabel="no"/> </scratch> </disk> </disks> </domainbackup> """.format(CHECKPOINT_1_ID, socket_path, scratch_disk_paths[0], CHECKPOINT_1_ID, scratch_disk_paths[1]) dom.output_checkpoints = [CHECKPOINT_1] # Set vda disk backup_mode to 'incremental' for disk in fake_disks: if disk["imageID"] == IMAGE_2_UUID: disk["backup_mode"] = backup.MODE_INCREMENTAL config = { 'backup_id': BACKUP_2_ID, 'disks': fake_disks, 'from_checkpoint_id': CHECKPOINT_1_ID, 'to_checkpoint_id': CHECKPOINT_2_ID, 'parent_checkpoint_id': CHECKPOINT_1_ID } backup.start_backup(vm, dom, config) assert indented(expected_xml) == indented(dom.input_backup_xml)
def test_start_stop_backup_transient_scratch_disk(tmp_dirs): vm = FakeVm() dom = FakeDomainAdapter() socket = backup.socket_path(BACKUP_1_ID) scratch1 = scratch_disk_path(vm, BACKUP_1_ID, "sda") scratch2 = scratch_disk_path(vm, BACKUP_1_ID, "vda") fake_disks = create_fake_disks(vm) config = {'backup_id': BACKUP_1_ID, 'disks': fake_disks} res = backup.start_backup(vm, dom, config) assert dom.backing_up backup_xml = f""" <domainbackup mode='pull'> <server transport='unix' socket='{socket}'/> <disks> <disk name='sda' backup='yes' type='file' backupmode='full' exportname='sda' index='7'> <driver type='qcow2'/> <scratch file='{scratch1}'> <seclabel model='dac' relabel='no'/> </scratch> </disk> <disk name='vda' backup='yes' type='file' backupmode='full' exportname='vda' index='8'> <driver type='qcow2'/> <scratch file='{scratch2}'> <seclabel model="dac" relabel="no"/> </scratch> </disk> </disks> </domainbackup> """ assert normalized(dom.backupGetXMLDesc()) == normalized(backup_xml) # We don't monitor file based scratch disks. for drive in vm.drives.values(): assert drive.scratch_disk is None verify_scratch_disks_exists(vm) # verify that the vm froze and thawed during the backup assert vm.froze assert vm.thawed assert 'checkpoint' not in res['result'] result_disks = res['result']['disks'] verify_backup_urls(vm, BACKUP_1_ID, result_disks) backup.stop_backup(vm, dom, BACKUP_1_ID) assert not dom.backing_up verify_scratch_disks_removed(vm)
def test_dump_checkpoint(): dom = FakeDomainAdapter() dom.output_checkpoints = [ FakeCheckpoint(CHECKPOINT_1_XML, CHECKPOINT_1_ID), FakeCheckpoint(CHECKPOINT_2_XML, CHECKPOINT_2_ID) ] for checkpoint_cfg in FAKE_CHECKPOINT_CFG: res = backup.dump_checkpoint(dom, checkpoint_cfg['id']) expected_result = {'checkpoint': checkpoint_cfg['xml']} assert res["result"] == expected_result
def test_dump_checkpoint_lookup_failed(): dom = FakeDomainAdapter() dom.errors["checkpointLookupByName"] = fake.libvirt_error( [libvirt.VIR_ERR_INTERNAL_ERROR], "Fake libvirt error") dom.output_checkpoints = [ FakeCheckpoint(CHECKPOINT_1_XML, CHECKPOINT_1_ID), FakeCheckpoint(CHECKPOINT_2_XML, CHECKPOINT_2_ID) ] with pytest.raises(libvirt.libvirtError) as e: backup.dump_checkpoint(dom, CHECKPOINT_1_ID) assert e.value.get_error_code() == libvirt.VIR_ERR_INTERNAL_ERROR
def test_backup_begin_checkpoint_inconsistent(tmp_backupdir, tmp_basedir): vm = FakeVm() dom = FakeDomainAdapter() dom.errors["backupBegin"] = fake.libvirt_error( [libvirt.VIR_ERR_CHECKPOINT_INCONSISTENT], "Fake libvirt error") fake_disks = create_fake_disks() config = {'backup_id': BACKUP_1_ID, 'disks': fake_disks} with pytest.raises(exception.InconsistentCheckpointError): backup.start_backup(vm, dom, config)
def test_fail_parse_backup_xml(tmp_dirs): vm = FakeVm() dom = FakeDomainAdapter() fake_disks = create_fake_disks(vm) config = {'backup_id': BACKUP_1_ID, 'disks': fake_disks} backup.start_backup(vm, dom, config) dom.backup_xml = """ <domainbackup mode='pull'> <disks/> </domainbackup> """ with pytest.raises(exception.BackupError): backup.backup_info(vm, dom, BACKUP_1_ID)
def test_delete_one_checkpoint(): dom = FakeDomainAdapter() dom.output_checkpoints = [ FakeCheckpoint(CHECKPOINT_1_XML, CHECKPOINT_1_ID, dom=dom), FakeCheckpoint(CHECKPOINT_2_XML, CHECKPOINT_2_ID, dom=dom) ] vm = FakeVm() res = backup.delete_checkpoints(vm, dom, [CHECKPOINT_1_ID]) expected_result = {'checkpoint_ids': [CHECKPOINT_1_ID]} assert res["result"] == expected_result res = backup.list_checkpoints(vm, dom) assert res["result"] == [CHECKPOINT_2_ID]
def test_start_backup_failed_get_checkpoint(tmp_backupdir, tmp_basedir): vm = FakeVm() dom = FakeDomainAdapter() fake_disks = create_fake_disks() config = { 'backup_id': BACKUP_ID, 'disks': fake_disks, 'to_checkpoint_id': TO_CHECKPOINT_ID } res = backup.start_backup(vm, dom, config) assert dom.backing_up verify_scratch_disks_exists(vm) # verify that the vm froze and thawed during the backup assert vm.froze assert vm.thawed assert 'checkpoint' not in res['result'] result_disks = res['result']['disks'] verify_backup_urls(BACKUP_ID, result_disks) backup.stop_backup(vm, dom, BACKUP_ID) assert not dom.backing_up verify_scratch_disks_removed(vm)
def test_backup_info(tmp_backupdir, tmp_basedir): vm = FakeVm() expected_xml = """ <domainbackup mode='pull'> <server transport='unix' socket='{}'/> <disks> <disk name='sda' backup='yes' type='file' exportname='sda'> <driver type='qcow2'/> <scratch file='/path/to/scratch_sda'> <seclabel model='dac' relabel='no'/> </scratch> </disk> <disk name='vda' backup='yes' type='file' exportname='vda'> <driver type='qcow2'/> <scratch file='/path/to/scratch_vda'> <seclabel model="dac" relabel="no"/> </scratch> </disk> <disk name='hdc' backup='no'/> </disks> </domainbackup> """.format(backup.socket_path(BACKUP_ID)) dom = FakeDomainAdapter(output_backup_xml=expected_xml) fake_disks = create_fake_disks() config = {'backup_id': BACKUP_ID, 'disks': fake_disks} res = backup.start_backup(vm, dom, config) backup_info = backup.backup_info(vm, dom, BACKUP_ID) assert res['result']['disks'] == backup_info['result']['disks'] assert 'checkpoint' not in backup_info['result']
def test_full_backup_without_checkpoint_with_previous_chain( tmp_backupdir, tmp_basedir): vm = FakeVm() # This test checks an edge case when a chain of incremental backup was # taken for a VM with RAW disks that a snapshot created for them so their # format is now QCOW2 and they are valid for incremental backup. In this # case, when the snapshot is removed, the disk format is RAW again and only # a full backup without a checkpoint can be taken while there are defined # checkpoints for the VM. dom = FakeDomainAdapter(output_checkpoints=[CHECKPOINT_1, CHECKPOINT_2]) fake_disks = create_fake_disks() # Start full backup without a checkpoint config = { 'backup_id': BACKUP_1_ID, 'disks': fake_disks, } # Start a full backup while skipping the validation for the # last defined checkpoint with the given parent checkpoint # since there is none when a checkpoint isn't created. res = backup.start_backup(vm, dom, config) assert dom.backing_up result_disks = res['result']['disks'] verify_backup_urls(BACKUP_1_ID, result_disks) backup.stop_backup(vm, dom, BACKUP_1_ID) assert not dom.backing_up verify_scratch_disks_removed(vm)
def test_list_checkpoints(): dom = FakeDomainAdapter(output_checkpoints=[CHECKPOINT_1, CHECKPOINT_2]) vm = FakeVm() res = backup.list_checkpoints(vm, dom) assert res["result"] == [CHECKPOINT_1.getName(), CHECKPOINT_2.getName()]
def test_dump_checkpoint_get_xml_failed(): checkpoint_2 = FakeCheckpoint(CHECKPOINT_2_XML, CHECKPOINT_2_ID) # simulating an error that raised when calling the getXMLDesc method # of a specific checkpoint checkpoint_2.errors["getXMLDesc"] = fake.libvirt_error( [libvirt.VIR_ERR_INTERNAL_ERROR, '', 'Internal get XML error'], "Fake libvirt error") dom = FakeDomainAdapter() dom.output_checkpoints = [ FakeCheckpoint(CHECKPOINT_1_XML, CHECKPOINT_1_ID), checkpoint_2 ] with pytest.raises(libvirt.libvirtError) as e: backup.dump_checkpoint(dom, CHECKPOINT_2_ID) assert e.value.get_error_code() == libvirt.VIR_ERR_INTERNAL_ERROR
def test_start_stop_backup_with_checkpoint(tmp_backupdir, tmp_basedir, disks_in_checkpoint, expected_checkpoint_xml): vm = FakeVm() dom = FakeDomainAdapter() fake_disks = create_fake_disks(disks_in_checkpoint) config = { 'backup_id': BACKUP_1_ID, 'disks': fake_disks, 'to_checkpoint_id': CHECKPOINT_1_ID } res = backup.start_backup(vm, dom, config) assert dom.backing_up assert indented(expected_checkpoint_xml) == (indented( dom.input_checkpoint_xml)) verify_scratch_disks_exists(vm) # verify that the vm froze and thawed during the backup assert vm.froze assert vm.thawed result_disks = res['result']['disks'] verify_backup_urls(BACKUP_1_ID, result_disks) backup.stop_backup(vm, dom, BACKUP_1_ID) assert not dom.backing_up verify_scratch_disks_removed(vm)
def test_full_backup_with_backup_mode(tmp_backupdir, tmp_basedir): vm = FakeVm() socket_path = backup.socket_path(BACKUP_1_ID) scratch_disk_paths = _get_scratch_disks_path(BACKUP_1_ID) expected_xml = """ <domainbackup mode='pull'> <server transport='unix' socket='{}'/> <disks> <disk backupmode="full" name='sda' type='file'> <scratch file='{}'> <seclabel model="dac" relabel="no"/> </scratch> </disk> <disk backupmode="full" name='vda' type='file'> <scratch file='{}'> <seclabel model="dac" relabel="no"/> </scratch> </disk> </disks> </domainbackup> """.format(socket_path, scratch_disk_paths[0], scratch_disk_paths[1]) dom = FakeDomainAdapter() fake_disks = create_fake_disks(backup_mode=backup.MODE_FULL) config = {'backup_id': BACKUP_1_ID, 'disks': fake_disks} backup.start_backup(vm, dom, config) assert normalized(expected_xml) == normalized(dom.input_backup_xml)
def test_backup_begin_failed_no_disks(tmp_backupdir, tmp_basedir): vm = FakeVm() dom = FakeDomainAdapter() config = {'backup_id': BACKUP_ID, 'disks': ()} with pytest.raises(exception.BackupError): backup.start_backup(vm, dom, config)
def test_delete_missing_checkpoint(): dom = FakeDomainAdapter() dom.output_checkpoints = [ FakeCheckpoint(CHECKPOINT_2_XML, CHECKPOINT_2_ID, dom=dom) ] vm = FakeVm() res = backup.delete_checkpoints(vm, dom, [CHECKPOINT_1_ID, CHECKPOINT_2_ID]) expected_result = {'checkpoint_ids': [CHECKPOINT_1_ID, CHECKPOINT_2_ID]} # validate that the missing checkpoint reported as # successfully removed assert res["result"] == expected_result res = backup.list_checkpoints(vm, dom) assert res["result"] == []
def test_backup_begin_failed(tmp_backupdir, tmp_basedir): vm = FakeVm() dom = FakeDomainAdapter() dom.errors["backupBegin"] = fake.libvirt_error( [libvirt.VIR_ERR_INTERNAL_ERROR], "Fake libvirt error") fake_disks = create_fake_disks() config = {'backup_id': BACKUP_ID, 'disks': fake_disks} with pytest.raises(exception.BackupError): backup.start_backup(vm, dom, config) verify_scratch_disks_removed(vm) # verify that the vm froze and thawed during the backup assert vm.froze assert vm.thawed
def test_backup_begin_failed_full_with_inremental_disks(tmp_dirs): vm = FakeVm() dom = FakeDomainAdapter() # Set disks backup_mode to 'incremental' fake_disks = create_fake_disks(vm, backup_mode=backup.MODE_INCREMENTAL) config = {'backup_id': BACKUP_1_ID, 'disks': fake_disks} with pytest.raises(exception.BackupError): backup.start_backup(vm, dom, config)
def test_backup_info(tmp_dirs): vm = FakeVm() dom = FakeDomainAdapter() fake_disks = create_fake_disks(vm) config = {'backup_id': BACKUP_1_ID, 'disks': fake_disks} res = backup.start_backup(vm, dom, config) backup_info = backup.backup_info(vm, dom, BACKUP_1_ID) assert res['result']['disks'] == backup_info['result']['disks'] assert 'checkpoint' not in backup_info['result']
def test_redefine_checkpoints_failed(): dom = FakeDomainAdapter() # simulating an error that raised during # checkpointCreateXML() method in libvirt. error_msg = "Create checkpoint XML Error" dom.errors["checkpointCreateXML"] = fake.libvirt_error( [libvirt.VIR_ERR_INTERNAL_ERROR, '', error_msg], "Fake libvirt error") vm = FakeVm() res = backup.redefine_checkpoints(vm, dom, FAKE_CHECKPOINT_CFG) expected_result = { 'checkpoint_ids': [], 'error': { 'code': 1, 'message': error_msg } } assert res["result"] == expected_result
def test_redefine_checkpoints_failed_no_xml_or_config(): dom = FakeDomainAdapter(output_checkpoints=[CHECKPOINT_1, CHECKPOINT_2]) vm = FakeVm() checkpoint_cfg = [ { 'id': CHECKPOINT_1_ID, }, ] with pytest.raises(exception.CheckpointError): backup.redefine_checkpoints(vm, dom, checkpoint_cfg)
def test_redefine_checkpoints_succeeded(): dom = FakeDomainAdapter(output_checkpoints=[CHECKPOINT_1, CHECKPOINT_2]) vm = FakeVm() res = backup.redefine_checkpoints(vm, dom, FAKE_CHECKPOINT_CFG) expected_result = { 'checkpoint_ids': [CHECKPOINT_1.getName(), CHECKPOINT_2.getName()], } assert res["result"] == expected_result