]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/scripts/create_node.py
8841d35041646759216b2d3e9b6248a59a5bf13a
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / scripts / create_node.py
1
2 import os, sys
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
7 import allmydata
8
9 class CreateClientOptions(BasedirMixin, usage.Options):
10     optParameters = [
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."),
19         ]
20
21 class CreateNodeOptions(CreateClientOptions):
22     optFlags = [
23         ("no-storage", None, "do not offer storage service to other nodes"),
24         ]
25
26 class CreateIntroducerOptions(NoDefaultBasedirMixin, usage.Options):
27     optParameters = [
28         ["basedir", "C", None, "which directory to create the introducer in"],
29         ]
30
31 client_tac = """
32 # -*- python -*-
33
34 import pkg_resources
35 pkg_resources.require('%s')
36 pkg_resources.require('twisted')
37 from allmydata import client
38 from twisted.application import service
39
40 c = client.Client()
41
42 application = service.Application("allmydata_client")
43 c.setServiceParent(application)
44 """ % (allmydata.__appname__,)
45
46 introducer_tac = """
47 # -*- python -*-
48
49 import pkg_resources
50 pkg_resources.require('%s')
51 pkg_resources.require('twisted')
52 from allmydata import introducer
53 from twisted.application import service
54
55 c = introducer.IntroducerNode()
56
57 application = service.Application("allmydata_introducer")
58 c.setServiceParent(application)
59 """ % (allmydata.__appname__,)
60
61 def write_node_config(c, config):
62     # this is shared between clients and introducers
63     c.write("# -*- mode: conf; coding: utf-8 -*-\n")
64     c.write("\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")
70     c.write("\n\n")
71
72     c.write("[node]\n")
73     nickname = argv_to_unicode(config.get("nickname") or "")
74     c.write("nickname = %s\n" % (nickname.encode('utf-8'),))
75
76     # TODO: validate webport
77     webport = argv_to_unicode(config.get("webport") or "none")
78     if webport.lower() == "none":
79         webport = ""
80     c.write("web.port = %s\n" % (webport.encode('utf-8'),))
81     c.write("web.static = public_html\n")
82     c.write("#tub.port =\n")
83     c.write("#tub.location = \n")
84     c.write("#log_gatherer.furl =\n")
85     c.write("#timeout.keepalive =\n")
86     c.write("#timeout.disconnect =\n")
87     c.write("#ssh.port = 8022\n")
88     c.write("#ssh.authorized_keys_file = ~/.ssh/authorized_keys\n")
89     c.write("\n")
90
91
92 def create_node(basedir, config, out=sys.stdout, err=sys.stderr):
93     # This should always be called with an absolute Unicode basedir.
94     precondition(isinstance(basedir, unicode), basedir)
95
96     if os.path.exists(basedir):
97         if listdir_unicode(basedir):
98             print >>err, "The base directory %s is not empty." % quote_output(basedir)
99             print >>err, "To avoid clobbering anything, I am going to quit now."
100             print >>err, "Please use a different directory, or empty this one."
101             return -1
102         # we're willing to use an empty directory
103     else:
104         os.mkdir(basedir)
105     f = open(os.path.join(basedir, "tahoe-client.tac"), "w")
106     f.write(client_tac)
107     f.close()
108
109     c = open(os.path.join(basedir, "tahoe.cfg"), "w")
110
111     write_node_config(c, config)
112
113     c.write("[client]\n")
114     c.write("introducer.furl = %s\n" % config.get("introducer", ""))
115     c.write("helper.furl =\n")
116     c.write("#key_generator.furl =\n")
117     c.write("#stats_gatherer.furl =\n")
118     c.write("#shares.needed = 3\n")
119     c.write("#shares.happy = 7\n")
120     c.write("#shares.total = 10\n")
121     c.write("\n")
122
123     boolstr = {True:"true", False:"false"}
124     c.write("[storage]\n")
125     storage_enabled = not config.get("no-storage", None)
126     c.write("enabled = %s\n" % boolstr[storage_enabled])
127     c.write("#readonly =\n")
128     c.write("#reserved_space =\n")
129     c.write("#expire.enabled =\n")
130     c.write("#expire.mode =\n")
131     c.write("\n")
132
133     c.write("[helper]\n")
134     c.write("enabled = false\n")
135     c.write("\n")
136
137     c.close()
138
139     from allmydata.util import fileutil
140     fileutil.make_dirs(os.path.join(basedir, "private"), 0700)
141     print >>out, "Node created in %s" % quote_output(basedir)
142     if not config.get("introducer", ""):
143         print >>out, " Please set [client]introducer.furl= in tahoe.cfg!"
144         print >>out, " The node cannot connect to a grid without it."
145     if not config.get("nickname", ""):
146         print >>out, " Please set [node]nickname= in tahoe.cfg"
147
148
149 def create_client(basedir, config, out=sys.stdout, err=sys.stderr):
150     config['no-storage'] = True
151     return create_node(basedir, config, out=out, err=err)
152
153
154 def create_introducer(basedir, config, out=sys.stdout, err=sys.stderr):
155     # This should always be called with an absolute Unicode basedir.
156     precondition(isinstance(basedir, unicode), basedir)
157
158     if os.path.exists(basedir):
159         if listdir_unicode(basedir):
160             print >>err, "The base directory %s is not empty." % quote_output(basedir)
161             print >>err, "To avoid clobbering anything, I am going to quit now."
162             print >>err, "Please use a different directory, or empty this one."
163             return -1
164         # we're willing to use an empty directory
165     else:
166         os.mkdir(basedir)
167     f = open(os.path.join(basedir, "tahoe-introducer.tac"), "w")
168     f.write(introducer_tac)
169     f.close()
170
171     c = open(os.path.join(basedir, "tahoe.cfg"), "w")
172     write_node_config(c, config)
173     c.close()
174
175     print >>out, "Introducer created in %s" % quote_output(basedir)
176
177
178 subCommands = [
179     ["create-node", None, CreateNodeOptions, "Create a node that acts as a client, server or both."],
180     ["create-client", None, CreateClientOptions, "Create a client node (with storage initially disabled)."],
181     ["create-introducer", None, CreateIntroducerOptions, "Create an introducer node."],
182 ]
183
184 dispatch = {
185     "create-node": create_node,
186     "create-client": create_client,
187     "create-introducer": create_introducer,
188     }