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 *
18 class GeniRecord(dict):
20 The GeniRecord class implements a Geni Record. A GeniRecord is a tuple
21 (Hrn, GID, Type, Info).
23 Hrn specifies the Human Readable Name of the object
24 GID is the GID of the object
25 Type is user | authority | slice | component
27 Info is comprised of the following sub-fields
28 pointer = a pointer to the record in the PL database
30 The pointer is interpreted depending on the type of the record. For example,
31 if the type=="user", then pointer is assumed to be a person_id that indexes
32 into the persons table.
34 A given HRN may have more than one record, provided that the records are
38 ### the wsdl generator assumes this is named 'fields'
40 'hrn': Parameter(str, "Human readable name of object"),
41 'gid': Parameter(str, "GID of the object"),
42 'type': Parameter(str, "Record type"),
43 'last_updated': Parameter(int, 'Date and time of last update'),
44 'date_created': Parameter(int, 'Date and time this record was created'),
48 # Create a Geni Record
50 # @param name if !=None, assign the name of the record
51 # @param gid if !=None, assign the gid of the record
52 # @param type one of user | authority | slice | component
53 # @param pointer is a pointer to a PLC record
54 # @param dict if !=None, then fill in this record from the dictionary
56 def __init__(self, hrn=None, gid=None, type=None, pointer=None, dict=None, string=None):
69 self.set_pointer(pointer)
71 self.load_from_dict(dict)
73 self.load_from_string(string)
76 def update(self, new_dict):
77 if isinstance(new_dict, list):
78 new_dict = new_dict[0]
80 # Convert any boolean strings to real bools
82 if isinstance(new_dict[key], StringTypes):
83 if new_dict[key].lower() in ["true"]:
85 elif new_dict[key].lower() in ["false"]:
87 dict.update(self, new_dict)
90 # Set the name of the record
92 # @param hrn is a string containing the HRN
94 def set_name(self, hrn):
96 Set the name of the record
102 # Set the GID of the record
104 # @param gid is a GID object or the string representation of a GID object
106 def set_gid(self, gid):
108 Set the GID of the record
111 if isinstance(gid, StringTypes):
114 self.gid = gid.save_to_string(save_parents=True)
118 # Set the type of the record
120 # @param type is a string: user | authority | slice | component
122 def set_type(self, type):
124 Set the type of the record
130 # Set the pointer of the record
132 # @param pointer is an integer containing the ID of a PLC record
134 def set_pointer(self, pointer):
136 Set the pointer of the record
138 self.pointer = pointer
142 # Return the name (HRN) of the record
146 Return the name (HRN) of the record
151 # Return the type of the record
155 Return the type of the record
160 # Return the pointer of the record. The pointer is an integer that may be
161 # used to look up the record in the PLC database. The evaluation of pointer
162 # depends on the type of the record
164 def get_pointer(self):
166 Return the pointer of the record. The pointer is an integer that may be
167 used to look up the record in the PLC database. The evaluation of pointer
168 depends on the type of the record
173 # Return the GID of the record, in the form of a GID object
174 # TODO: not the best name for the function, because we have things called
175 # gidObjects in the Cred
177 def get_gid_object(self):
179 Return the GID of the record, in the form of a GID object
181 return GID(string=self.gid)
184 # Return a key that uniquely identifies this record among all records in
185 # Geni. This key is used to uniquely identify the record in the Geni
190 Return a key that uniquely identifies this record among all records in
191 Geni. This key is used to uniquely identify the record in the Geni
194 return self.hrn + "#" + self.type
197 # Returns a list of field names in this record.
199 def get_field_names(self):
201 Returns a list of field names in this record.
203 return self.fields.keys()
206 # Given a field name ("hrn", "gid", ...) return the value of that field.
208 # @param fieldname is the name of field to be returned
210 def get_field_value_string(self, fieldname):
212 Given a field name ("hrn", "gid", ...) return the value of that field.
214 if fieldname == "key":
217 val = getattr(self, fieldname)
218 if isinstance(val, str):
219 return "'" + str(val) + "'"
224 # Given a list of field names, return a list of values for those public.
226 # @param fieldnames is a list of field names
228 def get_field_value_strings(self, fieldnames):
230 Given a list of field names, return a list of values for those public.
232 return [ self.get_field_value_string (fieldname) for fieldname in fieldnames ]
235 # Return the record in the form of a dictionary
239 Return the record in the form of a dictionary
244 # Load the record from a dictionary
246 # @param dict dictionary to load record public from
248 def load_from_dict(self, dict):
250 Load the record from a dictionary
252 self.set_name(dict['hrn'])
253 gidstr = dict.get("gid", None)
255 self.set_gid(dict['gid'])
257 if "pointer" in dict:
258 self.set_pointer(dict['pointer'])
260 self.set_type(dict['type'])
264 # Save the record to a string. The string contains an XML representation of
267 def save_to_string(self):
269 Save the record to a string. The string contains an XML representation of
272 recorddict = self.as_dict()
273 filteredDict = dict([(key, val) for (key, val) in recorddict.iteritems() if key in self.fields.keys()])
274 record = RecordSpec()
275 record.parseDict(filteredDict)
277 #str = xmlrpclib.dumps((dict,), allow_none=True)
281 # Load the record from a string. The string is assumed to contain an XML
282 # representation of the record.
284 def load_from_string(self, str):
286 Load the record from a string. The string is assumed to contain an XML
287 representation of the record.
289 #dict = xmlrpclib.loads(str)[0][0]
291 record = RecordSpec()
292 record.parseString(str)
293 record_dict = record.toDict()
294 geni_dict = record_dict['record']
295 self.load_from_dict(geni_dict)
298 # Dump the record to stdout
300 # @param dump_parents if true, then the parents of the GID will be dumped
302 def dump(self, dump_parents=False):
304 Walk tree and dump records.
306 #print "RECORD", self.name
307 #print " hrn:", self.name
308 #print " type:", self.type
313 # self.get_gid_object().dump(8, dump_parents)
314 #print " pointer:", self.pointer
316 order = GeniRecord.fields.keys()
317 for key in self.keys():
321 if key in (self and self.fields):
322 if key in 'gid' and self[key]:
323 gid = GID(string=self[key])
325 gid.dump(8, dump_parents)
327 print " %s: %s" % (key, self[key])
333 class UserRecord(GeniRecord):
336 'email': Parameter(str, 'email'),
337 'first_name': Parameter(str, 'First name'),
338 'last_name': Parameter(str, 'Last name'),
339 'phone': Parameter(str, 'Phone Number'),
340 'key': Parameter(str, 'Public key'),
341 'slices': Parameter([str], 'List of slices this user belongs to'),
343 fields.update(GeniRecord.fields)
345 class SliceRecord(GeniRecord):
347 'name': Parameter(str, 'Slice name'),
348 'url': Parameter(str, 'Slice url'),
349 'expires': Parameter(int, 'Date and time this slice exipres'),
350 'researcher': Parameter([str], 'List of users for this slice'),
351 'description': Parameter([str], 'Description of this slice'),
353 fields.update(GeniRecord.fields)
356 class NodeRecord(GeniRecord):
358 'hostname': Parameter(str, 'This nodes dns name'),
359 'node_type': Parameter(str, 'Type of node this is'),
360 'node_type': Parameter(str, 'Type of node this is'),
361 'latitude': Parameter(str, 'latitude'),
362 'longitude': Parameter(str, 'longitude'),
364 fields.update(GeniRecord.fields)
367 class AuthorityRecord(GeniRecord):
369 'name': Parameter(str, 'Name'),
370 'login_base': Parameter(str, 'login base'),
371 'enabled': Parameter(bool, 'Is this site enabled'),
372 'url': Parameter(str, 'URL'),
373 'nodes': Parameter([str], 'List of nodes at this site'),
374 'operator': Parameter([str], 'List of operators'),
375 'researcher': Parameter([str], 'List of researchers'),
376 'PI': Parameter([str], 'List of Principal Investigators'),
378 fields.update(GeniRecord.fields)