|
@@ -664,7 +664,7 @@ class LocalNodeBuilder(NodeBuilder):
|
|
|
def _makeDataDir(self):
|
|
|
"""Create the data directory (with keys subdirectory) for this node.
|
|
|
"""
|
|
|
- datadir = self._env['dir']
|
|
|
+ datadir = self._env['local_dir']
|
|
|
make_datadir_subdirectory(datadir, "keys")
|
|
|
|
|
|
def _makeHiddenServiceDir(self):
|
|
@@ -674,13 +674,13 @@ class LocalNodeBuilder(NodeBuilder):
|
|
|
key. It is combined with the 'dir' data directory key to yield the
|
|
|
path to the hidden service directory.
|
|
|
"""
|
|
|
- datadir = self._env['dir']
|
|
|
+ datadir = self._env['local_dir']
|
|
|
make_datadir_subdirectory(datadir, self._env['hs_directory'])
|
|
|
|
|
|
def _genAuthorityKey(self):
|
|
|
"""Generate an authority identity and signing key for this authority,
|
|
|
if they do not already exist."""
|
|
|
- datadir = self._env['dir']
|
|
|
+ datadir = self._env['local_dir']
|
|
|
tor_gencert = self._env['tor_gencert']
|
|
|
lifetime = self._env['auth_cert_lifetime']
|
|
|
idfile = os.path.join(datadir, 'keys', "authority_identity_key")
|
|
@@ -711,7 +711,7 @@ class LocalNodeBuilder(NodeBuilder):
|
|
|
"""Generate an identity key for this router, unless we already have,
|
|
|
and set up the 'fingerprint' entry in the Environ.
|
|
|
"""
|
|
|
- datadir = self._env['dir']
|
|
|
+ datadir = self._env['local_dir']
|
|
|
tor = self._env['tor']
|
|
|
torrc = self._getTorrcFname()
|
|
|
cmdline = [
|
|
@@ -737,7 +737,7 @@ class LocalNodeBuilder(NodeBuilder):
|
|
|
if not self._env['authority']:
|
|
|
return ""
|
|
|
|
|
|
- datadir = self._env['dir']
|
|
|
+ datadir = self._env['local_dir']
|
|
|
certfile = os.path.join(datadir, 'keys', "authority_certificate")
|
|
|
v3id = None
|
|
|
with open(certfile, 'r') as f:
|
|
@@ -812,56 +812,58 @@ class LocalNodeBuilder(NodeBuilder):
|
|
|
return bridgelines
|
|
|
|
|
|
|
|
|
-def scp_file(abs_filepath, host):
|
|
|
- if not os.path.isabs(abs_filepath) or abs_filepath[0:5] != '/tmp/':
|
|
|
- # this check for '/tmp' is in no way secure, but helps prevent me from shooting
|
|
|
- # myself in the foot
|
|
|
- raise Exception('SCP path must be absolute and must be in /tmp')
|
|
|
- assert(':' not in host)
|
|
|
- assert(':' not in abs_filepath)
|
|
|
- remote_filepath = os.path.dirname(abs_filepath)
|
|
|
- cmd = ['scp', abs_filepath, ':'.join([host, remote_filepath])]
|
|
|
- print('Transferring file: {}'.format(cmd))
|
|
|
- subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
|
|
-
|
|
|
-def scp_dir(abs_dirpath, host):
|
|
|
- if not os.path.isabs(abs_dirpath) or abs_dirpath[0:5] != '/tmp/':
|
|
|
- # this check for '/tmp' is in no way secure, but helps prevent me from shooting
|
|
|
- # myself in the foot
|
|
|
- raise Exception('SCP path must be absolute and must be in /tmp')
|
|
|
- assert(':' not in host)
|
|
|
- assert(':' not in abs_dirpath)
|
|
|
- remote_dirpath = os.path.dirname(abs_dirpath)
|
|
|
+#def scp_file(abs_filepath, host):
|
|
|
+# if not os.path.isabs(abs_filepath) or abs_filepath[0:5] != '/tmp/':
|
|
|
+# # this check for '/tmp' is in no way secure, but helps prevent me from shooting
|
|
|
+# # myself in the foot
|
|
|
+# raise Exception('SCP path must be absolute and must be in /tmp')
|
|
|
+# assert ':' not in host
|
|
|
+# assert ':' not in abs_filepath
|
|
|
+# remote_filepath = os.path.dirname(abs_filepath)
|
|
|
+# cmd = ['scp', abs_filepath, ':'.join([host, remote_filepath])]
|
|
|
+# print('Transferring file: {}'.format(cmd))
|
|
|
+# subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
|
|
+
|
|
|
+def scp_dir(abs_dirpath, abs_remote_dirpath, host):
|
|
|
+ #if not os.path.isabs(abs_dirpath) or abs_dirpath[0:5] != '/tmp/':
|
|
|
+ # # this check for '/tmp' is in no way secure, but helps prevent me from shooting
|
|
|
+ # # myself in the foot
|
|
|
+ # raise Exception('SCP path must be absolute and must be in /tmp')
|
|
|
+ assert ':' not in host
|
|
|
+ assert ':' not in abs_dirpath
|
|
|
+ assert ':' not in abs_remote_dirpath
|
|
|
+ remote_dirpath = os.path.dirname(abs_remote_dirpath)
|
|
|
cmd = ['scp', '-r', abs_dirpath, ':'.join([host, remote_dirpath])]
|
|
|
print('Transferring files: {}'.format(cmd))
|
|
|
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
|
|
|
|
|
-def scp_dir_backwards(abs_dirpath, host):
|
|
|
- if not os.path.isabs(abs_dirpath) or abs_dirpath[0:5] != '/tmp/':
|
|
|
- # this check for '/tmp' is in no way secure, but helps prevent me from shooting
|
|
|
- # myself in the foot
|
|
|
- raise Exception('SCP path must be absolute and must be in /tmp')
|
|
|
- assert(':' not in host)
|
|
|
- assert(':' not in abs_dirpath)
|
|
|
- remote_dirpath = os.path.dirname(abs_dirpath)
|
|
|
- cmd = ['scp', '-r', ':'.join([host, abs_dirpath]), remote_dirpath]
|
|
|
+def scp_dir_backwards(abs_remote_dirpath, abs_dirpath, host):
|
|
|
+ #if not os.path.isabs(abs_dirpath) or abs_dirpath[0:5] != '/tmp/':
|
|
|
+ # # this check for '/tmp' is in no way secure, but helps prevent me from shooting
|
|
|
+ # # myself in the foot
|
|
|
+ # raise Exception('SCP path must be absolute and must be in /tmp')
|
|
|
+ assert ':' not in host
|
|
|
+ assert ':' not in abs_dirpath
|
|
|
+ assert ':' not in abs_remote_dirpath
|
|
|
+ local_dirpath = os.path.dirname(abs_dirpath)
|
|
|
+ cmd = ['scp', '-r', ':'.join([host, abs_remote_dirpath]), local_dirpath]
|
|
|
print('Transferring files backwards: {}'.format(cmd))
|
|
|
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
|
|
|
|
|
def ssh_mkdir_p(abs_dirpath, remote_hostname):
|
|
|
- if not os.path.isabs(abs_dirpath) or abs_dirpath[0:5] != '/tmp/':
|
|
|
- # this check for '/tmp' is in no way secure, but helps prevent me from shooting
|
|
|
- # myself in the foot
|
|
|
- raise Exception('Path must be absolute and must be in /tmp')
|
|
|
+ #if not os.path.isabs(abs_dirpath) or abs_dirpath[0:5] != '/tmp/':
|
|
|
+ # # this check for '/tmp' is in no way secure, but helps prevent me from shooting
|
|
|
+ # # myself in the foot
|
|
|
+ # raise Exception('Path must be absolute and must be in /tmp')
|
|
|
cmd = ['ssh', remote_hostname, 'mkdir', '-p', abs_dirpath]
|
|
|
print('Making directory: {}'.format(cmd))
|
|
|
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
|
|
|
|
|
def ssh_rm_if_exists(abs_dirpath, remote_hostname):
|
|
|
- if not os.path.isabs(abs_dirpath) or abs_dirpath[0:5] != '/tmp/':
|
|
|
- # this check for '/tmp' is in no way secure, but helps prevent me from shooting
|
|
|
- # myself in the foot
|
|
|
- raise Exception('Path must be absolute and must be in /tmp')
|
|
|
+ #if not os.path.isabs(abs_dirpath) or abs_dirpath[0:5] != '/tmp/':
|
|
|
+ # # this check for '/tmp' is in no way secure, but helps prevent me from shooting
|
|
|
+ # # myself in the foot
|
|
|
+ # raise Exception('Path must be absolute and must be in /tmp')
|
|
|
cmd = ['ssh', remote_hostname, 'rm', '-f', abs_dirpath]
|
|
|
print('Removing: {}'.format(cmd))
|
|
|
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
|
@@ -1056,8 +1058,8 @@ class RemoteNodeBuilder(NodeBuilder):
|
|
|
def postConfig(self, net):
|
|
|
"""Called on each nodes after all nodes configure."""
|
|
|
# self.net.addNode(self)
|
|
|
- scp_dir(os.path.abspath(self._env['dir']), self._env['remote_hostname'])
|
|
|
- shutil.rmtree(self._env['dir'])
|
|
|
+ scp_dir(os.path.abspath(self._env['local_dir']), os.path.abspath(self._env['remote_dir']), self._env['remote_hostname'])
|
|
|
+ shutil.rmtree(self._env['local_dir'])
|
|
|
|
|
|
def isSupported(self, net):
|
|
|
"""Return true if this node appears to have everything it needs;
|
|
@@ -1077,7 +1079,7 @@ class RemoteNodeBuilder(NodeBuilder):
|
|
|
def _makeDataDir(self):
|
|
|
"""Create the data directory (with keys subdirectory) for this node.
|
|
|
"""
|
|
|
- datadir = self._env['dir']
|
|
|
+ datadir = self._env['local_dir']
|
|
|
make_datadir_subdirectory(datadir, "keys")
|
|
|
|
|
|
def _makeHiddenServiceDir(self):
|
|
@@ -1087,13 +1089,13 @@ class RemoteNodeBuilder(NodeBuilder):
|
|
|
key. It is combined with the 'dir' data directory key to yield the
|
|
|
path to the hidden service directory.
|
|
|
"""
|
|
|
- datadir = self._env['dir']
|
|
|
+ datadir = self._env['local_dir']
|
|
|
make_datadir_subdirectory(datadir, self._env['hs_directory'])
|
|
|
|
|
|
def _genAuthorityKey(self):
|
|
|
"""Generate an authority identity and signing key for this authority,
|
|
|
if they do not already exist."""
|
|
|
- datadir = self._env['dir']
|
|
|
+ datadir = self._env['local_dir']
|
|
|
tor_gencert = self._env['tor_gencert']
|
|
|
lifetime = self._env['auth_cert_lifetime']
|
|
|
idfile = os.path.join(datadir, 'keys', "authority_identity_key")
|
|
@@ -1124,7 +1126,7 @@ class RemoteNodeBuilder(NodeBuilder):
|
|
|
"""Generate an identity key for this router, unless we already have,
|
|
|
and set up the 'fingerprint' entry in the Environ.
|
|
|
"""
|
|
|
- datadir = self._env['dir']
|
|
|
+ datadir = self._env['local_dir']
|
|
|
tor = self._env['tor']
|
|
|
torrc = self._getTorrcFname()
|
|
|
cmdline = [
|
|
@@ -1150,7 +1152,7 @@ class RemoteNodeBuilder(NodeBuilder):
|
|
|
if not self._env['authority']:
|
|
|
return ""
|
|
|
|
|
|
- datadir = self._env['dir']
|
|
|
+ datadir = self._env['local_dir']
|
|
|
certfile = os.path.join(datadir, 'keys', "authority_certificate")
|
|
|
v3id = None
|
|
|
with open(certfile, 'r') as f:
|
|
@@ -1240,7 +1242,7 @@ class LocalNodeController(NodeController):
|
|
|
the pid of the running process, or None if there is no pid in the
|
|
|
file.
|
|
|
"""
|
|
|
- pidfile = os.path.join(self._env['dir'], 'pid')
|
|
|
+ pidfile = os.path.join(self._env['local_dir'], 'pid')
|
|
|
if not os.path.exists(pidfile):
|
|
|
return None
|
|
|
|
|
@@ -1281,7 +1283,7 @@ class LocalNodeController(NodeController):
|
|
|
# XXX Split this into "check" and "print" parts.
|
|
|
pid = self.getPid()
|
|
|
nick = self._env['nick']
|
|
|
- datadir = self._env['dir']
|
|
|
+ datadir = self._env['local_dir']
|
|
|
corefile = "core.%s" % pid
|
|
|
tor_version = get_tor_version(self._env['tor'])
|
|
|
if self.isRunning(pid):
|
|
@@ -1343,7 +1345,7 @@ class LocalNodeController(NodeController):
|
|
|
if self._env['google_cpu_profiler'] is True:
|
|
|
if add_environ_vars is None:
|
|
|
add_environ_vars = {}
|
|
|
- add_environ_vars['CPUPROFILE'] = os.path.join(self._env['dir'], 'cpu-prof.out')
|
|
|
+ add_environ_vars['CPUPROFILE'] = os.path.join(self._env['local_dir'], 'cpu-prof.out')
|
|
|
#
|
|
|
cmdline.extend([
|
|
|
tor_path,
|
|
@@ -1431,13 +1433,14 @@ class LocalNodeController(NodeController):
|
|
|
self._env['poll_launch_time_default']
|
|
|
return False
|
|
|
|
|
|
- def getLogfile(self, info=False):
|
|
|
+ def getLogfile(self):
|
|
|
"""Return the expected path to the logfile for this instance."""
|
|
|
- datadir = self._env['dir']
|
|
|
- if info:
|
|
|
- logname = "info.log"
|
|
|
- else:
|
|
|
- logname = "notice.log"
|
|
|
+ datadir = self._env['local_dir']
|
|
|
+ logfile_priority = ['notice', 'info', 'debug']
|
|
|
+ for p in logfile_priority:
|
|
|
+ if p in self._env['log_files']:
|
|
|
+ logname = p + '.log'
|
|
|
+ break
|
|
|
return os.path.join(datadir, logname)
|
|
|
|
|
|
def getLastBootstrapStatus(self):
|
|
@@ -1482,8 +1485,8 @@ class RemoteNodeController(NodeController):
|
|
|
the pid of the running process, or None if there is no pid in the
|
|
|
file.
|
|
|
"""
|
|
|
- pidfile = os.path.join(self._env['dir'], 'pid')
|
|
|
if self._env['remote_hostname'] is None:
|
|
|
+ pidfile = os.path.join(self._env['local_dir'], 'pid')
|
|
|
if not os.path.exists(pidfile):
|
|
|
return None
|
|
|
with open(pidfile, 'r') as f:
|
|
@@ -1492,6 +1495,7 @@ class RemoteNodeController(NodeController):
|
|
|
except ValueError:
|
|
|
return None
|
|
|
else:
|
|
|
+ pidfile = os.path.join(self._env['remote_dir'], 'pid')
|
|
|
pid = ssh_read_file(pidfile, self._env['remote_hostname'])
|
|
|
if pid is None:
|
|
|
return None
|
|
@@ -1533,7 +1537,10 @@ class RemoteNodeController(NodeController):
|
|
|
# XXX Split this into "check" and "print" parts.
|
|
|
pid = self.getPid()
|
|
|
nick = self._env['nick']
|
|
|
- datadir = self._env['dir']
|
|
|
+ if self._env['remote_hostname'] is None:
|
|
|
+ datadir = self._env['local_dir']
|
|
|
+ else:
|
|
|
+ datadir = self._env['remote_dir']
|
|
|
corefile = os.path.join(datadir, "core.%s" % pid)
|
|
|
tor_version = get_tor_version(self._env['tor'], remote_hostname=self._env['remote_hostname'])
|
|
|
|
|
@@ -1586,7 +1593,10 @@ class RemoteNodeController(NodeController):
|
|
|
print("{:12} is already running".format(self._env['nick']))
|
|
|
return True
|
|
|
tor_path = self._env['tor']
|
|
|
- torrc = self._getTorrcFname()
|
|
|
+ if self._env['remote_hostname'] is None:
|
|
|
+ torrc = self._getTorrcFname()
|
|
|
+ else:
|
|
|
+ torrc = os.path.join(self._env['remote_dir'], 'torrc')
|
|
|
#
|
|
|
add_environ_vars = self._env['add_environ_vars']
|
|
|
if add_environ_vars is not None:
|
|
@@ -1595,7 +1605,10 @@ class RemoteNodeController(NodeController):
|
|
|
if self._env['google_cpu_profiler'] is True:
|
|
|
if add_environ_vars is None:
|
|
|
add_environ_vars = {}
|
|
|
- add_environ_vars['CPUPROFILE'] = os.path.join(self._env['dir'], 'cpu-prof.out')
|
|
|
+ if self._env['remote_hostname'] is None:
|
|
|
+ add_environ_vars['CPUPROFILE'] = os.path.join(self._env['local_dir'], 'cpu-prof.out')
|
|
|
+ else:
|
|
|
+ add_environ_vars['CPUPROFILE'] = os.path.join(self._env['remote_dir'], 'cpu-prof.out')
|
|
|
#
|
|
|
cmdline = []
|
|
|
if self._env['remote_hostname'] is not None:
|
|
@@ -1712,13 +1725,17 @@ class RemoteNodeController(NodeController):
|
|
|
self._env['poll_launch_time_default']
|
|
|
return False
|
|
|
|
|
|
- def getLogfile(self, info=False):
|
|
|
+ def getLogfile(self):
|
|
|
"""Return the expected path to the logfile for this instance."""
|
|
|
- datadir = self._env['dir']
|
|
|
- if info:
|
|
|
- logname = "info.log"
|
|
|
+ if self._env['remote_hostname'] is None:
|
|
|
+ datadir = self._env['local_dir']
|
|
|
else:
|
|
|
- logname = "notice.log"
|
|
|
+ datadir = self._env['remote_dir']
|
|
|
+ logfile_priority = ['notice', 'info', 'debug']
|
|
|
+ for p in logfile_priority:
|
|
|
+ if p in self._env['log_files']:
|
|
|
+ logname = p + '.log'
|
|
|
+ break
|
|
|
return os.path.join(datadir, logname)
|
|
|
|
|
|
def getLastBootstrapStatus(self):
|
|
@@ -1757,9 +1774,10 @@ class RemoteNodeController(NodeController):
|
|
|
|
|
|
def getRemoteFiles(self):
|
|
|
if self._env['remote_hostname'] is not None:
|
|
|
- path = os.path.abspath(self._env['dir'])
|
|
|
- ssh_rm_if_exists(os.path.join(path, 'control'), self._env['remote_hostname'])
|
|
|
- scp_dir_backwards(path, self._env['remote_hostname'])
|
|
|
+ local_path = os.path.abspath(self._env['local_dir'])
|
|
|
+ remote_path = os.path.abspath(self._env['remote_dir'])
|
|
|
+ ssh_rm_if_exists(os.path.join(remote_path, 'control'), self._env['remote_hostname'])
|
|
|
+ scp_dir_backwards(remote_path, local_path, self._env['remote_hostname'])
|
|
|
|
|
|
# XXX: document these options
|
|
|
DEFAULTS = {
|
|
@@ -1786,7 +1804,7 @@ DEFAULTS = {
|
|
|
'ipv6_addr': os.environ.get('CHUTNEY_LISTEN_ADDRESS_V6', None),
|
|
|
'dirserver_flags': 'no-v2',
|
|
|
'chutney_dir': get_absolute_chutney_path(),
|
|
|
- 'torrc_fname': '${dir}/torrc',
|
|
|
+ 'torrc_fname': '${local_dir}/torrc',
|
|
|
'orport_base': 5000,
|
|
|
'dirport_base': 7000,
|
|
|
'controlport_base': 8000,
|
|
@@ -1846,6 +1864,7 @@ DEFAULTS = {
|
|
|
'log_files': ['notice', 'info', 'debug'],
|
|
|
'google_cpu_profiler': False,
|
|
|
'remote_hostname': None,
|
|
|
+ 'remote_net_dir': None,
|
|
|
'num_additional_eventloops': None,
|
|
|
'log_throughput': False,
|
|
|
}
|
|
@@ -1925,12 +1944,25 @@ class TorEnviron(chutney.Templating.Environ):
|
|
|
def _get_ptport(self, my):
|
|
|
return my['ptport_base'] + my['nodenum']
|
|
|
|
|
|
- def _get_dir(self, my):
|
|
|
+ def _get_local_dir(self, my):
|
|
|
return os.path.abspath(os.path.join(my['net_base_dir'],
|
|
|
"nodes",
|
|
|
"%03d%s" % (
|
|
|
my['nodenum'], my['tag'])))
|
|
|
|
|
|
+ def _get_remote_dir(self, my):
|
|
|
+ if my['remote_net_dir'] is None or my['remote_hostname'] is None:
|
|
|
+ return None
|
|
|
+ return os.path.abspath(os.path.join(my['remote_net_dir'],
|
|
|
+ "nodes",
|
|
|
+ "%03d%s" % (
|
|
|
+ my['nodenum'], my['tag'])))
|
|
|
+
|
|
|
+ def _get_dir(self, my):
|
|
|
+ if self['remote_dir'] is not None:
|
|
|
+ return self['remote_dir']
|
|
|
+ return self['local_dir']
|
|
|
+
|
|
|
def _get_nick(self, my):
|
|
|
return "%s%03d%s" % (my['nick_base'], my['nodenum'], my['tag'])
|
|
|
|
|
@@ -2104,10 +2136,12 @@ class Network(object):
|
|
|
print("NOTE: creating %r, linking to %r" % (newnodesdir, nodeslink))
|
|
|
# this gets created with mode 0700, that's probably ok
|
|
|
mkdir_p(newnodesdir)
|
|
|
- remote_hostnames = list(set([x._env['remote_hostname'] for x in self._nodes if x._env['remote_hostname'] is not None]))
|
|
|
- if len(remote_hostnames) != 0:
|
|
|
- for x in remote_hostnames:
|
|
|
- ssh_mkdir_p(newnodesdir, x)
|
|
|
+ remotes = list(set([(x._env['remote_hostname'],x._env['remote_net_dir']) for x in self._nodes if x._env['remote_hostname'] is not None]))
|
|
|
+ if len(remotes) != 0:
|
|
|
+ for (hostname, remote_net_dir) in remotes:
|
|
|
+ assert remote_net_dir is not None
|
|
|
+ remote_newnodesdir = os.path.join(remote_net_dir, os.path.basename(newnodesdir))
|
|
|
+ ssh_mkdir_p(remote_newnodesdir, hostname)
|
|
|
try:
|
|
|
os.unlink(nodeslink)
|
|
|
except OSError as e:
|
|
@@ -2116,13 +2150,18 @@ class Network(object):
|
|
|
pass
|
|
|
else:
|
|
|
raise
|
|
|
- if len(remote_hostnames) != 0:
|
|
|
- for x in remote_hostnames:
|
|
|
- ssh_rm_if_exists(nodeslink, x)
|
|
|
+ if len(remotes) != 0:
|
|
|
+ for (hostname, remote_net_dir) in remotes:
|
|
|
+ assert remote_net_dir is not None
|
|
|
+ remote_nodeslink = os.path.join(remote_net_dir, 'nodes')
|
|
|
+ ssh_rm_if_exists(remote_nodeslink, hostname)
|
|
|
os.symlink(newnodesdir, nodeslink)
|
|
|
- if len(remote_hostnames) != 0:
|
|
|
- for x in remote_hostnames:
|
|
|
- ssh_symlink(newnodesdir, nodeslink, x)
|
|
|
+ if len(remotes) != 0:
|
|
|
+ for (hostname, remote_net_dir) in remotes:
|
|
|
+ assert remote_net_dir is not None
|
|
|
+ remote_newnodesdir = os.path.join(remote_net_dir, os.path.basename(newnodesdir))
|
|
|
+ remote_nodeslink = os.path.join(remote_net_dir, 'nodes')
|
|
|
+ ssh_symlink(remote_newnodesdir, remote_nodeslink, hostname)
|
|
|
|
|
|
def _checkConfig(self):
|
|
|
for n in self._nodes:
|