mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-06-06 01:21:43 +00:00
check_grid.py: make it work, move node start/stop responsibility from Makefile to script
This commit is contained in:
parent
77f994d4c1
commit
9ed9eb2048
7
Makefile
7
Makefile
@ -258,12 +258,7 @@ check-speed: .built
|
|||||||
# in src/allmydata/test/check_grid.py to see how to set this up.
|
# in src/allmydata/test/check_grid.py to see how to set this up.
|
||||||
check-grid: .built
|
check-grid: .built
|
||||||
if [ -z '$(TESTCLIENTDIR)' ]; then exit 1; fi
|
if [ -z '$(TESTCLIENTDIR)' ]; then exit 1; fi
|
||||||
@echo "stopping any leftover client code"
|
$(PYTHON) src/allmydata/test/check_grid.py $(TESTCLIENTDIR) bin/tahoe
|
||||||
-$(PYTHON) bin/tahoe stop $(TESTCLIENTDIR)
|
|
||||||
$(PYTHON) bin/tahoe start $(TESTCLIENTDIR)
|
|
||||||
sleep 5
|
|
||||||
$(PYTHON) src/allmydata/test/check_grid.py $(TESTCLIENTDIR)
|
|
||||||
$(PYTHON) bin/tahoe stop $(TESTCLIENTDIR)
|
|
||||||
|
|
||||||
# 'make repl' is a simple-to-type command to get a Python interpreter loop
|
# 'make repl' is a simple-to-type command to get a Python interpreter loop
|
||||||
# from which you can type 'import allmydata'
|
# from which you can type 'import allmydata'
|
||||||
|
@ -9,10 +9,16 @@ This script uses a pre-established client node (configured to connect to the
|
|||||||
grid being tested) and a pre-established directory (stored as the 'testgrid:'
|
grid being tested) and a pre-established directory (stored as the 'testgrid:'
|
||||||
alias in that client node's aliases file). It then performs a number of
|
alias in that client node's aliases file). It then performs a number of
|
||||||
uploads and downloads to exercise compatibility in various directions (new
|
uploads and downloads to exercise compatibility in various directions (new
|
||||||
client vs old data).
|
client vs old data). All operations are performed by invoking various CLI
|
||||||
|
commands through bin/tahoe . The script must be given two arguments: the
|
||||||
|
client node directory, and the location of the bin/tahoe executable. Note
|
||||||
|
that this script does not import anything from tahoe directly, so it doesn't
|
||||||
|
matter what its PYTHONPATH is, as long as the bin/tahoe that it uses is
|
||||||
|
functional.
|
||||||
|
|
||||||
This script expects that the client node will be running before the script
|
This script expects that the client node will be not running when the script
|
||||||
starts.
|
starts, but it will forcibly shut down the node just to be sure. It will shut
|
||||||
|
down the node after the test finishes.
|
||||||
|
|
||||||
To set up the client node, do the following:
|
To set up the client node, do the following:
|
||||||
|
|
||||||
@ -20,13 +26,13 @@ To set up the client node, do the following:
|
|||||||
touch DIR/no_storage
|
touch DIR/no_storage
|
||||||
populate DIR/introducer.furl
|
populate DIR/introducer.furl
|
||||||
tahoe start DIR
|
tahoe start DIR
|
||||||
tahoe -d DIR add-alias testgrid `tahoe -d DIR mkdir`
|
tahoe add-alias -d DIR testgrid `tahoe mkdir -d DIR`
|
||||||
pick a 10kB-ish test file, compute its md5sum
|
pick a 10kB-ish test file, compute its md5sum
|
||||||
tahoe -d DIR put FILE testgrid:old.MD5SUM
|
tahoe put -d DIR FILE testgrid:old.MD5SUM
|
||||||
tahoe -d DIR put FILE testgrid:recent.MD5SUM
|
tahoe put -d DIR FILE testgrid:recent.MD5SUM
|
||||||
tahoe -d DIR put FILE testgrid:recentdir/recent.MD5SUM
|
tahoe put -d DIR FILE testgrid:recentdir/recent.MD5SUM
|
||||||
echo "" | tahoe -d DIR put --mutable testgrid:log
|
echo "" | tahoe put -d DIR --mutable testgrid:log
|
||||||
echo "" | tahoe -d DIR put --mutable testgrid:recentlog
|
echo "" | tahoe put -d DIR --mutable testgrid:recentlog
|
||||||
|
|
||||||
This script will perform the following steps (the kind of compatibility that
|
This script will perform the following steps (the kind of compatibility that
|
||||||
is being tested is in [brackets]):
|
is being tested is in [brackets]):
|
||||||
@ -50,3 +56,164 @@ in a machine-readable logfile.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import time, subprocess, md5, os.path, random
|
||||||
|
from twisted.python import usage
|
||||||
|
|
||||||
|
class GridTesterOptions(usage.Options):
|
||||||
|
|
||||||
|
optFlags = [
|
||||||
|
("no", "n", "Dry run: do not run any commands, just print them."),
|
||||||
|
]
|
||||||
|
|
||||||
|
def parseArgs(self, nodedir, tahoe):
|
||||||
|
self.nodedir = nodedir
|
||||||
|
self.tahoe = os.path.abspath(tahoe)
|
||||||
|
|
||||||
|
class CommandFailed(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class GridTester:
|
||||||
|
def __init__(self, config):
|
||||||
|
self.config = config
|
||||||
|
self.tahoe = config.tahoe
|
||||||
|
self.nodedir = config.nodedir
|
||||||
|
|
||||||
|
def command(self, *cmd, **kwargs):
|
||||||
|
expected_rc = kwargs.get("expected_rc", None)
|
||||||
|
stdin = kwargs.get("stdin", None)
|
||||||
|
if self.config["no"]:
|
||||||
|
return
|
||||||
|
if stdin is not None:
|
||||||
|
p = subprocess.Popen(cmd,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
|
(stdout,stderr) = p.communicate(stdin)
|
||||||
|
else:
|
||||||
|
p = subprocess.Popen(cmd,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
|
(stdout,stderr) = p.communicate()
|
||||||
|
rc = p.returncode
|
||||||
|
if expected_rc != None and rc != expected_rc:
|
||||||
|
raise CommandFailed("command '%s' failed: rc=%d" % (cmd, rc))
|
||||||
|
return stdout, stderr
|
||||||
|
|
||||||
|
def cli(self, cmd, *args, **kwargs):
|
||||||
|
print "tahoe", cmd, " ".join(args)
|
||||||
|
stdout, stderr = self.command(self.tahoe, cmd, "-d", self.nodedir,
|
||||||
|
*args, **kwargs)
|
||||||
|
if not kwargs.get("ignore_stderr", False) and stderr != "":
|
||||||
|
raise CommandFailed("command '%s' had stderr: %s" % (" ".join(args),
|
||||||
|
stderr))
|
||||||
|
return stdout
|
||||||
|
|
||||||
|
def stop_old_node(self):
|
||||||
|
print "tahoe stop", self.nodedir, "(force)"
|
||||||
|
self.command(self.tahoe, "stop", self.nodedir, expected_rc=None)
|
||||||
|
|
||||||
|
def start_node(self):
|
||||||
|
print "tahoe start", self.nodedir
|
||||||
|
self.command(self.tahoe, "start", self.nodedir)
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
def stop_node(self):
|
||||||
|
print "tahoe stop", self.nodedir
|
||||||
|
self.command(self.tahoe, "stop", self.nodedir)
|
||||||
|
|
||||||
|
def read_and_check(self, f):
|
||||||
|
expected_md5_s = f[f.find(".")+1:]
|
||||||
|
out = self.cli("get", "testgrid:" + f)
|
||||||
|
got_md5_s = md5.new(out).hexdigest()
|
||||||
|
if got_md5_s != expected_md5_s:
|
||||||
|
raise CommandFailed("%s had md5sum of %s" % (f, got_md5_s))
|
||||||
|
|
||||||
|
def delete_and_check(self, dirname, f):
|
||||||
|
oldfiles = self.listdir(dirname)
|
||||||
|
if dirname:
|
||||||
|
absfilename = "testgrid:" + dirname + "/" + f
|
||||||
|
else:
|
||||||
|
absfilename = "testgrid:" + f
|
||||||
|
if f not in oldfiles:
|
||||||
|
raise CommandFailed("um, '%s' was supposed to already be in %s"
|
||||||
|
% (f, dirname))
|
||||||
|
self.cli("rm", absfilename)
|
||||||
|
newfiles = self.listdir(dirname)
|
||||||
|
if f in newfiles:
|
||||||
|
raise CommandFailed("failed to remove '%s' from %s" % (f, dirname))
|
||||||
|
|
||||||
|
def listdir(self, dirname):
|
||||||
|
out = self.cli("ls", "testgrid:"+dirname).strip().split("\n")
|
||||||
|
files = [f.strip() for f in out]
|
||||||
|
print " ", files
|
||||||
|
return files
|
||||||
|
|
||||||
|
def do_test(self):
|
||||||
|
files = self.listdir("")
|
||||||
|
for f in files:
|
||||||
|
if f.startswith("old.") or f.startswith("recent."):
|
||||||
|
self.read_and_check("" + f)
|
||||||
|
for f in files:
|
||||||
|
if f.startswith("recent."):
|
||||||
|
self.delete_and_check("", f)
|
||||||
|
files = self.listdir("recentdir")
|
||||||
|
for f in files:
|
||||||
|
if f.startswith("old.") or f.startswith("recent."):
|
||||||
|
self.read_and_check("recentdir/" + f)
|
||||||
|
for f in files:
|
||||||
|
if f.startswith("recent."):
|
||||||
|
self.delete_and_check("recentdir", f)
|
||||||
|
self.delete_and_check("", "recentdir")
|
||||||
|
|
||||||
|
self.cli("mkdir", "testgrid:recentdir")
|
||||||
|
fn, data = self.makefile("recent")
|
||||||
|
self.put("recentdir/"+fn, data)
|
||||||
|
files = self.listdir("recentdir")
|
||||||
|
if fn not in files:
|
||||||
|
raise CommandFailed("failed to put %s in recentdir/" % fn)
|
||||||
|
fn, data = self.makefile("recent")
|
||||||
|
self.put(fn, data)
|
||||||
|
files = self.listdir("")
|
||||||
|
if fn not in files:
|
||||||
|
raise CommandFailed("failed to put %s in testgrid:" % fn)
|
||||||
|
|
||||||
|
self.update("log")
|
||||||
|
self.update("recentlog")
|
||||||
|
self.delete_and_check("", "recentlog")
|
||||||
|
self.put_mutable("recentlog", "Recent Mutable Log Header\n\n")
|
||||||
|
|
||||||
|
def put(self, fn, data):
|
||||||
|
self.cli("put", "testgrid:"+fn, stdin=data, ignore_stderr=True)
|
||||||
|
|
||||||
|
def put_mutable(self, fn, data):
|
||||||
|
self.cli("put", "--mutable", "testgrid:"+fn,
|
||||||
|
stdin=data, ignore_stderr=True)
|
||||||
|
|
||||||
|
def update(self, fn):
|
||||||
|
old = self.cli("get", "testgrid:"+fn)
|
||||||
|
new = old + time.ctime() + "\n"
|
||||||
|
self.put(fn, new)
|
||||||
|
|
||||||
|
def makefile(self, prefix):
|
||||||
|
size = random.randint(10001, 10100)
|
||||||
|
data = os.urandom(size)
|
||||||
|
md5sum = md5.new(data).hexdigest()
|
||||||
|
fn = prefix + "." + md5sum
|
||||||
|
return fn, data
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.stop_old_node()
|
||||||
|
self.start_node()
|
||||||
|
try:
|
||||||
|
self.do_test()
|
||||||
|
finally:
|
||||||
|
self.stop_node()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
config = GridTesterOptions()
|
||||||
|
config.parseOptions()
|
||||||
|
gt = GridTester(config)
|
||||||
|
gt.run()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user