def op_cb_compound(self, args, cred): env = CompoundState(args, cred) # Check for problems with the compound itself if args.minorversion != 0: if args.minorversion not in self.minor_versions: env.results.set_empty_return(NFS4ERR_MINOR_VERS_MISMATCH) return env try: self.check_utf8str_cs(args.tag) except NFS4Errror as e: env.results.set_empty_return(e.status, "Invalid utf8 tag") return env # Handle the individual operations status = NFS4_OK for arg in args.argarray: opname = nfs_cb_opnum4.get(arg.argop, 'op_cb_illegal') log_cb.info("*** %s (%d) ***" % (opname, arg.argop)) env.index += 1 # Look for function self.op_<name> funct = getattr(self, opname.lower(), None) if funct is None: # If it doesn't exist, return _NOTSUPP result = encode_status_by_name(opname.lower()[3:], NFS4ERR_NOTSUPP) else: try: # Otherwise, call the function result = funct(arg, env) except NFS4Error as e: # XXX NOTE this only works for error returns that # include no data. Must ensure others (eg setattr) # catch error themselves to encode properly. result = encode_status_by_name(opname.lower()[3:], e.status, msg=e.tag) except NFS4Replay: # Just pass this on up raise except StandardError: # Uh-oh. This is a server bug traceback.print_exc() result = encode_status_by_name(opname.lower()[3:], NFS4ERR_SERVERFAULT) env.results.append(result) status = result.status if status != NFS4_OK: break log_cb.info("Replying. Status %s (%d)" % (nfsstat4[status], status)) return env
try: self.check_utf8str_cs(args.tag) except NFS4Errror, e: env.results.set_empty_return(e.status, "Invalid utf8 tag") return env # Handle the individual operations status = NFS4_OK for arg in args.argarray: opname = nfs_cb_opnum4.get(arg.argop, 'op_cb_illegal') log_cb.info("*** %s (%d) ***" % (opname, arg.argop)) env.index += 1 # Look for function self.op_<name> funct = getattr(self, opname.lower(), None) if funct is None: # If it doesn't exist, return _NOTSUPP result = encode_status_by_name(opname.lower()[3:], NFS4ERR_NOTSUPP) else: try: # Otherwise, call the function result = funct(arg, env) except NFS4Error, e: # XXX NOTE this only works for error returns that # include no data. Must ensure others (eg setattr) # catch error themselves to encode properly. result = encode_status_by_name(opname.lower()[3:], e.status, msg=e.tag) except NFS4Replay: # Just pass this on up raise except StandardError: # Uh-oh. This is a server bug
def handle_1(self, data, cred, callback=False): """COMPOUND procedure""" log.debug("*" * 40) if callback: log.debug("** CALLBACK **") log.debug("Handling COMPOUND") # stage 1: data in XDR as received from the client unpacker = nfs4lib.FancyNFS4Unpacker(data) if callback: args = unpacker.unpack_CB_COMPOUNDargs() else: args = unpacker.unpack_COMPOUND4args() log.debug("Client sent:") log.debug(repr(args)) unpacker.done() # stage 2: pre-processing - data in COMPOUND4args # XXX: check operation, alter stuff, delay etc. etc. args.req_size = len(data) # BUG, need to use cred.payload_size if callback: env = CBCompoundState(args, cred) else: env = CompoundState(args, cred) for arg in args.argarray: env.index += 1 opname = nfs_opnum4.get(arg.argop, 'op_illegal') log.info("*** %s (%d) ***" % (opname, arg.argop)) # look for functions implemented by the proxy # that override communication funct = getattr(self, opname.lower(), None) if funct is not None and callable(funct): try: result = funct(arg, cred, direction=0) except Exception: log.error("Function override %s failed" % opname.lower()) # handle error condition if specified error = None if self.errorhandler is not None: error = self.errorhandler.get_error(opname.lower()[3:], arg, env) if error is not None: result = encode_status_by_name(opname.lower()[3:], int(error), msg="Proxy Rewrite Error") env.results.append(result) p = nfs4lib.FancyNFS4Packer() if callback: res = CB_COMPOUND4res(env.results.reply.status, env.results.reply.tag, env.results.reply.results) p.pack_CB_COMPOUND4res(res) else: res = COMPOUND4res(env.results.reply.status, env.results.reply.tag, env.results.reply.results) p.pack_COMPOUND4res(res) log.info(repr(res)) reply = p.get_buffer() return rpc.SUCCESS, reply #stage 3: repack the data and forward to server packer = nfs4lib.FancyNFS4Packer() if callback: packer.pack_CB_COMPOUND4args(args) else: packer.pack_COMPOUND4args(args) log.debug("Proxy sent:") log.debug(repr(args)) calldata = packer.get_buffer() try: ret_data = self.forward_call(calldata, callback) except rpc.RPCTimeout: log.critical("Error: cannot connect to destination server") return rpc.GARBAGE_ARGS, None # stage 4: data in XDR as returned by the server unpacker = nfs4lib.FancyNFS4Unpacker(ret_data) if callback: res = unpacker.unpack_CB_COMPOUND4res() else: res = unpacker.unpack_COMPOUND4res() log.debug("Server returned:") log.debug(repr(res)) unpacker.done() # stage 5: post-processing - data in COMPOUND4res # XXX: check operation etc. for arg in res.resarray: opname = nfs_opnum4.get(arg.resop, 'op_illegal') log.info("*** %s (%d) ***" % (opname, arg.resop)) # look for functions implemented by the proxy # that override communication funct = getattr(self, opname.lower(), None) if funct is not None and callable(funct): try: result = funct(arg, cred, direction=1) except Exception: log.error("Function override %s failed" % opname.lower()) # state 6: repack and return XDR data to client packer = nfs4lib.FancyNFS4Packer() if callback: packer.pack_CB_COMPOUND4res(res) else: packer.pack_COMPOUND4res(res) log.debug("Proxy returned:") log.debug(repr(res)) reply = packer.get_buffer() return rpc.SUCCESS, reply