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 (Name, GID, Type, Info).
23 Name specifies the HRN 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
39 'hrn': Parameter(str, "Human readable name of object"),
40 'gid': Parameter(str, "GID of the object"),
41 'type': Parameter(str, "Record type"),
42 #'last_updated': Parameter(int, 'Date and time of last update'),
43 #'date_created': Parameter(int, 'Date and time this record was created'),
47 # Create a Geni Record
49 # @param name if !=None, assign the name of the record
50 # @param gid if !=None, assign the gid of the record
51 # @param type one of user | authority | slice | component
52 # @param pointer is a pointer to a PLC record
53 # @param dict if !=None, then fill in this record from the dictionary
55 def __init__(self, name=None, gid=None, type=None, pointer=None, dict=None, string=None):
68 self.set_pointer(pointer)
70 self.load_from_dict(dict)
72 self.load_from_string(string)
75 def update(self, new_dict):
76 if isinstance(new_dict, list):
77 new_dict = new_dict[0]
79 # Convert any boolean strings to real bools
81 if isinstance(new_dict[key], StringTypes):
82 if new_dict[key].lower() in ["true"]:
84 elif new_dict[key].lower() in ["false"]:
86 dict.update(self, new_dict)
89 # Set the name of the record
91 # @param name is a string containing the HRN
93 def set_name(self, name):
95 Set the name of the record
101 # Set the GID of the record
103 # @param gid is a GID object or the string representation of a GID object
105 def set_gid(self, gid):
107 Set the GID of the record
110 if isinstance(gid, StringTypes):
113 self.gid = gid.save_to_string(save_parents=True)
117 # Set the type of the record
119 # @param type is a string: user | authority | slice | component
121 def set_type(self, type):
123 Set the type of the record
129 # Set the pointer of the record
131 # @param pointer is an integer containing the ID of a PLC record
133 def set_pointer(self, pointer):
135 Set the pointer of the record
137 self.pointer = pointer
141 # Return the name (HRN) of the record
145 Return the name (HRN) of the record
150 # Return the type of the record
154 Return the type of the record
159 # Return the pointer of the record. The pointer is an integer that may be
160 # used to look up the record in the PLC database. The evaluation of pointer
161 # depends on the type of the record
163 def get_pointer(self):
165 Return the pointer of the record. The pointer is an integer that may be
166 used to look up the record in the PLC database. The evaluation of pointer
167 depends on the type of the record
172 # Return the GID of the record, in the form of a GID object
173 # TODO: not the best name for the function, because we have things called
174 # gidObjects in the Cred
176 def get_gid_object(self):
178 Return the GID of the record, in the form of a GID object
180 return GID(string=self.gid)
183 # Return a key that uniquely identifies this record among all records in
184 # Geni. This key is used to uniquely identify the record in the Geni
189 Return a key that uniquely identifies this record among all records in
190 Geni. This key is used to uniquely identify the record in the Geni
193 return self.name + "#" + self.type
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 ["name", "gid", "type", "pointer"]
205 # Given a field name ("name", "gid", ...) return the value of that field.
207 # @param name is the name of field to be returned
209 def get_field_value_string(self, fieldname):
211 Given a field name ("name", "gid", ...) return the value of that field.
213 if fieldname == "key":
216 val = getattr(self, fieldname)
217 if isinstance(val, str):
218 return "'" + str(val) + "'"
223 # Given a list of field names, return a list of values for those public.
225 # @param fieldnames is a list of field names
227 def get_field_value_strings(self, fieldnames):
229 Given a list of field names, return a list of values for those public.
232 for fieldname in fieldnames:
233 strs.append(self.get_field_value_string(fieldname))
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['name'])
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'])
263 self['hrn'] = dict['hrn']
267 # Save the record to a string. The string contains an XML representation of
270 def save_to_string(self):
272 Save the record to a string. The string contains an XML representation of
275 recorddict = self.as_dict()
276 filteredDict = dict([(key, val) for (key, val) in recorddict.iteritems() if key in self.public.keys()])
277 record = RecordSpec()
278 record.parseDict(filteredDict)
280 #str = xmlrpclib.dumps((dict,), allow_none=True)
284 # Load the record from a string. The string is assumed to contain an XML
285 # representation of the record.
287 def load_from_string(self, str):
289 Load the record from a string. The string is assumed to contain an XML
290 representation of the record.
292 #dict = xmlrpclib.loads(str)[0][0]
294 record = RecordSpec()
295 record.parseString(str)
296 record_dict = record.toDict()
297 geni_dict = record_dict['record']
298 self.load_from_dict(geni_dict)
301 # Dump the record to stdout
303 # @param dump_parents if true, then the parents of the GID will be dumped
305 def dump(self, dump_parents=False):
307 Walk tree and dump records.
309 #print "RECORD", self.name
310 #print " hrn:", self.name
311 #print " type:", self.type
316 # self.get_gid_object().dump(8, dump_parents)
317 #print " pointer:", self.pointer
319 order = GeniRecord.public.keys()
320 for key in self.keys():
324 if key in (self and self.public):
325 if key in 'gid' and self[key]:
326 gid = GID(string=self[key])
328 gid.dump(8, dump_parents)
330 print " %s: %s" % (key, self[key])
336 class UserRecord(GeniRecord):
339 'email': Parameter(str, 'email'),
340 'first_name': Parameter(str, 'First name'),
341 'last_name': Parameter(str, 'Last name'),
342 'phone': Parameter(str, 'Phone Number'),
343 'key': Parameter(str, 'Public key'),
344 'slices': Parameter([str], 'List of slices this user belongs to'),
346 public.update(GeniRecord.public)
348 class SliceRecord(GeniRecord):
350 'name': Parameter(str, 'Slice name'),
351 'url': Parameter(str, 'Slice url'),
352 'expires': Parameter(int, 'Date and time this slice exipres'),
353 'researcher': Parameter([str], 'List of users for this slice'),
354 'description': Parameter([str], 'Description of this slice'),
356 public.update(GeniRecord.public)
359 class NodeRecord(GeniRecord):
361 'hostname': Parameter(str, 'This nodes dns name'),
362 'node_type': Parameter(str, 'Type of node this is'),
363 'node_type': Parameter(str, 'Type of node this is'),
364 'latitude': Parameter(str, 'latitude'),
365 'longitude': Parameter(str, 'longitude'),
367 public.update(GeniRecord.public)
370 class AuthorityRecord(GeniRecord):
372 'name': Parameter(str, 'Name'),
373 'login_base': Parameter(str, 'login base'),
374 'enabled': Parameter(bool, 'Is this site enabled'),
375 'url': Parameter(str, 'URL'),
376 'nodes': Parameter([str], 'List of nodes at this site'),
377 'operator': Parameter([str], 'List of operators'),
378 'researcher': Parameter([str], 'List of researchers'),
379 'PI': Parameter([str], 'List of Principal Investigators'),
381 public.update(GeniRecord.public)