summaryrefslogtreecommitdiffstats
path: root/Demo/rpc/mountclient.py
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1992-12-14 23:25:04 (GMT)
committerGuido van Rossum <guido@python.org>1992-12-14 23:25:04 (GMT)
commite3cafbe7b85c350d4dbeb2af53fd8fc1ae66689b (patch)
tree3a6030b09829c527c8bb0fdcd6b36f6e9e332fe1 /Demo/rpc/mountclient.py
parent5f59d6018e1b49c3bc581a0f69aa2bb1c88ae52b (diff)
downloadcpython-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.py166
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()