commit f2fe67e98d07ab26b62c2204b9087a40ecf70cb6 Author: teor teor2345@gmail.com Date: Mon Feb 27 23:36:33 2017 +1100
Make a unique directory each chutney run, and symlink to a standard name
Instead of moving the directory to a unique path at the start of the next run, which makes it impossible to find if running several networks in succession, like we do in 'make test-network-all'.
Closes 21567. --- lib/chutney/TorNet.py | 79 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 10 deletions(-)
diff --git a/lib/chutney/TorNet.py b/lib/chutney/TorNet.py index 33b7cde..6e3b77a 100644 --- a/lib/chutney/TorNet.py +++ b/lib/chutney/TorNet.py @@ -68,6 +68,26 @@ def get_absolute_net_path(): # ok, it's relative to the current directory, whatever that is return os.path.abspath(relative_net_path)
+def get_absolute_nodes_path(): + # there's no way to customise this: we really don't need more options + return os.path.join(get_absolute_net_path(), 'nodes') + +def get_new_absolute_nodes_path(now=time.time()): + # automatically chosen to prevent path collisions, and result in an ordered + # series of directory path names + # should only be called by 'chutney configure', all other chutney commands + # should use get_absolute_nodes_path() + nodesdir = get_absolute_nodes_path() + newdir = newdirbase = "%s.%d" % (nodesdir, now) + # if the time is the same, fall back to a simple integer count + # (this is very unlikely to happen unless the clock changes: it's not + # possible to run multiple chutney networks at the same time) + i = 0 + while os.path.exists(newdir): + i += 1 + newdir = "%s.%d" % (newdirbase, i) + return newdir + class Node(object):
"""A Node represents a Tor node or a set of Tor nodes. It's created @@ -838,29 +858,68 @@ class Network(object): self._nextnodenum += 1 self._nodes.append(n)
- def move_aside_nodes(self): - net_base_dir = get_absolute_net_path() - nodesdir = os.path.join(net_base_dir, 'nodes') + def move_aside_nodes_dir(self): + """Move aside the nodes directory, if it exists and is not a link. + Used for backwards-compatibility only: nodes is created as a link to + a new directory with a unique name in the current implementation. + """ + nodesdir = get_absolute_nodes_path()
+ # only move the directory if it exists if not os.path.exists(nodesdir): return + # and if it's not a link + if os.path.islink(nodesdir): + return
- newdir = newdirbase = "%s.%d" % (nodesdir, time.time()) - i = 0 - while os.path.exists(newdir): - i += 1 - newdir = "%s.%d" % (newdirbase, i) + # subtract 1 second to avoid collisions and get the correct ordering + newdir = get_new_absolute_nodes_path(time.time() - 1)
print("NOTE: renaming %r to %r" % (nodesdir, newdir)) os.rename(nodesdir, newdir)
+ def create_new_nodes_dir(self): + """Create a new directory with a unique name, and symlink it to nodes + """ + # for backwards compatibility, move aside the old nodes directory + # (if it's not a link) + self.move_aside_nodes_dir() + + # the unique directory we'll create + newnodesdir = get_new_absolute_nodes_path() + # the canonical name we'll link it to + nodeslink = get_absolute_nodes_path() + + # this path should be unique and should not exist + if os.path.exists(newnodesdir): + raise RuntimeError( + 'get_new_absolute_nodes_path returned a path that exists') + + # if this path exists, it must be a link + if os.path.exists(nodeslink) and not os.path.islink(nodeslink): + raise RuntimeError( + 'get_absolute_nodes_path returned a path that exists and is not a link') + + # create the new, uniquely named directory, and link it to nodes + print("NOTE: creating %r, linking to %r" % (newnodesdir, nodeslink)) + # this gets created with mode 0700, that's probably ok + mkdir_p(newnodesdir) + try: + os.unlink(nodeslink) + except OSError as e: + # it's ok if the link doesn't exist, we're just about to make it + if e.errno == errno.ENOENT: + pass + else: + raise + os.symlink(newnodesdir, nodeslink) + def _checkConfig(self): for n in self._nodes: n.getBuilder().checkConfig(self)
def configure(self): - # shutil.rmtree(os.path.join(os.getcwd(),'net','nodes'),ignore_errors=True) - self.move_aside_nodes() + self.create_new_nodes_dir() network = self altauthlines = [] bridgelines = []