Example #1
0
def delete_project(project_id):
    set_audit_resource_id(project_id)
    tenant = get_tenant(project_id)

    # NOTE(imelnikov): server deletion in OpenStack is asynchronous and
    #   takes a lot of time, so to avoid races we don't delete them here
    if _project_has_servers(project_id):
        raise exc.InvalidRequest("Can't delete project "
                                 "while there are instances in it")

    # NOTE(imelnikov): image deletion would work OK here, but for consistency
    #   and safety we opt for check instead
    if _project_has_images(project_id):
        raise exc.InvalidRequest("Can't delete project "
                                 "while there are images in it")

    # detach all networks
    net_client = admin_client_set().compute.networks
    for net in net_client.list():
        if net.project_id == tenant.id:
            net_client.disassociate(net)

    try:
        tenant.delete()
    except osc_exc.NotFound:
        pass  # already deleted by someone else
    return make_json_response(None, 204)
Example #2
0
def create_project():
    data = parse_request_data(_SCHEMA.allowed, _SCHEMA.create_required)

    # first, check network
    networks = g.client_set.compute.networks
    network_id = data['network']
    try:
        net = networks.get(data['network'])
    except osc_exc.NotFound:
        raise exc.InvalidElementValue('network', 'link object', network_id,
                                      'Network does not exist.')
    if net.project_id is not None:
        raise exc.InvalidElementValue('network', 'link object', network_id,
                                      'Network is already used.')
    tenant = g.client_set.identity_admin.tenants.create(
        data['name'], data.get('description', ''))
    set_audit_resource_id(tenant)

    try:
        networks.associate(net.id, tenant.id)
    except osc_exc.BadRequest:
        tenant.delete()
        raise exc.InvalidRequest('Failed to associate network %r '
                                 'with created project' % data['network'])
    _set_quota(tenant.id, data)
    result = _project_to_view(tenant, networks.get(net.id),
                              _quotaset_for_project(tenant.id))
    return make_json_response(result)
Example #3
0
def create_my_ssh_key():
    data = parse_request_data(_SCHEMA.allowed, _SCHEMA.required)
    try:
        kp = bound_client_set().compute.keypairs.create(
            data['name'], data.get('public-key'))
    except osc_exc.BadRequest, e:
        raise exc.InvalidRequest(str(e))
Example #4
0
def check_request_headers():
    """Checks that request has all the correct headers"""
    if request.accept_mimetypes and _JSON not in request.accept_mimetypes:
        raise exc.InvalidRequest('Unsupported reply mime types: %s' %
                                 request.accept_mimetypes)
    if request.accept_charsets and 'utf-8' not in request.accept_charsets:
        raise exc.InvalidRequest('Unsupported reply charset: %s' %
                                 request.accept_charsets)
    if any(
        (key.lower().startswith('if-') for key in request.headers.iterkeys())):
        raise exc.InvalidRequest('Unsupported conditional header')
    if not _is_data_request():
        # this two functions raise or abort on error:
        _check_request_content()
        _check_request_expectations()
    return None
Example #5
0
def _check_value(value, key, max_val_len):
    if isinstance(value, basestring):
        if len(value) > max_val_len:
            raise exc.InvalidRequest('Length of request element "%s" '
                                     'must not exceed %s' % (key, max_val_len))
    elif isinstance(value, list):
        for v in value:
            _check_value(v, key, max_val_len)
Example #6
0
def _json_object_hook(data):
    max_key_len = current_app.config['MAX_ELEMENT_NAME_LENGTH']
    max_val_len = current_app.config['MAX_PARAMETER_LENGTH']
    for key, value in data.iteritems():
        if isinstance(key, basestring) and len(key) > max_key_len:
            raise exc.InvalidRequest('Bad element name: %r' % key)
        _check_value(value, key, max_val_len)
    return data
Example #7
0
def _check_invite_allowed(email_domain):
    if not g.config('invitations', 'enabled'):
        # TODO(imelnikov): consider if this is error 403, not 400
        raise exc.InvalidRequest('Invitations disabled')

    domains_allowed = g.config('invitations', 'domains-allowed')
    if domains_allowed and email_domain not in domains_allowed:
        abort(403)
Example #8
0
def create_instance_type():
    data = parse_request_data(required=_SCHEMA.required)
    args = _instance_type_for_nova(data)
    args['flavorid'] = uuid.uuid4().int
    try:
        flavor = g.client_set.compute.flavors.create(**args)
    except osc_exc.HttpException, e:
        raise exc.InvalidRequest(str(e))
Example #9
0
def remove_instance_fw_rule_set(instance_id, set_id):
    server = fetch_instance(instance_id)
    sg = _find_sg_on_server(instance_id, set_id)
    tcs = client_set_for_tenant(server.tenant_id, fallback_to_api=g.is_admin)

    try:
        tcs.compute.servers.remove_security_group(server, sg.name)
    except osc_exc.BadRequest, e:
        raise exc.InvalidRequest(str(e))
Example #10
0
def create_network():
    param = parse_request_data(_SCHEMA.required)
    client = flask.g.client_set

    # create network
    try:
        new_net = client.compute.networks.create(label=param['name'],
                                                 vlan_start=param['vlan'],
                                                 cidr=param['cidr'])
    except osc_exc.BadRequest, e:
        raise exc.InvalidRequest(str(e))
Example #11
0
def _check_request_content():
    """Validates request content type and data

    If request has a body, it must be a JSON object.

    """
    if not request.content_type and not request.data:
        return
    if request.content_type:
        if request.content_type != _JSON:
            raise exc.InvalidRequest('Unsupported content type: %r' %
                                     request.content_type)
Example #12
0
def create_users_ssh_key(user_id):
    data = parse_request_data(required=_SCHEMA.required)

    if user_id != auth.current_user_id():
        auth.assert_admin()
    fetch_user(user_id, g.is_admin)  # check that user exists and is visible

    mgr = auth.admin_client_set().compute_ext.user_keypairs
    try:
        kp = mgr.create(user_id, data['name'], data['public-key'])
    except osc_exc.BadRequest, e:
        raise exc.InvalidRequest(str(e))
Example #13
0
    def get_search_matcher(self, filter_type):
        """Get search matcher by name.

        Matcher should take a value from result object (in internal
        representation, as returned by from_argument) and a value from
        match string, and return True or False.

        """
        try:
            return self._search_matchers[filter_type]
        except KeyError:
            raise exc.InvalidRequest('No search filter %r defined '
                                     'for element %r of type %r' %
                                     (filter_type, self.name, self.typename))
Example #14
0
def send_invite_for_user(user_id):
    if not g.config('invitations', 'enabled'):
        # TODO(imelnikov): consider if this is error 403, not 400
        raise exc.InvalidRequest('Invitations disabled')

    data = parse_request_data(_SEND_INVITE_SCHEMA)
    user = fetch_user(user_id, g.is_admin)

    if data.get('disable-user', False):
        auth.assert_admin()
        update_user_data(user, {'enabled': False, 'password': None})

    result = _invite_user(user, data)
    return make_json_response(result)
Example #15
0
def add_instance_fw_rule_set(instance_id):
    server = fetch_instance(instance_id)
    set_id = parse_request_data(required=_SCHEMA.required)['id']
    set_audit_resource_id(set_id)
    try:
        sg = admin_client_set().compute.security_groups.get(set_id)
    except osc_exc.NotFound:
        raise exc.InvalidElementValue('id', 'string', set_id,
                                      'Security group does not exist')

    tcs = client_set_for_tenant(server.tenant_id, fallback_to_api=g.is_admin)
    try:
        tcs.compute.servers.add_security_group(server, sg.name)
    except osc_exc.BadRequest, e:
        raise exc.InvalidRequest(str(e))
Example #16
0
def _find_user(data):
    if 1 != sum((1 if 'id' in data else 0, 1 if 'name' in data else 0,
                 1 if 'email' in data else 0)):
        raise exc.InvalidRequest('Exactly one element of id, name or email'
                                 ' must be present')
    user_mgr = g.client_set.identity_admin.users
    try:
        if 'id' in data:
            return user_mgr.get(data['id'])
        elif 'email' in data:
            return user_mgr.find(email=data['email'])
        elif 'name' in data:
            return user_mgr.find(name=data['name'])
    except osc_exc.NotFound:
        return None
Example #17
0
def parse_request_data(allowed=None, required=None):
    """Parse request body and check satisfies schema

    This function gets request data from request.json and checks that
    all elements from required schema are present, and all other
    elements are from allowed schema.

    """
    # NOTE(imelnikov): we don't use request.json because we want
    # to raise our custom exception and add our custom validation
    try:
        data = json.loads(request.data,
                          object_hook=_json_object_hook,
                          encoding=request.mimetype_params.get('charset'))
    except ValueError, e:
        raise exc.InvalidRequest('JSON decoding error: %s' % e)
Example #18
0
def upload_image_data(image_id):
    # first, we have to validate request
    if request.content_type != 'application/octet-stream':
        raise exc.InvalidRequest('Unsupported content type: %s' %
                                 request.content_type)
    if request.content_length is None:
        abort(411)  # Length required
    expect = request.headers.get('Expect', '')[:4]
    if expect not in ('', '100-', '200-', '204-'):
        abort(417)  # Expectations failed

    image = _fetch_image(image_id, to_modify=True)  # also, checks permissions
    if image.status != 'queued':
        abort(405)  # Method not allowed

    image.update(data=request.stream, size=request.content_length)
    return make_json_response(None, status_code=204)
Example #19
0
def parse_filters(param_pairs, schema):
    """Parse response filters.

    Returns dictionary of dictionaries name -> filter type -> value.
    """
    result = {}

    for argname, value in param_pairs:
        # filters are parameters with colons in name
        if ':' in argname:
            name, match_type = argname.split(':', 1)
            namefilts = result.setdefault(name, {})
            if match_type in namefilts:
                raise exc.InvalidRequest('Duplicated filters: %s' % argname)
            try:
                namefilts[match_type] = schema.parse_argument(
                    name, match_type, value)
            except KeyError:
                raise exc.UnknownArgument(argname)
    return result
Example #20
0
def create_user():
    data = parse_request_data(_SCHEMA.create_allowed, _SCHEMA.create_required)

    email = data['email']
    email_name, email_domain = email.rsplit('@', 1)
    name = data.get('name', email_name)

    invite = data.get('invite')
    if invite:
        _check_invite_allowed(email_domain)
    else:
        if 'password' not in data:
            raise exc.MissingElement('password')
        for e in ('send-invite-mail', 'link-template'):
            if e in data:
                reason = '%s element is allowed only when inviting user' % e
                raise exc.UnknownElement(e, reason)

    user_mgr = g.client_set.identity_admin.users
    # NOTE(imelnikov): there are some races: any other user can be created or
    #   changed between following check and creation time, but this check
    #   is not for integrity, but for convenience.
    _check_attributes_unique(user_mgr.list(), name=name, email=email)

    try:
        # NOTE(imelnikov): we disable user until she accepts invite
        new_user = user_mgr.create(name=name,
                                   password=data.get('password'),
                                   email=email,
                                   enabled=not invite)
        set_audit_resource_id(new_user)
        if 'fullname' in data:
            user_mgr.update(new_user, fullname=data['fullname'])
        if data.get('admin'):
            _grant_admin(new_user.id)
        _add_user_to_projects(new_user, data.get('projects'))
    except osc_exc.BadRequest, e:
        raise exc.InvalidRequest(str(e))
Example #21
0
def _parse_one_sortby_item(item, allowed_names):
    """Convert one item of sortby list to internal representation."""
    elems = item.rsplit(':', 1)

    name = elems[0]
    if name not in allowed_names:
        raise exc.InvalidRequest(
            'Could not sort: bad parameter: %r' % elems[0])

    if len(elems) == 1 or elems[1] == 'asc':
        is_asc = True
    elif elems[1] == 'desc':
        is_asc = False
    else:
        raise exc.InvalidArgumentValue(
            'sortby', 'string', item,
            'Invalid sorting direction: %r' % elems[1])

    keys = name.split('.')
    if len(keys) == 1:
        keyfun = lambda x: x.get(name)
    else:
        keyfun = lambda x: _get_nested(x, keys)
    return name, is_asc, keyfun
Example #22
0
def _check_attributes_unique(objects, **kwargs):
    for name, value in kwargs.iteritems():
        if any(getattr(obj, name, None) == value for obj in objects):
            raise exc.InvalidRequest('User with %s %s already exists' %
                                     (name, value))
Example #23
0
    This function gets request data from request.json and checks that
    all elements from required schema are present, and all other
    elements are from allowed schema.

    """
    # NOTE(imelnikov): we don't use request.json because we want
    # to raise our custom exception and add our custom validation
    try:
        data = json.loads(request.data,
                          object_hook=_json_object_hook,
                          encoding=request.mimetype_params.get('charset'))
    except ValueError, e:
        raise exc.InvalidRequest('JSON decoding error: %s' % e)

    if not isinstance(data, dict):
        raise exc.InvalidRequest('Bad %s request: JSON object expected' %
                                 request.method)

    result = {}

    if required is not None:
        for t in required.info:
            if t.name not in data:
                raise exc.MissingElement(t.name)
            result[t.name] = t.from_request(data[t.name])

    if allowed is not None:
        for t in allowed.info:
            if t.name in data:
                result[t.name] = t.from_request(data[t.name])

    for name in data: