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 *
11 from geni.util.parameter import *
13 class GeniRecord(dict):
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 | authority | slice | component
22 Info is comprised of the following sub-fields
23 pointer = a pointer to the record in the PL database
25 The pointer is interpreted depending on the type of the record. For example,
26 if the type=="user", then pointer is assumed to be a person_id that indexes
27 into the persons table.
29 A given HRN may have more than one record, provided that the records are
34 'hrn': Parameter(str, "Human readable name of object"),
35 'type': Parameter(str, "Record type"),
36 'gid': Parameter(str, "GID of the object")
40 'pointer': Parameter(int, "Internal ID")
44 # Create a Geni Record
46 # @param name if !=None, assign the name of the record
47 # @param gid if !=None, assign the gid of the record
48 # @param type one of user | authority | slice | component
49 # @param pointer is a pointer to a PLC record
50 # @param dict if !=None, then fill in this record from the dictionary
52 def __init__(self, name=None, gid=None, type=None, pointer=None, dict=None, string=None):
65 self.set_pointer(pointer)
67 self.load_from_dict(dict)
69 self.load_from_string(string)
72 def update(self, new_dict):
73 if isinstance(new_dict, list):
74 new_dict = new_dict[0]
76 # Convert any boolean strings to real bools
78 if isinstance(new_dict[key], StringTypes):
79 if new_dict[key].lower() in ["true"]:
81 elif new_dict[key].lower() in ["false"]:
83 dict.update(self, new_dict)
86 # Set the name of the record
88 # @param name is a string containing the HRN
90 def set_name(self, name):
92 Set the name of the record
98 # Set the GID of the record
100 # @param gid is a GID object or the string representation of a GID object
102 def set_gid(self, gid):
104 Set the GID of the record
107 if isinstance(gid, StringTypes):
110 self.gid = gid.save_to_string(save_parents=True)
114 # Set the type of the record
116 # @param type is a string: user | authority | slice | component
118 def set_type(self, type):
120 Set the type of the record
126 # Set the pointer of the record
128 # @param pointer is an integer containing the ID of a PLC record
130 def set_pointer(self, pointer):
132 Set the pointer of the record
134 self.pointer = pointer
138 # Return the name (HRN) of the record
142 Return the name (HRN) of the record
147 # Return the type of the record
151 Return the type of the record
156 # Return the pointer of the record. The pointer is an integer that may be
157 # used to look up the record in the PLC database. The evaluation of pointer
158 # depends on the type of the record
160 def get_pointer(self):
162 Return the pointer of the record. The pointer is an integer that may be
163 used to look up the record in the PLC database. The evaluation of pointer
164 depends on the type of the record
169 # Return the GID of the record, in the form of a GID object
170 # TODO: not the best name for the function, because we have things called
171 # gidObjects in the Cred
173 def get_gid_object(self):
175 Return the GID of the record, in the form of a GID object
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
186 Return a key that uniquely identifies this record among all records in
187 Geni. This key is used to uniquely identify the record in the Geni
190 return self.name + "#" + self.type
193 # Returns a list of field names in this record.
195 def get_field_names(self):
197 Returns a list of field names in this record.
199 return ["name", "gid", "type", "pointer"]
202 # Given a field name ("name", "gid", ...) return the value of that field.
204 # @param name is the name of field to be returned
206 def get_field_value_string(self, fieldname):
208 Given a field name ("name", "gid", ...) return the value of that field.
210 if fieldname == "key":
213 val = getattr(self, fieldname)
214 if isinstance(val, str):
215 return "'" + str(val) + "'"
220 # Given a list of field names, return a list of values for those fields.
222 # @param fieldnames is a list of field names
224 def get_field_value_strings(self, fieldnames):
226 Given a list of field names, return a list of values for those fields.
229 for fieldname in fieldnames:
230 strs.append(self.get_field_value_string(fieldname))
234 # Return the record in the form of a dictionary
238 Return the record in the form of a dictionary
243 # Load the record from a dictionary
245 # @param dict dictionary to load record fields from
247 def load_from_dict(self, dict):
249 Load the record from a dictionary
251 self.set_name(dict['name'])
252 gidstr = dict.get("gid", None)
254 self.set_gid(dict['gid'])
256 if "pointer" in dict:
257 self.set_pointer(dict['pointer'])
259 self.set_type(dict['type'])
260 self['hrn'] = dict['name']
264 # Save the record to a string. The string contains an XML representation of
267 def save_to_string(self):
269 Save the record to a string. The string contains an XML representation of
272 dict = self.as_dict()
273 record = RecordSpec()
274 record.parseDict(dict)
276 #str = xmlrpclib.dumps((dict,), allow_none=True)
280 # Load the record from a string. The string is assumed to contain an XML
281 # representation of the record.
283 def load_from_string(self, str):
285 Load the record from a string. The string is assumed to contain an XML
286 representation of the record.
288 #dict = xmlrpclib.loads(str)[0][0]
290 record = RecordSpec()
291 record.parseString(str)
292 record_dict = record.toDict()
293 geni_dict = record_dict['record']
294 self.load_from_dict(geni_dict)
297 # Dump the record to stdout
299 # @param dump_parents if true, then the parents of the GID will be dumped
301 def dump(self, dump_parents=False):
303 Walk tree and dump records.
305 #print "RECORD", self.name
306 #print " hrn:", self.name
307 #print " type:", self.type
312 # self.get_gid_object().dump(8, dump_parents)
313 #print " pointer:", self.pointer
315 order = GeniRecord.fields.keys()
316 for key in self.keys():
320 if key in (self and self.fields):
321 if key in 'gid' and self[key]:
322 gid = GID(string=self[key])
324 gid.dump(8, dump_parents)
326 print " %s: %s" % (key, self[key])
332 class UserRecord(GeniRecord):
335 'email': Parameter(str, 'email'),
336 'first_name': Parameter(str, 'First name'),
337 'last_name': Parameter(str, 'Last name'),
338 'title': Parameter(str, 'Title'),
339 'phone': Parameter(str, 'Phone Number'),
340 'sites': Parameter([str], 'List of sites this user belongs to'),
341 'slices': Parameter([str], 'List of slices this user belongs to'),
342 'keys': Parameter([str], 'Public keys'),
343 'enabled': Parameter(bool, 'Is this person enabled'),
344 'date_created': Parameter(int, 'Date and time this record was created'),
345 'last_updated': Parameter(int, 'Date and time of last update'),
347 fields.update(GeniRecord.fields)
350 'roles': Parameter([str], 'List of roles')
352 internal_fields.update(GeniRecord.internal_fields)
354 class SliceRecord(GeniRecord):
356 'name': Parameter(str, 'Slice name'),
357 'instantiation': Parameter(str, 'Slice instantiation'),
358 'url': Parameter(str, 'Slice url'),
359 'expires': Parameter(int, 'Date and time this slice exipres'),
360 'persons': Parameter([str], 'List of users for this slice'),
361 'description': Parameter([str], 'Description of this slice'),
362 'date_created': Parameter(int, 'Date and time this record was created'),
364 fields.update(GeniRecord.fields)
367 'nodes': Parameter([str], 'List of nodes this slice is instantiated on'),
368 'site': Parameter(str, 'Site this slice belongs to'),
369 'max_nodes': Parameter(int, 'Maximum number of nodes this slice is allowed on')
371 internal_fields.update(GeniRecord.internal_fields)
373 class NodeRecord(GeniRecord):
375 'slices': Parameter([str], 'List of instantiated slices on this node'),
376 'hostname': Parameter(str, 'This nodes dns name'),
377 'boot_state': Parameter(str, 'This nodes boot state'),
378 'node_type': Parameter(str, 'Type of node this is'),
379 'last_updated': Parameter(int, 'Date and time of last update'),
380 'slice_ids_whitelist': Parameter([str], 'List of allowed slices on this node'),
381 'date_created': Parameter(int, 'Date and time this node record was created'),
383 fields.update(GeniRecord.fields)
386 'site': Parameter(str, 'Site this node belongs to'),
387 'session': Parameter(str, 'This nodes session key'),
388 'ssh_rsa_key': Parameter(str, 'Last known ssh host key'),
389 'verified': Parameter(str, 'Whether the node configuration is verified correct'),
390 'last_contact': Parameter(int, 'Date and time this node last phoned home'),
391 'run_level': Parameter(str, 'Run level'),
392 'version': Parameter(str, 'Node software version'),
393 'key': Parameter(str, 'Node key'),
394 'boot_noonce': Parameter(str, 'Random value generate at nodes last boot'),
395 'model': Parameter(str, 'Model of node'),
396 'ports': Parameter([int], 'List of pcu ports this node is connected to')
398 internal_fields.update(GeniRecord.internal_fields)
400 class AuthorityRecord(GeniRecord):
402 'operators': Parameter([str], 'List of operators'),
403 'owners': Parameter([str], 'List of owners'),
404 'last_updated': Parameter(int, 'Date and time this record was last updated'),
405 'date_created': Parameter(int, 'Date and time this record was created'),
406 'name': Parameter(str, 'Name'),
407 'abbreviated_name': Parameter(str, 'Abbreviated name'),
408 'login_base': Parameter(str, 'login base'),
409 'enabled': Parameter(bool, 'Is this site enabled'),
410 'url': Parameter(str, 'URL'),
411 'slices': Parameter([str], 'List of slices instantiated by this site'),
412 'nodes': Parameter([str], 'List of nodes at this site'),
413 'latitude': Parameter(float, 'Decimal latitude of the site'),
414 'longitude': Parameter(float, 'Decimal longitude of the site'),
416 fields.update(GeniRecord.fields)
419 'max_slices': Parameter(int, 'Maximum number of slices this site can instantiate'),
420 'max_slivers': Parameter(int, 'Maximum number of slivers this site can instantiate'),
421 'pi': Parameter([str], 'List of pis'),
422 'is_public': Parameter(bool, 'Is this site public'),
425 internal_fields.update(GeniRecord.internal_fields)