def monetdbd_set(request):
    properties = request.get('properties', None)
    dbfarm = check_db_farm(request)

    # Check if the user input is empty
    if is_empty(properties):
        raise InvalidUsage('Provide at least one property.', status_code=400)

    whitelist = [
        'all', 'logfile', 'pidfile', 'sockdir', 'port', 'ipv6', 'listenaddr',
        'control', 'discovery', 'discoveryttl', 'dbfarm', 'exittimeout',
        'forward', 'snapshotdir', 'snapshotcompression', 'mapisock',
        'controlsock', 'status', 'hostname', 'passphrase'
    ]

    for entry in properties:
        if entry not in whitelist:
            raise InvalidUsage('No such property: ' + entry, status_code=400)

    properties = [
        '%s=%s' % (key, value) for (key, value) in properties.items()
    ]
    execute_command = ['monetdbd', 'set'] + properties + dbfarm
    current_app.logger.debug(execute_command)

    try:
        result = subprocess.check_output(execute_command,
                                         stderr=subprocess.STDOUT,
                                         shell=False)
        result = str(result.decode('ascii'))
    except subprocess.CalledProcessError as e:
        error_message = str(e.output.decode('ascii')).strip('\n')
        raise InvalidUsage(error_message, status_code=400)
    return result
def properties_get_request(request):
    properties = request.get('properties', None)
    # Check if the user input is empty
    if is_empty(properties):
        raise InvalidUsage('Provide at least one property.', status_code=400)

    properties = [
        '%s=%s' % (key, value) for (key, value) in properties.items()
    ]

    return properties
def monetdb_get(request):
    """
    Example of input:
    {'options': {'port': '50000'}, 'databases': ['mydb'], 'properties': ['mclients', 'type']}
    """
    request_model = validate_get_model(request)
    execute_command = ['monetdb']
    # Pass the options to the execute_command
    execute_command.extend(options_get_request(request_model))

    execute_command.append('get')
    properties = request_model.get('properties', None)
    # Properties should be a string in the monetdb execute_command
    properties = ','.join(properties)
    # Check if the user input is empty
    if is_empty(properties):
        raise InvalidUsage('Provide at least one property.', status_code=400)

    if 'all' in properties:
        execute_command.append('all')
    else:
        execute_command.append(properties)
    # Get all without db returns everything, while get all db will return all the properties for
    # the given database
    database = check_db_name(request_model, allow_empty=True)
    execute_command += database

    try:
        result = subprocess.check_output(execute_command,
                                         stderr=subprocess.STDOUT,
                                         shell=False)
        result = str(result.decode('ascii'))
    except subprocess.CalledProcessError as e:
        error_message = str(e.output.decode('ascii')).replace('\r',
                                                              ' ').replace(
                                                                  '\n', ' ')
        raise InvalidUsage(error_message, status_code=400)

    result = serialize_monetdb_get(result)

    return result
def monetdbd_get(request):
    """
    Accepts dictionary of dbfarm, properties
    e.g. {'dbfarm': 'mydbfarm', 'properties': ['hostname', 'status']}
    """
    properties = request.get('properties', None)
    dbfarm = check_db_farm(request)

    # Check if the user input is empty
    if is_empty(properties):
        raise InvalidUsage('Provide at least one property.', status_code=400)

    whitelist = [
        'all', 'logfile', 'pidfile', 'sockdir', 'port', 'ipv6', 'listenaddr',
        'control', 'discovery', 'discoveryttl', 'dbfarm', 'exittimeout',
        'forward', 'snapshotdir', 'snapshotcompression', 'mapisock',
        'controlsock', 'status', 'hostname'
    ]
    for entry in properties:
        if entry not in whitelist:
            raise InvalidUsage('No such property: ' + entry, status_code=400)

    if 'all' in properties:
        options = ['all']
    else:
        options = [','.join(map(str, properties))]
    execute_command = ['monetdbd', 'get'] + options + dbfarm

    try:
        result = subprocess.check_output(execute_command,
                                         stderr=subprocess.STDOUT,
                                         shell=False)
        result = str(result.decode('ascii'))
        result = parse_result(result)
    except subprocess.CalledProcessError as e:
        error_message = str(e.output.decode('ascii')).strip('\n')
        raise InvalidUsage(error_message, status_code=400)
    return result
def check_db_farm(request):
    """
    Sanitize dbfarm user input. Allow the dbfarm to exist on the current path, no subfolders
    """
    if request:
        dbfarm = (request.get('dbfarm', None))
    else:
        raise InvalidUsage('Provide one dbfarm', status_code=400)
    if dbfarm:
        dbfarm = dbfarm.split(',')
    else:
        raise InvalidUsage('Provide one dbfarm', status_code=400)
    if is_empty(dbfarm) or len(dbfarm) != 1:
        raise InvalidUsage('Provide one dbfarm', status_code=400)

    # Remove any unwanted charachters
    dbfarm[0] = slugify(dbfarm[0])
    # Allow dbfarm to be created only in the project's current path. Subject to change.
    basedir = os.getcwd()
    test_path = Path((basedir + '/' + dbfarm[0])).resolve()
    if test_path.parent != Path(basedir).resolve():
        raise InvalidUsage('Do not use a path with dbfarm', status_code=400)

    return dbfarm
def check_db_name(request_model, allow_empty=False):
    """
    Sanitize database user input. Allow multiple databases.
    """
    database = None
    if request_model:
        database = request_model.get('databases', None)
    if database is None and allow_empty:
        return None
    if is_empty(database) and allow_empty is False:
        raise InvalidUsage('Provide at least one database', status_code=400)
    elif isinstance(database, list):
        if not all(isinstance(entry, str) for entry in database):
            raise InvalidUsage('List of databases must be in string format',
                               status_code=400)
    else:
        raise InvalidUsage(
            'Provide a database as a list of strings: {"databases": ["<database>"]}',
            status_code=400)

    # Remove any unwanted charachters
    database = [slugify(entry) for entry in database]

    return database