misc mutable-type fixes:
* fix tahoe.cfg control of default mutable type * tolerate arbitrary case in [client]mutable.format value * small docs improvements * use get_mutable_type() as a format-is-mutable predicate * tighten up error message
This commit is contained in:
parent
01b00dc7dc
commit
210761cd49
|
@ -379,15 +379,20 @@ Writing/Uploading A File
|
||||||
immutable file, the "offset" parameter is not valid.
|
immutable file, the "offset" parameter is not valid.
|
||||||
|
|
||||||
When creating a new file, you can control the type of file created by
|
When creating a new file, you can control the type of file created by
|
||||||
specifying a format= argument in the query string. format=MDMF creates an MDMF
|
specifying a format= argument in the query string. format=MDMF creates an
|
||||||
mutable file. format=SDMF creates an SDMF mutable file. format=CHK creates an
|
MDMF mutable file. format=SDMF creates an SDMF mutable file. format=CHK
|
||||||
immutable file. The value of the format argument is case-insensitive. For
|
creates an immutable file. The value of the format argument is
|
||||||
compatibility with previous versions of Tahoe-LAFS, the webapi will also
|
case-insensitive. If no format is specified, the newly-created file will be
|
||||||
accept a mutable=true argument in the query string. If mutable=true is given,
|
immutable (but see below).
|
||||||
then the new file will be mutable, and its format will be the default mutable
|
|
||||||
file format, as configured on the Tahoe-LAFS node hosting the webapi server.
|
For compatibility with previous versions of Tahoe-LAFS, the web-API will
|
||||||
Use of mutable=true is discouraged; new code should use format= instead of
|
also accept a mutable=true argument in the query string. If mutable=true is
|
||||||
mutable=true. If neither format= nor mutable=true are given, the
|
given, then the new file will be mutable, and its format will be the default
|
||||||
|
mutable file format, as configured by the [client]mutable.format option of
|
||||||
|
tahoe.cfg on the Tahoe-LAFS node hosting the webapi server. Use of
|
||||||
|
mutable=true is discouraged; new code should use format= instead of
|
||||||
|
mutable=true (unless it needs to be compatible with web-API servers older
|
||||||
|
than v1.9.0). If neither format= nor mutable=true are given, the
|
||||||
newly-created file will be immutable.
|
newly-created file will be immutable.
|
||||||
|
|
||||||
This returns the file-cap of the resulting file. If a new file was created
|
This returns the file-cap of the resulting file. If a new file was created
|
||||||
|
|
|
@ -339,19 +339,20 @@ class Client(node.Node, pollmixin.PollMixin):
|
||||||
self.blacklist = Blacklist(fn)
|
self.blacklist = Blacklist(fn)
|
||||||
|
|
||||||
def init_nodemaker(self):
|
def init_nodemaker(self):
|
||||||
|
default = self.get_config("client", "mutable.format", default="SDMF")
|
||||||
|
if default.upper() == "MDMF":
|
||||||
|
self.mutable_file_default = MDMF_VERSION
|
||||||
|
else:
|
||||||
|
self.mutable_file_default = SDMF_VERSION
|
||||||
self.nodemaker = NodeMaker(self.storage_broker,
|
self.nodemaker = NodeMaker(self.storage_broker,
|
||||||
self._secret_holder,
|
self._secret_holder,
|
||||||
self.get_history(),
|
self.get_history(),
|
||||||
self.getServiceNamed("uploader"),
|
self.getServiceNamed("uploader"),
|
||||||
self.terminator,
|
self.terminator,
|
||||||
self.get_encoding_parameters(),
|
self.get_encoding_parameters(),
|
||||||
|
self.mutable_file_default,
|
||||||
self._key_generator,
|
self._key_generator,
|
||||||
self.blacklist)
|
self.blacklist)
|
||||||
default = self.get_config("client", "mutable.format", default="sdmf")
|
|
||||||
if default == "mdmf":
|
|
||||||
self.mutable_file_default = MDMF_VERSION
|
|
||||||
else:
|
|
||||||
self.mutable_file_default = SDMF_VERSION
|
|
||||||
|
|
||||||
def get_history(self):
|
def get_history(self):
|
||||||
return self.history
|
return self.history
|
||||||
|
@ -507,8 +508,6 @@ class Client(node.Node, pollmixin.PollMixin):
|
||||||
return self.nodemaker.create_immutable_directory(children, convergence)
|
return self.nodemaker.create_immutable_directory(children, convergence)
|
||||||
|
|
||||||
def create_mutable_file(self, contents=None, keysize=None, version=None):
|
def create_mutable_file(self, contents=None, keysize=None, version=None):
|
||||||
if not version:
|
|
||||||
version = self.mutable_file_default
|
|
||||||
return self.nodemaker.create_mutable_file(contents, keysize,
|
return self.nodemaker.create_mutable_file(contents, keysize,
|
||||||
version=version)
|
version=version)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import weakref
|
import weakref
|
||||||
from zope.interface import implements
|
from zope.interface import implements
|
||||||
from allmydata.util.assertutil import precondition
|
from allmydata.util.assertutil import precondition
|
||||||
from allmydata.interfaces import INodeMaker, SDMF_VERSION
|
from allmydata.interfaces import INodeMaker
|
||||||
from allmydata.immutable.literal import LiteralFileNode
|
from allmydata.immutable.literal import LiteralFileNode
|
||||||
from allmydata.immutable.filenode import ImmutableFileNode, CiphertextFileNode
|
from allmydata.immutable.filenode import ImmutableFileNode, CiphertextFileNode
|
||||||
from allmydata.immutable.upload import Data
|
from allmydata.immutable.upload import Data
|
||||||
|
@ -18,14 +18,15 @@ class NodeMaker:
|
||||||
|
|
||||||
def __init__(self, storage_broker, secret_holder, history,
|
def __init__(self, storage_broker, secret_holder, history,
|
||||||
uploader, terminator,
|
uploader, terminator,
|
||||||
default_encoding_parameters, key_generator,
|
default_encoding_parameters, mutable_file_default,
|
||||||
blacklist=None):
|
key_generator, blacklist=None):
|
||||||
self.storage_broker = storage_broker
|
self.storage_broker = storage_broker
|
||||||
self.secret_holder = secret_holder
|
self.secret_holder = secret_holder
|
||||||
self.history = history
|
self.history = history
|
||||||
self.uploader = uploader
|
self.uploader = uploader
|
||||||
self.terminator = terminator
|
self.terminator = terminator
|
||||||
self.default_encoding_parameters = default_encoding_parameters
|
self.default_encoding_parameters = default_encoding_parameters
|
||||||
|
self.mutable_file_default = mutable_file_default
|
||||||
self.key_generator = key_generator
|
self.key_generator = key_generator
|
||||||
self.blacklist = blacklist
|
self.blacklist = blacklist
|
||||||
|
|
||||||
|
@ -111,7 +112,7 @@ class NodeMaker:
|
||||||
|
|
||||||
def create_mutable_file(self, contents=None, keysize=None, version=None):
|
def create_mutable_file(self, contents=None, keysize=None, version=None):
|
||||||
if version is None:
|
if version is None:
|
||||||
version = SDMF_VERSION
|
version = self.mutable_file_default
|
||||||
n = MutableFileNode(self.storage_broker, self.secret_holder,
|
n = MutableFileNode(self.storage_broker, self.secret_holder,
|
||||||
self.default_encoding_parameters, self.history)
|
self.default_encoding_parameters, self.history)
|
||||||
d = self.key_generator.generate(keysize)
|
d = self.key_generator.generate(keysize)
|
||||||
|
|
|
@ -1376,7 +1376,7 @@ class Packing(testutil.ReallyEqualMixin, unittest.TestCase):
|
||||||
known_tree = b32decode(self.known_tree)
|
known_tree = b32decode(self.known_tree)
|
||||||
nodemaker = NodeMaker(None, None, None,
|
nodemaker = NodeMaker(None, None, None,
|
||||||
None, None,
|
None, None,
|
||||||
{"k": 3, "n": 10}, None)
|
{"k": 3, "n": 10}, None, None)
|
||||||
write_uri = "URI:SSK-RO:e3mdrzfwhoq42hy5ubcz6rp3o4:ybyibhnp3vvwuq2vaw2ckjmesgkklfs6ghxleztqidihjyofgw7q"
|
write_uri = "URI:SSK-RO:e3mdrzfwhoq42hy5ubcz6rp3o4:ybyibhnp3vvwuq2vaw2ckjmesgkklfs6ghxleztqidihjyofgw7q"
|
||||||
filenode = nodemaker.create_from_cap(write_uri)
|
filenode = nodemaker.create_from_cap(write_uri)
|
||||||
node = dirnode.DirectoryNode(filenode, nodemaker, None)
|
node = dirnode.DirectoryNode(filenode, nodemaker, None)
|
||||||
|
@ -1437,7 +1437,7 @@ class Packing(testutil.ReallyEqualMixin, unittest.TestCase):
|
||||||
return kids
|
return kids
|
||||||
|
|
||||||
def test_deep_immutable(self):
|
def test_deep_immutable(self):
|
||||||
nm = NodeMaker(None, None, None, None, None, {"k": 3, "n": 10}, None)
|
nm = NodeMaker(None, None, None, None, None, {"k": 3, "n": 10}, None, None)
|
||||||
fn = MinimalFakeMutableFile()
|
fn = MinimalFakeMutableFile()
|
||||||
|
|
||||||
kids = self._make_kids(nm, ["imm", "lit", "write", "read",
|
kids = self._make_kids(nm, ["imm", "lit", "write", "read",
|
||||||
|
@ -1536,7 +1536,7 @@ class FakeClient2(Client):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.nodemaker = FakeNodeMaker(None, None, None,
|
self.nodemaker = FakeNodeMaker(None, None, None,
|
||||||
None, None,
|
None, None,
|
||||||
{"k":3,"n":10}, None)
|
{"k":3,"n":10}, None, None)
|
||||||
def create_node_from_uri(self, rwcap, rocap):
|
def create_node_from_uri(self, rwcap, rocap):
|
||||||
return self.nodemaker.create_from_cap(rwcap, rocap)
|
return self.nodemaker.create_from_cap(rwcap, rocap)
|
||||||
|
|
||||||
|
@ -1825,6 +1825,7 @@ class Deleter(GridTestMixin, testutil.ReallyEqualMixin, unittest.TestCase):
|
||||||
c0.get_history(), c0.getServiceNamed("uploader"),
|
c0.get_history(), c0.getServiceNamed("uploader"),
|
||||||
c0.terminator,
|
c0.terminator,
|
||||||
c0.get_encoding_parameters(),
|
c0.get_encoding_parameters(),
|
||||||
|
c0.mutable_file_default,
|
||||||
c0._key_generator)
|
c0._key_generator)
|
||||||
n = nm.create_from_cap(self.root_uri)
|
n = nm.create_from_cap(self.root_uri)
|
||||||
assert n._node.please_ucwe_after_next_upload == False
|
assert n._node.please_ucwe_after_next_upload == False
|
||||||
|
|
|
@ -239,7 +239,7 @@ def make_nodemaker(s=None, num_peers=10):
|
||||||
keygen.set_default_keysize(TEST_RSA_KEY_SIZE)
|
keygen.set_default_keysize(TEST_RSA_KEY_SIZE)
|
||||||
nodemaker = NodeMaker(storage_broker, sh, None,
|
nodemaker = NodeMaker(storage_broker, sh, None,
|
||||||
None, None,
|
None, None,
|
||||||
{"k": 3, "n": 10}, keygen)
|
{"k": 3, "n": 10}, SDMF_VERSION, keygen)
|
||||||
return nodemaker
|
return nodemaker
|
||||||
|
|
||||||
class Filenode(unittest.TestCase, testutil.ShouldFailMixin):
|
class Filenode(unittest.TestCase, testutil.ShouldFailMixin):
|
||||||
|
|
|
@ -56,6 +56,11 @@ def get_mutable_type(file_format): # accepts result of get_format()
|
||||||
elif file_format == "MDMF":
|
elif file_format == "MDMF":
|
||||||
return MDMF_VERSION
|
return MDMF_VERSION
|
||||||
else:
|
else:
|
||||||
|
# this is also used to identify which formats are mutable. Use
|
||||||
|
# if get_mutable_type(file_format) is not None:
|
||||||
|
# do_mutable()
|
||||||
|
# else:
|
||||||
|
# do_immutable()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,8 @@ class ReplaceMeMixin:
|
||||||
def replace_me_with_a_child(self, req, client, replace):
|
def replace_me_with_a_child(self, req, client, replace):
|
||||||
# a new file is being uploaded in our place.
|
# a new file is being uploaded in our place.
|
||||||
file_format = get_format(req, "CHK")
|
file_format = get_format(req, "CHK")
|
||||||
if file_format in ("SDMF", "MDMF"):
|
|
||||||
mutable_type = get_mutable_type(file_format)
|
mutable_type = get_mutable_type(file_format)
|
||||||
|
if mutable_type is not None:
|
||||||
data = MutableFileHandle(req.content)
|
data = MutableFileHandle(req.content)
|
||||||
d = client.create_mutable_file(data, version=mutable_type)
|
d = client.create_mutable_file(data, version=mutable_type)
|
||||||
def _uploaded(newnode):
|
def _uploaded(newnode):
|
||||||
|
|
|
@ -46,9 +46,9 @@ class URIHandler(RenderMixin, rend.Page):
|
||||||
t = get_arg(req, "t", "").strip()
|
t = get_arg(req, "t", "").strip()
|
||||||
if t == "":
|
if t == "":
|
||||||
file_format = get_format(req, "CHK")
|
file_format = get_format(req, "CHK")
|
||||||
if file_format in ("SDMF", "MDMF"):
|
mutable_type = get_mutable_type(file_format)
|
||||||
version = get_mutable_type(file_format)
|
if mutable_type is not None:
|
||||||
return unlinked.PUTUnlinkedSSK(req, self.client, version)
|
return unlinked.PUTUnlinkedSSK(req, self.client, mutable_type)
|
||||||
else:
|
else:
|
||||||
return unlinked.PUTUnlinkedCHK(req, self.client)
|
return unlinked.PUTUnlinkedCHK(req, self.client)
|
||||||
if t == "mkdir":
|
if t == "mkdir":
|
||||||
|
@ -65,9 +65,9 @@ class URIHandler(RenderMixin, rend.Page):
|
||||||
t = get_arg(req, "t", "").strip()
|
t = get_arg(req, "t", "").strip()
|
||||||
if t in ("", "upload"):
|
if t in ("", "upload"):
|
||||||
file_format = get_format(req)
|
file_format = get_format(req)
|
||||||
if file_format in ("SDMF", "MDMF"):
|
mutable_type = get_mutable_type(file_format)
|
||||||
version = get_mutable_type(file_format)
|
if mutable_type is not None:
|
||||||
return unlinked.POSTUnlinkedSSK(req, self.client, version)
|
return unlinked.POSTUnlinkedSSK(req, self.client, mutable_type)
|
||||||
else:
|
else:
|
||||||
return unlinked.POSTUnlinkedCHK(req, self.client)
|
return unlinked.POSTUnlinkedCHK(req, self.client)
|
||||||
if t == "mkdir":
|
if t == "mkdir":
|
||||||
|
|
|
@ -29,7 +29,7 @@ def PUTUnlinkedCreateDirectory(req, client):
|
||||||
# "PUT /uri?t=mkdir", to create an unlinked directory.
|
# "PUT /uri?t=mkdir", to create an unlinked directory.
|
||||||
file_format = get_format(req, None)
|
file_format = get_format(req, None)
|
||||||
if file_format == "CHK":
|
if file_format == "CHK":
|
||||||
raise WebError("format=CHK not currently accepted for PUT /uri?t=mkdir",
|
raise WebError("format=CHK not accepted for PUT /uri?t=mkdir",
|
||||||
http.BAD_REQUEST)
|
http.BAD_REQUEST)
|
||||||
mt = None
|
mt = None
|
||||||
if file_format:
|
if file_format:
|
||||||
|
|
Loading…
Reference in New Issue