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 'hrn': Parameter(str, "Human readable name of object"),
49 'gid': Parameter(str, "GID of the object"),
50 'type': Parameter(str, "Record type"),
51 'last_updated': Parameter(int, 'Date and time of last update'),
52 'date_created': Parameter(int, 'Date and time this record was created'),
54 all_fields = dict(fields.items() + internal_fields.items())
56 # Create a Geni Record
58 # @param name if !=None, assign the name of the record
59 # @param gid if !=None, assign the gid of the record
60 # @param type one of user | authority | slice | component
61 # @param pointer is a pointer to a PLC record
62 # @param dict if !=None, then fill in this record from the dictionary
64 def __init__(self, hrn=None, gid=None, type=None, pointer=None, dict=None, string=None):
77 self.set_pointer(pointer)
79 self.load_from_dict(dict)
81 self.load_from_string(string)
83 def update(self, new_dict):
84 if isinstance(new_dict, list):
85 new_dict = new_dict[0]
87 # Convert any boolean strings to real bools
89 if isinstance(new_dict[key], StringTypes):
90 if new_dict[key].lower() in ["true"]:
92 elif new_dict[key].lower() in ["false"]:
94 dict.update(self, new_dict)
97 # Set the name of the record
99 # @param hrn is a string containing the HRN
101 def set_name(self, hrn):
103 Set the name of the record
110 # Set the GID of the record
112 # @param gid is a GID object or the string representation of a GID object
114 def set_gid(self, gid):
116 Set the GID of the record
119 if isinstance(gid, StringTypes):
123 self.gid = gid.save_to_string(save_parents=True)
124 self['gid'] = gid.save_to_string(save_parents=True)
128 # Set the type of the record
130 # @param type is a string: user | authority | slice | component
132 def set_type(self, type):
134 Set the type of the record
141 # Set the pointer of the record
143 # @param pointer is an integer containing the ID of a PLC record
145 def set_pointer(self, pointer):
147 Set the pointer of the record
149 self.pointer = pointer
150 self['pointer'] = pointer
154 # Return the name (HRN) of the record
158 Return the name (HRN) of the record
163 # Return the type of the record
167 Return the type of the record
172 # Return the pointer of the record. The pointer is an integer that may be
173 # used to look up the record in the PLC database. The evaluation of pointer
174 # depends on the type of the record
176 def get_pointer(self):
178 Return the pointer of the record. The pointer is an integer that may be
179 used to look up the record in the PLC database. The evaluation of pointer
180 depends on the type of the record
185 # Return the GID of the record, in the form of a GID object
186 # TODO: not the best name for the function, because we have things called
187 # gidObjects in the Cred
189 def get_gid_object(self):
191 Return the GID of the record, in the form of a GID object
193 return GID(string=self.gid)
196 # Returns a list of field names in this record.
198 def get_field_names(self):
200 Returns a list of field names in this record.
202 return self.fields.keys()
205 # Given a field name ("hrn", "gid", ...) return the value of that field.
207 # @param fieldname is the name of field to be returned
209 def get_field_value_string(self, fieldname):
211 Given a field name ("hrn", "gid", ...) return the value of that field.
213 if fieldname == "authority":
214 val = get_authority(self['hrn'])
217 val = getattr(self, fieldname)
219 val = self[fieldname]
220 if isinstance(val, str):
221 return "'" + str(val) + "'"
226 # Given a list of field names, return a list of values for those public.
228 # @param fieldnames is a list of field names
230 def get_field_value_strings(self, fieldnames):
232 Given a list of field names, return a list of values for those public.
234 return [ self.get_field_value_string (fieldname) for fieldname in fieldnames ]
237 # Return the record in the form of a dictionary
241 Return the record in the form of a dictionary
246 # Load the record from a dictionary
248 # @param dict dictionary to load record public from
250 def load_from_dict(self, dict):
252 Load the record from a dictionary
254 self.set_name(dict['hrn'])
255 gidstr = dict.get("gid", None)
257 self.set_gid(dict['gid'])
259 if "pointer" in dict:
260 self.set_pointer(dict['pointer'])
262 self.set_type(dict['type'])
266 # Save the record to a string. The string contains an XML representation of
269 def save_to_string(self):
271 Save the record to a string. The string contains an XML representation of
274 recorddict = self.as_dict()
275 filteredDict = dict([(key, val) for (key, val) in recorddict.iteritems() if key in self.fields.keys()])
276 record = RecordSpec()
277 record.parseDict(filteredDict)
279 #str = xmlrpclib.dumps((dict,), allow_none=True)
283 # Load the record from a string. The string is assumed to contain an XML
284 # representation of the record.
286 def load_from_string(self, str):
288 Load the record from a string. The string is assumed to contain an XML
289 representation of the record.
291 #dict = xmlrpclib.loads(str)[0][0]
293 record = RecordSpec()
294 record.parseString(str)
295 record_dict = record.toDict()
296 geni_dict = record_dict['record']
297 self.load_from_dict(geni_dict)
300 # Dump the record to stdout
302 # @param dump_parents if true, then the parents of the GID will be dumped
304 def dump(self, dump_parents=False):
306 Walk tree and dump records.
308 #print "RECORD", self.name
309 #print " hrn:", self.name
310 #print " type:", self.type
315 # self.get_gid_object().dump(8, dump_parents)
316 #print " pointer:", self.pointer
318 order = GeniRecord.fields.keys()
319 for key in self.keys():
323 if key in self and key in self.fields:
324 if key in 'gid' and self[key]:
325 gid = GID(string=self[key])
327 gid.dump(8, dump_parents)
329 print " %s: %s" % (key, self[key])
335 class UserRecord(GeniRecord):
338 'email': Parameter(str, 'email'),
339 'first_name': Parameter(str, 'First name'),
340 'last_name': Parameter(str, 'Last name'),
341 'phone': Parameter(str, 'Phone Number'),
342 'key': Parameter(str, 'Public key'),
343 'slices': Parameter([str], 'List of slices this user belongs to'),
345 fields.update(GeniRecord.fields)
347 class SliceRecord(GeniRecord):
349 'name': Parameter(str, 'Slice name'),
350 'url': Parameter(str, 'Slice url'),
351 'expires': Parameter(int, 'Date and time this slice exipres'),
352 'researcher': Parameter([str], 'List of users for this slice'),
353 'description': Parameter([str], 'Description of this slice'),
355 fields.update(GeniRecord.fields)
358 class NodeRecord(GeniRecord):
360 'hostname': Parameter(str, 'This nodes dns name'),
361 'node_type': Parameter(str, 'Type of node this is'),
362 'node_type': Parameter(str, 'Type of node this is'),
363 'latitude': Parameter(str, 'latitude'),
364 'longitude': Parameter(str, 'longitude'),
366 fields.update(GeniRecord.fields)
369 class AuthorityRecord(GeniRecord):
371 'name': Parameter(str, 'Name'),
372 'login_base': Parameter(str, 'login base'),
373 'enabled': Parameter(bool, 'Is this site enabled'),
374 'url': Parameter(str, 'URL'),
375 'nodes': Parameter([str], 'List of nodes at this site'),
376 'operator': Parameter([str], 'List of operators'),
377 'researcher': Parameter([str], 'List of researchers'),
378 'PI': Parameter([str], 'List of Principal Investigators'),
380 fields.update(GeniRecord.fields)