def start_backups(parsed_args, *args, **kwargs): vir_event_loop_native_start() config = get_setup_config() conn = get_setup_conn(config) callbacks_registrer = DomExtSnapshotCallbackRegistrer(conn) if config.get("groups", None): groups = build_all_or_selected_groups( config, conn, callbacks_registrer, parsed_args.groups ) main_group = build_main_backup_group(groups) nb_threads = config.get("threads", 0) try: try: with callbacks_registrer: if nb_threads > 1 or nb_threads == 0: main_group.start_multithread(nb_threads=nb_threads) else: main_group.start() except BackupsFailureInGroupError as e: logger.error(e) sys.exit(2) except KeyboardInterrupt: print("Cancelled…") sys.exit(1)
def test_groups_from_dict_multiple_groups(build_mock_libvirtconn_filled): """ Test match_domains_from_config with a str pattern """ conn = build_mock_libvirtconn_filled callbacks_registrer = DomExtSnapshotCallbackRegistrer(conn) groups_config = { "test0": { "target": "/mnt/test0", "packager": "tar", "hosts": [ "matching2", ], }, "test1": { "target": "/mnt/test1", "hosts": ["matching", "a"], }, } groups = tuple(groups_from_dict(groups_config, conn, callbacks_registrer)) assert len(groups) == 2 group0, group1 = groups assert sorted((group0.name, group1.name)) == ["test0", "test1"]
def test_groups_from_sanitize_dict_all_config_group_param( build_mock_libvirtconn_filled, ): """ Test with the example config, containing every possible parameter Related to issue #13 """ conn = build_mock_libvirtconn_filled callbacks_registrer = DomExtSnapshotCallbackRegistrer(conn) groups_config = { "test": { "target": "/mnt/test", "packager": "tar", "autostart": True, "hourly": 1, "daily": 3, "weekly": 2, "monthly": 5, "yearly": 1, "hosts": [ {"host": r"r:^matching\d?$", "disks": ["vda", "vdb"]}, "!matching2", "nonexisting", ], }, } group = next(iter(groups_from_dict(groups_config, conn, callbacks_registrer))) for prop in ("hourly", "daily", "weekly", "monthly", "yearly"): assert prop not in group.default_bak_param
def test_clean_broken(self, build_backup_directory, build_mock_domain, build_mock_libvirtconn, mocker): build_mock_libvirtconn._domains.append(build_mock_domain) callbacks_registrer = DomExtSnapshotCallbackRegistrer( build_mock_libvirtconn) backup_dir = build_backup_directory["backup_dir"] group = CompleteBackupGroup(name="test", backup_dir=str(backup_dir), hosts=["r:.*"], conn=build_mock_libvirtconn, callbacks_registrer=callbacks_registrer) dombkup = DomBackup(dom=build_mock_domain, target_dir=str( backup_dir.mkdir(build_mock_domain.name())), callbacks_registrer=callbacks_registrer) dombkup.pending_info["domain_name"] = build_mock_domain.name() dombkup.pending_info["date"] = 0 dombkup._dump_pending_info() group.scan_backup_dir() nb_initial_backups = sum(len(b) for b in group.broken_backups.values()) assert nb_initial_backups == 1 broken_backup = group.broken_backups[build_mock_domain.name()][0] mocker.spy(broken_backup, "clean_aborted") group.clean_broken_backups() assert not group.broken_backups[build_mock_domain.name()] assert broken_backup.clean_aborted.called
def test_groups_from_dict(build_mock_libvirtconn_filled): """ Test groups_from_dict with only one group """ conn = build_mock_libvirtconn_filled callbacks_registrer = DomExtSnapshotCallbackRegistrer(conn) groups_config = { "test": { "target": "/mnt/test", "packager": "tar", "hosts": [ {"host": r"r:^matching\d?$", "disks": ["vda", "vdb"]}, "!matching2", "nonexisting", ], }, } groups = tuple(groups_from_dict(groups_config, conn, callbacks_registrer)) assert len(groups) == 1 test_group = groups[0] assert test_group.default_bak_param["backup_dir"] == "/mnt/test" assert test_group.default_bak_param["packager"] == "tar" dombackups = test_group.backups assert len(dombackups) == 1 matching_backup = dombackups[0] assert matching_backup.dom.name() == "matching" assert tuple(sorted(matching_backup.disks.keys())) == ("vda", "vdb")
def test_groups_from_dict_multiple_filters(build_mock_libvirtconn_filled): """ Test groups_from_dict with only one group, multiple filters Linked to issue #28 """ conn = build_mock_libvirtconn_filled callbacks_registrer = DomExtSnapshotCallbackRegistrer(conn) groups_config = { "test": { "target": "/mnt/test", "packager": "tar", "hosts": [ {"host": "matching", "disks": ["vda", "vdb"]}, {"host": "matching2", "disks": ["vda"]}, ], }, } groups = tuple(groups_from_dict(groups_config, conn, callbacks_registrer)) dombackups = groups[0].backups assert dombackups[0].dom.name() == "matching" assert tuple(sorted(dombackups[0].disks.keys())) == ("vda", "vdb") assert dombackups[1].dom.name() == "matching2" assert tuple(sorted(dombackups[1].disks.keys())) == ("vda",)
def list_groups(parsed_args, *args, **kwargs): vir_event_loop_native_start() config = get_setup_config() conn = get_setup_conn(config) callbacks_registrer = DomExtSnapshotCallbackRegistrer(conn) complete_groups = {g.name: g for g in get_usable_complete_groups(config)} if parsed_args.list_all: backups_by_group = _get_all_hosts_and_bak_by_groups( parsed_args.groups, config, conn, callbacks_registrer ) else: backups_by_group = {} for cmplgroup in complete_groups.values(): cmplgroup.scan_backup_dir() backups_by_group[cmplgroup.name] = cmplgroup.backups.copy() for group_name, dom_backups in backups_by_group.items(): if parsed_args.domains_names: return list_detailed_backups_for_domain( complete_groups[group_name], parsed_args.domains_names, short=parsed_args.short, ) print(" {}\n{}\n".format(group_name, (2 + len(group_name)) * "=")) print( "Total backups: {} hosts, {} backups".format( len(dom_backups), sum(len(backups) for backups in dom_backups.values()) ) ) if not parsed_args.short: print("Hosts:") # TODO: Should also print hosts matching in libvirt but not backup # yet for dom, backups in sorted(dom_backups.items()): print("\t{}: {} backup(s)".format(dom, len(backups)))
def compare_parsed_groups_with_complete(self, parsed_groups, config): """ :param additional_domains: domains without backup, by group, needed to be printed in the listing """ callbacks_registrer = DomExtSnapshotCallbackRegistrer(self.conn) complete_groups = { g.name: g for g in get_usable_complete_groups(config) } pending_groups = { g.name: g for g in build_all_or_selected_groups(config, self.conn, callbacks_registrer) } for parsed_group, parsed_values in parsed_groups.items(): cgroup = complete_groups[parsed_group] cgroup.scan_backup_dir() pgroup = pending_groups[parsed_group] expected_domains = set(cgroup.backups.keys()) expected_domains.update(set(b.dom.name() for b in pgroup.backups)) assert sorted(parsed_values.keys()) == sorted(expected_domains) for parsed_domain, parsed_backups in parsed_values.items(): assert parsed_backups == len( cgroup.backups.get(parsed_domain, []))
def get_uncompressed_dombackup(build_mock_domain, build_mock_libvirtconn): callbacks_registrer = DomExtSnapshotCallbackRegistrer( build_mock_libvirtconn) return DomBackup(dom=build_mock_domain, dev_disks=("vda", ), compression=None, callbacks_registrer=callbacks_registrer)
def clean_backups(parsed_args, *args, **kwargs): vir_event_loop_native_start() config = get_setup_config() conn = get_setup_conn(config) callbacks_registrer = DomExtSnapshotCallbackRegistrer(conn) groups = get_usable_complete_groups(config, parsed_args.groups, conn, callbacks_registrer) with callbacks_registrer: for g in groups: g.scan_backup_dir() current_group_config = config.get_groups()[g.name] clean_params = { "hourly": current_group_config.get("hourly", "*"), "daily": current_group_config.get("daily", "*"), "weekly": current_group_config.get("weekly", "*"), "monthly": current_group_config.get("monthly", "*"), "yearly": current_group_config.get("yearly", "*"), } if not parsed_args.broken_only: print("Backups removed for group {}: {}".format( g.name or "Undefined", len(g.clean(**clean_params)))) if not parsed_args.no_broken: print("Broken backups removed for group {}: {}".format( g.name or "Undefined", len(g.clean_broken_backups())))
def restore_backup(parsed_args, *args, **kwargs): vir_event_loop_native_start() config = get_setup_config() conn = get_setup_conn(config) callbacks_registrer = DomExtSnapshotCallbackRegistrer(conn) try: group = next( get_usable_complete_groups(config, [parsed_args.group], conn, callbacks_registrer)) except StopIteration: logger.critical("Group {} not found".format(parsed_args.group)) sys.exit(1) group.scan_backup_dir() domain_name = parsed_args.domain_name target_dir = parsed_args.target_dir target_date = arrow.get(parsed_args.date) if parsed_args.date else None if target_date: backup = group.get_backup_at_date(domain_name, target_date) else: try: backup = group.backups[domain_name][-1] except KeyError: raise BackupNotFoundError with callbacks_registrer: backup.restore_to(target_dir)
def get_backup_group(build_mock_domain, build_mock_libvirtconn): callbacks_registrer = DomExtSnapshotCallbackRegistrer(build_mock_libvirtconn) return BackupGroup( build_mock_libvirtconn, domlst=((build_mock_domain, None),), callbacks_registrer=callbacks_registrer, )
def get_uncompressed_dombackup(build_mock_domain, build_mock_libvirtconn): callbacks_registrer = DomExtSnapshotCallbackRegistrer(build_mock_libvirtconn) return DomBackup( dom=build_mock_domain, dev_disks=("vda",), packager="directory", callbacks_registrer=callbacks_registrer, )
def get_compressed_dombackup(build_mock_domain, build_mock_libvirtconn): callbacks_registrer = DomExtSnapshotCallbackRegistrer(build_mock_libvirtconn) return DomBackup( dom=build_mock_domain, dev_disks=("vda",), packager="tar", packager_opts={"compression": "xz", "compression_lvl": 4}, callbacks_registrer=callbacks_registrer, )
def build_backup_group(conn, *group_args, **group_kwargs): callbacks_registrer = DomExtSnapshotCallbackRegistrer(conn) return BackupGroup(*group_args, callbacks_registrer=callbacks_registrer, **group_kwargs)
def build_dombackup(dom, *dombackup_args, **dombackup_kwargs): callbacks_registrer = DomExtSnapshotCallbackRegistrer(dom._conn) return DomBackup(dom, *dombackup_args, callbacks_registrer=callbacks_registrer, **dombackup_kwargs)
def get_dombackup(build_mock_domain, build_mock_libvirtconn): callbacks_registrer = DomExtSnapshotCallbackRegistrer( build_mock_libvirtconn) return DomBackup(build_mock_domain, callbacks_registrer=callbacks_registrer)