@fab.parallel
def bootstrap(git_fetch=True, revision_override=None):
    """Install and configure the specified product on each host

    Returns the git id for the version checked out.
    """
    partitioner = config['partitioner']

    fab.run('mkdir -p fab')

    if config['product'] in (None, ''):
        logger.warn("revision product was not set -- defaulting to cassandra")
        config['product'] = 'cassandra'
    elif config['product'] not in ('cassandra', 'dse'):
        raise ValueError("Invalid product. Should be cassandra or dse")

    product = dse if config['product'] == 'dse' else cstar

    if product.name == 'dse':
        rev_id = dse.bootstrap(config)
    else:
        rev_id = cstar.bootstrap(config, git_fetch=git_fetch, revision_override=revision_override)

    cassandra_path = product.get_cassandra_path()

    # Get host config:
    try:
        cfg = config['hosts'][fab.env.host]
    except KeyError:
        # If host has no config, don't configure it. This is used for
        # compiling the source on the controlling node which is
        # usually not a part of the cluster.
        return rev_id

    #Ensure JNA is available:
    if config['use_jna']:
        # Check if JNA already exists:
        jna_jars = os.path.join(cassandra_path, 'lib/jna*.jar')
        jna_jar = os.path.join(cassandra_path, 'lib/jna.jar')
        jna_exists = fab.run('ls {}'.format(jna_jars), quiet=True)
        if jna_exists.return_code != 0:
            # Symlink system JNA to cassandra lib dir:
            jna_candidates = ['/usr/share/java/jna/jna.jar', '/usr/share/java/jna.jar']
            for jar in jna_candidates:
                if fab.run('ls {jar}'.format(jar=jar), quiet=True).return_code == 0:
                    fab.run('ln -s {jar} {jna}'.format(jar=jar, jna=jna_jar))
                    break
            else:
                if not os.path.exists('fab/jna.jar'):
                    request = download_file(JNA_LIB_URL, 'fab/jna.jar')
                    if request.status_code != requests.codes.ok:
                        raise AssertionError('Could not force JNA loading, no JNA jar found.')

                fab.put('fab/jna.jar', jna_jar)
    else:
        fab.run('rm -f {}'.format(os.path.join(cassandra_path, 'lib/jna*')))

    # Configure cassandra.yaml:
    conf_file = StringIO()
    fab.get(os.path.join(cassandra_path, 'conf/cassandra.yaml'), conf_file)
    conf_file.seek(0)
    cass_yaml = yaml.load(conf_file.read())

    # Get the canonical list of options from the c* source code:
    cstar_config_opts = product.get_cassandra_config_options(config)
    # CASSANDRA-11217 brought in a 'log' method and locals() contains 'log' which taints our cassandra.yaml. Delete it.
    try:
        cstar_config_opts.remove('log')
    except ValueError:
        pass

    if product.name == 'dse':
        dse_config_options = product.get_dse_config_options(config)
        dse_conf_file = StringIO()
        dse_yaml_path = os.path.join(product.get_dse_conf_path(), 'dse.yaml')
        fab.get(dse_yaml_path, dse_conf_file)
        dse_conf_file.seek(0)
        dse_yaml = yaml.load(dse_conf_file.read())

        configured_dse_yaml_settings = config.get('dse_yaml', {})
        if configured_dse_yaml_settings:
            for option, value in configured_dse_yaml_settings.items():
                if option not in dse_config_options:
                    raise ValueError('Unknown dse.yaml option: {}'.format(option))
                dse_yaml[option] = value

            # write values to dse.yaml
            dse_conf_file = StringIO()
            dse_conf_file.write(yaml.safe_dump(dse_yaml, encoding='utf-8', allow_unicode=True))
            dse_conf_file.seek(0)
            fab.put(dse_conf_file, dse_yaml_path)

    # Cassandra YAML values can come from two places:
    # 1) Set as options at the top level of the config. This is how
    # legacy cstar_perf did it. These are unvalidated:
    for option, value in config.items():
        if option in cstar_config_opts:
            cass_yaml[option] = value
    # 2) Set in the second level 'yaml' dictionary. This is how the
    # frontend and bootstrap.py does it. These take precedence over
    # the #1 style and are always validated for typos / invalid options.
    for option, value in config.get('yaml', {}).items():
        if option in DENIED_CSTAR_CONFIG:
            raise ValueError(
                'C* yaml option "{}" can only be set in the cluster config.'.format(option)
            )
        elif cstar_config_opts not in option:
            raise ValueError('Unknown C* yaml option: {}'.format(option))
        cass_yaml[option] = value

    if 'num_tokens' not in config.get('yaml', {}):
        if config.get('use_vnodes', True):
            cass_yaml['num_tokens'] = config['num_tokens']
        else:
            cass_yaml['initial_token'] = cfg['initial_token']
            cass_yaml['num_tokens'] = 1
    cass_yaml['listen_address'] = cfg['internal_ip']
    cass_yaml['broadcast_address'] = cfg.get('external_ip', cfg['internal_ip'])
    cass_yaml['seed_provider'][0]['parameters'][0]['seeds'] =  ",".join(config['seeds'])
    if partitioner == 'random':
        cass_yaml['partitioner'] = 'org.apache.cassandra.dht.RandomPartitioner'
    elif partitioner == 'murmur3':
        cass_yaml['partitioner'] = 'org.apache.cassandra.dht.Murmur3Partitioner'
    cass_yaml['rpc_address'] = cfg['internal_ip']

    #Configure Topology:
    if not config.has_key('endpoint_snitch'):
        for node in config['hosts'].values():
            if node.get('datacenter',False):
                config['endpoint_snitch'] = "GossipingPropertyFileSnitch"
                cass_yaml['auto_bootstrap'] = False
                break
        else:
            config['endpoint_snitch'] = "SimpleSnitch"

    conf_dir = os.path.join(cassandra_path, 'conf/')
    if config['endpoint_snitch'] == 'PropertyFileSnitch':
        cass_yaml['endpoint_snitch'] = 'PropertyFileSnitch'
        fab.run("echo 'default=dc1:r1' > {}".format(conf_dir+'cassandra-topology.properties'))
        for node in config['hosts'].values():
            line = '%s=%s:%s' % (node['external_ip'], node.get('datacenter', 'dc1'), node.get('rack', 'r1'))
            fab.run("echo '{}' >> {}".format(line, conf_dir+'cassandra-topology.properties'))
    if config['endpoint_snitch'] == "GossipingPropertyFileSnitch":
        cass_yaml['endpoint_snitch'] = 'GossipingPropertyFileSnitch'
        fab.run("echo 'dc={dc}\nrack={rack}' > {out}".format(
            dc=cfg.get('datacenter','dc1'), rack=cfg.get('rack','r1'),
            out=conf_dir+'cassandra-rackdc.properties'))

    # Save config:
    conf_file = StringIO()
    conf_file.write(yaml.safe_dump(cass_yaml, encoding='utf-8', allow_unicode=True))
    conf_file.seek(0)
    fab.put(conf_file, conf_dir+'cassandra.yaml')

    # Configure logback:
    logback_conf = StringIO()
    # Get absolute path to log dir:
    log_dir = fab.run("readlink -m {log_dir}".format(log_dir=config['log_dir']))
    logback_conf.write(logback_template.replace("${cassandra.logdir}",log_dir))
    logback_conf.seek(0)
    fab.put(logback_conf, conf_dir+'logback.xml')

    # Configure log4j:
    log4j_conf = StringIO()
    log4j_conf.write(log4j_template.replace("${cassandra.logdir}",log_dir))
    log4j_conf.seek(0)
    fab.put(log4j_conf, conf_dir+'log4j-server.properties')

    # Copy fincore utility:
    fincore_script = os.path.join(os.path.dirname(os.path.realpath(__file__)),'fincore_capture.py')
    fab.put(fincore_script, '~/fab/fincore_capture.py')
    return rev_id
dataset/ETHPy150Open datastax/cstar_perf/tool/cstar_perf/tool/fab_common.py/bootstrap/swapped operands of `not in`