2 # Implements support for SFA 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.namespace import *
18 from sfa.util.row import Row
22 The SfaRecord class implements an SFA Record. A SfaRecord 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
42 primary_key = 'record_id'
44 ### the wsdl generator assumes this is named 'fields'
46 'record_id': Parameter(int, 'An id that uniquely identifies this record', ro=True),
47 'pointer': Parameter(int, 'An id that uniquely identifies this record in an external database ')
51 'authority': Parameter(str, "The authority for this record"),
52 'peer_authority': Parameter(str, "The peer authority for this record"),
53 'hrn': Parameter(str, "Human readable name of object"),
54 'gid': Parameter(str, "GID of the object"),
55 'type': Parameter(str, "Record type"),
56 'last_updated': Parameter(int, 'Date and time of last update', ro=True),
57 'date_created': Parameter(int, 'Date and time this record was created', ro=True),
59 all_fields = dict(fields.items() + internal_fields.items())
61 # Create an SFA Record
63 # @param name if !=None, assign the name of the record
64 # @param gid if !=None, assign the gid of the record
65 # @param type one of user | authority | slice | component
66 # @param pointer is a pointer to a PLC record
67 # @param dict if !=None, then fill in this record from the dictionary
69 def __init__(self, hrn=None, gid=None, type=None, pointer=None, peer_authority=None, dict=None, string=None):
75 self.set_peer_auth(peer_authority)
83 self.set_pointer(pointer)
85 self.load_from_dict(dict)
87 self.load_from_string(string)
90 def validate_last_updated(self, last_updated):
91 return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
93 def update(self, new_dict):
94 if isinstance(new_dict, list):
95 new_dict = new_dict[0]
97 # Convert any boolean strings to real bools
99 if isinstance(new_dict[key], StringTypes):
100 if new_dict[key].lower() in ["true"]:
102 elif new_dict[key].lower() in ["false"]:
103 new_dict[key] = False
104 dict.update(self, new_dict)
107 # Set the name of the record
109 # @param hrn is a string containing the HRN
111 def set_name(self, hrn):
113 Set the name of the record
120 # Set the GID of the record
122 # @param gid is a GID object or the string representation of a GID object
124 def set_gid(self, gid):
126 Set the GID of the record
129 if isinstance(gid, StringTypes):
133 self.gid = gid.save_to_string(save_parents=True)
134 self['gid'] = gid.save_to_string(save_parents=True)
138 # Set the type of the record
140 # @param type is a string: user | authority | slice | component
142 def set_type(self, type):
144 Set the type of the record
151 # Set the pointer of the record
153 # @param pointer is an integer containing the ID of a PLC record
155 def set_pointer(self, pointer):
157 Set the pointer of the record
159 self.pointer = pointer
160 self['pointer'] = pointer
164 def set_peer_auth(self, peer_authority):
165 self.peer_authority = peer_authority
166 self['peer_authority'] = peer_authority
170 # Return the name (HRN) of the record
174 Return the name (HRN) of the record
179 # Return the type of the record
183 Return the type of the record
188 # Return the pointer of the record. The pointer is an integer that may be
189 # used to look up the record in the PLC database. The evaluation of pointer
190 # depends on the type of the record
192 def get_pointer(self):
194 Return the pointer of the record. The pointer is an integer that may be
195 used to look up the record in the PLC database. The evaluation of pointer
196 depends on the type of the record
201 # Return the GID of the record, in the form of a GID object
202 # TODO: not the best name for the function, because we have things called
203 # gidObjects in the Cred
205 def get_gid_object(self):
207 Return the GID of the record, in the form of a GID object
209 return GID(string=self.gid)
212 # Returns a list of field names in this record.
214 def get_field_names(self):
216 Returns a list of field names in this record.
218 return self.fields.keys()
221 # Given a field name ("hrn", "gid", ...) return the value of that field.
223 # @param fieldname is the name of field to be returned
225 def get_field_value_string(self, fieldname):
227 Given a field name ("hrn", "gid", ...) return the value of that field.
229 if fieldname == "authority":
230 val = get_authority(self['hrn'])
233 val = getattr(self, fieldname)
235 val = self[fieldname]
236 if isinstance(val, str):
237 return "'" + str(val) + "'"
242 # Given a list of field names, return a list of values for those public.
244 # @param fieldnames is a list of field names
246 def get_field_value_strings(self, fieldnames):
248 Given a list of field names, return a list of values for those public.
250 return [ self.get_field_value_string (fieldname) for fieldname in fieldnames ]
253 # Return the record in the form of a dictionary
257 Return the record in the form of a dictionary
262 # Load the record from a dictionary
264 # @param dict dictionary to load record public from
266 def load_from_dict(self, dict):
268 Load the record from a dictionary
270 self.set_name(dict['hrn'])
271 gidstr = dict.get("gid", None)
273 self.set_gid(dict['gid'])
275 if "pointer" in dict:
276 self.set_pointer(dict['pointer'])
278 self.set_type(dict['type'])
282 # Save the record to a string. The string contains an XML representation of
285 def save_to_string(self):
287 Save the record to a string. The string contains an XML representation of
290 recorddict = self.as_dict()
291 filteredDict = dict([(key, val) for (key, val) in recorddict.iteritems() if key in self.fields.keys()])
292 record = RecordSpec()
293 record.parseDict(filteredDict)
295 #str = xmlrpclib.dumps((dict,), allow_none=True)
299 # Load the record from a string. The string is assumed to contain an XML
300 # representation of the record.
302 def load_from_string(self, str):
304 Load the record from a string. The string is assumed to contain an XML
305 representation of the record.
307 #dict = xmlrpclib.loads(str)[0][0]
309 record = RecordSpec()
310 record.parseString(str)
311 record_dict = record.toDict()
312 sfa_dict = record_dict['record']
313 self.load_from_dict(sfa_dict)
316 # Dump the record to stdout
318 # @param dump_parents if true, then the parents of the GID will be dumped
320 def dump(self, dump_parents=False):
322 Walk tree and dump records.
324 #print "RECORD", self.name
325 #print " hrn:", self.name
326 #print " type:", self.type
331 # self.get_gid_object().dump(8, dump_parents)
332 #print " pointer:", self.pointer
334 order = SfaRecord.fields.keys()
335 for key in self.keys():
339 if key in self and key in self.fields:
340 if key in 'gid' and self[key]:
341 gid = GID(string=self[key])
343 gid.dump(8, dump_parents)
345 print " %s: %s" % (key, self[key])
351 class UserRecord(SfaRecord):
354 'email': Parameter(str, 'email'),
355 'first_name': Parameter(str, 'First name'),
356 'last_name': Parameter(str, 'Last name'),
357 'phone': Parameter(str, 'Phone Number'),
358 'key': Parameter(str, 'Public key'),
359 'slices': Parameter([str], 'List of slices this user belongs to'),
361 fields.update(SfaRecord.fields)
363 class SliceRecord(SfaRecord):
365 'name': Parameter(str, 'Slice name'),
366 'url': Parameter(str, 'Slice url'),
367 'expires': Parameter(int, 'Date and time this slice exipres'),
368 'researcher': Parameter([str], 'List of users for this slice'),
369 'PI': Parameter([str], 'List of PIs responsible for this slice'),
370 'description': Parameter([str], 'Description of this slice'),
372 fields.update(SfaRecord.fields)
375 class NodeRecord(SfaRecord):
377 'hostname': Parameter(str, 'This nodes dns name'),
378 'node_type': Parameter(str, 'Type of node this is'),
379 'node_type': Parameter(str, 'Type of node this is'),
380 'latitude': Parameter(str, 'latitude'),
381 'longitude': Parameter(str, 'longitude'),
383 fields.update(SfaRecord.fields)
386 class AuthorityRecord(SfaRecord):
388 'name': Parameter(str, 'Name'),
389 'login_base': Parameter(str, 'login base'),
390 'enabled': Parameter(bool, 'Is this site enabled'),
391 'url': Parameter(str, 'URL'),
392 'nodes': Parameter([str], 'List of nodes at this site'),
393 'operator': Parameter([str], 'List of operators'),
394 'researcher': Parameter([str], 'List of researchers'),
395 'PI': Parameter([str], 'List of Principal Investigators'),
397 fields.update(SfaRecord.fields)