~ubuntu-branches/ubuntu/vivid/swift/vivid-updates

« back to all changes in this revision

Viewing changes to swift/obj/server.py

  • Committer: Package Import Robot
  • Author(s): James Page, Chuck Short, James Page
  • Date: 2014-10-06 10:06:11 UTC
  • mfrom: (1.2.31)
  • Revision ID: package-import@ubuntu.com-20141006100611-wdzkkuoru7ubtlml
Tags: 2.1.0-0ubuntu1
[ Chuck Short ]
* debian/patches/fix-doc-no-network.patch: Refreshed.
* debian/control: Add python-oslosphinx as a build dependency.

[ James Page ]
* New upstream release for OpenStack Juno.
* d/copyright: Add linebreaks to fixup file-without-copyright-
  information warning.

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
 
30
30
from swift.common.utils import public, get_logger, \
31
31
    config_true_value, timing_stats, replication, \
32
 
    normalize_delete_at_timestamp, get_log_line, Timestamp
 
32
    normalize_delete_at_timestamp, get_log_line, Timestamp, \
 
33
    get_expirer_container
33
34
from swift.common.bufferedhttp import http_connect
34
35
from swift.common.constraints import check_object_creation, \
35
36
    valid_timestamp, check_utf8
38
39
    DiskFileDeviceUnavailable, DiskFileExpired, ChunkReadTimeout
39
40
from swift.obj import ssync_receiver
40
41
from swift.common.http import is_success
41
 
from swift.common.request_helpers import get_name_and_placement, is_user_meta
 
42
from swift.common.request_helpers import get_name_and_placement, \
 
43
    is_user_meta, is_sys_or_user_meta
42
44
from swift.common.swob import HTTPAccepted, HTTPBadRequest, HTTPCreated, \
43
45
    HTTPInternalServerError, HTTPNoContent, HTTPNotFound, \
44
46
    HTTPPreconditionFailed, HTTPRequestTimeout, HTTPUnprocessableEntity, \
46
48
    HTTPInsufficientStorage, HTTPForbidden, HTTPException, HeaderKeyDict, \
47
49
    HTTPConflict
48
50
from swift.obj.diskfile import DATAFILE_SYSTEM_META, DiskFileManager
49
 
from swift.common.storage_policy import POLICY_INDEX
50
51
 
51
52
 
52
53
class ObjectController(object):
113
114
        # network_chunk_size parameter value instead.
114
115
        socket._fileobject.default_bufsize = self.network_chunk_size
115
116
 
116
 
        # Provide further setup sepecific to an object server implemenation.
 
117
        # Provide further setup specific to an object server implementation.
117
118
        self.setup(conf)
118
119
 
119
120
    def setup(self, conf):
170
171
        :param objdevice: device name that the object is in
171
172
        :param policy_index: the associated storage policy index
172
173
        """
173
 
        headers_out['user-agent'] = 'obj-server %s' % os.getpid()
 
174
        headers_out['user-agent'] = 'object-server %s' % os.getpid()
174
175
        full_path = '/%s/%s/%s' % (account, container, obj)
175
176
        if all([host, partition, contdevice]):
176
177
            try:
240
241
 
241
242
        headers_out['x-trans-id'] = headers_in.get('x-trans-id', '-')
242
243
        headers_out['referer'] = request.as_referer()
243
 
        headers_out[POLICY_INDEX] = policy_idx
 
244
        headers_out['X-Backend-Storage-Policy-Index'] = policy_idx
244
245
        for conthost, contdevice in updates:
245
246
            self.async_update(op, account, container, obj, conthost,
246
247
                              contpartition, contdevice, headers_out,
270
271
        hosts = contdevices = [None]
271
272
        headers_in = request.headers
272
273
        headers_out = HeaderKeyDict({
273
 
            POLICY_INDEX: 0,  # system accounts are always Policy-0
 
274
            # system accounts are always Policy-0
 
275
            'X-Backend-Storage-Policy-Index': 0,
274
276
            'x-timestamp': request.timestamp.internal,
275
277
            'x-trans-id': headers_in.get('x-trans-id', '-'),
276
278
            'referer': request.as_referer()})
283
285
                    'best guess as to the container name for now.' % op)
284
286
                # TODO(gholt): In a future release, change the above warning to
285
287
                # a raised exception and remove the guess code below.
286
 
                delete_at_container = (
287
 
                    int(delete_at) / self.expiring_objects_container_divisor *
288
 
                    self.expiring_objects_container_divisor)
 
288
                delete_at_container = get_expirer_container(
 
289
                    delete_at, self.expiring_objects_container_divisor,
 
290
                    account, container, obj)
289
291
            partition = headers_in.get('X-Delete-At-Partition', None)
290
292
            hosts = headers_in.get('X-Delete-At-Host', '')
291
293
            contdevices = headers_in.get('X-Delete-At-Device', '')
306
308
            # exist there and the original data is left where it is, where
307
309
            # it will be ignored when the expirer eventually tries to issue the
308
310
            # object DELETE later since the X-Delete-At value won't match up.
309
 
            delete_at_container = str(
310
 
                int(delete_at) / self.expiring_objects_container_divisor *
311
 
                self.expiring_objects_container_divisor)
 
311
            delete_at_container = get_expirer_container(
 
312
                delete_at, self.expiring_objects_container_divisor,
 
313
                account, container, obj)
312
314
        delete_at_container = normalize_delete_at_timestamp(
313
315
            delete_at_container)
314
316
 
342
344
            return HTTPNotFound(request=request)
343
345
        orig_timestamp = Timestamp(orig_metadata.get('X-Timestamp', 0))
344
346
        if orig_timestamp >= req_timestamp:
345
 
            return HTTPConflict(request=request)
 
347
            return HTTPConflict(
 
348
                request=request,
 
349
                headers={'X-Backend-Timestamp': orig_timestamp.internal})
346
350
        metadata = {'X-Timestamp': req_timestamp.internal}
347
351
        metadata.update(val for val in request.headers.iteritems()
348
352
                        if is_user_meta('object', val[0]))
402
406
                return HTTPPreconditionFailed(request=request)
403
407
 
404
408
        orig_timestamp = Timestamp(orig_metadata.get('X-Timestamp', 0))
405
 
        if orig_timestamp and orig_timestamp >= req_timestamp:
406
 
            return HTTPConflict(request=request)
 
409
        if orig_timestamp >= req_timestamp:
 
410
            return HTTPConflict(
 
411
                request=request,
 
412
                headers={'X-Backend-Timestamp': orig_timestamp.internal})
407
413
        orig_delete_at = int(orig_metadata.get('X-Delete-At') or 0)
408
414
        upload_expiration = time.time() + self.max_upload_time
409
415
        etag = md5()
445
451
                    'Content-Length': str(upload_size),
446
452
                }
447
453
                metadata.update(val for val in request.headers.iteritems()
448
 
                                if is_user_meta('object', val[0]))
 
454
                                if is_sys_or_user_meta('object', val[0]))
449
455
                for header_key in (
450
456
                        request.headers.get('X-Backend-Replication-Headers') or
451
457
                        self.allowed_headers):
503
509
                response.headers['Content-Type'] = metadata.get(
504
510
                    'Content-Type', 'application/octet-stream')
505
511
                for key, value in metadata.iteritems():
506
 
                    if is_user_meta('object', key) or \
 
512
                    if is_sys_or_user_meta('object', key) or \
507
513
                            key.lower() in self.allowed_headers:
508
514
                        response.headers[key] = value
509
515
                response.etag = metadata['ETag']
549
555
        response.headers['Content-Type'] = metadata.get(
550
556
            'Content-Type', 'application/octet-stream')
551
557
        for key, value in metadata.iteritems():
552
 
            if is_user_meta('object', key) or \
 
558
            if is_sys_or_user_meta('object', key) or \
553
559
                    key.lower() in self.allowed_headers:
554
560
                response.headers[key] = value
555
561
        response.etag = metadata['ETag']
598
604
                response_class = HTTPNoContent
599
605
            else:
600
606
                response_class = HTTPConflict
 
607
        response_timestamp = max(orig_timestamp, req_timestamp)
601
608
        orig_delete_at = int(orig_metadata.get('X-Delete-At') or 0)
602
609
        try:
603
610
            req_if_delete_at_val = request.headers['x-if-delete-at']
631
638
                'DELETE', account, container, obj, request,
632
639
                HeaderKeyDict({'x-timestamp': req_timestamp.internal}),
633
640
                device, policy_idx)
634
 
        return response_class(request=request)
 
641
        return response_class(
 
642
            request=request,
 
643
            headers={'X-Backend-Timestamp': response_timestamp.internal})
635
644
 
636
645
    @public
637
646
    @replication