2 # Thierry Parmentelat - INRIA
6 from types import StringTypes
8 from PLC.Faults import *
9 from PLC.Parameter import Parameter, Mixed
10 from PLC.Filter import Filter
11 from PLC.Table import Row, Table
14 from PLC.Nodes import Nodes,Node
15 from PLC.Slices import Slices,Slice
18 from PLC.PyCurl import PyCurlTransport
19 from PLC.GPG import gpg_sign
23 Stores the list of peering PLCs in the peers table.
24 See the Row class for more details
28 primary_key = 'peer_id'
30 'peer_id' : Parameter (int, "Peer identifier"),
31 'peername' : Parameter (str, "Peer name"),
32 'peer_url' : Parameter (str, "Peer API url"),
33 'key': Parameter(str, "Peer GPG public key"),
34 'cacert': Parameter(str, "Peer SSL public certificate"),
36 'site_ids' : Parameter ([int], "This peer's sites ids"),
37 'person_ids' : Parameter ([int], "This peer's persons ids"),
38 'node_ids' : Parameter ([int], "This peer's nodes ids"),
39 'slice_ids' : Parameter ([int], "This peer's slices ids"),
42 def validate_peer_url (self, url):
44 Validate URL, checks it looks like https
46 invalid_url = PLCInvalidArgument("Invalid URL")
47 if not re.compile ("^https://.*$").match(url) :
51 def delete (self, commit=True):
56 assert 'peer_id' in self
58 # remove nodes depending on this peer
59 for foreign_node in Nodes (self.api, self['node_ids']):
60 foreign_node.delete(commit)
63 self['deleted'] = True
66 def connect(self, **kwds):
68 Connect to this peer via XML-RPC.
71 self.server = xmlrpclib.ServerProxy(self['peer_url'],
72 PyCurlTransport(self['peer_url'], self['cacert']),
73 allow_none = 1, **kwds)
75 def add_auth(self, function, methodname, **kwds):
77 Sign the specified XML-RPC call and add an auth struct as the
78 first argument of the call.
81 def wrapper(*args, **kwds):
82 signature = gpg_sign(methodname, args,
83 self.api.config.PLC_ROOT_GPG_KEY,
84 self.api.config.PLC_ROOT_GPG_KEY_PUB)
86 auth = {'AuthMethod': "gpg",
87 'name': self.api.config.PLC_NAME,
88 'signature': signature}
90 # Automagically add auth struct to every call
93 return function(*args)
97 def __getattr__(self, methodname):
99 Fetch a callable for the specified method.
102 function = getattr(self.server, methodname)
105 # Figure out if the function is a PLCAPI function and
106 # requires an authentication structure as its first
108 api_function = self.api.callable(methodname)
109 if api_function.accepts and \
110 (isinstance(api_function.accepts[0], PLC.Auth.Auth) or \
111 (isinstance(api_function.accepts[0], Mixed) and \
112 filter(lambda param: isinstance(param, Auth), func.accepts[0]))):
113 function = self.add_auth(function, methodname)
114 except Exception, err:
121 Maps to the peers table in the database
124 def __init__ (self, api, peer_filter = None, columns = None):
125 Table.__init__(self, api, Peer, columns)
127 sql = "SELECT %s FROM view_peers WHERE deleted IS False" % \
128 ", ".join(self.columns)
130 if peer_filter is not None:
131 if isinstance(peer_filter, (list, tuple, set)):
132 # Separate the list into integers and strings
133 ints = filter(lambda x: isinstance(x, (int, long)), peer_filter)
134 strs = filter(lambda x: isinstance(x, StringTypes), peer_filter)
135 peer_filter = Filter(Peer.fields, {'peer_id': ints, 'peername': strs})
136 sql += " AND (%s)" % peer_filter.sql(api, "OR")
137 elif isinstance(peer_filter, dict):
138 peer_filter = Filter(Peer.fields, peer_filter)
139 sql += " AND (%s)" % peer_filter.sql(api, "AND")