146 |
146 |
else:
|
147 |
147 |
meta = {}
|
148 |
148 |
if props is not None:
|
149 |
|
meta.update(dict(self.node.attribute_get(props[self.SERIAL])))
|
|
149 |
meta.update(dict(self.node.attribute_get(props[self.SERIAL], domain)))
|
150 |
150 |
if until is not None:
|
151 |
151 |
meta.update({'until_timestamp': tstamp})
|
152 |
152 |
meta.update({'name': account, 'count': count, 'bytes': bytes})
|
... | ... | |
161 |
161 |
if user != account:
|
162 |
162 |
raise NotAllowedError
|
163 |
163 |
path, node = self._lookup_account(account, True)
|
164 |
|
self._put_metadata(user, node, meta, replace)
|
|
164 |
self._put_metadata(user, node, domain, meta, replace)
|
165 |
165 |
|
166 |
166 |
@backend_method
|
167 |
167 |
def get_account_groups(self, user, account):
|
... | ... | |
261 |
261 |
start, limit = self._list_limits(allowed, marker, limit)
|
262 |
262 |
return allowed[start:start + limit]
|
263 |
263 |
node = self.node.node_lookup(account)
|
264 |
|
return [x[0] for x in self._list_objects(node, account, '', '/', marker, limit, False, [], until)]
|
|
264 |
return [x[0] for x in self._list_objects(node, account, '', '/', marker, limit, False, None, [], until)]
|
265 |
265 |
|
266 |
266 |
@backend_method
|
267 |
267 |
def get_container_meta(self, user, account, container, domain, until=None):
|
... | ... | |
285 |
285 |
if user != account:
|
286 |
286 |
meta = {'name': container}
|
287 |
287 |
else:
|
288 |
|
meta = dict(self.node.attribute_get(props[self.SERIAL]))
|
|
288 |
meta = dict(self.node.attribute_get(props[self.SERIAL], domain))
|
289 |
289 |
if until is not None:
|
290 |
290 |
meta.update({'until_timestamp': tstamp})
|
291 |
291 |
meta.update({'name': container, 'count': count, 'bytes': bytes})
|
... | ... | |
300 |
300 |
if user != account:
|
301 |
301 |
raise NotAllowedError
|
302 |
302 |
path, node = self._lookup_container(account, container)
|
303 |
|
self._put_metadata(user, node, meta, replace)
|
|
303 |
self._put_metadata(user, node, domain, meta, replace)
|
304 |
304 |
|
305 |
305 |
@backend_method
|
306 |
306 |
def get_container_policy(self, user, account, container):
|
... | ... | |
386 |
386 |
if not allowed:
|
387 |
387 |
return []
|
388 |
388 |
path, node = self._lookup_container(account, container)
|
389 |
|
return self._list_objects(node, path, prefix, delimiter, marker, limit, virtual, keys, until, allowed)
|
|
389 |
return self._list_objects(node, path, prefix, delimiter, marker, limit, virtual, domain, keys, until, allowed)
|
390 |
390 |
|
391 |
391 |
@backend_method
|
392 |
392 |
def list_object_meta(self, user, account, container, domain, until=None):
|
... | ... | |
402 |
402 |
raise NotAllowedError
|
403 |
403 |
path, node = self._lookup_container(account, container)
|
404 |
404 |
before = until if until is not None else inf
|
405 |
|
return self.node.latest_attribute_keys(node, before, CLUSTER_DELETED, allowed)
|
|
405 |
return self.node.latest_attribute_keys(node, domain, before, CLUSTER_DELETED, allowed)
|
406 |
406 |
|
407 |
407 |
@backend_method
|
408 |
408 |
def get_object_meta(self, user, account, container, name, domain, version=None):
|
... | ... | |
423 |
423 |
raise NameError('Object does not exist')
|
424 |
424 |
modified = del_props[self.MTIME]
|
425 |
425 |
|
426 |
|
meta = dict(self.node.attribute_get(props[self.SERIAL]))
|
|
426 |
meta = dict(self.node.attribute_get(props[self.SERIAL], domain))
|
427 |
427 |
meta.update({'name': name, 'bytes': props[self.SIZE], 'hash':props[self.HASH]})
|
428 |
428 |
meta.update({'version': props[self.SERIAL], 'version_timestamp': props[self.MTIME]})
|
429 |
429 |
meta.update({'modified': modified, 'modified_by': props[self.MUSER]})
|
... | ... | |
436 |
436 |
logger.debug("update_object_meta: %s %s %s %s %s %s", account, container, name, domain, meta, replace)
|
437 |
437 |
self._can_write(user, account, container, name)
|
438 |
438 |
path, node = self._lookup_object(account, container, name)
|
439 |
|
src_version_id, dest_version_id = self._put_metadata(user, node, meta, replace)
|
|
439 |
src_version_id, dest_version_id = self._put_metadata(user, node, domain, meta, replace)
|
440 |
440 |
self._apply_versioning(account, container, src_version_id)
|
441 |
441 |
return dest_version_id
|
442 |
442 |
|
... | ... | |
505 |
505 |
hashmap = self.store.map_get(binascii.unhexlify(props[self.HASH]))
|
506 |
506 |
return props[self.SIZE], [binascii.hexlify(x) for x in hashmap]
|
507 |
507 |
|
508 |
|
def _update_object_hash(self, user, account, container, name, size, hash, meta={}, replace_meta=False, permissions=None):
|
|
508 |
def _update_object_hash(self, user, account, container, name, size, hash, permissions=None):
|
509 |
509 |
if permissions is not None and user != account:
|
510 |
510 |
raise NotAllowedError
|
511 |
511 |
self._can_write(user, account, container, name)
|
... | ... | |
528 |
528 |
# This must be executed in a transaction, so the version is never created if it fails.
|
529 |
529 |
raise QuotaError
|
530 |
530 |
|
531 |
|
if not replace_meta and src_version_id is not None:
|
532 |
|
self.node.attribute_copy(src_version_id, dest_version_id)
|
533 |
|
self.node.attribute_set(dest_version_id, ((k, v) for k, v in meta.iteritems()))
|
534 |
531 |
if permissions is not None:
|
535 |
532 |
self.permissions.access_set(path, permissions)
|
536 |
533 |
self._apply_versioning(account, container, src_version_id)
|
537 |
|
return dest_version_id
|
|
534 |
return src_version_id, dest_version_id
|
538 |
535 |
|
539 |
536 |
@backend_method
|
540 |
537 |
def update_object_hashmap(self, user, account, container, name, size, hashmap, domain, meta={}, replace_meta=False, permissions=None):
|
... | ... | |
552 |
549 |
raise ie
|
553 |
550 |
|
554 |
551 |
hash = map.hash()
|
555 |
|
dest_version_id = self._update_object_hash(user, account, container, name, size, binascii.hexlify(hash), meta, replace_meta, permissions)
|
|
552 |
src_version_id, dest_version_id = self._update_object_hash(user, account, container, name, size, binascii.hexlify(hash), permissions)
|
|
553 |
self._put_metadata_duplicate(src_version_id, dest_version_id, domain, meta, replace_meta)
|
556 |
554 |
self.store.map_put(hash, map)
|
557 |
555 |
return dest_version_id
|
558 |
556 |
|
559 |
|
def _copy_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, dest_meta={}, replace_meta=False, permissions=None, src_version=None):
|
|
557 |
def _copy_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, dest_domain=None, dest_meta={}, replace_meta=False, permissions=None, src_version=None):
|
560 |
558 |
self._can_read(user, src_account, src_container, src_name)
|
561 |
559 |
path, node = self._lookup_object(src_account, src_container, src_name)
|
562 |
560 |
props = self._get_version(node, src_version)
|
... | ... | |
564 |
562 |
hash = props[self.HASH]
|
565 |
563 |
size = props[self.SIZE]
|
566 |
564 |
|
567 |
|
if (src_account, src_container, src_name) == (dest_account, dest_container, dest_name):
|
568 |
|
dest_version_id = self._update_object_hash(user, dest_account, dest_container, dest_name, size, hash, dest_meta, replace_meta, permissions)
|
569 |
|
else:
|
570 |
|
if replace_meta:
|
571 |
|
meta = dest_meta
|
572 |
|
else:
|
573 |
|
meta = {}
|
574 |
|
dest_version_id = self._update_object_hash(user, dest_account, dest_container, dest_name, size, hash, meta, True, permissions)
|
575 |
|
if not replace_meta:
|
576 |
|
self.node.attribute_copy(src_version_id, dest_version_id)
|
577 |
|
self.node.attribute_set(dest_version_id, ((k, v) for k, v in dest_meta.iteritems()))
|
|
565 |
src_v_id, dest_version_id = self._update_object_hash(user, dest_account, dest_container, dest_name, size, hash, permissions)
|
|
566 |
self._put_metadata_duplicate(src_version_id, dest_version_id, dest_domain, dest_meta, replace_meta)
|
578 |
567 |
return dest_version_id
|
579 |
568 |
|
580 |
569 |
@backend_method
|
... | ... | |
582 |
571 |
"""Copy an object's data and metadata."""
|
583 |
572 |
|
584 |
573 |
logger.debug("copy_object: %s %s %s %s %s %s %s %s %s %s %s", src_account, src_container, src_name, dest_account, dest_container, dest_name, domain, meta, replace_meta, permissions, src_version)
|
585 |
|
return self._copy_object(user, src_account, src_container, src_name, dest_account, dest_container, dest_name, dest_meta, replace_meta, permissions, src_version)
|
|
574 |
return self._copy_object(user, src_account, src_container, src_name, dest_account, dest_container, dest_name, domain, meta, replace_meta, permissions, src_version)
|
586 |
575 |
|
587 |
576 |
@backend_method
|
588 |
577 |
def move_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, domain, meta={}, replace_meta=False, permissions=None):
|
... | ... | |
591 |
580 |
logger.debug("move_object: %s %s %s %s %s %s %s %s %s %s", src_account, src_container, src_name, dest_account, dest_container, dest_name, domain, meta, replace_meta, permissions)
|
592 |
581 |
if user != src_account:
|
593 |
582 |
raise NotAllowedError
|
594 |
|
dest_version_id = self._copy_object(user, src_account, src_container, src_name, dest_account, dest_container, dest_name, meta, replace_meta, permissions, None)
|
|
583 |
dest_version_id = self._copy_object(user, src_account, src_container, src_name, dest_account, dest_container, dest_name, domain, meta, replace_meta, permissions, None)
|
595 |
584 |
if (src_account, src_container, src_name) != (dest_account, dest_container, dest_name):
|
596 |
585 |
self._delete_object(user, src_account, src_container, src_name)
|
597 |
586 |
return dest_version_id
|
... | ... | |
768 |
757 |
dest_version_id, mtime = self.node.version_create(node, hash, size, src_version_id, user, cluster)
|
769 |
758 |
return src_version_id, dest_version_id
|
770 |
759 |
|
771 |
|
def _put_metadata(self, user, node, meta, replace=False):
|
|
760 |
def _put_metadata_duplicate(self, src_version_id, dest_version_id, domain, meta, replace=False):
|
|
761 |
if src_version_id is not None:
|
|
762 |
self.node.attribute_copy(src_version_id, dest_version_id)
|
|
763 |
if not replace:
|
|
764 |
self.node.attribute_del(dest_version_id, domain, (k for k, v in meta.iteritems() if v == ''))
|
|
765 |
self.node.attribute_set(dest_version_id, domain, ((k, v) for k, v in meta.iteritems() if v != ''))
|
|
766 |
else:
|
|
767 |
self.node.attribute_del(dest_version_id, domain)
|
|
768 |
self.node.attribute_set(dest_version_id, domain, ((k, v) for k, v in meta.iteritems()))
|
|
769 |
|
|
770 |
def _put_metadata(self, user, node, domain, meta, replace=False):
|
772 |
771 |
"""Create a new version and store metadata."""
|
773 |
772 |
|
774 |
773 |
src_version_id, dest_version_id = self._put_version_duplicate(user, node)
|
775 |
|
|
776 |
|
# TODO: Merge with other functions that update metadata...
|
777 |
|
if not replace:
|
778 |
|
if src_version_id is not None:
|
779 |
|
self.node.attribute_copy(src_version_id, dest_version_id)
|
780 |
|
self.node.attribute_del(dest_version_id, (k for k, v in meta.iteritems() if v == ''))
|
781 |
|
self.node.attribute_set(dest_version_id, ((k, v) for k, v in meta.iteritems() if v != ''))
|
782 |
|
else:
|
783 |
|
self.node.attribute_set(dest_version_id, ((k, v) for k, v in meta.iteritems()))
|
|
774 |
self._put_metadata_duplicate(src_version_id, dest_version_id, domain, meta, replace)
|
784 |
775 |
return src_version_id, dest_version_id
|
785 |
776 |
|
786 |
777 |
def _list_limits(self, listing, marker, limit):
|
... | ... | |
794 |
785 |
limit = 10000
|
795 |
786 |
return start, limit
|
796 |
787 |
|
797 |
|
def _list_objects(self, parent, path, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, keys=[], until=None, allowed=[]):
|
|
788 |
def _list_objects(self, parent, path, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, domain=None, keys=[], until=None, allowed=[]):
|
798 |
789 |
cont_prefix = path + '/'
|
799 |
790 |
prefix = cont_prefix + prefix
|
800 |
791 |
start = cont_prefix + marker if marker else None
|
801 |
792 |
before = until if until is not None else inf
|
802 |
|
filterq = ','.join(keys) if keys else None
|
|
793 |
filterq = keys if domain else []
|
803 |
794 |
|
804 |
|
objects, prefixes = self.node.latest_version_list(parent, prefix, delimiter, start, limit, before, CLUSTER_DELETED, allowed, filterq)
|
|
795 |
objects, prefixes = self.node.latest_version_list(parent, prefix, delimiter, start, limit, before, CLUSTER_DELETED, allowed, domain, filterq)
|
805 |
796 |
objects.extend([(p, None) for p in prefixes] if virtual else [])
|
806 |
797 |
objects.sort(key=lambda x: x[0])
|
807 |
798 |
objects = [(x[0][len(cont_prefix):], x[1]) for x in objects]
|