Revision 4d15c94e snf-pithos-backend/pithos/backends/modular.py
b/snf-pithos-backend/pithos/backends/modular.py | ||
---|---|---|
476 | 476 |
allowed = self._get_formatted_paths(allowed) |
477 | 477 |
return self._list_object_properties(node, path, prefix, delimiter, marker, limit, virtual, domain, keys, until, size_range, allowed, all_props) |
478 | 478 |
|
479 |
def _list_objects_no_limit(self, user, account, container, prefix, delimiter, virtual, domain, keys, shared, until, size_range, all_props, public): |
|
480 |
objects = [] |
|
481 |
while True: |
|
482 |
marker = objects[-1] if objects else None |
|
483 |
limit = 10000 |
|
484 |
l = self._list_objects(user, account, container, prefix, delimiter, marker, limit, virtual, domain, keys, shared, until, size_range, all_props, public) |
|
485 |
objects.extend(l) |
|
486 |
if not l or len(l) < limit: |
|
487 |
break |
|
488 |
return objects |
|
489 |
|
|
479 | 490 |
def _list_object_permissions(self, user, account, container, prefix, shared, public): |
480 | 491 |
allowed = [] |
481 | 492 |
path = '/'.join((account, container, prefix)).rstrip('/') |
... | ... | |
724 | 735 |
if x[self.SERIAL] >= int(version) and x[self.HASH] == props[self.HASH] and x[self.SIZE] == props[self.SIZE]: |
725 | 736 |
self.node.version_put_property(x[self.SERIAL], 'checksum', checksum) |
726 | 737 |
|
727 |
def _copy_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, dest_domain=None, dest_meta={}, replace_meta=False, permissions=None, src_version=None, is_move=False): |
|
738 |
def _copy_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, dest_domain=None, dest_meta={}, replace_meta=False, permissions=None, src_version=None, is_move=False, delimiter=None): |
|
739 |
dest_version_ids = [] |
|
728 | 740 |
self._can_read(user, src_account, src_container, src_name) |
729 | 741 |
path, node = self._lookup_object(src_account, src_container, src_name) |
730 | 742 |
# TODO: Will do another fetch of the properties in duplicate version... |
... | ... | |
732 | 744 |
src_version_id = props[self.SERIAL] |
733 | 745 |
hash = props[self.HASH] |
734 | 746 |
size = props[self.SIZE] |
735 |
|
|
736 | 747 |
is_copy = not is_move and (src_account, src_container, src_name) != (dest_account, dest_container, dest_name) # New uuid. |
737 |
dest_version_id = self._update_object_hash(user, dest_account, dest_container, dest_name, size, type, hash, None, dest_domain, dest_meta, replace_meta, permissions, src_node=node, src_version_id=src_version_id, is_copy=is_copy) |
|
738 |
return dest_version_id |
|
748 |
dest_version_ids.append(self._update_object_hash(user, dest_account, dest_container, dest_name, size, type, hash, None, dest_domain, dest_meta, replace_meta, permissions, src_node=node, src_version_id=src_version_id, is_copy=is_copy)) |
|
749 |
if is_move: |
|
750 |
self._delete_object(user, src_account, src_container, src_name) |
|
751 |
|
|
752 |
if delimiter: |
|
753 |
prefix = src_name + delimiter if not src_name.endswith(delimiter) else src_name |
|
754 |
src_names = self._list_objects_no_limit(user, src_account, src_container, prefix, delimiter=None, virtual=True, domain=None, keys=[], shared=False, until=None, size_range=None, all_props=True, public=False) |
|
755 |
paths = [elem[0] for elem in src_names] |
|
756 |
nodes = [elem[2] for elem in src_names] |
|
757 |
# TODO: Will do another fetch of the properties in duplicate version... |
|
758 |
props = self._get_versions(nodes) # Check to see if source exists. |
|
759 |
|
|
760 |
for prop, path, node in zip(props, paths, nodes): |
|
761 |
src_version_id = prop[self.SERIAL] |
|
762 |
hash = prop[self.HASH] |
|
763 |
vtype = prop[self.TYPE] |
|
764 |
dest_prefix = dest_name + delimiter if not dest_name.endswith(delimiter) else dest_name |
|
765 |
vdest_name = path.replace(prefix, dest_prefix, 1) |
|
766 |
dest_version_ids.append(self._update_object_hash(user, dest_account, dest_container, vdest_name, size, vtype, hash, None, dest_domain, dest_meta, replace_meta, permissions, src_node=node, src_version_id=src_version_id, is_copy=is_copy)) |
|
767 |
if is_move: |
|
768 |
self._delete_object(user, src_account, src_container, path) |
|
769 |
return dest_version_ids[0] if len(dest_version_ids) == 1 else dest_version_ids |
|
739 | 770 |
|
740 | 771 |
@backend_method |
741 |
def copy_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, domain, meta={}, replace_meta=False, permissions=None, src_version=None): |
|
772 |
def copy_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, domain, meta={}, replace_meta=False, permissions=None, src_version=None, delimiter=None):
|
|
742 | 773 |
"""Copy an object's data and metadata.""" |
743 | 774 |
|
744 |
logger.debug("copy_object: %s %s %s %s %s %s %s %s %s %s %s %s %s", user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, domain, meta, replace_meta, permissions, src_version)
|
|
745 |
dest_version_id = self._copy_object(user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, domain, meta, replace_meta, permissions, src_version, False) |
|
775 |
logger.debug("copy_object: %s %s %s %s %s %s %s %s %s %s %s %s %s %s", user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, domain, meta, replace_meta, permissions, src_version, delimiter)
|
|
776 |
dest_version_id = self._copy_object(user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, domain, meta, replace_meta, permissions, src_version, False, delimiter)
|
|
746 | 777 |
return dest_version_id |
747 | 778 |
|
748 | 779 |
@backend_method |
749 |
def move_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, domain, meta={}, replace_meta=False, permissions=None): |
|
780 |
def move_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, domain, meta={}, replace_meta=False, permissions=None, delimiter=None):
|
|
750 | 781 |
"""Move an object's data and metadata.""" |
751 | 782 |
|
752 |
logger.debug("move_object: %s %s %s %s %s %s %s %s %s %s %s %s", user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, domain, meta, replace_meta, permissions)
|
|
783 |
logger.debug("move_object: %s %s %s %s %s %s %s %s %s %s %s %s %s", user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, domain, meta, replace_meta, permissions, delimiter)
|
|
753 | 784 |
if user != src_account: |
754 | 785 |
raise NotAllowedError |
755 |
dest_version_id = self._copy_object(user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, domain, meta, replace_meta, permissions, None, True) |
|
756 |
if (src_account, src_container, src_name) != (dest_account, dest_container, dest_name): |
|
757 |
self._delete_object(user, src_account, src_container, src_name) |
|
786 |
dest_version_id = self._copy_object(user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, domain, meta, replace_meta, permissions, None, True, delimiter) |
|
758 | 787 |
return dest_version_id |
759 | 788 |
|
760 |
def _delete_object(self, user, account, container, name, until=None, prefix='', delimiter=None):
|
|
789 |
def _delete_object(self, user, account, container, name, until=None, delimiter=None): |
|
761 | 790 |
if user != account: |
762 | 791 |
raise NotAllowedError |
763 | 792 |
|
... | ... | |
791 | 820 |
self._report_size_change(user, account, -del_size, {'action': 'object delete'}) |
792 | 821 |
self._report_object_change(user, account, path, details={'action': 'object delete'}) |
793 | 822 |
self.permissions.access_clear(path) |
823 |
|
|
824 |
if delimiter: |
|
825 |
prefix = name + delimiter if not name.endswith(delimiter) else name |
|
826 |
src_names = self._list_objects_no_limit(user, account, container, prefix, delimiter=None, virtual=True, domain=None, keys=[], shared=False, until=None, size_range=None, all_props=True, public=False) |
|
827 |
paths = [] |
|
828 |
for t in src_names: |
|
829 |
path = '/'.join((account, container, t[0])) |
|
830 |
node = t[2] |
|
831 |
src_version_id, dest_version_id = self._put_version_duplicate(user, node, size=0, type='', hash=None, checksum='', cluster=CLUSTER_DELETED) |
|
832 |
del_size = self._apply_versioning(account, container, src_version_id) |
|
833 |
if del_size: |
|
834 |
self._report_size_change(user, account, -del_size, {'action': 'object delete'}) |
|
835 |
self._report_object_change(user, account, path, details={'action': 'object delete'}) |
|
836 |
paths.append(path) |
|
837 |
self.permissions.access_clear_bulk(paths) |
|
794 | 838 |
|
795 | 839 |
@backend_method |
796 |
def (self, user, account, container, name, until=None, prefix='', delimiter=None): |
|
840 |
def delete_object(self, user, account, container, name, until=None, prefix='', delimiter=None):
|
|
797 | 841 |
"""Delete/purge an object.""" |
798 | 842 |
|
799 | 843 |
logger.debug("delete_object: %s %s %s %s %s %s %s", user, account, container, name, until, prefix, delimiter) |
800 |
self._delete_object(user, account, container, name, until) |
|
844 |
self._delete_object(user, account, container, name, until, delimiter)
|
|
801 | 845 |
|
802 | 846 |
@backend_method |
803 | 847 |
def list_versions(self, user, account, container, name): |
... | ... | |
936 | 980 |
if props is None or props[self.CLUSTER] == CLUSTER_DELETED: |
937 | 981 |
raise IndexError('Version does not exist') |
938 | 982 |
return props |
983 |
|
|
984 |
def _get_versions(self, nodes, version=None): |
|
985 |
if version is None: |
|
986 |
props = self.node.version_lookup_bulk(nodes, inf, CLUSTER_NORMAL) |
|
987 |
if not props: |
|
988 |
raise NameError('Object does not exist') |
|
989 |
else: |
|
990 |
try: |
|
991 |
version = int(version) |
|
992 |
except ValueError: |
|
993 |
raise IndexError('Version does not exist') |
|
994 |
props = self.node.version_get_properties(version) |
|
995 |
if props is None or props[self.CLUSTER] == CLUSTER_DELETED: |
|
996 |
raise IndexError('Version does not exist') |
|
997 |
return props |
|
939 | 998 |
|
940 | 999 |
def _put_version_duplicate(self, user, node, src_node=None, size=None, type=None, hash=None, checksum=None, cluster=CLUSTER_NORMAL, is_copy=False): |
941 | 1000 |
"""Create a new version of the node.""" |
Also available in: Unified diff