2 # Implements support for geni records
4 # TODO: Use existing PLC database methods? or keep this separate?
8 from types import StringTypes
10 from geni.util.rspec import *
15 The GeniRecord class implements a Geni Record. A GeniRecord is a tuple
16 (Name, GID, Type, Info).
18 Name specifies the HRN of the object
19 GID is the GID of the object
20 Type is user | sa | ma | slice | component
22 Info is comprised of the following sub-fields
23 pointer = a pointer to the record in the PL database
24 pl_info = planetlab-specific info (when talking to client)
25 geni_info = geni-specific info (when talking to client)
27 The pointer is interpreted depending on the type of the record. For example,
28 if the type=="user", then pointer is assumed to be a person_id that indexes
29 into the persons table.
31 A given HRN may have more than one record, provided that the records are
32 of different types. For example, planetlab.us.arizona may have both an SA
33 and a MA record, but cannot have two SA records.
37 # Create a Geni Record
39 # @param name if !=None, assign the name of the record
40 # @param gid if !=None, assign the gid of the record
41 # @param type one of user | sa | ma | slice | component
42 # @param pointer is a pointer to a PLC record
43 # @param dict if !=None, then fill in this record from the dictionary
45 def __init__(self, name=None, gid=None, type=None, pointer=None, dict=None, string=None):
60 self.set_pointer(pointer)
62 self.load_from_dict(dict)
64 self.load_from_string(string)
67 # Set the name of the record
69 # @param name is a string containing the HRN
71 def set_name(self, name):
73 Set the name of the record
79 # Set the GID of the record
81 # @param gid is a GID object or the string representation of a GID object
83 def set_gid(self, gid):
85 Set the GID of the record
88 if isinstance(gid, StringTypes):
91 self.gid = gid.save_to_string(save_parents=True)
95 # Set the type of the record
97 # @param type is a string: user | sa | ma | slice | component
99 def set_type(self, type):
101 Set the type of the record
107 # Set the pointer of the record
109 # @param pointer is an integer containing the ID of a PLC record
111 def set_pointer(self, pointer):
113 Set the pointer of the record
115 self.pointer = pointer
119 # Set the PLC info of the record
121 # @param pl_info is a dictionary containing planetlab info
123 def set_pl_info(self, pl_info):
125 Set the PLC info of the record
127 if isinstance(pl_info, list):
130 # Convert any boolean strings to real bools
132 if isinstance(pl_info[key], StringTypes):
133 if pl_info[key].lower() in ["true"]:
135 elif pl_info[key].lower() in ["false"]:
137 self.pl_info = pl_info
141 # Set the geni info the record
143 # @param geni_info is a dictionary containing geni info
145 def set_geni_info(self, geni_info):
147 Set the geni info the record
149 if isinstance(geni_info, list):
150 geni_info = geni_info[0]
151 self.geni_info = geni_info
155 # Return the pl_info of the record, or an empty dictionary if none exists
157 def get_pl_info(self):
159 Return the pl_info of the record, or an empty dictionary if none exists
167 # Return the geni_info of the record, or an empty dictionary if none exists
169 def get_geni_info(self):
171 Return the geni_info of the record, or an empty dictionary if none exists
174 return self.geni_info
179 # Return the name (HRN) of the record
183 Return the name (HRN) of the record
188 # Return the type of the record
192 Return the type of the record
197 # Return the pointer of the record. The pointer is an integer that may be
198 # used to look up the record in the PLC database. The evaluation of pointer
199 # depends on the type of the record
201 def get_pointer(self):
203 Return the pointer of the record. The pointer is an integer that may be
204 used to look up the record in the PLC database. The evaluation of pointer
205 depends on the type of the record
210 # Return the GID of the record, in the form of a GID object
211 # TODO: not the best name for the function, because we have things called
212 # gidObjects in the Cred
214 def get_gid_object(self):
216 Return the GID of the record, in the form of a GID object
218 return GID(string=self.gid)
221 # Return a key that uniquely identifies this record among all records in
222 # Geni. This key is used to uniquely identify the record in the Geni
227 Return a key that uniquely identifies this record among all records in
228 Geni. This key is used to uniquely identify the record in the Geni
231 return self.name + "#" + self.type
234 # Returns a list of field names in this record. pl_info, geni_info are not
235 # included because they are not part of the record that is stored in the
236 # database, but are rather computed values from other entities
238 def get_field_names(self):
240 Returns a list of field names in this record. pl_info, geni_info are not
241 included because they are not part of the record that is stored in the
242 database, but are rather computed values from other entities
244 return ["name", "gid", "type", "pointer"]
247 # Given a field name ("name", "gid", ...) return the value of that field.
249 # @param name is the name of field to be returned
251 def get_field_value_string(self, fieldname):
253 Given a field name ("name", "gid", ...) return the value of that field.
255 if fieldname == "key":
258 val = getattr(self, fieldname)
259 if isinstance(val, str):
260 return "'" + str(val) + "'"
265 # Given a list of field names, return a list of values for those fields.
267 # @param fieldnames is a list of field names
269 def get_field_value_strings(self, fieldnames):
271 Given a list of field names, return a list of values for those fields.
274 for fieldname in fieldnames:
275 strs.append(self.get_field_value_string(fieldname))
279 # Return the record in the form of a dictionary
283 Return the record in the form of a dictionary
286 names = self.get_field_names()
288 dict[name] = getattr(self, name)
291 dict['pl_info'] = self.pl_info
294 dict['geni_info'] = self.geni_info
299 # Load the record from a dictionary
301 # @param dict dictionary to load record fields from
303 def load_from_dict(self, dict):
305 Load the record from a dictionary
307 self.set_name(dict['name'])
308 gidstr = dict.get("gid", None)
310 self.set_gid(dict['gid'])
312 self.set_type(dict['type'])
313 self.set_pointer(dict['pointer'])
314 if "pl_info" in dict and dict['pl_info']:
315 self.set_pl_info(dict["pl_info"])
316 if "geni_info" in dict and dict['geni_info']:
317 self.set_geni_info(dict["geni_info"])
320 # Save the record to a string. The string contains an XML representation of
323 def save_to_string(self):
325 Save the record to a string. The string contains an XML representation of
328 dict = self.as_dict()
329 record = RecordSpec()
330 record.parseDict(dict)
332 #str = xmlrpclib.dumps((dict,), allow_none=True)
336 # Load the record from a string. The string is assumed to contain an XML
337 # representation of the record.
339 def load_from_string(self, str):
341 Load the record from a string. The string is assumed to contain an XML
342 representation of the record.
344 #dict = xmlrpclib.loads(str)[0][0]
346 record = RecordSpec()
347 record.parseString(str)
348 record_dict = record.toDict()
349 geni_dict = record_dict['record']
350 self.load_from_dict(geni_dict)
353 # Dump the record to stdout
355 # @param dump_parents if true, then the parents of the GID will be dumped
357 def dump(self, dump_parents=False):
359 Walk tree and dump records.
361 print "RECORD", self.name
362 print " hrn:", self.name
363 print " type:", self.type
368 self.get_gid_object().dump(8, dump_parents)
369 print " pointer:", self.pointer
372 geni_info = getattr(self, "geni_info", {})
374 for key in geni_info.keys():
375 print " ", key, ":", geni_info[key]
378 pl_info = getattr(self, "pl_info", {})
381 for key in (s for s in pl_info.keys()\
382 if (s.endswith("_ids") or s.endswith("_id")) == False):
383 print " ", key, ":", pl_info[key]
387 info = {'hrn': self.name, 'type': self.type, 'gid': self.gid}
388 geni_info = getattr(self, "geni_info", {})
389 pl_info = getattr(self, "pl_info", {})
391 info.update(geni_info)