diff options
author | Guido van Rossum <guido@python.org> | 1992-12-14 23:25:04 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1992-12-14 23:25:04 (GMT) |
commit | e3cafbe7b85c350d4dbeb2af53fd8fc1ae66689b (patch) | |
tree | 3a6030b09829c527c8bb0fdcd6b36f6e9e332fe1 /Demo/rpc/mountclient.py | |
parent | 5f59d6018e1b49c3bc581a0f69aa2bb1c88ae52b (diff) | |
download | cpython-e3cafbe7b85c350d4dbeb2af53fd8fc1ae66689b.zip cpython-e3cafbe7b85c350d4dbeb2af53fd8fc1ae66689b.tar.gz cpython-e3cafbe7b85c350d4dbeb2af53fd8fc1ae66689b.tar.bz2 |
Initial revision
Diffstat (limited to 'Demo/rpc/mountclient.py')
-rw-r--r-- | Demo/rpc/mountclient.py | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/Demo/rpc/mountclient.py b/Demo/rpc/mountclient.py new file mode 100644 index 0000000..021de8c --- /dev/null +++ b/Demo/rpc/mountclient.py @@ -0,0 +1,166 @@ +# Mount RPC client -- RFC 1094 (NFS), Appendix A + +# This module demonstrates how to write your own RPC client in Python. +# Since there is no RPC compiler for Python (yet), you must first +# create classes derived from Packer and Unpacker to handle the data +# types for the server you want to interface to. You then write the +# client class. If you want to support both the TCP and the UDP +# version of a protocol, use multiple inheritance as shown below. + + +from rpc import Packer, Unpacker, TCPClient, UDPClient + +MOUNTPROG = 100005 +MOUNTVERS = 1 + +FHSIZE = 32 + + +# Packer derived class for Mount protocol clients. +# The only thing we need to pack beyond basic types is an 'fhandle' + +class MountPacker(Packer): + + def pack_fhandle(self, fhandle): + self.pack_fopaque(FHSIZE, fhandle) + + +# Unpacker derived class for Mount protocol clients. +# The important types we need to unpack are fhandle, fhstatus, +# mountlist and exportlist; mountstruct, exportstruct and groups are +# used to unpack components of mountlist and exportlist and the +# corresponding functions are passed as function argument to the +# generic unpack_list function. + +class MountUnpacker(Unpacker): + + def unpack_fhandle(self): + return self.unpack_fopaque(FHSIZE) + + def unpack_fhstatus(self): + status = self.unpack_uint() + if status == 0: + fh = self.unpack_fhandle() + else: + fh = None + return status, fh + + def unpack_mountlist(self): + return self.unpack_list(self.unpack_mountstruct) + + def unpack_mountstruct(self): + hostname = self.unpack_string() + directory = self.unpack_string() + return (hostname, directory) + + def unpack_exportlist(self): + return self.unpack_list(self.unpack_exportstruct) + + def unpack_exportstruct(self): + filesys = self.unpack_string() + groups = self.unpack_groups() + return (filesys, groups) + + def unpack_groups(self): + return self.unpack_list(self.unpack_string) + + +# These are the procedures specific to the Mount client class. +# Think of this as a derived class of either TCPClient or UDPClient. + +class PartialMountClient: + + # This method is called by Client.init to initialize + # self.packer and self.unpacker + def addpackers(self): + self.packer = MountPacker().init() + self.unpacker = MountUnpacker().init('') + + # The methods Mnt, Dump etc. each implement one Remote + # Procedure Call. Their general structure is + # self.start_call(<procedure-number>) + # <pack arguments using self.packer> + # self.do_call() # This does the actual message exchange + # <unpack reply using self.unpacker> + # self.end_call() + # return <reply> + # If the call fails, an exception is raised by do_call(). + # If the reply does not match what you unpack, an exception is + # raised either during unpacking (if you overrun the buffer) + # or by end_call() (if you leave values in the buffer). + # Calling packer methods with invalid arguments (e.g. if + # invalid arguments were passed from outside) will also result + # in exceptions during packing. + + def Mnt(self, directory): + self.start_call(1) + self.packer.pack_string(directory) + self.do_call() + stat = self.unpacker.unpack_fhstatus() + self.end_call() + return stat + + def Dump(self): + self.start_call(2) + self.do_call() + list = self.unpacker.unpack_mountlist() + self.end_call() + return list + + def Umnt(self, directory): + self.start_call(3) + self.packer.pack_string(directory) + self.do_call() + self.end_call() + + def Umntall(self): + self.start_call(4) + self.do_call() + self.end_call() + + def Export(self): + self.start_call(5) + self.do_call() + list = self.unpacker.unpack_exportlist() + self.end_call() + return list + + +# We turn the partial Mount client into a full one for either protocol +# by use of multiple inheritance. (In general, when class C has base +# classes B1...Bn, if x is an instance of class C, methods of x are +# searched first in C, then in B1, then in B2, ..., finally in Bn.) + +class TCPMountClient(PartialMountClient, TCPClient): + + def init(self, host): + return TCPClient.init(self, host, MOUNTPROG, MOUNTVERS) + + +class UDPMountClient(PartialMountClient, UDPClient): + + def init(self, host): + return UDPClient.init(self, host, MOUNTPROG, MOUNTVERS) + + +# A little test program for the Mount client. This takes a host as +# command line argument (default the local machine), prints its export +# list, and attempt to mount and unmount each exported files system. + +def test(): + import sys + if sys.argv[1:]: host = sys.argv[1] + else: host = '' + mcl = UDPMountClient().init(host) + list = mcl.Export() + for item in list: + print item + try: + mcl.Mnt(item[0]) + except: + print 'Sorry' + continue + mcl.Umnt(item[0]) + return + +#test() |