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 *
12 # The GeniRecord class implements a Geni Record. A GeniRecord is a tuple
13 # (Name, GID, Type, Info).
15 # Name specifies the HRN of the object
16 # GID is the GID of the object
17 # Type is user | sa | ma | slice | component
19 # Info is comprised of the following sub-fields
20 # pointer = a pointer to the record in the PL database
21 # pl_info = planetlab-specific info (when talking to client)
22 # geni_info = geni-specific info (when talking to client)
24 # The pointer is interpreted depending on the type of the record. For example,
25 # if the type=="user", then pointer is assumed to be a person_id that indexes
26 # into the persons table.
28 # A given HRN may have more than one record, provided that the records are
29 # of different types. For example, planetlab.us.arizona may have both an SA
30 # and a MA record, but cannot have two SA records.
35 # Create a Geni Record
37 # @param name if !=None, assign the name of the record
38 # @param gid if !=None, assign the gid of the record
39 # @param type one of user | sa | ma | slice | component
40 # @param pointer is a pointer to a PLC record
41 # @param dict if !=None, then fill in this record from the dictionary
43 def __init__(self, name=None, gid=None, type=None, pointer=None, dict=None, string=None):
58 self.set_pointer(pointer)
60 self.load_from_dict(dict)
62 self.load_from_string(string)
65 # Set the name of the record
67 # @param name is a string containing the HRN
69 def set_name(self, name):
74 # Set the GID of the record
76 # @param gid is a GID object or the string representation of a GID object
78 def set_gid(self, gid):
79 if isinstance(gid, StringTypes):
82 self.gid = gid.save_to_string(save_parents=True)
86 # Set the type of the record
88 # @param type is a string: user | sa | ma | slice | component
90 def set_type(self, type):
95 # Set the pointer of the record
97 # @param pointer is an integer containing the ID of a PLC record
99 def set_pointer(self, pointer):
100 self.pointer = pointer
104 # Set the PLC info of the record
106 # @param pl_info is a dictionary containing planetlab info
108 def set_pl_info(self, pl_info):
109 if isinstance(pl_info, list):
112 # Convert any boolean strings to real bools
114 if isinstance(pl_info[key], StringTypes):
115 if pl_info[key].lower() in ["true"]:
117 elif pl_info[key].lower() in ["false"]:
119 self.pl_info = pl_info
123 # Set the geni info the record
125 # @param geni_info is a dictionary containing geni info
127 def set_geni_info(self, geni_info):
128 if isinstance(geni_info, list):
129 geni_info = geni_info[0]
130 self.geni_info = geni_info
134 # Return the pl_info of the record, or an empty dictionary if none exists
136 def get_pl_info(self):
143 # Return the geni_info of the record, or an empty dictionary if none exists
145 def get_geni_info(self):
147 return self.geni_info
152 # Return the name (HRN) of the record
158 # Return the type of the record
164 # Return the pointer of the record. The pointer is an integer that may be
165 # used to look up the record in the PLC database. The evaluation of pointer
166 # depends on the type of the record
168 def get_pointer(self):
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):
177 return GID(string=self.gid)
180 # Return a key that uniquely identifies this record among all records in
181 # Geni. This key is used to uniquely identify the record in the Geni
185 return self.name + "#" + self.type
188 # Returns a list of field names in this record. pl_info, geni_info are not
189 # included because they are not part of the record that is stored in the
190 # database, but are rather computed values from other entities
192 def get_field_names(self):
193 return ["name", "gid", "type", "pointer"]
196 # Given a field name ("name", "gid", ...) return the value of that field.
198 # @param name is the name of field to be returned
200 def get_field_value_string(self, fieldname):
201 if fieldname == "key":
204 val = getattr(self, fieldname)
205 if isinstance(val, str):
206 return "'" + str(val) + "'"
211 # Given a list of field names, return a list of values for those fields.
213 # @param fieldnames is a list of field names
215 def get_field_value_strings(self, fieldnames):
217 for fieldname in fieldnames:
218 strs.append(self.get_field_value_string(fieldname))
222 # Return the record in the form of a dictionary
226 names = self.get_field_names()
228 dict[name] = getattr(self, name)
231 dict['pl_info'] = self.pl_info
234 dict['geni_info'] = self.geni_info
239 # Load the record from a dictionary
241 # @param dict dictionary to load record fields from
243 def load_from_dict(self, dict):
244 self.set_name(dict['name'])
245 gidstr = dict.get("gid", None)
247 self.set_gid(dict['gid'])
249 self.set_type(dict['type'])
250 self.set_pointer(dict['pointer'])
251 if "pl_info" in dict and dict['pl_info']:
252 self.set_pl_info(dict["pl_info"])
253 if "geni_info" in dict and dict['geni_info']:
254 self.set_geni_info(dict["geni_info"])
257 # Save the record to a string. The string contains an XML representation of
260 def save_to_string(self):
262 dict = self.as_dict()
263 record = RecordSpec()
264 record.parseDict(dict)
266 #str = xmlrpclib.dumps((dict,), allow_none=True)
270 # Load the record from a string. The string is assumed to contain an XML
271 # representation of the record.
273 def load_from_string(self, str):
274 #dict = xmlrpclib.loads(str)[0][0]
276 record = RecordSpec()
277 record.parseString(str)
278 record_dict = record.toDict()
279 geni_dict = record_dict['record']
280 self.load_from_dict(geni_dict)
283 # Dump the record to stdout
285 # @param dump_parents if true, then the parents of the GID will be dumped
287 def dump(self, dump_parents=False):
288 print "RECORD", self.name
289 print " hrn:", self.name
290 print " type:", self.type
295 self.get_gid_object().dump(8, dump_parents)
296 print " pointer:", self.pointer
299 geni_info = getattr(self, "geni_info", {})
301 for key in geni_info.keys():
302 print " ", key, ":", geni_info[key]
305 pl_info = getattr(self, "pl_info", {})
308 for key in pl_info.keys():
309 print " ", key, ":", pl_info[key]
313 info = {'hrn': self.name, 'type': self.type, 'gid': self.gid}
314 geni_info = getattr(self, "geni_info", {})
315 pl_info = getattr(self, "pl_info", {})
317 info.update(geni_info)