blob: 021de8c760a35c8fab61cb3571fa9423224d763d [file] [log] [blame]
Guido van Rossume3cafbe1992-12-14 23:25:04 +00001# Mount RPC client -- RFC 1094 (NFS), Appendix A
2
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.
9
10
11from rpc import Packer, Unpacker, TCPClient, UDPClient
12
13MOUNTPROG = 100005
14MOUNTVERS = 1
15
16FHSIZE = 32
17
18
19# Packer derived class for Mount protocol clients.
20# The only thing we need to pack beyond basic types is an 'fhandle'
21
22class MountPacker(Packer):
23
24 def pack_fhandle(self, fhandle):
25 self.pack_fopaque(FHSIZE, fhandle)
26
27
28# Unpacker derived class for Mount protocol clients.
29# The important types we need to unpack are fhandle, fhstatus,
30# mountlist and exportlist; mountstruct, exportstruct and groups are
31# used to unpack components of mountlist and exportlist and the
32# corresponding functions are passed as function argument to the
33# generic unpack_list function.
34
35class MountUnpacker(Unpacker):
36
37 def unpack_fhandle(self):
38 return self.unpack_fopaque(FHSIZE)
39
40 def unpack_fhstatus(self):
41 status = self.unpack_uint()
42 if status == 0:
43 fh = self.unpack_fhandle()
44 else:
45 fh = None
46 return status, fh
47
48 def unpack_mountlist(self):
49 return self.unpack_list(self.unpack_mountstruct)
50
51 def unpack_mountstruct(self):
52 hostname = self.unpack_string()
53 directory = self.unpack_string()
54 return (hostname, directory)
55
56 def unpack_exportlist(self):
57 return self.unpack_list(self.unpack_exportstruct)
58
59 def unpack_exportstruct(self):
60 filesys = self.unpack_string()
61 groups = self.unpack_groups()
62 return (filesys, groups)
63
64 def unpack_groups(self):
65 return self.unpack_list(self.unpack_string)
66
67
68# These are the procedures specific to the Mount client class.
69# Think of this as a derived class of either TCPClient or UDPClient.
70
71class PartialMountClient:
72
73 # This method is called by Client.init to initialize
74 # self.packer and self.unpacker
75 def addpackers(self):
76 self.packer = MountPacker().init()
77 self.unpacker = MountUnpacker().init('')
78
79 # The methods Mnt, Dump etc. each implement one Remote
80 # Procedure Call. Their general structure is
81 # self.start_call(<procedure-number>)
82 # <pack arguments using self.packer>
83 # self.do_call() # This does the actual message exchange
84 # <unpack reply using self.unpacker>
85 # self.end_call()
86 # return <reply>
87 # If the call fails, an exception is raised by do_call().
88 # If the reply does not match what you unpack, an exception is
89 # raised either during unpacking (if you overrun the buffer)
90 # or by end_call() (if you leave values in the buffer).
91 # Calling packer methods with invalid arguments (e.g. if
92 # invalid arguments were passed from outside) will also result
93 # in exceptions during packing.
94
95 def Mnt(self, directory):
96 self.start_call(1)
97 self.packer.pack_string(directory)
98 self.do_call()
99 stat = self.unpacker.unpack_fhstatus()
100 self.end_call()
101 return stat
102
103 def Dump(self):
104 self.start_call(2)
105 self.do_call()
106 list = self.unpacker.unpack_mountlist()
107 self.end_call()
108 return list
109
110 def Umnt(self, directory):
111 self.start_call(3)
112 self.packer.pack_string(directory)
113 self.do_call()
114 self.end_call()
115
116 def Umntall(self):
117 self.start_call(4)
118 self.do_call()
119 self.end_call()
120
121 def Export(self):
122 self.start_call(5)
123 self.do_call()
124 list = self.unpacker.unpack_exportlist()
125 self.end_call()
126 return list
127
128
129# We turn the partial Mount client into a full one for either protocol
130# by use of multiple inheritance. (In general, when class C has base
131# classes B1...Bn, if x is an instance of class C, methods of x are
132# searched first in C, then in B1, then in B2, ..., finally in Bn.)
133
134class TCPMountClient(PartialMountClient, TCPClient):
135
136 def init(self, host):
137 return TCPClient.init(self, host, MOUNTPROG, MOUNTVERS)
138
139
140class UDPMountClient(PartialMountClient, UDPClient):
141
142 def init(self, host):
143 return UDPClient.init(self, host, MOUNTPROG, MOUNTVERS)
144
145
146# A little test program for the Mount client. This takes a host as
147# command line argument (default the local machine), prints its export
148# list, and attempt to mount and unmount each exported files system.
149
150def test():
151 import sys
152 if sys.argv[1:]: host = sys.argv[1]
153 else: host = ''
154 mcl = UDPMountClient().init(host)
155 list = mcl.Export()
156 for item in list:
157 print item
158 try:
159 mcl.Mnt(item[0])
160 except:
161 print 'Sorry'
162 continue
163 mcl.Umnt(item[0])
164 return
165
166#test()