directory on a separate size-limited filesystem, and/or use per-user
OS/filesystem quotas.
-my_private_dir.cap (optional): When you create a new tahoe client, this
-file is created with no contents (as an empty file). When the node starts
-up, it will inspect this file. If the file doesn't exist then nothing will
-be done. If the file exists, then the node will try to read the contents of
-the file and parse the contents as a read-write URI to a mutable directory.
-If the file exists but doesn't contain a well-formed read-write URI to a
-mutable directory (which is the case if the file is empty), then the node
-will create a new decentralized mutable directory and write its URI into this
-file. The start.html page will contain a URL pointing to this directory if
-it exists.
+root_dir.cap (optional): The command-line tools will read a directory cap out of
+this file and use it, if you don't specify a '--dir-uri' option or if you
+specify '--dir-uri=root'.
== Node State ==
from allmydata.checker import Checker
from allmydata.control import ControlServer
from allmydata.introducer import IntroducerClient
-from allmydata.util import hashutil, idlib, testutil, observer
+from allmydata.util import hashutil, idlib, testutil
from allmydata.filenode import FileNode
from allmydata.dirnode import NewDirectoryNode
from allmydata.mutable import MutableFileNode
from allmydata.interfaces import IURI, INewDirectoryURI, \
IReadonlyNewDirectoryURI, IFileURI, IMutableFileURI
-from allmydata import uri
class Client(node.Node, Referenceable, testutil.PollMixin):
implements(RIClient)
STOREDIR = 'storage'
NODETYPE = "client"
SUICIDE_PREVENTION_HOTLINE_FILE = "suicide_prevention_hotline"
- MY_PRIVATE_DIR_FILE = "my_private_dir.cap"
# we're pretty narrow-minded right now
OLDEST_SUPPORTED_VERSION = allmydata.__version__
self.add_service(Uploader())
self.add_service(Downloader())
self.add_service(Checker())
- self.private_directory_uri = None
- self._private_uri_observers = None
- self._start_page_observers = None
self.introducer_furl = self.get_config("introducer.furl", required=True)
if webport:
self.init_web(webport) # strports string
- def _init_start_page(self, privdiruri):
- ws = self.getServiceNamed("webish")
- startfile = os.path.join(self.basedir, "private", "start.html")
- nodeurl_file = os.path.join(self.basedir, "node.url")
- return ws.create_start_html(privdiruri, startfile, nodeurl_file)
-
- def init_start_page(self):
- if not self._start_page_observers:
- self._start_page_observers = observer.OneShotObserverList()
- d = self.get_private_uri()
- d.addCallback(self._init_start_page)
- d.addCallback(self._start_page_observers.fire)
- d.addErrback(log.err)
- return self._start_page_observers.when_fired()
-
def init_lease_secret(self):
def make_secret():
return idlib.b2a(os.urandom(hashutil.CRYPTO_VAL_SIZE)) + "\n"
if self.get_config("push_to_ourselves") is not None:
self.push_to_ourselves = True
- def _maybe_create_private_directory(self):
- """
- If 'my_private_dir.cap' exists, then I try to read a mutable
- directory URI from it. If it exists but doesn't contain a well-formed
- read-write mutable directory URI, then I create a new mutable
- directory and write its URI into that file.
- """
- # TODO: change this to use Node.get_or_create_private_config(). That
- # will probably require passing a validation function in, or
- # something.
- privdirfile = os.path.join(self.basedir, "private",
- self.MY_PRIVATE_DIR_FILE)
- if os.path.exists(privdirfile):
- try:
- theuri = open(privdirfile, "r").read().strip()
- try:
- uri.NewDirectoryURI.init_from_human_encoding(theuri)
- except:
- raise EnvironmentError("not a well-formed mutable directory uri")
- except EnvironmentError, le:
- d = self.when_tub_ready()
- def _when_tub_ready(res):
- return self.create_empty_dirnode(wait_for_numpeers=1)
- d.addCallback(_when_tub_ready)
- def _when_created(newdirnode):
- log.msg("created new private directory: %s" % (newdirnode,))
- privdiruri = newdirnode.get_uri()
- self.private_directory_uri = privdiruri
- open(privdirfile, "w").write(privdiruri + "\n")
- self._private_uri_observers.fire(privdiruri)
- d.addCallback(_when_created)
- d.addErrback(self._private_uri_observers.fire)
- else:
- self.private_directory_uri = theuri
- log.msg("loaded private directory: %s" % (self.private_directory_uri,))
- self._private_uri_observers.fire(self.private_directory_uri)
- else:
- # If there is no such file then this is how the node is configured
- # to not create a private directory.
- self._private_uri_observers.fire(None)
-
- def get_private_uri(self):
- """
- Eventually fires with the URI (as a string) to this client's private
- directory, or with None if this client has been configured not to
- create one.
- """
- if self._private_uri_observers is None:
- self._private_uri_observers = observer.OneShotObserverList()
- self._maybe_create_private_directory()
- return self._private_uri_observers.when_fired()
-
def init_web(self, webport):
self.log("init_web(webport=%s)", args=(webport,))
if self.get_config("webport_allow_localfile") is not None:
ws.allow_local_access(True)
self.add_service(ws)
- self.init_start_page()
def _check_hotline(self, hotline_file):
if os.path.exists(hotline_file):
"Look here to find out which Tahoe node should be used for all "
"operations. The directory should either contain a full Tahoe node, "
"or a file named node.url which points to some other Tahoe node. "
- "It should also contain a file named my_private_dir.cap which contains "
+ "It should also contain a file named root_dir.cap which contains "
"the root dirnode URI that should be used."
],
["node-url", "u", None,
"URL of the tahoe node to use, a URL like \"http://127.0.0.1:8123\". "
"This overrides the URL found in the --node-directory ."],
- ["root-uri", "r", "private",
- "Which dirnode URI should be used as a root directory. The "
- "string 'private' is also, and means we should use the "
- "private vdrive as found in the my_private_dir.cap file in the "
- "--node-directory ."],
+ ["dir-uri", "r", "root",
+ "Which dirnode URI should be used as a root directory. The "
+ "string 'root' is special, and means we should use the "
+ "directory found in the 'root_dir.cap' file in the 'private' "
+ "subdirectory of the --node-directory ."],
]
def postOptions(self):
node_url_file = os.path.join(self['node-directory'], "node.url")
self['node-url'] = open(node_url_file, "r").read().strip()
- # also compute self['root-uri']
- if self['root-uri'] == "private":
- uri_file = os.path.join(self['node-directory'], "my_private_dir.cap")
- self['root-uri'] = open(uri_file, "r").read().strip()
- else:
- from allmydata import uri
- parsed = uri.from_string(self['root-uri'])
- if not uri.IDirnodeURI.providedBy(parsed):
- raise usage.UsageError("--root-uri must be a dirnode URI, or "
- "'public' or 'private'")
+ # also compute self['dir-uri']
+ if self['dir-uri'] == "root":
+ uri_file = os.path.join(self['node-directory'], "root_dir.cap")
+ self['dir-uri'] = open(uri_file, "r").read().strip()
+ from allmydata import uri
+ parsed = uri.NewDirectoryURI.init_from_human_encoding(self['dir-uri'])
+ if not uri.IDirnodeURI.providedBy(parsed):
+ raise usage.UsageError("--dir-uri must be a dir URI, or 'root'")
class ListOptions(VDriveOptions):
def list(config, stdout, stderr):
from allmydata.scripts import tahoe_ls
rc = tahoe_ls.list(config['node-url'],
- config['root-uri'],
+ config['dir-uri'],
config['vdrive_pathname'],
stdout, stderr)
return rc
vdrive_filename = config['vdrive_filename']
local_filename = config['local_filename']
rc = tahoe_get.get(config['node-url'],
- config['root-uri'],
+ config['dir-uri'],
vdrive_filename,
local_filename,
stdout, stderr)
else:
verbosity = 2
rc = tahoe_put.put(config['node-url'],
- config['root-uri'],
+ config['dir-uri'],
local_filename,
vdrive_filename,
verbosity,
else:
verbosity = 2
rc = tahoe_rm.rm(config['node-url'],
- config['root-uri'],
+ config['dir-uri'],
vdrive_pathname,
verbosity,
stdout, stderr)
frompath = config['from']
topath = config['to']
rc = tahoe_mv.mv(config['node-url'],
- config['root-uri'],
+ config['dir-uri'],
frompath,
topath,
stdout, stderr)
f = open(os.path.join(basedir, "webport"), "w")
f.write(config['webport'] + "\n")
f.close()
- # Create an empty my_private_dir.cap file, indicating that the node
+ # Create an empty root_dir.cap file, indicating that the node
# should fill it with the URI after creating the directory.
from allmydata.util import fileutil
fileutil.make_dirs(os.path.join(basedir, "private"), 0700)
- open(os.path.join(basedir, "private", "my_private_dir.cap"), "w")
+ open(os.path.join(basedir, "private", "root_dir.cap"), "w")
print >>out, "client created in %s" % basedir
print >>out, " please copy introducer.furl into the directory"
import urllib
-def get(nodeurl, root_uri, vdrive_fname, local_file, stdout, stderr):
+def get(nodeurl, dir_uri, vdrive_fname, local_file, stdout, stderr):
if nodeurl[-1] != "/":
nodeurl += "/"
- url = nodeurl + "uri/%s/" % urllib.quote(root_uri)
+ url = nodeurl + "uri/%s/" % urllib.quote(dir_uri)
if vdrive_fname:
url += urllib.quote(vdrive_fname)
import optparse, re
parser = optparse.OptionParser()
parser.add_option("-u", "--nodeurl", dest="nodeurl")
- parser.add_option("-r", "--root-uri", dest="rooturi")
+ parser.add_option("-r", "--dir-uri", dest="rooturi")
(options, args) = parser.parse_args()
raise ValueError("--node-url is required to be a string and look like \"http://HOSTNAMEORADDR:PORT\", not: %r" % (options.nodeurl,))
if not options.rooturi:
- raise ValueError("must provide --root-uri")
+ raise ValueError("must provide --dir-uri")
vdrive_fname = args[0]
local_file = None
import urllib
import simplejson
-def list(nodeurl, root_uri, vdrive_pathname, stdout, stderr):
+def list(nodeurl, dir_uri, vdrive_pathname, stdout, stderr):
if nodeurl[-1] != "/":
nodeurl += "/"
- url = nodeurl + "uri/%s/" % urllib.quote(root_uri)
+ url = nodeurl + "uri/%s/" % urllib.quote(dir_uri)
if vdrive_pathname:
url += urllib.quote(vdrive_pathname)
url += "?t=json"
import optparse, re
parser = optparse.OptionParser()
parser.add_option("-u", "--node-url", dest="nodeurl")
- parser.add_option("-r", "--root-uri", dest="rooturi")
+ parser.add_option("-r", "--dir-uri", dest="rooturi")
(options, args) = parser.parse_args()
raise ValueError("--node-url is required to be a string and look like \"http://HOSTNAMEORADDR:PORT\", not: %r" % (options.nodeurl,))
if not options.rooturi:
- raise ValueError("must provide --root-uri")
+ raise ValueError("must provide --dir-uri")
vdrive_pathname = ""
if args:
import simplejson
from allmydata.scripts.common_http import do_http
-def mv(nodeurl, root_uri, frompath, topath, stdout, stderr):
+def mv(nodeurl, dir_uri, frompath, topath, stdout, stderr):
frompath = urllib.quote(frompath)
topath = urllib.quote(topath)
if nodeurl[-1] != "/":
nodeurl += "/"
- url = nodeurl + "uri/%s/" % urllib.quote(root_uri)
+ url = nodeurl + "uri/%s/" % urllib.quote(dir_uri)
data = urllib.urlopen(url + frompath + "?t=json").read()
nodetype, attrs = simplejson.loads(data)
import urllib
from allmydata.scripts.common_http import do_http
-def put(nodeurl, root_uri, local_fname, vdrive_fname, verbosity,
+def put(nodeurl, dir_uri, local_fname, vdrive_fname, verbosity,
stdout, stderr):
"""
@param verbosity: 0, 1, or 2, meaning quiet, verbose, or very verbose
"""
if nodeurl[-1] != "/":
nodeurl += "/"
- url = nodeurl + "uri/%s/" % urllib.quote(root_uri)
+ url = nodeurl + "uri/%s/" % urllib.quote(dir_uri)
if vdrive_fname:
url += urllib.quote(vdrive_fname)
import optparse, re
parser = optparse.OptionParser()
parser.add_option("-u", "--node-url", dest="nodeurl")
- parser.add_option("-r", "--root-uri", dest="rooturi")
+ parser.add_option("-r", "--dir-uri", dest="rooturi")
(options, args) = parser.parse_args()
raise ValueError("--node-url is required to be a string and look like \"http://HOSTNAMEORADDR:PORT\", not: %r" % (options.nodeurl,))
if not options.rooturi:
- raise ValueError("must provide --root-uri")
+ raise ValueError("must provide --dir-uri")
local_file = args[0]
vdrive_fname = None
import urllib
from allmydata.scripts.common_http import do_http
-def rm(nodeurl, root_uri, vdrive_pathname, verbosity, stdout, stderr):
+def rm(nodeurl, dir_uri, vdrive_pathname, verbosity, stdout, stderr):
"""
@param verbosity: 0, 1, or 2, meaning quiet, verbose, or very verbose
"""
if nodeurl[-1] != "/":
nodeurl += "/"
- url = nodeurl + "uri/%s/" % urllib.quote(root_uri)
+ url = nodeurl + "uri/%s/" % urllib.quote(dir_uri)
if vdrive_pathname:
url += urllib.quote(vdrive_pathname)
import optparse, re
parser = optparse.OptionParser()
parser.add_option("-u", "--node-url", dest="nodeurl")
- parser.add_option("-r", "--root-uri", dest="rooturi")
+ parser.add_option("-r", "--dir-uri", dest="rooturi")
(options, args) = parser.parse_args()
raise ValueError("--node-url is required to be a string and look like \"http://HOSTNAMEORADDR:PORT\", not: %r" % (options.nodeurl,))
if not options.rooturi:
- raise ValueError("must provide --root-uri")
+ raise ValueError("must provide --dir-uri")
vdrive_pathname = args[0]
filenode_uri = uri.WriteableSSKFileURI(writekey="\x00"*16,
fingerprint="\x00"*32)
private_uri = uri.NewDirectoryURI(filenode_uri).to_string()
- open("cli/test_options/my_private_dir.cap", "w").write(private_uri + "\n")
+ open("cli/test_options/root_dir.cap", "w").write(private_uri + "\n")
o = cli.ListOptions()
o.parseOptions(["--node-directory", "cli/test_options"])
self.failUnlessEqual(o['node-url'], "http://localhost:8080/")
- self.failUnlessEqual(o['root-uri'], private_uri)
+ self.failUnlessEqual(o['dir-uri'], private_uri)
self.failUnlessEqual(o['vdrive_pathname'], "")
o = cli.ListOptions()
o.parseOptions(["--node-directory", "cli/test_options",
"--node-url", "http://example.org:8111/"])
self.failUnlessEqual(o['node-url'], "http://example.org:8111/")
- self.failUnlessEqual(o['root-uri'], private_uri)
+ self.failUnlessEqual(o['dir-uri'], private_uri)
self.failUnlessEqual(o['vdrive_pathname'], "")
o = cli.ListOptions()
o.parseOptions(["--node-directory", "cli/test_options",
- "--root-uri", "private"])
+ "--dir-uri", "root"])
self.failUnlessEqual(o['node-url'], "http://localhost:8080/")
- self.failUnlessEqual(o['root-uri'], private_uri)
+ self.failUnlessEqual(o['dir-uri'], private_uri)
self.failUnlessEqual(o['vdrive_pathname'], "")
o = cli.ListOptions()
fingerprint="\x11"*32)
other_uri = uri.NewDirectoryURI(other_filenode_uri).to_string()
o.parseOptions(["--node-directory", "cli/test_options",
- "--root-uri", other_uri])
+ "--dir-uri", other_uri])
self.failUnlessEqual(o['node-url'], "http://localhost:8080/")
- self.failUnlessEqual(o['root-uri'], other_uri)
+ self.failUnlessEqual(o['dir-uri'], other_uri)
self.failUnlessEqual(o['vdrive_pathname'], "")
o = cli.ListOptions()
o.parseOptions(["--node-directory", "cli/test_options",
- "--root-uri", other_uri, "subdir"])
+ "--dir-uri", other_uri, "subdir"])
self.failUnlessEqual(o['node-url'], "http://localhost:8080/")
- self.failUnlessEqual(o['root-uri'], other_uri)
+ self.failUnlessEqual(o['dir-uri'], other_uri)
self.failUnlessEqual(o['vdrive_pathname'], "subdir")
open(os.path.join(basedir, "webport"), "w").write("tcp:0:interface=127.0.0.1")
if self.createprivdir:
fileutil.make_dirs(os.path.join(basedir, "private"))
- open(os.path.join(basedir, "private", "my_private_dir.cap"), "w")
+ open(os.path.join(basedir, "private", "root_dir.cap"), "w")
open(os.path.join(basedir, "introducer.furl"), "w").write(self.introducer_furl)
c = self.add_service(client.Client(basedir=basedir))
self.clients.append(c)
d.addCallback(self.log, "did _check_publish2")
d.addCallback(self._do_publish_private)
d.addCallback(self.log, "did _do_publish_private")
- # now we also have (where "P" denotes clients[0]'s automatic private
- # dir):
+ # now we also have (where "P" denotes a new dir):
# P/personal/sekrit data
# P/s2-rw -> /subdir1/subdir2/
# P/s2-ro -> /subdir1/subdir2/ (read-only)
d.addCallback(self._check_publish_private)
d.addCallback(self.log, "did _check_publish_private")
d.addCallback(self._test_web)
- d.addCallback(self._test_web_start)
d.addCallback(self._test_control)
d.addCallback(self._test_cli)
# P now has four top-level children:
def _do_publish_private(self, res):
self.smalldata = "sssh, very secret stuff"
ut = upload.Data(self.smalldata)
- d = self.clients[0].get_private_uri()
+ d = self.clients[0].create_empty_dirnode(wait_for_numpeers=self.numclients)
d.addCallback(self.log, "GOT private directory")
- def _got_root_uri(privuri):
- assert privuri
- privnode = self.clients[0].create_node_from_uri(privuri)
+ def _got_new_dir(privnode):
rootnode = self.clients[0].create_node_from_uri(self._root_directory_uri)
d1 = privnode.create_empty_directory("personal", wait_for_numpeers=self.numclients)
d1.addCallback(self.log, "made P/personal")
d2.addCallback(lambda node: privnode.set_uri("s2-ro", s2node.get_readonly_uri(), wait_for_numpeers=self.numclients))
return d2
d1.addCallback(_got_s2)
+ d1.addCallback(lambda res: privnode)
return d1
- d.addCallback(_got_root_uri)
+ d.addCallback(_got_new_dir)
return d
def _check_publish1(self, res):
d.addCallback(_got_filenode)
return d
- def _check_publish_private(self, res):
+ def _check_publish_private(self, resnode):
# this one uses the path-based API
- d = self.clients[0].get_private_uri()
- def _got_private_uri(privateuri):
- self._private_node = self.clients[0].create_node_from_uri(privateuri)
- d.addCallback(_got_private_uri)
+ self._private_node = resnode
- d.addCallback(lambda res: self._private_node.get_child_at_path("personal"))
+ d = self._private_node.get_child_at_path("personal")
def _got_personal(personal):
self._personal_node = personal
return personal
return d
- def _test_web_start(self, res):
- basedir = self.clients[0].basedir
- startfile = os.path.join(basedir, "private", "start.html")
- self.failUnless(os.path.exists(startfile))
- start_html = open(startfile, "r").read()
- self.failUnless(self.webish_url in start_html)
- d = self.clients[0].get_private_uri()
- def done(private_uri):
- private_url = self.webish_url + "uri/" + private_uri
- self.failUnless(private_url in start_html)
- d.addCallback(done)
- return d
-
def _test_runner(self, res):
# exercise some of the diagnostic tools in runner.py
nodeargs = [
"--node-url", self.webish_url,
- "--root-uri", private_uri,
+ "--dir-uri", private_uri,
]
public_nodeargs = [
"--node-url", self.webish_url,
- "--root-uri", some_uri,
+ "--dir-uri", some_uri,
]
TESTDATA = "I will not write the same thing over and over.\n" * 100
def _check(res):
self.failUnless('Welcome To AllMyData' in res)
self.failUnless('Tahoe' in res)
- self.failUnless('personal vdrive not available.' in res)
self.s.basedir = 'web/test_welcome'
fileutil.make_dirs("web/test_welcome")
fileutil.make_dirs("web/test_welcome/private")
- self.ws.create_start_html("private_uri",
- "web/test_welcome/private/start.html",
- "web/test_welcome/node.url")
return self.GET("/")
d.addCallback(_check)
- def _check2(res):
- # We shouldn't link to the start.html page since we don't have a
- # private directory cap.
- self.failIf('To view your personal private non-shared' in res)
- self.failIf('from your local filesystem:' in res)
- self.failIf(os.path.abspath('web/test_welcome/private/start.html') in res)
- d.addCallback(_check2)
return d
def test_provisioning_math(self):
d.addCallback(_check4)
return d
- def test_start_html(self):
- fileutil.make_dirs("web")
- fileutil.make_dirs("web/private")
- startfile = "web/private/start.html"
- nodeurlfile = "web/node.url"
- self.ws.create_start_html("private_uri", startfile, nodeurlfile)
-
- self.failUnless(os.path.exists(startfile))
- start_html = open(startfile, "r").read()
- self.failUnless(self.webish_url in start_html)
- private_url = self.webish_url + "/uri/private_uri"
- self.failUnless(private_url in start_html)
-
- self.failUnless(os.path.exists(nodeurlfile))
- nodeurl = open(nodeurlfile, "r").read().strip()
- self.failUnless(nodeurl.startswith("http://localhost"))
-
def test_GET_FILEURL(self):
d = self.GET(self.public_url + "/foo/bar.txt")
d.addCallback(self.failUnlessIsBarDotTxt)
+++ /dev/null
-<html>
- <head>
- <title>AllMyData - Tahoe</title>
- <!-- <link href="http://www.allmydata.com/common/css/styles.css"
- rel="stylesheet" type="text/css"/> -->
- <link href="/webform_css" rel="stylesheet" type="text/css"/>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- </head>
- <body>
-
-<h1>Welcome To Your AllMyData "Tahoe" Node!</h1>
-
-<div>%(link_to_private_uri)s</div>
-
-<div>View <a href="%(base_url)s/">this node's status page</a>.</div>
-
-
-<div>Please visit the <a href="http://allmydata.org">Tahoe home page</a> for
-code updates and bug reporting.</div>
-
- </body>
-</html>
<h1>Welcome To AllMyData "Tahoe"!</h1>
-<div n:render="private_vdrive" />
-
<div>Please visit the <a href="http://allmydata.org">Tahoe home page</a> for
code updates and bug reporting. The <a href="provisioning">provisioning
tool</a> may also be useful.</div>
from base64 import b32encode
import os.path
-from twisted.application import service, strports, internet
+from twisted.application import service, strports
from twisted.web import static, resource, server, html, http
from twisted.python import util, log
from twisted.internet import defer
ctx.fillSlots("peerid", nodeid_a)
return ctx.tag
- def render_private_vdrive(self, ctx, data):
- basedir = IClient(ctx).basedir
- start_html = os.path.abspath(os.path.join(basedir, "private", "start.html"))
- basedir = IClient(ctx).basedir
- if os.path.exists(start_html) and os.path.exists(os.path.join(basedir, "private", "my_private_dir.cap")):
- return T.p["To view your personal private non-shared filestore, ",
- "use this browser to open the following file from ",
- "your local filesystem:",
- T.pre[start_html],
- ]
- return T.p["personal vdrive not available."]
-
# this is a form where users can download files by URI
def render_download_form(self, ctx, data):
form = T.form(action="uri", method="get",
# apparently 'ISite' does not exist
#self.site._client = self.parent
self._started.callback(None)
-
- def create_start_html(self, private_uri, startfile, nodeurl_file):
- """
- Returns a deferred that eventually fires once the start.html page has
- been created.
- """
- self._started.addCallback(self._create_start_html, private_uri, startfile, nodeurl_file)
- return self._started
-
- def _create_start_html(self, dummy, private_uri, startfile, nodeurl_file):
- f = open(startfile, "w")
- template = open(util.sibpath(__file__, "web/start.html"), "r").read()
- # what is our webport?
- s = self.listener
- if isinstance(s, internet.TCPServer):
- base_url = "http://localhost:%d" % s._port.getHost().port
- elif isinstance(s, internet.SSLServer):
- base_url = "https://localhost:%d" % s._port.getHost().port
- else:
- base_url = "UNKNOWN" # this will break the href
- # TODO: emit a start.html that explains that we don't know
- # how to create a suitable URL
- if private_uri:
- link_to_private_uri = "View <a href=\"%s/uri/%s\">your personal private non-shared filestore</a>." % (base_url, private_uri)
- fields = {"link_to_private_uri": link_to_private_uri,
- "base_url": base_url,
- }
- else:
- fields = {"link_to_private_uri": "",
- "base_url": base_url,
- }
- f.write(template % fields)
- f.close()
-
- f = open(nodeurl_file, "w")
- # this file is world-readable
- f.write(base_url + "\n")
- f.close()