removed another bunch of references to geni
[sfa.git] / sfa / util / record.py
1 ##
2 # Implements support for SFA records
3 #
4 # TODO: Use existing PLC database methods? or keep this separate?
5 ##
6
7 ### $Id$
8 ### $URL$
9
10 from types import StringTypes
11
12 from sfa.trust.gid import *
13
14 import sfa.util.report
15 from sfa.util.rspec import *
16 from sfa.util.parameter import *
17 from sfa.util.namespace import *
18 from sfa.util.row import Row
19
20 class SfaRecord(Row):
21     """ 
22     The SfaRecord class implements an SFA Record. A SfaRecord is a tuple
23     (Hrn, GID, Type, Info).
24  
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
28  
29     Info is comprised of the following sub-fields
30            pointer = a pointer to the record in the PL database
31  
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.
35  
36     A given HRN may have more than one record, provided that the records are
37     of different types.
38     """
39
40     table_name = 'sfa'
41     
42     primary_key = 'record_id'
43
44     ### the wsdl generator assumes this is named 'fields'
45     internal_fields = {
46         'record_id': Parameter(int, 'An id that uniquely identifies this record', ro=True),
47         'pointer': Parameter(int, 'An id that uniquely identifies this record in an external database ')
48     }
49
50     fields = {
51         'authority': Parameter(str, "The authority for this record"),
52         'peer_authority': Parameter(str, "The peer authority for this record"),
53         'hrn': Parameter(str, "Human readable name of object"),
54         'gid': Parameter(str, "GID of the object"),
55         'type': Parameter(str, "Record type"),
56         'last_updated': Parameter(int, 'Date and time of last update', ro=True),
57         'date_created': Parameter(int, 'Date and time this record was created', ro=True),
58     }
59     all_fields = dict(fields.items() + internal_fields.items())
60     ##
61     # Create an SFA Record
62     #
63     # @param name if !=None, assign the name of the record
64     # @param gid if !=None, assign the gid of the record
65     # @param type one of user | authority | slice | component
66     # @param pointer is a pointer to a PLC record
67     # @param dict if !=None, then fill in this record from the dictionary
68
69     def __init__(self, hrn=None, gid=None, type=None, pointer=None, peer_authority=None, dict=None, string=None):
70         self.dirty = True
71         self.hrn = None
72         self.gid = None
73         self.type = None
74         self.pointer = None
75         self.set_peer_auth(peer_authority)
76         if hrn:
77             self.set_name(hrn)
78         if gid:
79             self.set_gid(gid)
80         if type:
81             self.set_type(type)
82         if pointer:
83             self.set_pointer(pointer)
84         if dict:
85             self.load_from_dict(dict)
86         if string:
87             self.load_from_string(string)
88
89
90     def validate_last_updated(self, last_updated):
91         return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
92         
93     def update(self, new_dict):
94         if isinstance(new_dict, list):
95             new_dict = new_dict[0]
96
97         # Convert any boolean strings to real bools
98         for key in new_dict:
99             if isinstance(new_dict[key], StringTypes):
100                 if new_dict[key].lower() in ["true"]:
101                     new_dict[key] = True
102                 elif new_dict[key].lower() in ["false"]:
103                     new_dict[key] = False
104         dict.update(self, new_dict)
105
106     ##
107     # Set the name of the record
108     #
109     # @param hrn is a string containing the HRN
110
111     def set_name(self, hrn):
112         """
113         Set the name of the record
114         """
115         self.hrn = hrn
116         self['hrn'] = hrn
117         self.dirty = True
118
119     ##
120     # Set the GID of the record
121     #
122     # @param gid is a GID object or the string representation of a GID object
123
124     def set_gid(self, gid):
125         """
126         Set the GID of the record
127         """
128
129         if isinstance(gid, StringTypes):
130             self.gid = gid
131             self['gid'] = gid
132         else:
133             self.gid = gid.save_to_string(save_parents=True)
134             self['gid'] = gid.save_to_string(save_parents=True)
135         self.dirty = True
136
137     ##
138     # Set the type of the record
139     #
140     # @param type is a string: user | authority | slice | component
141
142     def set_type(self, type):
143         """
144         Set the type of the record
145         """
146         self.type = type
147         self['type'] = type
148         self.dirty = True
149
150     ##
151     # Set the pointer of the record
152     #
153     # @param pointer is an integer containing the ID of a PLC record
154
155     def set_pointer(self, pointer):
156         """
157         Set the pointer of the record
158         """
159         self.pointer = pointer
160         self['pointer'] = pointer
161         self.dirty = True
162
163
164     def set_peer_auth(self, peer_authority):
165         self.peer_authority = peer_authority
166         self['peer_authority'] = peer_authority
167         self.dirty = True
168
169     ##
170     # Return the name (HRN) of the record
171
172     def get_name(self):
173         """
174         Return the name (HRN) of the record
175         """
176         return self.hrn
177
178     ##
179     # Return the type of the record
180
181     def get_type(self):
182         """
183         Return the type of the record
184         """
185         return self.type
186
187     ##
188     # Return the pointer of the record. The pointer is an integer that may be
189     # used to look up the record in the PLC database. The evaluation of pointer
190     # depends on the type of the record
191
192     def get_pointer(self):
193         """
194         Return the pointer of the record. The pointer is an integer that may be
195         used to look up the record in the PLC database. The evaluation of pointer
196         depends on the type of the record
197         """
198         return self.pointer
199
200     ##
201     # Return the GID of the record, in the form of a GID object
202     # TODO: not the best name for the function, because we have things called
203     # gidObjects in the Cred
204
205     def get_gid_object(self):
206         """
207         Return the GID of the record, in the form of a GID object
208         """
209         return GID(string=self.gid)
210
211     ##
212     # Returns a list of field names in this record. 
213
214     def get_field_names(self):
215         """
216         Returns a list of field names in this record.
217         """
218         return self.fields.keys()
219
220     ##
221     # Given a field name ("hrn", "gid", ...) return the value of that field.
222     #
223     # @param fieldname is the name of field to be returned
224
225     def get_field_value_string(self, fieldname):
226         """
227         Given a field name ("hrn", "gid", ...) return the value of that field.
228         """
229         if fieldname == "authority":
230             val = get_authority(self['hrn'])
231         else:
232             try:
233                 val = getattr(self, fieldname)
234             except:
235                 val = self[fieldname] 
236         if isinstance(val, str):
237             return "'" + str(val) + "'"
238         else:
239             return str(val)
240
241     ##
242     # Given a list of field names, return a list of values for those public.
243     #
244     # @param fieldnames is a list of field names
245
246     def get_field_value_strings(self, fieldnames):
247         """
248         Given a list of field names, return a list of values for those public.
249         """
250         return [ self.get_field_value_string (fieldname) for fieldname in fieldnames ]
251
252     ##
253     # Return the record in the form of a dictionary
254
255     def as_dict(self):
256         """
257         Return the record in the form of a dictionary
258         """
259         return dict(self)
260
261     ##
262     # Load the record from a dictionary
263     #
264     # @param dict dictionary to load record public from
265
266     def load_from_dict(self, dict):
267         """
268         Load the record from a dictionary 
269         """
270         self.set_name(dict['hrn'])
271         gidstr = dict.get("gid", None)
272         if gidstr:
273             self.set_gid(dict['gid'])
274
275         if "pointer" in dict:
276            self.set_pointer(dict['pointer'])
277
278         self.set_type(dict['type'])
279         self.update(dict)        
280     
281     ##
282     # Save the record to a string. The string contains an XML representation of
283     # the record.
284
285     def save_to_string(self):
286         """
287         Save the record to a string. The string contains an XML representation of
288         the record.
289         """
290         recorddict = self.as_dict()
291         filteredDict = dict([(key, val) for (key, val) in recorddict.iteritems() if key in self.fields.keys()])
292         record = RecordSpec()
293         record.parseDict(filteredDict)
294         str = record.toxml()
295         #str = xmlrpclib.dumps((dict,), allow_none=True)
296         return str
297
298     ##
299     # Load the record from a string. The string is assumed to contain an XML
300     # representation of the record.
301
302     def load_from_string(self, str):
303         """
304         Load the record from a string. The string is assumed to contain an XML
305         representation of the record.
306         """
307         #dict = xmlrpclib.loads(str)[0][0]
308         
309         record = RecordSpec()
310         record.parseString(str)
311         record_dict = record.toDict()
312         sfa_dict = record_dict['record']
313         self.load_from_dict(sfa_dict)
314
315     ##
316     # Dump the record to stdout
317     #
318     # @param dump_parents if true, then the parents of the GID will be dumped
319
320     def dump(self, dump_parents=False):
321         """
322         Walk tree and dump records.
323         """
324         #print "RECORD", self.name
325         #print "        hrn:", self.name
326         #print "       type:", self.type
327         #print "        gid:"
328         #if (not self.gid):
329         #    print "        None"
330         #else:
331         #    self.get_gid_object().dump(8, dump_parents)
332         #print "    pointer:", self.pointer
333        
334         order = SfaRecord.fields.keys() 
335         for key in self.keys():
336             if key not in order:
337                 order.append(key)
338         for key in order:
339             if key in self and key in self.fields:
340                 if key in 'gid' and self[key]:
341                     gid = GID(string=self[key])
342                     print "     %s:" % key
343                     gid.dump(8, dump_parents)
344                 else:    
345                     print "     %s: %s" % (key, self[key])
346     
347     def getdict(self):
348         return dict(self)
349     
350
351 class UserRecord(SfaRecord):
352
353     fields = {
354         'email': Parameter(str, 'email'),
355         'first_name': Parameter(str, 'First name'),
356         'last_name': Parameter(str, 'Last name'),
357         'phone': Parameter(str, 'Phone Number'),
358         'key': Parameter(str, 'Public key'),
359         'slices': Parameter([str], 'List of slices this user belongs to'),
360         }
361     fields.update(SfaRecord.fields)
362     
363 class SliceRecord(SfaRecord):
364     fields = {
365         'name': Parameter(str, 'Slice name'),
366         'url': Parameter(str, 'Slice url'),
367         'expires': Parameter(int, 'Date and time this slice exipres'),
368         'researcher': Parameter([str], 'List of users for this slice'),
369         'description': Parameter([str], 'Description of this slice'), 
370         }
371     fields.update(SfaRecord.fields)
372
373  
374 class NodeRecord(SfaRecord):
375     fields = {
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'),
381         }
382     fields.update(SfaRecord.fields)
383
384
385 class AuthorityRecord(SfaRecord):
386     fields =  {
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'),
395         }
396     fields.update(SfaRecord.fields)
397     
398