mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-04-13 22:03:04 +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.
|
||||
check-grid: .built
|
||||
if [ -z '$(TESTCLIENTDIR)' ]; then exit 1; fi
|
||||
@echo "stopping any leftover client code"
|
||||
-$(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)
|
||||
$(PYTHON) src/allmydata/test/check_grid.py $(TESTCLIENTDIR) bin/tahoe
|
||||
|
||||
# 'make repl' is a simple-to-type command to get a Python interpreter loop
|
||||
# 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:'
|
||||
alias in that client node's aliases file). It then performs a number of
|
||||
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
|
||||
starts.
|
||||
This script expects that the client node will be not running when the script
|
||||
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:
|
||||
|
||||
@ -20,13 +26,13 @@ To set up the client node, do the following:
|
||||
touch DIR/no_storage
|
||||
populate DIR/introducer.furl
|
||||
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
|
||||
tahoe -d DIR put FILE testgrid:old.MD5SUM
|
||||
tahoe -d DIR put FILE testgrid:recent.MD5SUM
|
||||
tahoe -d DIR put FILE testgrid:recentdir/recent.MD5SUM
|
||||
echo "" | tahoe -d DIR put --mutable testgrid:log
|
||||
echo "" | tahoe -d DIR put --mutable testgrid:recentlog
|
||||
tahoe put -d DIR FILE testgrid:old.MD5SUM
|
||||
tahoe put -d DIR FILE testgrid:recent.MD5SUM
|
||||
tahoe put -d DIR FILE testgrid:recentdir/recent.MD5SUM
|
||||
echo "" | tahoe put -d DIR --mutable testgrid:log
|
||||
echo "" | tahoe put -d DIR --mutable testgrid:recentlog
|
||||
|
||||
This script will perform the following steps (the kind of compatibility that
|
||||
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