Revision 5df6c6d1

b/docs/source/devguide.rst
25 25
=========================  ================================
26 26
Revision                   Description
27 27
=========================  ================================
28
0.7 (Oct 13, 2011)         Suggest upload/download methods using hashmaps.
28
0.7 (Oct 17, 2011)         Suggest upload/download methods using hashmaps.
29 29
\                          Propose syncing algorithm.
30 30
\                          Support cross-account object copy and move.
31 31
\                          Pass token as a request parameter when using ``POST`` via an HTML form.
32 32
\                          Optionally use source account to update object from another object.
33 33
\                          Use container ``POST`` to upload missing blocks of data.
34 34
\                          Report policy in account headers.
35
\                          Add insufficient quota reply.
35 36
0.6 (Sept 13, 2011)        Reply with Merkle hash as the ETag when updating objects.
36 37
\                          Include version id in object replace/change replies.
37 38
\                          Change conflict (409) replies format to text.
......
763 764

  
764 765
The ``X-Object-Sharing`` header may include either a ``read=...`` comma-separated user/group list, or a ``write=...`` comma-separated user/group list, or both separated by a semicolon (``;``). Groups are specified as ``<account>:<group>``. To publish the object, set ``X-Object-Public`` to ``true``. To unpublish, set to ``false``, or use an empty header value.
765 766

  
766
===========================  ==============================
767
Return Code                  Description
768
===========================  ==============================
769
201 (Created)                The object has been created
770
409 (Conflict)               The object can not be created from the provided hashmap, or there are conflicting permissions (a list of missing hashes, or a list of conflicting sharing paths will be included in the reply - in simple text format)
771
411 (Length Required)        Missing ``Content-Length`` or ``Content-Type`` in the request
772
422 (Unprocessable Entity)   The MD5 checksum of the data written to the storage system does not match the (optionally) supplied ETag value
773
===========================  ==============================
767
==============================  ==============================
768
Return Code                     Description
769
==============================  ==============================
770
201 (Created)                   The object has been created
771
409 (Conflict)                  The object can not be created from the provided hashmap, or there are conflicting permissions (a list of missing hashes, or a list of conflicting sharing paths will be included in the reply - in simple text format)
772
411 (Length Required)           Missing ``Content-Length`` or ``Content-Type`` in the request
773
413 (Request Entity Too Large)  Insufficient quota to complete the request
774
422 (Unprocessable Entity)      The MD5 checksum of the data written to the storage system does not match the (optionally) supplied ETag value
775
==============================  ==============================
774 776

  
775 777

  
776 778
COPY
......
803 805

  
804 806
|
805 807

  
806
===========================  ==============================
807
Return Code                  Description
808
===========================  ==============================
809
201 (Created)                The object has been created
810
409 (Conflict)               There are conflicting permissions (a list of conflicting sharing paths will be included in the reply - in simple text format)
811
===========================  ==============================
808
==============================  ==============================
809
Return Code                     Description
810
==============================  ==============================
811
201 (Created)                   The object has been created
812
409 (Conflict)                  There are conflicting permissions (a list of conflicting sharing paths will be included in the reply - in simple text format)
813
413 (Request Entity Too Large)  Insufficient quota to complete the request
814
==============================  ==============================
812 815

  
813 816

  
814 817
MOVE
......
878 881

  
879 882
|
880 883

  
881
===========================  ==============================
882
Return Code                  Description
883
===========================  ==============================
884
202 (Accepted)               The request has been accepted (not a data update)
885
204 (No Content)             The request succeeded (data updated)
886
409 (Conflict)               There are conflicting permissions (a list of conflicting sharing paths will be included in the reply - in simple text format)
887
411 (Length Required)        Missing ``Content-Length`` in the request
888
416 (Range Not Satisfiable)  The supplied range is invalid
889
===========================  ==============================
884
==============================  ==============================
885
Return Code                     Description
886
==============================  ==============================
887
202 (Accepted)                  The request has been accepted (not a data update)
888
204 (No Content)                The request succeeded (data updated)
889
409 (Conflict)                  There are conflicting permissions (a list of conflicting sharing paths will be included in the reply - in simple text format)
890
411 (Length Required)           Missing ``Content-Length`` in the request
891
413 (Request Entity Too Large)  Insufficient quota to complete the request
892
416 (Range Not Satisfiable)     The supplied range is invalid
893
==============================  ==============================
890 894

  
891 895
The ``POST`` method can also be used for creating an object via a standard HTML form. If the request ``Content-Type`` is ``multipart/form-data``, none of the above headers will be processed. The form should have an ``X-Object-Data`` field, as in the following example. The token is passed as a request parameter. ::
892 896

  
......
906 910

  
907 911
|
908 912

  
909
===========================  ==============================
910
Return Code                  Description
911
===========================  ==============================
912
201 (Created)                The object has been created
913
===========================  ==============================
913
==============================  ==============================
914
Return Code                     Description
915
==============================  ==============================
916
201 (Created)                   The object has been created
917
413 (Request Entity Too Large)  Insufficient quota to complete the request
918
==============================  ==============================
914 919

  
915 920

  
916 921
DELETE
b/pithos/api/functions.py
43 43
from xml.dom import minidom
44 44

  
45 45
from pithos.api.faults import (Fault, NotModified, BadRequest, Unauthorized, ItemNotFound, Conflict,
46
    LengthRequired, PreconditionFailed, RangeNotSatisfiable, UnprocessableEntity)
46
    LengthRequired, PreconditionFailed, RequestEntityTooLarge, RangeNotSatisfiable, UnprocessableEntity)
47 47
from pithos.api.util import (rename_meta_key, format_header_key, printable_header_dict, get_account_headers,
48 48
    put_account_headers, get_container_headers, put_container_headers, get_object_headers, put_object_headers,
49 49
    update_manifest_meta, update_sharing_meta, update_public_meta, validate_modification_preconditions,
......
51 51
    get_int_parameter, get_content_length, get_content_range, socket_read_iterator,
52 52
    object_data_response, put_object_block, hashmap_hash, api_method, json_encode_decimal)
53 53
from pithos.backends import connect_backend
54
from pithos.backends.base import NotAllowedError
54
from pithos.backends.base import NotAllowedError, QuotaError
55 55

  
56 56

  
57 57
logger = logging.getLogger(__name__)
......
838 838
        raise BadRequest('Invalid sharing header')
839 839
    except AttributeError, e:
840 840
        raise Conflict('\n'.join(e.data) + '\n')
841
    except QuotaError:
842
        raise RequestEntityTooLarge('Quota exceeded')
841 843
    if public is not None:
842 844
        try:
843 845
            request.backend.update_object_public(request.user, v_account,
......
884 886
        raise Unauthorized('Access denied')
885 887
    except NameError:
886 888
        raise ItemNotFound('Container does not exist')
889
    except QuotaError:
890
        raise RequestEntityTooLarge('Quota exceeded')
887 891
    
888 892
    response = HttpResponse(status=201)
889 893
    response['ETag'] = meta['hash']
......
1163 1167
        raise BadRequest('Invalid sharing header')
1164 1168
    except AttributeError, e:
1165 1169
        raise Conflict('\n'.join(e.data) + '\n')
1170
    except QuotaError:
1171
        raise RequestEntityTooLarge('Quota exceeded')
1166 1172
    if public is not None:
1167 1173
        try:
1168 1174
            request.backend.update_object_public(request.user, v_account,
b/pithos/api/util.py
46 46

  
47 47
from pithos.api.compat import parse_http_date_safe, parse_http_date
48 48
from pithos.api.faults import (Fault, NotModified, BadRequest, Unauthorized, ItemNotFound,
49
                                Conflict, LengthRequired, PreconditionFailed, RangeNotSatisfiable,
50
                                ServiceUnavailable)
49
                                Conflict, LengthRequired, PreconditionFailed, RequestEntityTooLarge,
50
                                RangeNotSatisfiable, ServiceUnavailable)
51 51
from pithos.backends import connect_backend
52
from pithos.backends.base import NotAllowedError
52
from pithos.backends.base import NotAllowedError, QuotaError
53 53

  
54 54
import logging
55 55
import re
......
310 310
        raise BadRequest('Invalid sharing header')
311 311
    except AttributeError, e:
312 312
        raise Conflict('\n'.join(e.data) + '\n')
313
    except QuotaError:
314
        raise RequestEntityTooLarge('Quota exceeded')
313 315
    if public is not None:
314 316
        try:
315 317
            request.backend.update_object_public(request.user, dest_account, dest_container, dest_name, public)
b/pithos/backends/base.py
34 34
class NotAllowedError(Exception):
35 35
    pass
36 36

  
37
class QuotaError(Exception):
38
    pass
39

  
37 40
class BaseBackend(object):
38 41
    """Abstract backend class that serves as a reference for actual implementations.
39 42
    
......
427 430
            ValueError: Invalid users/groups in permissions
428 431
            
429 432
            AttributeError: Can not set permissions
433
            
434
            QuotaError: Account or container quota exceeded
430 435
        """
431 436
        return ''
432 437
    
......
452 457
            ValueError: Invalid users/groups in permissions
453 458
            
454 459
            AttributeError: Can not set permissions
460
            
461
            QuotaError: Account or container quota exceeded
455 462
        """
456 463
        return ''
457 464
    
......
473 480
            ValueError: Invalid users/groups in permissions
474 481
            
475 482
            AttributeError: Can not set permissions
483
            
484
            QuotaError: Account or container quota exceeded
476 485
        """
477 486
        return ''
478 487
    
b/pithos/backends/modular.py
38 38
import hashlib
39 39
import binascii
40 40

  
41
from base import NotAllowedError, BaseBackend
41
from base import NotAllowedError, QuotaError, BaseBackend
42 42
from lib.hashfiler import Mapper, Blocker
43 43

  
44 44
( CLUSTER_NORMAL, CLUSTER_HISTORY, CLUSTER_DELETED ) = range(3)
......
546 546
            if (account_quota > 0 and self._get_statistics(account_node)[1] + size_delta > account_quota) or \
547 547
               (container_quota > 0 and self._get_statistics(container_node)[1] + size_delta > container_quota):
548 548
                # This must be executed in a transaction, so the version is never created if it fails.
549
                raise
549
                raise QuotaError
550 550
        
551 551
        if not replace_meta and src_version_id is not None:
552 552
            self.node.attribute_copy(src_version_id, dest_version_id)

Also available in: Unified diff