Updated for 2.1b2 distribution.
[python/dscho.git] / Demo / rpc / mountclient.py
blobff66b3d6ccf54b1e0d1cca3590847e5c2b4ade10
1 # Mount RPC client -- RFC 1094 (NFS), Appendix A
3 # This module demonstrates how to write your own RPC client in Python.
4 # Since there is no RPC compiler for Python (yet), you must first
5 # create classes derived from Packer and Unpacker to handle the data
6 # types for the server you want to interface to. You then write the
7 # client class. If you want to support both the TCP and the UDP
8 # version of a protocol, use multiple inheritance as shown below.
11 import rpc
12 from rpc import Packer, Unpacker, TCPClient, UDPClient
15 # Program number and version for the mount protocol
16 MOUNTPROG = 100005
17 MOUNTVERS = 1
19 # Size of the 'fhandle' opaque structure
20 FHSIZE = 32
23 # Packer derived class for Mount protocol clients.
24 # The only thing we need to pack beyond basic types is an 'fhandle'
26 class MountPacker(Packer):
28 def pack_fhandle(self, fhandle):
29 self.pack_fopaque(FHSIZE, fhandle)
32 # Unpacker derived class for Mount protocol clients.
33 # The important types we need to unpack are fhandle, fhstatus,
34 # mountlist and exportlist; mountstruct, exportstruct and groups are
35 # used to unpack components of mountlist and exportlist and the
36 # corresponding functions are passed as function argument to the
37 # generic unpack_list function.
39 class MountUnpacker(Unpacker):
41 def unpack_fhandle(self):
42 return self.unpack_fopaque(FHSIZE)
44 def unpack_fhstatus(self):
45 status = self.unpack_uint()
46 if status == 0:
47 fh = self.unpack_fhandle()
48 else:
49 fh = None
50 return status, fh
52 def unpack_mountlist(self):
53 return self.unpack_list(self.unpack_mountstruct)
55 def unpack_mountstruct(self):
56 hostname = self.unpack_string()
57 directory = self.unpack_string()
58 return (hostname, directory)
60 def unpack_exportlist(self):
61 return self.unpack_list(self.unpack_exportstruct)
63 def unpack_exportstruct(self):
64 filesys = self.unpack_string()
65 groups = self.unpack_groups()
66 return (filesys, groups)
68 def unpack_groups(self):
69 return self.unpack_list(self.unpack_string)
72 # These are the procedures specific to the Mount client class.
73 # Think of this as a derived class of either TCPClient or UDPClient.
75 class PartialMountClient:
77 # This method is called by Client.__init__ to initialize
78 # self.packer and self.unpacker
79 def addpackers(self):
80 self.packer = MountPacker()
81 self.unpacker = MountUnpacker('')
83 # This method is called by Client.__init__ to bind the socket
84 # to a particular network interface and port. We use the
85 # default network interface, but if we're running as root,
86 # we want to bind to a reserved port
87 def bindsocket(self):
88 import os
89 try:
90 uid = os.getuid()
91 except AttributeError:
92 uid = 1
93 if uid == 0:
94 port = rpc.bindresvport(self.sock, '')
95 # 'port' is not used
96 else:
97 self.sock.bind(('', 0))
99 # This function is called to cough up a suitable
100 # authentication object for a call to procedure 'proc'.
101 def mkcred(self):
102 if self.cred == None:
103 self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix_default()
104 return self.cred
106 # The methods Mnt, Dump etc. each implement one Remote
107 # Procedure Call. This is done by calling self.make_call()
108 # with as arguments:
110 # - the procedure number
111 # - the arguments (or None)
112 # - the "packer" function for the arguments (or None)
113 # - the "unpacker" function for the return value (or None)
115 # The packer and unpacker function, if not None, *must* be
116 # methods of self.packer and self.unpacker, respectively.
117 # A value of None means that there are no arguments or is no
118 # return value, respectively.
120 # The return value from make_call() is the return value from
121 # the remote procedure call, as unpacked by the "unpacker"
122 # function, or None if the unpacker function is None.
124 # (Even if you expect a result of None, you should still
125 # return the return value from make_call(), since this may be
126 # needed by a broadcasting version of the class.)
128 # If the call fails, make_call() raises an exception
129 # (this includes time-outs and invalid results).
131 # Note that (at least with the UDP protocol) there is no
132 # guarantee that a call is executed at most once. When you do
133 # get a reply, you know it has been executed at least once;
134 # when you don't get a reply, you know nothing.
136 def Mnt(self, directory):
137 return self.make_call(1, directory, \
138 self.packer.pack_string, \
139 self.unpacker.unpack_fhstatus)
141 def Dump(self):
142 return self.make_call(2, None, \
143 None, self.unpacker.unpack_mountlist)
145 def Umnt(self, directory):
146 return self.make_call(3, directory, \
147 self.packer.pack_string, None)
149 def Umntall(self):
150 return self.make_call(4, None, None, None)
152 def Export(self):
153 return self.make_call(5, None, \
154 None, self.unpacker.unpack_exportlist)
157 # We turn the partial Mount client into a full one for either protocol
158 # by use of multiple inheritance. (In general, when class C has base
159 # classes B1...Bn, if x is an instance of class C, methods of x are
160 # searched first in C, then in B1, then in B2, ..., finally in Bn.)
162 class TCPMountClient(PartialMountClient, TCPClient):
164 def __init__(self, host):
165 TCPClient.__init__(self, host, MOUNTPROG, MOUNTVERS)
168 class UDPMountClient(PartialMountClient, UDPClient):
170 def __init__(self, host):
171 UDPClient.__init__(self, host, MOUNTPROG, MOUNTVERS)
174 # A little test program for the Mount client. This takes a host as
175 # command line argument (default the local machine), prints its export
176 # list, and attempts to mount and unmount each exported files system.
177 # An optional first argument of -t or -u specifies the protocol to use
178 # (TCP or UDP), default is UDP.
180 def test():
181 import sys
182 if sys.argv[1:] and sys.argv[1] == '-t':
183 C = TCPMountClient
184 del sys.argv[1]
185 elif sys.argv[1:] and sys.argv[1] == '-u':
186 C = UDPMountClient
187 del sys.argv[1]
188 else:
189 C = UDPMountClient
190 if sys.argv[1:]: host = sys.argv[1]
191 else: host = ''
192 mcl = C(host)
193 list = mcl.Export()
194 for item in list:
195 print item
196 try:
197 mcl.Mnt(item[0])
198 except:
199 print 'Sorry'
200 continue
201 mcl.Umnt(item[0])