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 from sfa.util.rspec import *
15 from sfa.util.parameter import *
16 from sfa.util.xrn import get_authority
17 from sfa.util.row import Row
21 The SfaRecord class implements an SFA Record. A SfaRecord is a tuple
22 (Hrn, GID, Type, Info).
24 Hrn specifies the Human Readable Name of the object
25 GID is the GID of the object
26 Type is user | authority | slice | component
28 Info is comprised of the following sub-fields
29 pointer = a pointer to the record in the PL database
31 The pointer is interpreted depending on the type of the record. For example,
32 if the type=="user", then pointer is assumed to be a person_id that indexes
33 into the persons table.
35 A given HRN may have more than one record, provided that the records are
41 primary_key = 'record_id'
43 ### the wsdl generator assumes this is named 'fields'
45 'record_id': Parameter(int, 'An id that uniquely identifies this record', ro=True),
46 'pointer': Parameter(int, 'An id that uniquely identifies this record in an external database ')
50 'authority': Parameter(str, "The authority for this record"),
51 'peer_authority': Parameter(str, "The peer authority for this record"),
52 'hrn': Parameter(str, "Human readable name of object"),
53 'gid': Parameter(str, "GID of the object"),
54 'type': Parameter(str, "Record type"),
55 'last_updated': Parameter(int, 'Date and time of last update', ro=True),
56 'date_created': Parameter(int, 'Date and time this record was created', ro=True),
58 all_fields = dict(fields.items() + internal_fields.items())
60 # Create an SFA Record
62 # @param name if !=None, assign the name of the record
63 # @param gid if !=None, assign the gid of the record
64 # @param type one of user | authority | slice | component
65 # @param pointer is a pointer to a PLC record
66 # @param dict if !=None, then fill in this record from the dictionary
68 def __init__(self, hrn=None, gid=None, type=None, pointer=None, peer_authority=None, dict=None, string=None):
74 self.set_peer_auth(peer_authority)
82 self.set_pointer(pointer)
84 self.load_from_dict(dict)
86 self.load_from_string(string)
89 def validate_last_updated(self, last_updated):
90 return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
92 def update(self, new_dict):
93 if isinstance(new_dict, list):
94 new_dict = new_dict[0]
96 # Convert any boolean strings to real bools
98 if isinstance(new_dict[key], StringTypes):
99 if new_dict[key].lower() in ["true"]:
101 elif new_dict[key].lower() in ["false"]:
102 new_dict[key] = False
103 dict.update(self, new_dict)
106 # Set the name of the record
108 # @param hrn is a string containing the HRN
110 def set_name(self, hrn):
112 Set the name of the record
119 # Set the GID of the record
121 # @param gid is a GID object or the string representation of a GID object
123 def set_gid(self, gid):
125 Set the GID of the record
128 if isinstance(gid, StringTypes):
132 self.gid = gid.save_to_string(save_parents=True)
133 self['gid'] = gid.save_to_string(save_parents=True)
137 # Set the type of the record
139 # @param type is a string: user | authority | slice | component
141 def set_type(self, type):
143 Set the type of the record
150 # Set the pointer of the record
152 # @param pointer is an integer containing the ID of a PLC record
154 def set_pointer(self, pointer):
156 Set the pointer of the record
158 self.pointer = pointer
159 self['pointer'] = pointer
163 def set_peer_auth(self, peer_authority):
164 self.peer_authority = peer_authority
165 self['peer_authority'] = peer_authority
169 # Return the name (HRN) of the record
173 Return the name (HRN) of the record
178 # Return the type of the record
182 Return the type of the record
187 # Return the pointer of the record. The pointer is an integer that may be
188 # used to look up the record in the PLC database. The evaluation of pointer
189 # depends on the type of the record
191 def get_pointer(self):
193 Return the pointer of the record. The pointer is an integer that may be
194 used to look up the record in the PLC database. The evaluation of pointer
195 depends on the type of the record
200 # Return the GID of the record, in the form of a GID object
201 # TODO: not the best name for the function, because we have things called
202 # gidObjects in the Cred
204 def get_gid_object(self):
206 Return the GID of the record, in the form of a GID object
208 return GID(string=self.gid)
211 # Returns a list of field names in this record.
213 def get_field_names(self):
215 Returns a list of field names in this record.
217 return self.fields.keys()
220 # Given a field name ("hrn", "gid", ...) return the value of that field.
222 # @param fieldname is the name of field to be returned
224 def get_field_value_string(self, fieldname):
226 Given a field name ("hrn", "gid", ...) return the value of that field.
228 if fieldname == "authority":
229 val = get_authority(self['hrn'])
232 val = getattr(self, fieldname)
234 val = self[fieldname]
235 if isinstance(val, str):
236 return "'" + str(val) + "'"
241 # Given a list of field names, return a list of values for those public.
243 # @param fieldnames is a list of field names
245 def get_field_value_strings(self, fieldnames):
247 Given a list of field names, return a list of values for those public.
249 return [ self.get_field_value_string (fieldname) for fieldname in fieldnames ]
252 # Return the record in the form of a dictionary
256 Return the record in the form of a dictionary
261 # Load the record from a dictionary
263 # @param dict dictionary to load record public from
265 def load_from_dict(self, dict):
267 Load the record from a dictionary
269 self.set_name(dict['hrn'])
270 gidstr = dict.get("gid", None)
272 self.set_gid(dict['gid'])
274 if "pointer" in dict:
275 self.set_pointer(dict['pointer'])
277 self.set_type(dict['type'])
281 # Save the record to a string. The string contains an XML representation of
284 def save_to_string(self):
286 Save the record to a string. The string contains an XML representation of
289 recorddict = self.as_dict()
290 filteredDict = dict([(key, val) for (key, val) in recorddict.iteritems() if key in self.fields.keys()])
291 record = RecordSpec()
292 record.parseDict(filteredDict)
294 #str = xmlrpclib.dumps((dict,), allow_none=True)
298 # Load the record from a string. The string is assumed to contain an XML
299 # representation of the record.
301 def load_from_string(self, str):
303 Load the record from a string. The string is assumed to contain an XML
304 representation of the record.
306 #dict = xmlrpclib.loads(str)[0][0]
308 record = RecordSpec()
309 record.parseString(str)
310 record_dict = record.toDict()
311 sfa_dict = record_dict['record']
312 self.load_from_dict(sfa_dict)
315 # Dump the record to stdout
317 # @param dump_parents if true, then the parents of the GID will be dumped
319 def dump(self, dump_parents=False):
321 Walk tree and dump records.
323 #print "RECORD", self.name
324 #print " hrn:", self.name
325 #print " type:", self.type
330 # self.get_gid_object().dump(8, dump_parents)
331 #print " pointer:", self.pointer
333 order = SfaRecord.fields.keys()
334 for key in self.keys():
338 if key in self and key in self.fields:
339 if key in 'gid' and self[key]:
340 gid = GID(string=self[key])
342 gid.dump(8, dump_parents)
344 print " %s: %s" % (key, self[key])
350 class UserRecord(SfaRecord):
353 'email': Parameter(str, 'email'),
354 'first_name': Parameter(str, 'First name'),
355 'last_name': Parameter(str, 'Last name'),
356 'phone': Parameter(str, 'Phone Number'),
357 'keys': Parameter(str, 'Public key'),
358 'slices': Parameter([str], 'List of slices this user belongs to'),
360 fields.update(SfaRecord.fields)
362 class SliceRecord(SfaRecord):
364 'name': Parameter(str, 'Slice name'),
365 'url': Parameter(str, 'Slice url'),
366 'expires': Parameter(int, 'Date and time this slice exipres'),
367 'researcher': Parameter([str], 'List of users for this slice'),
368 'PI': Parameter([str], 'List of PIs responsible for this slice'),
369 'description': Parameter([str], 'Description of this slice'),
371 fields.update(SfaRecord.fields)
374 class NodeRecord(SfaRecord):
376 'hostname': Parameter(str, 'This nodes dns name'),
377 'node_type': Parameter(str, 'Type of node this is'),
378 'node_type': Parameter(str, 'Type of node this is'),
379 'latitude': Parameter(str, 'latitude'),
380 'longitude': Parameter(str, 'longitude'),
382 fields.update(SfaRecord.fields)
385 class AuthorityRecord(SfaRecord):
387 'name': Parameter(str, 'Name'),
388 'login_base': Parameter(str, 'login base'),
389 'enabled': Parameter(bool, 'Is this site enabled'),
390 'url': Parameter(str, 'URL'),
391 'nodes': Parameter([str], 'List of nodes at this site'),
392 'operator': Parameter([str], 'List of operators'),
393 'researcher': Parameter([str], 'List of researchers'),
394 'PI': Parameter([str], 'List of Principal Investigators'),
396 fields.update(SfaRecord.fields)