]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/scripts/create_node.py
Remove magic_folder subsection from default tahoe.cfg
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / scripts / create_node.py
1
2 import os, sys
3 from allmydata.scripts.common import BasedirOptions, NoDefaultBasedirOptions
4 from allmydata.scripts.default_nodedir import _default_nodedir
5 from allmydata.util.assertutil import precondition
6 from allmydata.util.encodingutil import listdir_unicode, argv_to_unicode, quote_local_unicode_path
7 import allmydata
8
9 class _CreateBaseOptions(BasedirOptions):
10     optParameters = [
11         # we provide 'create-node'-time options for the most common
12         # configuration knobs. The rest can be controlled by editing
13         # tahoe.cfg before node startup.
14         ("nickname", "n", None, "Specify the nickname for this node."),
15         ("introducer", "i", None, "Specify the introducer FURL to use."),
16         ("webport", "p", "tcp:3456:interface=127.0.0.1",
17          "Specify which TCP port to run the HTTP interface on. Use 'none' to disable."),
18         ("basedir", "C", None, "Specify which Tahoe base directory should be used. This has the same effect as the global --node-directory option. [default: %s]"
19          % quote_local_unicode_path(_default_nodedir)),
20
21         ]
22
23     # This is overridden in order to ensure we get a "Wrong number of
24     # arguments." error when more than one argument is given.
25     def parseArgs(self, basedir=None):
26         BasedirOptions.parseArgs(self, basedir)
27
28 class CreateClientOptions(_CreateBaseOptions):
29     synopsis = "[options] [NODEDIR]"
30     description = "Create a client-only Tahoe-LAFS node (no storage server)."
31
32 class CreateNodeOptions(CreateClientOptions):
33     optFlags = [
34         ("no-storage", None, "Do not offer storage service to other nodes."),
35         ]
36     synopsis = "[options] [NODEDIR]"
37     description = "Create a full Tahoe-LAFS node (client+server)."
38
39 class CreateIntroducerOptions(NoDefaultBasedirOptions):
40     subcommand_name = "create-introducer"
41     description = "Create a Tahoe-LAFS introducer."
42
43
44 client_tac = """
45 # -*- python -*-
46
47 import pkg_resources
48 pkg_resources.require('%s')
49 pkg_resources.require('twisted')
50 from allmydata import client
51 from twisted.application import service
52
53 c = client.Client()
54
55 application = service.Application("allmydata_client")
56 c.setServiceParent(application)
57 """ % (allmydata.__appname__,)
58
59 introducer_tac = """
60 # -*- python -*-
61
62 import pkg_resources
63 pkg_resources.require('%s')
64 pkg_resources.require('twisted')
65 from allmydata import introducer
66 from twisted.application import service
67
68 c = introducer.IntroducerNode()
69
70 application = service.Application("allmydata_introducer")
71 c.setServiceParent(application)
72 """ % (allmydata.__appname__,)
73
74 def write_node_config(c, config):
75     # this is shared between clients and introducers
76     c.write("# -*- mode: conf; coding: utf-8 -*-\n")
77     c.write("\n")
78     c.write("# This file controls the configuration of the Tahoe node that\n")
79     c.write("# lives in this directory. It is only read at node startup.\n")
80     c.write("# For details about the keys that can be set here, please\n")
81     c.write("# read the 'docs/configuration.rst' file that came with your\n")
82     c.write("# Tahoe installation.\n")
83     c.write("\n\n")
84
85     c.write("[node]\n")
86     nickname = argv_to_unicode(config.get("nickname") or "")
87     c.write("nickname = %s\n" % (nickname.encode('utf-8'),))
88
89     # TODO: validate webport
90     webport = argv_to_unicode(config.get("webport") or "none")
91     if webport.lower() == "none":
92         webport = ""
93     c.write("web.port = %s\n" % (webport.encode('utf-8'),))
94     c.write("web.static = public_html\n")
95     c.write("#tub.port =\n")
96     c.write("#tub.location = \n")
97     c.write("#log_gatherer.furl =\n")
98     c.write("#timeout.keepalive =\n")
99     c.write("#timeout.disconnect =\n")
100     c.write("#ssh.port = 8022\n")
101     c.write("#ssh.authorized_keys_file = ~/.ssh/authorized_keys\n")
102     c.write("\n")
103
104
105 def create_node(config, out=sys.stdout, err=sys.stderr):
106     basedir = config['basedir']
107     # This should always be called with an absolute Unicode basedir.
108     precondition(isinstance(basedir, unicode), basedir)
109
110     if os.path.exists(basedir):
111         if listdir_unicode(basedir):
112             print >>err, "The base directory %s is not empty." % quote_local_unicode_path(basedir)
113             print >>err, "To avoid clobbering anything, I am going to quit now."
114             print >>err, "Please use a different directory, or empty this one."
115             return -1
116         # we're willing to use an empty directory
117     else:
118         os.mkdir(basedir)
119     f = open(os.path.join(basedir, "tahoe-client.tac"), "w")
120     f.write(client_tac)
121     f.close()
122
123     c = open(os.path.join(basedir, "tahoe.cfg"), "w")
124
125     write_node_config(c, config)
126
127     c.write("[client]\n")
128     c.write("# Which services should this client connect to?\n")
129     c.write("introducer.furl = %s\n" % config.get("introducer", ""))
130     c.write("helper.furl =\n")
131     c.write("#key_generator.furl =\n")
132     c.write("#stats_gatherer.furl =\n")
133     c.write("\n")
134     c.write("# What encoding parameters should this client use for uploads?\n")
135     c.write("#shares.needed = 3\n")
136     c.write("#shares.happy = 7\n")
137     c.write("#shares.total = 10\n")
138     c.write("\n")
139
140     boolstr = {True:"true", False:"false"}
141     c.write("[storage]\n")
142     c.write("# Shall this node provide storage service?\n")
143     storage_enabled = not config.get("no-storage", None)
144     c.write("enabled = %s\n" % boolstr[storage_enabled])
145     c.write("#readonly =\n")
146     c.write("reserved_space = 1G\n")
147     c.write("#expire.enabled =\n")
148     c.write("#expire.mode =\n")
149     c.write("\n")
150
151     c.write("[helper]\n")
152     c.write("# Shall this node run a helper service that clients can use?\n")
153     c.write("enabled = false\n")
154     c.write("\n")
155
156     c.close()
157
158     from allmydata.util import fileutil
159     fileutil.make_dirs(os.path.join(basedir, "private"), 0700)
160     print >>out, "Node created in %s" % quote_local_unicode_path(basedir)
161     if not config.get("introducer", ""):
162         print >>out, " Please set [client]introducer.furl= in tahoe.cfg!"
163         print >>out, " The node cannot connect to a grid without it."
164     if not config.get("nickname", ""):
165         print >>out, " Please set [node]nickname= in tahoe.cfg"
166     return 0
167
168 def create_client(config, out=sys.stdout, err=sys.stderr):
169     config['no-storage'] = True
170     return create_node(config, out=out, err=err)
171
172
173 def create_introducer(config, out=sys.stdout, err=sys.stderr):
174     basedir = config['basedir']
175     # This should always be called with an absolute Unicode basedir.
176     precondition(isinstance(basedir, unicode), basedir)
177
178     if os.path.exists(basedir):
179         if listdir_unicode(basedir):
180             print >>err, "The base directory %s is not empty." % quote_local_unicode_path(basedir)
181             print >>err, "To avoid clobbering anything, I am going to quit now."
182             print >>err, "Please use a different directory, or empty this one."
183             return -1
184         # we're willing to use an empty directory
185     else:
186         os.mkdir(basedir)
187     f = open(os.path.join(basedir, "tahoe-introducer.tac"), "w")
188     f.write(introducer_tac)
189     f.close()
190
191     c = open(os.path.join(basedir, "tahoe.cfg"), "w")
192     write_node_config(c, config)
193     c.close()
194
195     print >>out, "Introducer created in %s" % quote_local_unicode_path(basedir)
196     return 0
197
198
199 subCommands = [
200     ["create-node", None, CreateNodeOptions, "Create a node that acts as a client, server or both."],
201     ["create-client", None, CreateClientOptions, "Create a client node (with storage initially disabled)."],
202     ["create-introducer", None, CreateIntroducerOptions, "Create an introducer node."],
203 ]
204
205 dispatch = {
206     "create-node": create_node,
207     "create-client": create_client,
208     "create-introducer": create_introducer,
209     }