def delete(avatar, fullpath, on_behalf=None): """ Delete a blob. """ log.msg("Deleting %s" % fullpath) uid, vals = vcdm.env['ds'].find_by_path(fullpath, object_type='blob', fields=['parent_container', 'metadata','backend_name']) if uid is None: return NOT_FOUND else: try: # authorize call acls = vals['metadata'].get('cdmi_acl', None) if not authorize(avatar, fullpath, "delete_blob", acls): return UNAUTHORIZED vcdm.env['blobs'][vals['backend_name']].delete(uid) vcdm.env['ds'].delete(uid) # find parent container and update its children range from vcdm.container import _remove_child _remove_child(vals['parent_container'], uid) log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type='blob_delete') return NO_CONTENT except: #TODO: - how do we handle failed delete? return CONFLICT
def delete(avatar, fullpath, on_behalf=None): """ Delete a blob. """ log.msg("Deleting %s" % fullpath) uid, vals = vcdm.env['ds'].find_by_path( fullpath, object_type='blob', fields=['parent_container', 'metadata', 'backend_name']) if uid is None: return NOT_FOUND else: try: # authorize call acls = vals['metadata'].get('cdmi_acl', None) if not authorize(avatar, fullpath, "delete_blob", acls): return UNAUTHORIZED vcdm.env['blobs'][vals['backend_name']].delete(uid) vcdm.env['ds'].delete(uid) # find parent container and update its children range from vcdm.container import _remove_child _remove_child(vals['parent_container'], uid) log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type='blob_delete') return NO_CONTENT except: #TODO: - how do we handle failed delete? return CONFLICT
def delete(avatar, fullpath, on_behalf=None): """ Delete a container.""" log.msg("Deleting a container %s" % fullpath) uid, vals = vcdm.env["ds"].find_by_path( fullpath, object_type="container", fields=["children", "parent_container", "metadata"] ) if uid is None: return NOT_FOUND else: # authorize call acls = vals["metadata"].get("cdmi_acl", None) if not authorize(avatar, fullpath, "delete_container", acls): log.err("Authorization failed.") return UNAUTHORIZED # fail if we are deleting a non-empty container if len(vals["children"]) != 0: log.err("Cannot delete non-empty container %s. Existing children: %s." % (fullpath, vals["children"])) # we do not allow deleting non-empty containers return CONFLICT vcdm.env["ds"].delete(uid) if fullpath != "/": _remove_child(vals["parent_container"], uid) ## XXX: delete all children? log.msg(type="accounting", avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type="container_delete") return NO_CONTENT
def read(avatar, requested_path, on_behalf=None): """ Read a specified container.""" expected_fields = ['children', 'metadata', 'mtime'] unique_request = re.match('/cdmi_objectid/\w+$', requested_path) if unique_request is not None: requested_uid = unique_request.group(0).split('/')[2] uid, vals = vcdm.env['ds'].find_by_uid(requested_uid, object_type='container', fields=expected_fields + ['fullpath']) fullpath = vals['fullpath'] else: fullpath = requested_path uid, vals = vcdm.env['ds'].find_by_path(fullpath, object_type='container', fields=expected_fields) if uid is None: return (NOT_FOUND, None) else: # authorize call acls = vals['metadata'].get('cdmi_acl') if not authorize(avatar, fullpath, 'read_container', acls): return (UNAUTHORIZED, None) vals['uid'] = uid log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type='container_read') return (OK, vals)
def delete(avatar, fullpath, on_behalf=None): """ Delete a container.""" log.msg("Deleting a container %s" % fullpath) uid, vals = vcdm.env['ds'].find_by_path( fullpath, object_type='container', fields=['children', 'parent_container', 'metadata']) if uid is None: return NOT_FOUND else: # authorize call acls = vals['metadata'].get('cdmi_acl', None) if not authorize(avatar, fullpath, "delete_container", acls): log.err("Authorization failed.") return UNAUTHORIZED # fail if we are deleting a non-empty container if len(vals['children']) != 0: log.err( "Cannot delete non-empty container %s. Existing children: %s." % (fullpath, vals['children'])) # we do not allow deleting non-empty containers return CONFLICT vcdm.env['ds'].delete(uid) if fullpath != '/': _remove_child(vals['parent_container'], uid) ## XXX: delete all children? log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type='container_delete') return NO_CONTENT
def read(avatar, fullpath, tre_request=False, on_behalf=None): """ Return contents of a blob. Returns: (HTTP_STATUS_CODE, dictionary_of_metadata) """ # if the object was requested with a 'cdmi_objectid/' prefix, we query for that expected_fields = [ 'metadata', 'mimetype', 'mtime', 'size', 'actual_uri', 'valuetransferencoding', 'backend_name' ] unique_request = re.match('/cdmi_objectid/\w+$', fullpath) if unique_request is not None: log.msg('Looking up a blob by a unique key.') requested_uid = unique_request.group(0).split('/')[2] uid, vals = vcdm.env['ds'].find_by_uid(requested_uid, object_type='blob', fields=expected_fields) else: uid, vals = vcdm.env['ds'].find_by_path(fullpath, object_type='blob', fields=expected_fields) log.msg("Reading path %s, uid: %s" % (fullpath, uid)) if uid is None: return (NOT_FOUND, None) else: # authorize call acls = vals['metadata'].get('cdmi_acl') if not authorize(avatar, fullpath, "read_blob", acls): log.msg("Authorization failed for %s on %s (%s)" % (avatar, fullpath, acls)) return (UNAUTHORIZED, None) # read the content from the corresponding backend vals['content'] = vcdm.env['blobs'][vals['backend_name']].read(uid) # update access time vcdm.env['ds'].write({ 'atime': str(time.time()), }, uid) log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf, amount=vals['size'], acc_type='blob_read') vals['uid'] = uid # TRE-request? if tre_request: if not vcdm.env['tre_enabled']: return (NOT_IMPLEMENTED, None) # XXX only local blob backend supports that at the moment vcdm.env['blob'].move_to_tre_server(uid) return (FOUND, vals) return (OK, vals)
def read(avatar, fullpath, tre_request=False, on_behalf=None): """ Return contents of a blob. Returns: (HTTP_STATUS_CODE, dictionary_of_metadata) """ # if the object was requested with a 'cdmi_objectid/' prefix, we query for that expected_fields = ['metadata', 'mimetype', 'mtime', 'size', 'actual_uri', 'valuetransferencoding','backend_name'] unique_request = re.match('/cdmi_objectid/\w+$', fullpath) if unique_request is not None: log.msg('Looking up a blob by a unique key.') requested_uid = unique_request.group(0).split('/')[2] uid, vals = vcdm.env['ds'].find_by_uid(requested_uid, object_type='blob', fields=expected_fields) else: uid, vals = vcdm.env['ds'].find_by_path(fullpath, object_type='blob', fields=expected_fields) log.msg("Reading path %s, uid: %s" % (fullpath, uid)) if uid is None: return (NOT_FOUND, None) else: # authorize call acls = vals['metadata'].get('cdmi_acl') if not authorize(avatar, fullpath, "read_blob", acls): log.msg("Authorization failed for %s on %s (%s)" % (avatar, fullpath, acls)) return (UNAUTHORIZED, None) # read the content from the corresponding backend vals['content'] = vcdm.env['blobs'][vals['backend_name']].read(uid) # update access time vcdm.env['ds'].write({ 'atime': str(time.time()), }, uid) log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf, amount=vals['size'], acc_type='blob_read') vals['uid'] = uid # TRE-request? if tre_request: if not vcdm.env['tre_enabled']: return (NOT_IMPLEMENTED, None) # XXX only local blob backend supports that at the moment vcdm.env['blob'].move_to_tre_server(uid) return (FOUND, vals) return (OK, vals)
def read(avatar, fullpath, tre_request=False, on_behalf=None): """ Return contents of a blob. Returns: (HTTP_STATUS_CODE, dictionary_of_metadata) """ # if the object was requested with a 'cdmi_objectid/' prefix, we query for that expected_fields = ["metadata", "mimetype", "mtime", "size", "actual_uri", "valuetransferencoding"] unique_request = re.match("/cdmi_objectid/\w+$", fullpath) if unique_request is not None: log.msg("Looking up a blob by a unique key.") requested_uid = unique_request.group(0).split("/")[2] uid, vals = vcdm.env["ds"].find_by_uid(requested_uid, object_type="blob", fields=expected_fields) else: uid, vals = vcdm.env["ds"].find_by_path(fullpath, object_type="blob", fields=expected_fields) log.msg("Reading path %s, uid: %s" % (fullpath, uid)) if uid is None: return (NOT_FOUND, None) else: # authorize call acls = vals["metadata"].get("cdmi_acl") if not authorize(avatar, fullpath, "read_blob", acls): log.msg("Authorization failed for %s on %s (%s)" % (avatar, fullpath, acls)) return (UNAUTHORIZED, None) vals["content"] = vcdm.env["blob"].read(uid) # update access time vcdm.env["ds"].write({"atime": str(time.time())}, uid) log.msg( type="accounting", avatar=avatar if not on_behalf else on_behalf, amount=vals["size"], acc_type="blob_read" ) vals["uid"] = uid # TRE-request? if tre_request: if not vcdm.env["tre_enabled"]: return (NOT_IMPLEMENTED, None) # XXX only local blob backend supports that at the moment vcdm.env["blob"].move_to_tre_server(uid) return (FOUND, vals) return (OK, vals)
def delete(avatar, fullpath, on_behalf=None): """ Delete a blob. """ log.msg("Deleting %s" % fullpath) uid, vals = vcdm.env["ds"].find_by_path(fullpath, object_type="blob", fields=["parent_container", "metadata"]) if uid is None: return NOT_FOUND else: try: # authorize call acls = vals["metadata"].get("cdmi_acl", None) if not authorize(avatar, fullpath, "delete_blob", acls): return UNAUTHORIZED vcdm.env["blob"].delete(uid) vcdm.env["ds"].delete(uid) # find parent container and update its children range from vcdm.container import _remove_child _remove_child(vals["parent_container"], uid) log.msg(type="accounting", avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type="blob_delete") return NO_CONTENT except: # TODO: - how do we handle failed delete? return CONFLICT
def read(avatar, requested_path, on_behalf=None): """ Read a specified container.""" expected_fields = ["children", "metadata", "mtime"] unique_request = re.match("/cdmi_objectid/\w+$", requested_path) if unique_request is not None: requested_uid = unique_request.group(0).split("/")[2] uid, vals = vcdm.env["ds"].find_by_uid( requested_uid, object_type="container", fields=expected_fields + ["fullpath"] ) fullpath = vals["fullpath"] else: fullpath = requested_path uid, vals = vcdm.env["ds"].find_by_path(fullpath, object_type="container", fields=expected_fields) if uid is None: return (NOT_FOUND, None) else: # authorize call acls = vals["metadata"].get("cdmi_acl") if not authorize(avatar, fullpath, "read_container", acls): return (UNAUTHORIZED, None) vals["uid"] = uid log.msg(type="accounting", avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type="container_read") return (OK, vals)
def write(avatar, name, container_path, fullpath, mimetype, metadata, content, valueencoding, on_behalf=None, desired_backend=None): """ Write or update content of a blob. """ from vcdm.server.cdmi.generic import get_parent parent_container = get_parent(fullpath) uid, vals = vcdm.env['ds'].find_by_path(fullpath, object_type='blob', fields=['parent_container','backend_name']) # assert that we have a consistency in case of an existig blob if uid is not None and parent_container != vals['parent_container']: log.err("ERROR: Inconsistent information! path: %s, parent_container in db: %s" % (fullpath, vals['parent_container'])) return (INTERNAL_SERVER_ERROR, uid) # assert we can write to the defined path # TODO: expensive check for consistency, make optional if config.getboolean('general', 'check_for_existing_parents'): if not check_path(container_path): log.err("Writing to a container is not allowed. Container path: %s" % '/'.join(container_path)) return (FORBIDDEN, uid) # authorize call if uid is None: # the new file # take parent permissions _, cvals = vcdm.env['ds'].find_by_path(parent_container, object_type='container', fields=['metadata']) else: # updating the file # take file permissions _, cvals = vcdm.env['ds'].find_by_path(fullpath, object_type='blob', fields=['metadata']) acl = cvals['metadata'].get('cdmi_acl', {}) if not authorize(avatar, parent_container, "write_blob", acl): return (UNAUTHORIZED, uid) # ok, time for action # pick a blob back-end # if file going to be updated take backend_name from metadata # otherwise use backend is specified in the request # if it is not available in the system - resolve to default one. if uid is not None: desired_backend=vals['backend_name'] blob_backend = vcdm.env['blobs'].get(desired_backend, vcdm.env['blob']) # add default acls if avatar is None: avatar = 'Anonymous' blob_acl = metadata.get('cdmi_acl') if blob_acl is None: metadata['cdmi_acl'] = acl # append parent ACLs for a new folder metadata['cdmi_acl'].update({avatar: 'rwd'}) # and creator's ACLs just in case # if uid is None, create a new entry, update otherwise if uid is None: uid = uuid4().hex actual_uri = blob_backend.create(uid, content) vcdm.env['ds'].write({ 'object': 'blob', 'owner': avatar, 'fullpath': fullpath, 'mimetype': mimetype, 'metadata': metadata, 'valuetransferencoding': valueencoding, 'filename': name, 'actual_uri': actual_uri, 'parent_container': parent_container, 'ctime': str(time.time()), 'mtime': str(time.time()), 'atime': str(time.time()), 'size': int(content[1]), # length 'backend_type': blob_backend.backend_type, 'backend_name': blob_backend.backend_name}, uid) # update the parent container as well from vcdm.container import _append_child _append_child(parent_container, uid, name) log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf, amount=int(content[1]), acc_type='blob_creation') return (CREATED, uid) else: actual_uri = blob_backend.update(uid, content) uid = vcdm.env['ds'].write({ 'metadata': metadata, 'mimetype': mimetype, 'mtime': str(time.time()), 'actual_uri': actual_uri, 'atime': str(time.time()), 'size': int(content[1]), # length 'backend_type': blob_backend.backend_type, 'backend_name': blob_backend.backend_name}, uid) log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf, amount=int(content[1]), acc_type='blob_update') return (NO_CONTENT, uid)
def write( avatar, name, container_path, fullpath, mimetype, metadata, content, valueencoding, on_behalf=None, desired_backend=None, ): """ Write or update content of a blob. """ from vcdm.server.cdmi.generic import get_parent parent_container = get_parent(fullpath) uid, vals = vcdm.env["ds"].find_by_path(fullpath, object_type="blob", fields=["parent_container"]) # assert that we have a consistency in case of an existig blob if uid is not None and parent_container != vals["parent_container"]: log.err( "ERROR: Inconsistent information! path: %s, parent_container in db: %s" % (fullpath, vals["parent_container"]) ) return (INTERNAL_SERVER_ERROR, uid) # assert we can write to the defined path # TODO: expensive check for consistency, make optional if config.getboolean("general", "check_for_existing_parents"): if not check_path(container_path): log.err("Writing to a container is not allowed. Container path: %s" % "/".join(container_path)) return (FORBIDDEN, uid) # authorize call, take parent permissions _, cvals = vcdm.env["ds"].find_by_path(parent_container, object_type="container", fields=["metadata"]) acl = cvals["metadata"].get("cdmi_acl", {}) if not authorize(avatar, parent_container, "write_blob", acl): return (UNAUTHORIZED, uid) # ok, time for action # pick a blob back-end - if request_backend is specified in the metadata and # available in the system - use it. Else - resolve to default one. blob_backend = vcdm.env["blobs"].get(desired_backend, vcdm.env["blob"]) # add default acls if avatar is None: avatar = "Anonymous" blob_acl = metadata.get("cdmi_acl") if blob_acl is None: metadata["cdmi_acl"] = acl # append parent ACLs for a new folder metadata["cdmi_acl"].update({avatar: "rwd"}) # and creator's ACLs just in case # if uid is None, create a new entry, update otherwise if uid is None: uid = uuid4().hex actual_uri = blob_backend.create(uid, content) vcdm.env["ds"].write( { "object": "blob", "owner": avatar, "fullpath": fullpath, "mimetype": mimetype, "metadata": metadata, "valuetransferencoding": valueencoding, "filename": name, "actual_uri": actual_uri, "parent_container": parent_container, "ctime": str(time.time()), "mtime": str(time.time()), "atime": str(time.time()), "size": int(content[1]), # length "backend_type": blob_backend.backend_type, "backend_name": blob_backend.backend_name, }, uid, ) # update the parent container as well from vcdm.container import _append_child _append_child(parent_container, uid, name) log.msg( type="accounting", avatar=avatar if not on_behalf else on_behalf, amount=int(content[1]), acc_type="blob_creation", ) return (CREATED, uid) else: actual_uri = blob_backend.update(uid, content) uid = vcdm.env["ds"].write( { "metadata": metadata, "mimetype": mimetype, "mtime": str(time.time()), "actual_uri": actual_uri, "atime": str(time.time()), "size": int(content[1]), # length "backend_type": blob_backend.backend_type, "backend_name": blob_backend.backend_name, }, uid, ) log.msg( type="accounting", avatar=avatar if not on_behalf else on_behalf, amount=int(content[1]), acc_type="blob_update", ) return (NO_CONTENT, uid)
def create_or_update(avatar, name, container_path, fullpath, metadata=None, on_behalf=None): """Create or update a container.""" log.msg("Container create/update: %s" % fullpath) parent_container = get_parent(fullpath) uid, vals = vcdm.env["ds"].find_by_path( fullpath, object_type="container", fields=["children", "parent_container", "owner"] ) vals["uid"] = uid # XXX: duplication of checks with blob (vcdm). Refactor. if uid is not None and parent_container != vals["parent_container"]: log.err("Inconsistency! path: %s, parent_container in db: %s" % (fullpath, vals["parent_container"])) return (FORBIDDEN, vals) # assert we can write to the defined path if not check_path(container_path): log.err("Writing to a container is not allowed. Container path: %s" % "/".join(container_path)) return (FORBIDDEN, vals) # authorize call, take parent permissions _, cvals = vcdm.env["ds"].find_by_path(parent_container, object_type="container", fields=["metadata"]) acl = cvals["metadata"].get("cdmi_acl", {}) if not authorize(avatar, parent_container, "write_container", acl): return (UNAUTHORIZED, vals) # add default acls if avatar is None: avatar = "Anonymous" container_acl = metadata.get("cdmi_acl") if container_acl is None: metadata["cdmi_acl"] = acl # append parent ACLs for a new folder metadata["cdmi_acl"].update({avatar: "rwd"}) # and creator's ACLs # if uid is None, it shall create a new entry, update otherwise if uid is None: uid = vcdm.env["ds"].write( { "object": "container", "metadata": metadata, "owner": avatar, "fullpath": fullpath, "name": name, "parent_container": parent_container, "children": {}, "ctime": str(time.time()), "mtime": str(time.time()), }, uid, ) vals["uid"] = uid # update the parent container as well, unless it's a top-level container if fullpath != "/": _append_child(parent_container, uid, name + "/") log.msg(type="accounting", avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type="container_create") return (CREATED, vals) else: # update container # forbid rewrites of containers by other users if vals.get("owner") is not None and vals.get("owner") != avatar: return (UNAUTHORIZED, vals) uid = vcdm.env["ds"].write({"metadata": metadata, "mtime": str(time.time())}, uid) log.msg(type="accounting", avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type="container_update") return (NO_CONTENT, vals)
def write(avatar, name, container_path, fullpath, mimetype, metadata, content, valueencoding, on_behalf=None, desired_backend=None): """ Write or update content of a blob. """ from vcdm.server.cdmi.generic import get_parent parent_container = get_parent(fullpath) uid, vals = vcdm.env['ds'].find_by_path( fullpath, object_type='blob', fields=['parent_container', 'backend_name']) # assert that we have a consistency in case of an existig blob if uid is not None and parent_container != vals['parent_container']: log.err( "ERROR: Inconsistent information! path: %s, parent_container in db: %s" % (fullpath, vals['parent_container'])) return (INTERNAL_SERVER_ERROR, uid) # assert we can write to the defined path # TODO: expensive check for consistency, make optional if config.getboolean('general', 'check_for_existing_parents'): if not check_path(container_path): log.err( "Writing to a container is not allowed. Container path: %s" % '/'.join(container_path)) return (FORBIDDEN, uid) # authorize call if uid is None: # the new file # take parent permissions _, cvals = vcdm.env['ds'].find_by_path(parent_container, object_type='container', fields=['metadata']) else: # updating the file # take file permissions _, cvals = vcdm.env['ds'].find_by_path(fullpath, object_type='blob', fields=['metadata']) acl = cvals['metadata'].get('cdmi_acl', {}) if not authorize(avatar, parent_container, "write_blob", acl): return (UNAUTHORIZED, uid) # ok, time for action # pick a blob back-end # if file going to be updated take backend_name from metadata # otherwise use backend is specified in the request # if it is not available in the system - resolve to default one. if uid is not None: desired_backend = vals['backend_name'] blob_backend = vcdm.env['blobs'].get(desired_backend, vcdm.env['blob']) # add default acls if avatar is None: avatar = 'Anonymous' blob_acl = metadata.get('cdmi_acl') if blob_acl is None: metadata['cdmi_acl'] = acl # append parent ACLs for a new folder metadata['cdmi_acl'].update({avatar: 'rwd'}) # and creator's ACLs just in case # if uid is None, create a new entry, update otherwise if uid is None: uid = uuid4().hex actual_uri = blob_backend.create(uid, content) vcdm.env['ds'].write( { 'object': 'blob', 'owner': avatar, 'fullpath': fullpath, 'mimetype': mimetype, 'metadata': metadata, 'valuetransferencoding': valueencoding, 'filename': name, 'actual_uri': actual_uri, 'parent_container': parent_container, 'ctime': str(time.time()), 'mtime': str(time.time()), 'atime': str(time.time()), 'size': int(content[1]), # length 'backend_type': blob_backend.backend_type, 'backend_name': blob_backend.backend_name }, uid) # update the parent container as well from vcdm.container import _append_child _append_child(parent_container, uid, name) log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf, amount=int(content[1]), acc_type='blob_creation') return (CREATED, uid) else: actual_uri = blob_backend.update(uid, content) uid = vcdm.env['ds'].write( { 'metadata': metadata, 'mimetype': mimetype, 'mtime': str(time.time()), 'actual_uri': actual_uri, 'atime': str(time.time()), 'size': int(content[1]), # length 'backend_type': blob_backend.backend_type, 'backend_name': blob_backend.backend_name }, uid) log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf, amount=int(content[1]), acc_type='blob_update') return (NO_CONTENT, uid)
def create_or_update(avatar, name, container_path, fullpath, metadata=None, on_behalf=None): """Create or update a container.""" log.msg("Container create/update: %s" % fullpath) parent_container = get_parent(fullpath) uid, vals = vcdm.env['ds'].find_by_path( fullpath, object_type='container', fields=['children', 'parent_container', 'owner']) vals['uid'] = uid # XXX: duplication of checks with blob (vcdm). Refactor. if uid is not None and parent_container != vals['parent_container']: log.err("Inconsistency! path: %s, parent_container in db: %s" % (fullpath, vals['parent_container'])) return (FORBIDDEN, vals) # assert we can write to the defined path if not check_path(container_path): log.err("Writing to a container is not allowed. Container path: %s" % '/'.join(container_path)) return (FORBIDDEN, vals) # authorize call, take parent permissions _, cvals = vcdm.env['ds'].find_by_path(parent_container, object_type='container', fields=['metadata']) acl = cvals['metadata'].get('cdmi_acl', {}) if not authorize(avatar, parent_container, "write_container", acl): return (UNAUTHORIZED, vals) # add default acls if avatar is None: avatar = 'Anonymous' container_acl = metadata.get('cdmi_acl') if container_acl is None: metadata['cdmi_acl'] = acl # append parent ACLs for a new folder metadata['cdmi_acl'].update({avatar: 'rwd'}) # and creator's ACLs # if uid is None, it shall create a new entry, update otherwise if uid is None: uid = vcdm.env['ds'].write( { 'object': 'container', 'metadata': metadata, 'owner': avatar, 'fullpath': fullpath, 'name': name, 'parent_container': parent_container, 'children': {}, 'ctime': str(time.time()), 'mtime': str(time.time()) }, uid) vals['uid'] = uid # update the parent container as well, unless it's a top-level container if fullpath != '/': _append_child(parent_container, uid, name + "/") log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type='container_create') return (CREATED, vals) else: # update container # forbid rewrites of containers by other users if vals.get('owner') is not None and vals.get('owner') != avatar: return (UNAUTHORIZED, vals) uid = vcdm.env['ds'].write( { 'metadata': metadata, 'mtime': str(time.time()) }, uid) log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type='container_update') return (NO_CONTENT, vals)