Revision bd40abfa snf-pithos-app/pithos/api/util.py

b/snf-pithos-app/pithos/api/util.py
50 50

  
51 51
from synnefo.lib.parsedate import parse_http_date_safe, parse_http_date
52 52
from synnefo.lib.astakos import get_user
53
from snf_django.lib.api import faults
53 54

  
54
from pithos.api.faults import (
55
    Fault, NotModified, BadRequest, Unauthorized, Forbidden, ItemNotFound,
56
    Conflict, LengthRequired, PreconditionFailed, RequestEntityTooLarge,
57
    RangeNotSatisfiable, InternalServerError, NotImplemented)
58 55
from pithos.api.settings import (BACKEND_DB_MODULE, BACKEND_DB_CONNECTION,
59 56
                                 BACKEND_BLOCK_MODULE, BACKEND_BLOCK_PATH,
60 57
                                 BACKEND_BLOCK_UMASK,
......
143 140

  
144 141
def check_meta_headers(meta):
145 142
    if len(meta) > 90:
146
        raise BadRequest('Too many headers.')
143
        raise faults.BadRequest('Too many headers.')
147 144
    for k, v in meta.iteritems():
148 145
        if len(k) > 128:
149
            raise BadRequest('Header name too large.')
146
            raise faults.BadRequest('Header name too large.')
150 147
        if len(v) > 256:
151
            raise BadRequest('Header value too large.')
148
            raise faults.BadRequest('Header value too large.')
152 149

  
153 150

  
154 151
def get_account_headers(request):
......
158 155
    for k, v in get_header_prefix(request, 'X-Account-Group-').iteritems():
159 156
        n = k[16:].lower()
160 157
        if '-' in n or '_' in n:
161
            raise BadRequest('Bad characters in group name')
158
            raise faults.BadRequest('Bad characters in group name')
162 159
        groups[n] = v.replace(' ', '').split(',')
163 160
        while '' in groups[n]:
164 161
            groups[n].remove('')
......
401 398
    if if_modified_since is not None:
402 399
        if_modified_since = parse_http_date_safe(if_modified_since)
403 400
    if if_modified_since is not None and int(meta['modified']) <= if_modified_since:
404
        raise NotModified('Resource has not been modified')
401
        raise faults.NotModified('Resource has not been modified')
405 402

  
406 403
    if_unmodified_since = request.META.get('HTTP_IF_UNMODIFIED_SINCE')
407 404
    if if_unmodified_since is not None:
408 405
        if_unmodified_since = parse_http_date_safe(if_unmodified_since)
409 406
    if if_unmodified_since is not None and int(meta['modified']) > if_unmodified_since:
410
        raise PreconditionFailed('Resource has been modified')
407
        raise faults.PreconditionFailed('Resource has been modified')
411 408

  
412 409

  
413 410
def validate_matching_preconditions(request, meta):
......
420 417
    if_match = request.META.get('HTTP_IF_MATCH')
421 418
    if if_match is not None:
422 419
        if etag is None:
423
            raise PreconditionFailed('Resource does not exist')
420
            raise faults.PreconditionFailed('Resource does not exist')
424 421
        if if_match != '*' and etag not in [x.lower() for x in parse_etags(if_match)]:
425
            raise PreconditionFailed('Resource ETag does not match')
422
            raise faults.PreconditionFailed('Resource ETag does not match')
426 423

  
427 424
    if_none_match = request.META.get('HTTP_IF_NONE_MATCH')
428 425
    if if_none_match is not None:
......
431 428
            if if_none_match == '*' or etag in [x.lower() for x in parse_etags(if_none_match)]:
432 429
                # TODO: Continue if an If-Modified-Since header is present.
433 430
                if request.method in ('HEAD', 'GET'):
434
                    raise NotModified('Resource ETag matches')
435
                raise PreconditionFailed('Resource exists or ETag matches')
431
                    raise faults.NotModified('Resource ETag matches')
432
                raise faults.PreconditionFailed('Resource exists or ETag matches')
436 433

  
437 434

  
438 435
def split_container_object_string(s):
......
464 461
                dest_account, dest_container, dest_name,
465 462
                content_type, 'pithos', meta, False, permissions, src_version, delimiter)
466 463
    except NotAllowedError:
467
        raise Forbidden('Not allowed')
464
        raise faults.Forbidden('Not allowed')
468 465
    except (ItemNotExists, VersionNotExists):
469
        raise ItemNotFound('Container or object does not exist')
466
        raise faults.ItemNotFound('Container or object does not exist')
470 467
    except ValueError:
471
        raise BadRequest('Invalid sharing header')
468
        raise faults.BadRequest('Invalid sharing header')
472 469
    except QuotaError, e:
473
        raise RequestEntityTooLarge('Quota error: %s' % e)
470
        raise faults.RequestEntityTooLarge('Quota error: %s' % e)
474 471
    if public is not None:
475 472
        try:
476 473
            request.backend.update_object_public(request.user_uniq, dest_account, dest_container, dest_name, public)
477 474
        except NotAllowedError:
478
            raise Forbidden('Not allowed')
475
            raise faults.Forbidden('Not allowed')
479 476
        except ItemNotExists:
480
            raise ItemNotFound('Object does not exist')
477
            raise faults.ItemNotFound('Object does not exist')
481 478
    return version_id
482 479

  
483 480

  
......
495 492
def get_content_length(request):
496 493
    content_length = get_int_parameter(request.META.get('CONTENT_LENGTH'))
497 494
    if content_length is None:
498
        raise LengthRequired('Missing or invalid Content-Length header')
495
        raise faults.LengthRequired('Missing or invalid Content-Length header')
499 496
    return content_length
500 497

  
501 498

  
......
604 601
            if '*' in ret['read']:
605 602
                ret['read'] = ['*']
606 603
            if len(ret['read']) == 0:
607
                raise BadRequest(
604
                raise faults.BadRequest(
608 605
                    'Bad X-Object-Sharing header value: invalid length')
609 606
        elif perm.startswith('write='):
610 607
            ret['write'] = list(set(
......
614 611
            if '*' in ret['write']:
615 612
                ret['write'] = ['*']
616 613
            if len(ret['write']) == 0:
617
                raise BadRequest(
614
                raise faults.BadRequest(
618 615
                    'Bad X-Object-Sharing header value: invalid length')
619 616
        else:
620
            raise BadRequest(
617
            raise faults.BadRequest(
621 618
                'Bad X-Object-Sharing header value: missing prefix')
622 619

  
623 620
    # replace displayname with uuid
......
630 627
                    getattr(request, 'token', None), x) \
631 628
                        for x in ret.get('write', [])]
632 629
        except ItemNotExists, e:
633
            raise BadRequest(
630
            raise faults.BadRequest(
634 631
                'Bad X-Object-Sharing header value: unknown account: %s' % e)
635 632

  
636 633
    # Keep duplicates only in write list.
......
660 657
        return True
661 658
    elif public == 'false' or public == '':
662 659
        return False
663
    raise BadRequest('Bad X-Object-Public header value')
660
    raise faults.BadRequest('Bad X-Object-Public header value')
664 661

  
665 662

  
666 663
def raw_input_socket(request):
......
692 689
                if data == '':
693 690
                    return
694 691
                yield data
695
            raise BadRequest('Maximum size is reached')
692
            raise faults.BadRequest('Maximum size is reached')
696 693

  
697 694
        # Long version (do the dechunking).
698 695
        data = ''
......
710 707
                chunk_length = chunk_length[:pos]
711 708
            try:
712 709
                chunk_length = int(chunk_length, 16)
713
            except Exception, e:
714
                raise BadRequest('Bad chunk size')
710
            except Exception:
711
                raise faults.BadRequest('Bad chunk size')
715 712
                                 # TODO: Change to something more appropriate.
716 713
            # Check if done.
717 714
            if chunk_length == 0:
......
730 727
                    data = data[blocksize:]
731 728
                    yield ret
732 729
            sock.read(2)  # CRLF
733
        raise BadRequest('Maximum size is reached')
730
        raise faults.BadRequest('Maximum size is reached')
734 731
    else:
735 732
        if length > MAX_UPLOAD_SIZE:
736
            raise BadRequest('Maximum size is reached')
733
            raise faults.BadRequest('Maximum size is reached')
737 734
        while length > 0:
738 735
            data = sock.read(min(length, blocksize))
739 736
            if not data:
740
                raise BadRequest()
737
                raise faults.BadRequest()
741 738
            length -= len(data)
742 739
            yield data
743 740

  
......
820 817
                try:
821 818
                    self.block = self.backend.get_block(self.block_hash)
822 819
                except ItemNotExists:
823
                    raise ItemNotFound('Block does not exist')
820
                    raise faults.ItemNotFound('Block does not exist')
824 821

  
825 822
            # Get the data from the block.
826 823
            bo = self.offset % self.backend.block_size
......
884 881
                 offset < 0 or offset >= size or
885 882
                 offset + length > size]
886 883
        if len(check) > 0:
887
            raise RangeNotSatisfiable('Requested range exceeds object limits')
884
            raise faults.RangeNotSatisfiable('Requested range exceeds object limits')
888 885
        ret = 206
889 886
        if_range = request.META.get('HTTP_IF_RANGE')
890 887
        if if_range:
......
1005 1002
            k.decode('ascii')
1006 1003
            v.decode('ascii')
1007 1004
        except UnicodeDecodeError:
1008
            raise BadRequest('Bad character in headers.')
1005
            raise faults.BadRequest('Bad character in headers.')
1009 1006
        if '%' in k or '%' in v:
1010 1007
            del(request.META[k])
1011 1008
            request.META[unquote(k)] = smart_unicode(unquote(
......
1035 1032

  
1036 1033

  
1037 1034
def render_fault(request, fault):
1038
    if isinstance(fault, InternalServerError) and settings.DEBUG:
1035
    if isinstance(fault, faults.InternalServerError) and settings.DEBUG:
1039 1036
        fault.details = format_exc(fault)
1040 1037

  
1041 1038
    request.serialization = 'text'
......
1085 1082
        def wrapper(request, *args, **kwargs):
1086 1083
            try:
1087 1084
                if http_method and request.method != http_method:
1088
                    raise BadRequest('Method not allowed.')
1085
                    raise faults.BadRequest('Method not allowed.')
1089 1086

  
1090 1087
                if user_required:
1091 1088
                    token = None
......
1099 1096
                             token,
1100 1097
                             request_usage)
1101 1098
                    if  getattr(request, 'user', None) is None:
1102
                        raise Unauthorized('Access denied')
1099
                        raise faults.Unauthorized('Access denied')
1103 1100
                    assert getattr(request, 'user_uniq', None) != None
1104 1101
                    request.user_usage = get_pithos_usage(request.user.get('usage', []))
1105 1102
                    request.token = request.GET.get('X-Auth-Token', request.META.get('HTTP_X_AUTH_TOKEN', token))
1106 1103

  
1107 1104
                # The args variable may contain up to (account, container, object).
1108 1105
                if len(args) > 1 and len(args[1]) > 256:
1109
                    raise BadRequest('Container name too large.')
1106
                    raise faults.BadRequest('Container name too large.')
1110 1107
                if len(args) > 2 and len(args[2]) > 1024:
1111
                    raise BadRequest('Object name too large.')
1108
                    raise faults.BadRequest('Object name too large.')
1112 1109

  
1113 1110
                # Format and check headers.
1114 1111
                update_request_headers(request)
......
1121 1118
                response = func(request, *args, **kwargs)
1122 1119
                update_response_headers(request, response)
1123 1120
                return response
1124
            except Fault, fault:
1121
            except faults.Fault, fault:
1125 1122
                if fault.code >= 500:
1126 1123
                    logger.exception("API Fault")
1127 1124
                return render_fault(request, fault)
1128 1125
            except BaseException, e:
1129 1126
                logger.exception('Unexpected error: %s' % e)
1130
                fault = InternalServerError('Unexpected error')
1127
                fault = faults.InternalServerError('Unexpected error')
1131 1128
                return render_fault(request, fault)
1132 1129
            finally:
1133 1130
                if getattr(request, 'backend', None) is not None:

Also available in: Unified diff