Commit 8aecc4fc authored by David Johnson's avatar David Johnson

Add a little class with a couple SimpleXMLRPCServer class extensions. The

first one makes python's basic xmlrpc facility act a bit like java RMI
(the SimpleObjectXMLRPCServer).  The second (InetACLXMLRPCServer) filters
incoming requests based on allowed networks (i.e., 155.98.32.0/20 or
similar).  If ever desired, they should be compatible with the boss xmlrpc
server model) with just a tiny hack.
parent 3fb8f66a
#!/usr/local/bin/python
#
# A simple little xmlrpc server that provides an interface to flexlab data.
# At present, basically just exports goodnodes.pl functionality, but could
# do more if desired.
#
import os
import pwd
import xmlrpclib
import SimpleXMLRPCServer
import SocketServer
import sys
import types
import exceptions
import traceback
debug = True
class NetworkAuthError(exceptions.Exception):
pass
class SimpleObjectXMLRPCServer(SocketServer.ThreadingMixIn,
SimpleXMLRPCServer.SimpleXMLRPCServer,object):
"""
Extension to the simple xmlrpc server that registers member functions
of a class as xmlrpc functions, so they can be called as
<classname>.<method>. The whole point is to be compatible with existing
Emulab xmlrpc infrastructure (i.e., emulabserver.py classes).
"""
def __init__(self,addr,**kwargs):
super(SimpleObjectXMLRPCServer,self).__init__(addr,**kwargs)
self.classfuncs = dict({})
self.classinitargs = dict({})
return
"""
Register all non-private functions, or only the supplied method names,
in a class as RPCs. Passes initargs to __init__ on class instantiation.
"""
def register_class_functions(self,myclass,methods=None,initargs=()):
for f in dir(myclass):
if (type(myclass.__dict__[f]) == types.FunctionType \
and not f.startswith('_')) \
or (methods != None and f in methods):
myname = myclass.__name__ + "." + f
self.register_function(myclass.__dict__[f],myname)
self.classfuncs[myname] = myclass
self.classinitargs[myname] = initargs
pass
pass
return
"""
Add class object instantiation prior to method calls on the object for
rpc methods added via register_class_functions; else use normal _dispatch.
"""
def _dispatch(self,method,params):
if self.classfuncs.has_key(method):
try:
myclass = self.classfuncs[method]
myargs = self.classinitargs[method]
obj = myclass(*myargs)
# ugh, nasty way to get reflectiveness
return myclass.__dict__[self.funcs[method].func_name](obj,
*params)
except:
traceback.print_exc()
pass
else:
return super(SimpleObjectXMLRPCServer,self)._dispatch(method,params)
pass
pass
class InetAclXMLRPCServer(SimpleObjectXMLRPCServer):
def __init__(self,addr,netacllist=[],**kwargs):
super(InetAclXMLRPCServer,self).__init__(addr,**kwargs)
self.acllist = []
for acl in netacllist:
explicitmask = False
sa = acl.split('/')
matchbits = 32
if len(sa) > 1:
explicitmask = True
matchbits = int(sa[1])
pass
sa = sa[0].split('.')
if sa[len(sa)-1] == '':
sa[len(sa)-1] = 0
pass
if (len(sa) < 4):
for i in range(len(sa)-1,4):
sa[i] = 0
pass
pass
# 192.168/16 == 192.168.0.0
if not explicitmask:
for i in range(len(sa)-1,-1,-1):
if (sa[i]) == 0:
matchbits = matchbits - 8
else:
break
pass
# 0.0.0.0 == all
if i == 0:
matchbits = 0
pass
pass
shiftamt = 24
netbits = 0
for i in range(0,4):
netbits = netbits | ((int(sa[i]) & 0xff) << shiftamt)
shiftamt -= 8
pass
mask = 0
for i in range(31,matchbits-1,-1):
mask |= (0x1 << i)
pass
# now we can check addresses via
# if ((addr|netbits)&mask == netbits); then valid.
if debug:
print "allowing from %s: net=%s,mask=%s" \
% (str(acl),str(netbits),str(mask))
self.acllist.append((netbits,mask))
pass
return
def verify_request(self,request,client_address):
if debug:
print "request = '" + str(request) + "'"
print "client_address = '" + str(client_address) + "'"
(cip,cport) = client_address
match = False
clientbits = 0
sa = cip.split('.')
shiftamt = 24
for i in range(0,len(sa)):
clientbits = clientbits | (int(sa[i]) << shiftamt)
shiftamt = shiftamt - 8
pass
if debug:
print "client "+cip+": clientbits="+str(clientbits)
for (netbits,mask) in self.acllist:
if clientbits & mask == netbits & mask:
match = True
break
pass
if debug:
print "verify_request returning " + str(match)
return match
pass
......@@ -27,7 +27,8 @@ EXPANDCOPYRIGHT = /usr/site/lib/copyright/expand-copyr
# These are the ones installed on plastic (users, control, etc).
#
CLIENTBINS = sshxmlrpc_client.py script_wrapper.py sslxmlrpc_client.py
USERLIBS = sshxmlrpc.py emulabclient.py libxmlrpc.pm
USERLIBS = sshxmlrpc.py emulabclient.py libxmlrpc.pm \
BasicXMLRPCServers.py
SYMLINKS = node_admin node_reboot os_load create_image node_list \
delay_config wilink_config savelogs portstats eventsys_control \
readycount nscheck startexp batchexp startexp swapexp endexp \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment