2 # Implements support for geni records
4 # TODO: Use existing PLC database methods? or keep this separate?
10 from types import StringTypes
12 from sfa.trust.gid import *
14 import sfa.util.report
15 from sfa.util.rspec import *
16 from sfa.util.parameter import *
17 from sfa.util.misc import *
20 class GeniRecord(dict):
22 The GeniRecord class implements a Geni Record. A GeniRecord is a tuple
23 (Hrn, GID, Type, Info).
25 Hrn specifies the Human Readable Name of the object
26 GID is the GID of the object
27 Type is user | authority | slice | component
29 Info is comprised of the following sub-fields
30 pointer = a pointer to the record in the PL database
32 The pointer is interpreted depending on the type of the record. For example,
33 if the type=="user", then pointer is assumed to be a person_id that indexes
34 into the persons table.
36 A given HRN may have more than one record, provided that the records are
40 ### the wsdl generator assumes this is named 'fields'
42 'record_id': Parameter(int, 'An id that uniquely identifies this record'),
43 'pointer': Parameter(int, 'An id that uniquely identifies this record in an external database ')
47 'authority': Parameter(str, "The authority for this record"),
48 'peer_authority': Parameter(str, "The peer authority for this record"),
49 'hrn': Parameter(str, "Human readable name of object"),
50 'gid': Parameter(str, "GID of the object"),
51 'type': Parameter(str, "Record type"),
52 'last_updated': Parameter(int, 'Date and time of last update', ro=True),
53 'date_created': Parameter(int, 'Date and time this record was created', ro=True),
55 all_fields = dict(fields.items() + internal_fields.items())
57 # Create a Geni Record
59 # @param name if !=None, assign the name of the record
60 # @param gid if !=None, assign the gid of the record
61 # @param type one of user | authority | slice | component
62 # @param pointer is a pointer to a PLC record
63 # @param dict if !=None, then fill in this record from the dictionary
65 def __init__(self, hrn=None, gid=None, type=None, pointer=None, peer_authority=None, dict=None, string=None):
71 self.set_peer_auth(peer_authority)
79 self.set_pointer(pointer)
81 self.load_from_dict(dict)
83 self.load_from_string(string)
85 def update(self, new_dict):
86 if isinstance(new_dict, list):
87 new_dict = new_dict[0]
89 # Convert any boolean strings to real bools
91 if isinstance(new_dict[key], StringTypes):
92 if new_dict[key].lower() in ["true"]:
94 elif new_dict[key].lower() in ["false"]:
96 dict.update(self, new_dict)
99 # Set the name of the record
101 # @param hrn is a string containing the HRN
103 def set_name(self, hrn):
105 Set the name of the record
112 # Set the GID of the record
114 # @param gid is a GID object or the string representation of a GID object
116 def set_gid(self, gid):
118 Set the GID of the record
121 if isinstance(gid, StringTypes):
125 self.gid = gid.save_to_string(save_parents=True)
126 self['gid'] = gid.save_to_string(save_parents=True)
130 # Set the type of the record
132 # @param type is a string: user | authority | slice | component
134 def set_type(self, type):
136 Set the type of the record
143 # Set the pointer of the record
145 # @param pointer is an integer containing the ID of a PLC record
147 def set_pointer(self, pointer):
149 Set the pointer of the record
151 self.pointer = pointer
152 self['pointer'] = pointer
156 def set_peer_auth(self, peer_authority):
157 self.peer_authority = peer_authority
158 self['peer_authority'] = peer_authority
162 # Return the name (HRN) of the record
166 Return the name (HRN) of the record
171 # Return the type of the record
175 Return the type of the record
180 # Return the pointer of the record. The pointer is an integer that may be
181 # used to look up the record in the PLC database. The evaluation of pointer
182 # depends on the type of the record
184 def get_pointer(self):
186 Return the pointer of the record. The pointer is an integer that may be
187 used to look up the record in the PLC database. The evaluation of pointer
188 depends on the type of the record
193 # Return the GID of the record, in the form of a GID object
194 # TODO: not the best name for the function, because we have things called
195 # gidObjects in the Cred
197 def get_gid_object(self):
199 Return the GID of the record, in the form of a GID object
201 return GID(string=self.gid)
204 # Returns a list of field names in this record.
206 def get_field_names(self):
208 Returns a list of field names in this record.
210 return self.fields.keys()
213 # Given a field name ("hrn", "gid", ...) return the value of that field.
215 # @param fieldname is the name of field to be returned
217 def get_field_value_string(self, fieldname):
219 Given a field name ("hrn", "gid", ...) return the value of that field.
221 if fieldname == "authority":
222 val = get_authority(self['hrn'])
225 val = getattr(self, fieldname)
227 val = self[fieldname]
228 if isinstance(val, str):
229 return "'" + str(val) + "'"
234 # Given a list of field names, return a list of values for those public.
236 # @param fieldnames is a list of field names
238 def get_field_value_strings(self, fieldnames):
240 Given a list of field names, return a list of values for those public.
242 return [ self.get_field_value_string (fieldname) for fieldname in fieldnames ]
245 # Return the record in the form of a dictionary
249 Return the record in the form of a dictionary
254 # Load the record from a dictionary
256 # @param dict dictionary to load record public from
258 def load_from_dict(self, dict):
260 Load the record from a dictionary
262 self.set_name(dict['hrn'])
263 gidstr = dict.get("gid", None)
265 self.set_gid(dict['gid'])
267 if "pointer" in dict:
268 self.set_pointer(dict['pointer'])
270 self.set_type(dict['type'])
274 # Save the record to a string. The string contains an XML representation of
277 def save_to_string(self):
279 Save the record to a string. The string contains an XML representation of
282 recorddict = self.as_dict()
283 filteredDict = dict([(key, val) for (key, val) in recorddict.iteritems() if key in self.fields.keys()])
284 record = RecordSpec()
285 record.parseDict(filteredDict)
287 #str = xmlrpclib.dumps((dict,), allow_none=True)
291 # Load the record from a string. The string is assumed to contain an XML
292 # representation of the record.
294 def load_from_string(self, str):
296 Load the record from a string. The string is assumed to contain an XML
297 representation of the record.
299 #dict = xmlrpclib.loads(str)[0][0]
301 record = RecordSpec()
302 record.parseString(str)
303 record_dict = record.toDict()
304 geni_dict = record_dict['record']
305 self.load_from_dict(geni_dict)
308 # Dump the record to stdout
310 # @param dump_parents if true, then the parents of the GID will be dumped
312 def dump(self, dump_parents=False):
314 Walk tree and dump records.
316 #print "RECORD", self.name
317 #print " hrn:", self.name
318 #print " type:", self.type
323 # self.get_gid_object().dump(8, dump_parents)
324 #print " pointer:", self.pointer
326 order = GeniRecord.fields.keys()
327 for key in self.keys():
331 if key in self and key in self.fields:
332 if key in 'gid' and self[key]:
333 gid = GID(string=self[key])
335 gid.dump(8, dump_parents)
337 print " %s: %s" % (key, self[key])
343 class UserRecord(GeniRecord):
346 'email': Parameter(str, 'email'),
347 'first_name': Parameter(str, 'First name'),
348 'last_name': Parameter(str, 'Last name'),
349 'phone': Parameter(str, 'Phone Number'),
350 'key': Parameter(str, 'Public key'),
351 'slices': Parameter([str], 'List of slices this user belongs to'),
353 fields.update(GeniRecord.fields)
355 class SliceRecord(GeniRecord):
357 'name': Parameter(str, 'Slice name'),
358 'url': Parameter(str, 'Slice url'),
359 'expires': Parameter(int, 'Date and time this slice exipres'),
360 'researcher': Parameter([str], 'List of users for this slice'),
361 'description': Parameter([str], 'Description of this slice'),
363 fields.update(GeniRecord.fields)
366 class NodeRecord(GeniRecord):
368 'hostname': Parameter(str, 'This nodes dns name'),
369 'node_type': Parameter(str, 'Type of node this is'),
370 'node_type': Parameter(str, 'Type of node this is'),
371 'latitude': Parameter(str, 'latitude'),
372 'longitude': Parameter(str, 'longitude'),
374 fields.update(GeniRecord.fields)
377 class AuthorityRecord(GeniRecord):
379 'name': Parameter(str, 'Name'),
380 'login_base': Parameter(str, 'login base'),
381 'enabled': Parameter(bool, 'Is this site enabled'),
382 'url': Parameter(str, 'URL'),
383 'nodes': Parameter([str], 'List of nodes at this site'),
384 'operator': Parameter([str], 'List of operators'),
385 'researcher': Parameter([str], 'List of researchers'),
386 'PI': Parameter([str], 'List of Principal Investigators'),
388 fields.update(GeniRecord.fields)