Beispiel #1
0
def restore_node_sstableloader(config, temp_dir, backup_name, in_place,
                               keep_auth, seeds, storage, keyspaces, tables):
    node_backup = None
    fqdns = config.storage.fqdn.split(",")
    for fqdn in fqdns:
        incremental_blob = storage.storage_driver.get_blob(
            os.path.join(fqdn, backup_name, 'meta', 'incremental'))

        node_backup = storage.get_node_backup(
            fqdn=fqdn,
            name=backup_name,
            incremental_mode=True if incremental_blob is not None else False)

        if not node_backup.exists():
            logging.error('No such backup')
            sys.exit(1)

        fqtns_to_restore = get_fqtns_to_restore(keyspaces, tables,
                                                node_backup.manifest)

        if len(fqtns_to_restore) == 0:
            logging.error('There is nothing to restore')
            sys.exit(0)

        # Download the backup
        download_dir = temp_dir / 'medusa-restore-{}'.format(uuid.uuid4())
        logging.info('Downloading data from backup to {}'.format(download_dir))
        download_data(config.storage,
                      node_backup,
                      fqtns_to_restore,
                      destination=download_dir)
        invoke_sstableloader(config, download_dir, keep_auth, fqtns_to_restore)
        logging.info('Finished loading backup from {}'.format(fqdn))

    return node_backup
def restore_node_sstableloader(config, temp_dir, backup_name, in_place,
                               keep_auth, seeds, storage, keyspaces, tables):
    cassandra = Cassandra(config)
    node_backup = None
    fqdns = config.storage.fqdn.split(",")
    for fqdn in fqdns:
        differential_blob = storage.storage_driver.get_blob(
            os.path.join(fqdn, backup_name, 'meta', 'differential'))

        node_backup = storage.get_node_backup(
            fqdn=fqdn,
            name=backup_name,
            differential_mode=True if differential_blob is not None else False)

        if not node_backup.exists():
            logging.error('No such backup')
            sys.exit(1)

        fqtns_to_restore, ignored_fqtns = filter_fqtns(keyspaces, tables,
                                                       node_backup.manifest)

        for fqtns in ignored_fqtns:
            logging.info('Skipping restore of {}'.format(fqtns))

        if len(fqtns_to_restore) == 0:
            logging.error('There is nothing to restore')
            sys.exit(0)

        # Download the backup
        download_dir = temp_dir / 'medusa-restore-{}'.format(uuid.uuid4())
        logging.info('Downloading data from backup to {}'.format(download_dir))
        download_data(config.storage,
                      node_backup,
                      fqtns_to_restore,
                      destination=download_dir)
        invoke_sstableloader(config, download_dir, keep_auth, fqtns_to_restore,
                             cassandra.storage_port)
        logging.info('Finished loading backup from {}'.format(fqdn))

    # Clean the restored data from local temporary folder
    clean_path(download_dir, keep_folder=False)
    return node_backup
def restore_node_locally(config, temp_dir, backup_name, in_place, keep_auth,
                         seeds, storage, keyspaces, tables):
    differential_blob = storage.storage_driver.get_blob(
        os.path.join(config.storage.fqdn, backup_name, 'meta', 'differential'))

    node_backup = storage.get_node_backup(
        fqdn=config.storage.fqdn,
        name=backup_name,
        differential_mode=True if differential_blob is not None else False)

    if not node_backup.exists():
        logging.error('No such backup')
        sys.exit(1)

    fqtns_to_restore = get_fqtns_to_restore(keyspaces, tables,
                                            node_backup.manifest)
    if len(fqtns_to_restore) == 0:
        logging.error('There is nothing to restore')
        sys.exit(0)

    cassandra = Cassandra(config.cassandra)

    # Download the backup
    download_dir = temp_dir / 'medusa-restore-{}'.format(uuid.uuid4())
    logging.info('Downloading data from backup to {}'.format(download_dir))
    download_data(config.storage,
                  node_backup,
                  fqtns_to_restore,
                  destination=download_dir)

    logging.info('Stopping Cassandra')
    cassandra.shutdown()

    # Clean the commitlogs, the saved cache to prevent any kind of conflict
    # especially around system tables.
    clean_path(cassandra.commit_logs_path)
    clean_path(cassandra.saved_caches_path)

    # move backup data to Cassandra data directory according to system table
    logging.info('Moving backup data to Cassandra data directory')
    manifest = json.loads(node_backup.manifest)
    for section in manifest:
        fqtn = "{}.{}".format(section['keyspace'], section['columnfamily'])
        if fqtn not in fqtns_to_restore:
            logging.debug('Skipping restore for {}'.format(fqtn))
            continue
        maybe_restore_section(section, download_dir, cassandra.root, in_place,
                              keep_auth)

    node_fqdn = storage.config.fqdn
    token_map_file = download_dir / 'tokenmap.json'
    with open(str(token_map_file), 'r') as f:
        tokens = get_node_tokens(node_fqdn, f)
        logging.debug("Parsed tokens: {}".format(tokens))

    # possibly wait for seeds
    if seeds is not None:
        wait_for_seeds(config, seeds)
    else:
        logging.info('No --seeds specified so we will not wait for any')

    # Start up Cassandra
    logging.info('Starting Cassandra')
    # restoring in place retains system.local, which has tokens in it. no need to specify extra
    if in_place:
        cassandra.start_with_implicit_token()
    else:
        cassandra.start(tokens)

    return node_backup
def restore_node_locally(config, temp_dir, backup_name, in_place, keep_auth,
                         seeds, storage, keyspaces, tables):
    storage.storage_driver.prepare_download()
    differential_blob = storage.storage_driver.get_blob(
        os.path.join(config.storage.fqdn, backup_name, 'meta', 'differential'))

    node_backup = storage.get_node_backup(
        fqdn=config.storage.fqdn,
        name=backup_name,
        differential_mode=True if differential_blob is not None else False)

    if not node_backup.exists():
        logging.error('No such backup')
        sys.exit(1)

    fqtns_to_restore, ignored_fqtns = filter_fqtns(keyspaces, tables,
                                                   node_backup.manifest)
    for fqtns in ignored_fqtns:
        logging.info('Skipping restore of {}'.format(fqtns))

    if len(fqtns_to_restore) == 0:
        logging.error('There is nothing to restore')
        sys.exit(0)

    cassandra = Cassandra(config)

    # Download the backup
    download_dir = temp_dir / 'medusa-restore-{}'.format(uuid.uuid4())
    logging.info('Downloading data from backup to {}'.format(download_dir))
    download_data(config.storage,
                  node_backup,
                  fqtns_to_restore,
                  destination=download_dir)

    if not medusa.utils.evaluate_boolean(config.kubernetes.enabled):
        logging.info('Stopping Cassandra')
        cassandra.shutdown()
        wait_for_node_to_go_down(config, cassandra.hostname)

    # Clean the commitlogs, the saved cache to prevent any kind of conflict
    # especially around system tables.
    use_sudo = not medusa.utils.evaluate_boolean(config.kubernetes.enabled)
    clean_path(cassandra.commit_logs_path, use_sudo, keep_folder=True)
    clean_path(cassandra.saved_caches_path, use_sudo, keep_folder=True)

    # move backup data to Cassandra data directory according to system table
    logging.info('Moving backup data to Cassandra data directory')
    manifest = json.loads(node_backup.manifest)
    for section in manifest:
        fqtn = "{}.{}".format(section['keyspace'], section['columnfamily'])
        if fqtn not in fqtns_to_restore:
            logging.debug('Skipping restore for {}'.format(fqtn))
            continue
        maybe_restore_section(section, download_dir, cassandra.root, in_place,
                              keep_auth, use_sudo)

    node_fqdn = storage.config.fqdn
    token_map_file = download_dir / 'tokenmap.json'
    with open(str(token_map_file), 'r') as f:
        tokens = get_node_tokens(node_fqdn, f)
        logging.debug("Parsed tokens: {}".format(tokens))

    # possibly wait for seeds
    #
    # In a Kubernetes deployment we can assume that seed nodes will be started first. It will
    # handled either by the statefulset controller or by the controller of a Cassandra
    # operator.
    if not medusa.utils.evaluate_boolean(config.kubernetes.enabled):
        if seeds is not None:
            wait_for_seeds(config, seeds)
        else:
            logging.info('No --seeds specified so we will not wait for any')

        # Start up Cassandra
        logging.info('Starting Cassandra')
        # restoring in place retains system.local, which has tokens in it. no need to specify extra
        if in_place:
            cassandra.start_with_implicit_token()
        else:
            cassandra.start(tokens)

    # Clean the restored data from local temporary folder
    clean_path(download_dir, use_sudo, keep_folder=False)
    return node_backup