[PATCH pynfs 12/13] server41tests: support a second server for inter-server copy
Jeff Layton <[email protected]>
| Newsgroups | gmane.linux.nfs |
|---|---|
| Message-ID | <[email protected]> |
Inter-server (server-to-server) COPY tests need to talk to two servers. Add a --server2 SERVER:/PATH option, parsed with parse_nfs_url, and an optional second client env.c2 in the test environment. The environment now creates, initializes, and cleans up the test tree on both servers, and factors credential creation into a helper so c2 gets a credential built the same way as c1. When --server2 is not given, c2 is None and single-server runs are unaffected. Signed-off-by: Jeff Layton <[email protected]> --- nfs4.1/server41tests/environment.py | 127 ++++++++++++++++++++++++------------ nfs4.1/testserver.py | 14 ++++ 2 files changed, 98 insertions(+), 43 deletions(-) diff --git a/nfs4.1/server41tests/environment.py b/nfs4.1/server41tests/environment.py index c14b12cbfca5..38cd5a7a7185 100644 --- a/nfs4.1/server41tests/environment.py +++ b/nfs4.1/server41tests/environment.py @@ -119,23 +119,23 @@ class Environment(testmod.Environment): self._lock = Lock() self.opts = opts self.c1 = nfs4client.NFS4Client(opts.server, opts.port, opts.minorversion, secure=opts.secure) - s1 = rpc.security.instance(opts.flavor) - if opts.flavor == rpc.AUTH_NONE: - self.cred1 = s1.init_cred() - elif opts.flavor == rpc.AUTH_SYS: - self.cred1 = s1.init_cred(uid=opts.uid, gid=opts.gid, name=opts.machinename) - elif opts.flavor == rpc.RPCSEC_GSS: - call = self.c1.make_call_function(self.c1.c1, 0, - self.c1.default_prog, - self.c1.default_vers) - krb5_cred = AuthGss().init_cred(call, target="nfs@%s" % opts.server) - krb5_cred.service = opts.service - self.cred1 = krb5_cred - self.c1.set_cred(self.cred1) + self.cred1 = self._make_cred(self.c1, opts.server) self.cred2 = AuthSys().init_cred(uid=1111, gid=37, name=b"shampoo") opts.home = opts.path + [b'tmp'] self.c1.homedir = opts.home + + # Optional second server, used only by inter-server (server-to-server) + # COPY tests. Enabled by passing --server2 SERVER:/PATH on the + # command line; None otherwise so single-server runs are unaffected. + self.c2 = None + if getattr(opts, "server2", None): + self.c2 = nfs4client.NFS4Client(opts.server2_host, opts.server2_port, + opts.minorversion, secure=opts.secure) + opts.server2_home = opts.server2_path + [b'tmp'] + self.c2.homedir = opts.server2_home + self._make_cred(self.c2, opts.server2_host) + # Put this after client creation, to ensure _last_verf bigger than # any natural client verifiers self.timestamp = int(time.time()) @@ -146,38 +146,72 @@ class Environment(testmod.Environment): self.stateid1 = stateid4(0xffffffff, b'\xff'*12) log.info("Created client to %s, %i" % (opts.server, opts.port)) + if self.c2 is not None: + log.info("Created second client to %s, %i" % + (opts.server2_host, opts.server2_port)) + + def _make_cred(self, client, server_host): + """Build and install an RPC credential on client for server_host.""" + s = rpc.security.instance(self.opts.flavor) + if self.opts.flavor == rpc.AUTH_NONE: + cred = s.init_cred() + elif self.opts.flavor == rpc.AUTH_SYS: + cred = s.init_cred(uid=self.opts.uid, gid=self.opts.gid, + name=self.opts.machinename) + elif self.opts.flavor == rpc.RPCSEC_GSS: + call = client.make_call_function(client.c1, 0, + client.default_prog, + client.default_vers) + cred = AuthGss().init_cred(call, target="nfs@%s" % server_host) + cred.service = self.opts.service + client.set_cred(cred) + return cred + + def _all_clients(self): + """All configured clients (c1, and c2 if a second server was given).""" + return [c for c in (self.c1, self.c2) if c is not None] def init(self): """Run once before any test is run""" if self.opts.noinit: return - sess = self.c1.new_client_session(b"Environment.init_%i" % - self.timestamp) + self._init_server(self.c1, self.opts.path, self.opts.home) + if self.c2 is not None: + self._init_server(self.c2, self.opts.server2_path, + self.opts.server2_home) + self.clean_sessions() + self.clean_clients() + + def _init_server(self, c, path, home): + """Prepare (and optionally build) the test tree on a single server.""" + sess = c.new_client_session(b"Environment.init_%i" % self.timestamp) if self.opts.maketree: - self._maketree(sess) - # Make sure opts.home exists - res = sess.compound(use_obj(self.opts.home)) - check(res, msg="Could not LOOKUP /%s," % b'/'.join(self.opts.home)) + self._maketree(sess, path, home) + # Make sure home exists + res = sess.compound(use_obj(home)) + check(res, msg="Could not LOOKUP /%s," % b'/'.join(home)) # Make sure it is empty - clean_dir(sess, self.opts.home) + clean_dir(sess, home) sess.c.null() - self.clean_sessions() - self.clean_clients() - def _maketree(self, sess): + def _maketree(self, sess, path=None, home=None): """Make test tree""" + if path is None: + path = self.opts.path + if home is None: + home = self.opts.home # ensure /tmp (and path leading up) exists - path = [] - for comp in self.opts.home: - path.append(comp) - res = sess.compound(use_obj(path)) + p = [] + for comp in home: + p.append(comp) + res = sess.compound(use_obj(p)) check(res, [NFS4_OK, NFS4ERR_NOENT], - "LOOKUP /%s," % b'/'.join(path)) + "LOOKUP /%s," % b'/'.join(p)) if res.status == NFS4ERR_NOENT: - res = create_obj(sess, path, NF4DIR) - check(res, msg="Trying to create /%s," % b'/'.join(path)) + res = create_obj(sess, p, NF4DIR) + check(res, msg="Trying to create /%s," % b'/'.join(p)) # ensure /tree exists and is empty - tree = self.opts.path + [b'tree'] + tree = path + [b'tree'] res = sess.compound(use_obj(tree)) check(res, [NFS4_OK, NFS4ERR_NOENT]) if res.status == NFS4ERR_NOENT: @@ -210,16 +244,21 @@ class Environment(testmod.Environment): """Run once after all tests are run""" if self.opts.nocleanup: return - sess = self.c1.new_client_session(b"Environment.init_%i" % self.timestamp) - clean_dir(sess, self.opts.home) - sess.c.null() + homes = [(self.c1, self.opts.home)] + if self.c2 is not None: + homes.append((self.c2, self.opts.server2_home)) + for c, home in homes: + sess = c.new_client_session(b"Environment.init_%i" % self.timestamp) + clean_dir(sess, home) + sess.c.null() self.clean_sessions() self.clean_clients() def startUp(self): """Run before each test""" log.debug("Sending pretest NULL") - self.c1.null() + for c in self._all_clients(): + c.null() log.debug("Got pretest NULL response") def sleep(self, sec, msg=''): @@ -260,16 +299,18 @@ class Environment(testmod.Environment): return b"%s_%i" % (os.fsencode(t.code), self.timestamp) def clean_sessions(self): - """Destroy client name env.c1""" - for sessionid in list(self.c1.sessions): - self.c1.compound([op.destroy_session(sessionid)]) - del(self.c1.sessions[sessionid]) + """Destroy all sessions on all configured clients""" + for c in self._all_clients(): + for sessionid in list(c.sessions): + c.compound([op.destroy_session(sessionid)]) + del(c.sessions[sessionid]) def clean_clients(self): - """Destroy client name env.c1""" - for clientid in list(self.c1.clients): - self.c1.compound([op.destroy_clientid(clientid)]) - del(self.c1.clients[clientid]) + """Destroy all client ids on all configured clients""" + for c in self._all_clients(): + for clientid in list(c.clients): + c.compound([op.destroy_clientid(clientid)]) + del(c.clients[clientid]) ######################################### debug_fail = False diff --git a/nfs4.1/testserver.py b/nfs4.1/testserver.py index 0970c64efe34..f38279b36cba 100755 --- a/nfs4.1/testserver.py +++ b/nfs4.1/testserver.py @@ -153,6 +153,13 @@ def scan_options(p): help="Use FH for certain specialized tests") p.add_option_group(g) + g = OptionGroup(p, "Inter-server copy options", + "A second server enables NFSv4.2 inter-server " + "(server-to-server) COPY tests.") + g.add_option("--server2", default=None, metavar="SERVER:/PATH", + help="Second server and export for inter-server copy tests") + p.add_option_group(g) + g = OptionGroup(p, "Server workaround options", "Certain servers handle certain things in unexpected ways." " These options allow you to alter test behavior so that " @@ -259,6 +266,13 @@ def main(): opt.server, opt.port = server_list[0] + # Optional second server for inter-server copy tests + if opt.server2 is not None: + server2_list, opt.server2_path = nfs4lib.parse_nfs_url(opt.server2) + if not server2_list: + p.error("%s not a valid server name" % opt.server2) + opt.server2_host, opt.server2_port = server2_list[0] + if not args: p.error("No tests given") -- 2.55.0