3 from twisted.python import usage
4 from allmydata.scripts.common import BasedirMixin, NoDefaultBasedirMixin
5 from allmydata.util.assertutil import precondition
6 from allmydata.util.encodingutil import listdir_unicode, argv_to_unicode, quote_output
9 class CreateClientOptions(BasedirMixin, usage.Options):
11 ("basedir", "C", None, "which directory to create the node in"),
12 # we provide 'create-node'-time options for the most common
13 # configuration knobs. The rest can be controlled by editing
14 # tahoe.cfg before node startup.
15 ("nickname", "n", None, "nickname for this node"),
16 ("introducer", "i", None, "introducer FURL to use"),
17 ("webport", "p", "tcp:3456:interface=127.0.0.1",
18 "which TCP port to run the HTTP interface on. Use 'none' to disable."),
21 class CreateNodeOptions(CreateClientOptions):
23 ("no-storage", None, "do not offer storage service to other nodes"),
26 class CreateIntroducerOptions(NoDefaultBasedirMixin, usage.Options):
28 ["basedir", "C", None, "which directory to create the introducer in"],
35 pkg_resources.require('%s')
36 pkg_resources.require('twisted')
37 from allmydata import client
38 from twisted.application import service
42 application = service.Application("allmydata_client")
43 c.setServiceParent(application)
44 """ % (allmydata.__appname__,)
50 pkg_resources.require('%s')
51 pkg_resources.require('twisted')
52 from allmydata import introducer
53 from twisted.application import service
55 c = introducer.IntroducerNode()
57 application = service.Application("allmydata_introducer")
58 c.setServiceParent(application)
59 """ % (allmydata.__appname__,)
61 def write_node_config(c, config):
62 # this is shared between clients and introducers
63 c.write("# -*- mode: conf; coding: utf-8 -*-\n")
65 c.write("# This file controls the configuration of the Tahoe node that\n")
66 c.write("# lives in this directory. It is only read at node startup.\n")
67 c.write("# For details about the keys that can be set here, please\n")
68 c.write("# read the 'docs/configuration.txt' file that came with your\n")
69 c.write("# Tahoe installation.\n")
73 c.write("nickname = %s\n" % config.get("nickname", "")) #TODO: utf8 in argv?
74 webport = config.get("webport", "none")
75 if webport.lower() == "none":
77 c.write("web.port = %s\n" % webport)
78 c.write("web.static = public_html\n")
79 c.write("#tub.port =\n")
80 c.write("#tub.location = \n")
81 c.write("#log_gatherer.furl =\n")
82 c.write("#timeout.keepalive =\n")
83 c.write("#timeout.disconnect =\n")
84 c.write("#ssh.port = 8022\n")
85 c.write("#ssh.authorized_keys_file = ~/.ssh/authorized_keys\n")
89 def create_node(basedir, config, out=sys.stdout, err=sys.stderr):
90 # This should always be called with an absolute Unicode basedir.
91 precondition(isinstance(basedir, unicode), basedir)
93 if os.path.exists(basedir):
94 if listdir_unicode(basedir):
95 print >>err, "The base directory %s is not empty." % quote_output(basedir)
96 print >>err, "To avoid clobbering anything, I am going to quit now."
97 print >>err, "Please use a different directory, or empty this one."
99 # we're willing to use an empty directory
102 f = open(os.path.join(basedir, "tahoe-client.tac"), "w")
106 c = open(os.path.join(basedir, "tahoe.cfg"), "w")
108 write_node_config(c, config)
110 c.write("[client]\n")
111 c.write("introducer.furl = %s\n" % config.get("introducer", ""))
112 c.write("helper.furl =\n")
113 c.write("#key_generator.furl =\n")
114 c.write("#stats_gatherer.furl =\n")
115 c.write("#shares.needed = 3\n")
116 c.write("#shares.happy = 7\n")
117 c.write("#shares.total = 10\n")
120 boolstr = {True:"true", False:"false"}
121 c.write("[storage]\n")
122 storage_enabled = not config.get("no-storage", None)
123 c.write("enabled = %s\n" % boolstr[storage_enabled])
124 c.write("#readonly =\n")
125 c.write("#reserved_space =\n")
126 c.write("#expire.enabled =\n")
127 c.write("#expire.mode =\n")
130 c.write("[helper]\n")
131 c.write("enabled = false\n")
136 from allmydata.util import fileutil
137 fileutil.make_dirs(os.path.join(basedir, "private"), 0700)
138 print >>out, "Node created in %s" % quote_output(basedir)
139 if not config.get("introducer", ""):
140 print >>out, " Please set [client]introducer.furl= in tahoe.cfg!"
141 print >>out, " The node cannot connect to a grid without it."
142 if not config.get("nickname", ""):
143 print >>out, " Please set [node]nickname= in tahoe.cfg"
146 def create_client(basedir, config, out=sys.stdout, err=sys.stderr):
147 config['no-storage'] = True
148 return create_node(basedir, config, out=out, err=err)
151 def create_introducer(basedir, config, out=sys.stdout, err=sys.stderr):
152 # This should always be called with an absolute Unicode basedir.
153 precondition(isinstance(basedir, unicode), basedir)
155 if os.path.exists(basedir):
156 if listdir_unicode(basedir):
157 print >>err, "The base directory %s is not empty." % quote_output(basedir)
158 print >>err, "To avoid clobbering anything, I am going to quit now."
159 print >>err, "Please use a different directory, or empty this one."
161 # we're willing to use an empty directory
164 f = open(os.path.join(basedir, "tahoe-introducer.tac"), "w")
165 f.write(introducer_tac)
168 c = open(os.path.join(basedir, "tahoe.cfg"), "w")
169 write_node_config(c, config)
172 print >>out, "Introducer created in %s" % quote_output(basedir)
176 ["create-node", None, CreateNodeOptions, "Create a node that acts as a client, server or both."],
177 ["create-client", None, CreateClientOptions, "Create a client node (with storage initially disabled)."],
178 ["create-introducer", None, CreateIntroducerOptions, "Create an introducer node."],
182 "create-node": create_node,
183 "create-client": create_client,
184 "create-introducer": create_introducer,