def __init__(self, auth=None): if auth is None: auth = { 'AuthMethod': Parameter(str, "Authentication method to use", optional=False) } Parameter.__init__(self, auth, "API authentication structure")
class methodSignature(Method): """ Returns an array of known signatures (an array of arrays) for the method name passed. If no signatures are known, returns a none-array (test for type != array to detect missing signature). """ roles = [] accepts = [Parameter(str, "Method name")] returns = [Parameter([str], "Method signature")] def __init__(self, api): Method.__init__(self, api) self.name = "system.methodSignature" def possible_signatures(self, signature, arg): """ Return a list of the possible new signatures given a current signature and the next argument. """ if isinstance(arg, Mixed): arg_types = [xmlrpc_type(mixed_arg) for mixed_arg in arg] else: arg_types = [xmlrpc_type(arg)] return [signature + [arg_type] for arg_type in arg_types] def signatures(self, returns, args): """ Returns a list of possible signatures given a return value and a set of arguments. """ signatures = [[xmlrpc_type(returns)]] for arg in args: # Create lists of possible new signatures for each current # signature. Reduce the list of lists back down to a # single list. signatures = reduce(lambda a, b: a + b, [self.possible_signatures(signature, arg) \ for signature in signatures]) return signatures def call(self, method): function = self.api.callable(method) (min_args, max_args, defaults) = function.args() signatures = [] assert len(max_args) >= len(min_args) for num_args in range(len(min_args), len(max_args) + 1): signatures += self.signatures(function.returns, function.accepts[:num_args]) return signatures
class Content(Row): table_name = 'contents' primary_key = 'content_id' join_tables = ['user_content'] fields = { 'content_id': Parameter(int, "Content server identifier"), 'host_url': Parameter(str, "Base URL of the content server"), 'owner': Parameter(long, "User ID of the user that is responsible for this content server") }
def __init__(self, fields = {}, filter = {}, doc = "Attribute filter"): # Store the filter in our dict instance dict.__init__(self, filter) # Declare ourselves as a type of parameter that can take # either a value or a list of values for each of the specified # fields. self.fields = dict ( [ ( field, Mixed (expected, [expected])) for (field,expected) in fields.iteritems() ] ) # Null filter means no filter Parameter.__init__(self, self.fields, doc = doc, nullok = True)
def __init__(self, fields={}, filter={}, doc="Attribute filter"): # Store the filter in our dict instance dict.__init__(self, filter) # Declare ourselves as a type of parameter that can take # either a value or a list of values for each of the specified # fields. self.fields = dict([(field, Mixed(expected, [expected])) for (field, expected) in fields.iteritems()]) # Null filter means no filter Parameter.__init__(self, self.fields, doc=doc, nullok=True)
def __init__(self): Auth.__init__( self, { 'AuthMethod': Parameter(str, "Authentication method to use, always 'anonymous'", False), })
def __init__(self): Auth.__init__( self, { 'AuthMethod': Parameter( str, "Authentication method to use, always 'password' or 'capability'", optional=False), 'Username': Parameter(str, "PlanetLab username, typically an e-mail address", optional=False), 'AuthString': Parameter(str, "Authentication string, typically a password", optional=False), })
class methodHelp(Method): """ Returns help text if defined for the method passed, otherwise returns an empty string. """ roles = [] accepts = [Parameter(str, 'Method name')] returns = Parameter(str, 'Method help') def __init__(self, api): Method.__init__(self, api) self.name = "system.methodHelp" def call(self, method): function = self.api.callable(method) return function.help()
class multicall(Method): """ Process an array of calls, and return an array of results. Calls should be structs of the form {'methodName': string, 'params': array} Each result will either be a single-item array containg the result value, or a struct of the form {'faultCode': int, 'faultString': string} This is useful when you need to make lots of small calls without lots of round trips. """ roles = [] accepts = [[{'methodName': Parameter(str, "Method name"), 'params': Parameter(list, "Method arguments")}]] returns = Mixed([Mixed()], {'faultCode': Parameter(int, "XML-RPC fault code"), 'faultString': Parameter(int, "XML-RPC fault detail")}) def __init__(self, api): Method.__init__(self, api) self.name = "system.multicall" def call(self, calls): # Some error codes, borrowed from xmlrpc-c. REQUEST_REFUSED_ERROR = -507 results = [] for call in calls: try: name = call['methodName'] params = call['params'] if name == 'system.multicall': errmsg = "Recursive system.multicall forbidden" raise xmlrpclib.Fault(REQUEST_REFUSED_ERROR, errmsg) result = [self.api.call(self.source, name, *params)] except xmlrpclib.Fault, fault: result = {'faultCode': fault.faultCode, 'faultString': fault.faultString} except:
class listMethods(Method): """ This method lists all the methods that the XML-RPC server knows how to dispatch. """ roles = [] accepts = [] returns = Parameter(list, 'List of methods') def __init__(self, api): Method.__init__(self, api) self.name = "system.listMethods" def call(self): return self.api.all_methods
class MDServer(Row): table_name = 'mdservers' primary_key = 'server_id' join_tables = ['user_mdserver', 'mdserver_user'] fields = { 'server_id': Parameter(long, "Server ID"), 'name': Parameter( str, "Owner-given name of this metadata server (will be URL-encoded)"), 'host': Parameter(str, "Name of the host that hosts this metadata server"), 'portnum': Parameter(int, "Port on which this metadata server listens", min=1025, max=65534), 'status': Parameter(str, "Desired status of this metadata server"), 'auth_read': Parameter(bool, "Must a user authenticate with the server to read from it?"), 'auth_write': Parameter(bool, "Must a user authenticate with the server to write to it?"), 'owner': Parameter( int, "User ID of the user who created and controls this metadata server" ), 'user_ids': Parameter([int], "User IDs of users subscribed to this metadata server") } related_fields = {'user_ids': [Parameter(int, "Subscribed user ID")]} def __init__(self, api, fields={}): super(MDServer, self).__init__(api, fields) import SMDS.user self._add_user = Row.add_object(SMDS.user.User, 'mdserver_user') self._remove_user = Row.remove_object(SMDS.user.User, 'mdserver_user') def add_user(self, obj, commit=True): self._add_user(self, obj, commit=commit) def remove_user(self, obj, commit=True): self._remove_user(self, obj, commit=commit) @classmethod def refresh(api, m): md = MDServers(api, [m['server_id']])[0] m.update(md) def remove_users(self, user_ids): import SMDS.user users = SMDS.user.Users(self.api, user_ids) if users: for user in users: self.remove_user(user, commit=False) self.commit() def create_server(self): # signal the controller on this metadata server's host to create this server self['status'] = 'stopped' server = self.api.connect_mdctl(self['host']) import SMDS.user # get our users if self.get('user_ids') == None: self['user_ids'] = [] user_ids = self['user_ids'] users = [] if user_ids: users = SMDS.user.Users(self.api, user_ids) logger.info("Creating metadata server '%s' with users '%s'" % (self['name'], [user['username'] for user in users])) rc = 0 try: as_dict = {} as_dict.update(self) user_dicts = [] for user in users: user_dict = {} user_dict.update(user) user_dicts.append(user_dict) rc = server.create_server(as_dict, user_dicts) except Exception, e: logger.exception(e, "Could not restart metadata server") rc = -500 if rc == 1: self.sync() else: logger.error("Could not create metadata server, rc = %s" % rc) return rc
def Parameter(doc): return Mixed( Parameter(int, doc + " (unix timestamp)"), Parameter(str, doc + " (formatted as %s)" % Timestamp.sql_format), )
def __init__(self, auth = None): if auth is None: auth = {'AuthMethod': Parameter(str, "Authentication method to use", optional = False)} Parameter.__init__(self, auth, "API authentication structure")
class User(Row): table_name = 'users' primary_key = 'user_id' fields = { 'user_id': Parameter(long, "User ID"), 'username': Parameter(str, "Username", max=128), 'password': Parameter(str, "Password hash", max=254), 'email': Parameter(str, "User's email address", max=254), 'enabled': Parameter(bool, "Has the user been enabled?"), 'roles': Parameter([str], "List of roles this user fulfulls"), 'max_mdservers': Parameter(int, "Maximum number of metadata servers this user can own"), 'max_contents': Parameter(int, "Maximum number of content servers this user can register"), 'my_mdserver_ids': Parameter([int], "Server IDs of servers owned by this user"), 'sub_mdserver_ids': Parameter([int], "Server IDs of servers this user is subscribed to"), 'content_ids': Parameter([int], "Content IDs of content servers owned by this user") } related_fields = { 'my_mdserver_ids': [Parameter(int, "Server ID")], 'sub_mdserver_ids': [Parameter(int, "Server ID")], 'content_ids': [Parameter(int, "Content ID")] } user_content_view = 'user_contents' user_mdserver_view = 'user_mdservers' join_tables = ['user_mdserver', 'user_content', 'mdserver_user'] add_mdserver = Row.add_object(SMDS.mdserver.MDServer, 'user_mdserver') remove_mdserver = Row.remove_object(SMDS.mdserver.MDServer, 'user_mdserver') add_content = Row.add_object(Content, 'user_content') remove_content = Row.remove_object(Content, 'user_content') public_fieldnames = filter( lambda f: f not in ['password'], fields.keys()) register_fieldnames = ['username','password','email'] def public(self): ret = {} for f in self.public_fieldnames: ret[f] = self.get(f) return ret @staticmethod def refresh( api, u): user = Users( api, [u['user_id']] )[0] u.update( user )