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.
233 for fieldname in fieldnames:
234 strs.append(self.get_field_value_string(fieldname))
238 # Return the record in the form of a dictionary
242 Return the record in the form of a dictionary
247 # Load the record from a dictionary
249 # @param dict dictionary to load record public from
251 def load_from_dict(self, dict):
253 Load the record from a dictionary
255 self.set_name(dict['hrn'])
256 gidstr = dict.get("gid", None)
258 self.set_gid(dict['gid'])
260 if "pointer" in dict:
261 self.set_pointer(dict['pointer'])
263 self.set_type(dict['type'])
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.fields.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.fields.keys()
320 for key in self.keys():
324 if key in (self and self.fields):
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 fields.update(GeniRecord.fields)
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 fields.update(GeniRecord.fields)
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 fields.update(GeniRecord.fields)
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 fields.update(GeniRecord.fields)