remove creategid from sfi; store gid creating info in record and silently create...
[sfa.git] / geni / util / record.py
1 ##
2 # Implements support for geni records
3 #
4 # TODO: Use existing PLC database methods? or keep this separate?
5 ##
6
7 import report
8 from gid import *
9
10 ##
11 # The GeniRecord class implements a Geni Record. A GeniRecord is a tuple
12 # (Name, GID, Type, Info).
13 #
14 # Name specifies the HRN of the object
15 # GID is the GID of the object
16 # Type is user | sa | ma | slice | component
17 #
18 # Info is comprised of the following sub-fields
19 #        pointer = a pointer to the record in the PL database
20 #        pl_info = planetlab-specific info (when talking to client)
21 #        geni_info = geni-specific info (when talking to client)
22 #
23 # The pointer is interpreted depending on the type of the record. For example,
24 # if the type=="user", then pointer is assumed to be a person_id that indexes
25 # into the persons table.
26 #
27 # A given HRN may have more than one record, provided that the records are
28 # of different types. For example, planetlab.us.arizona may have both an SA
29 # and a MA record, but cannot have two SA records.
30
31 class GeniRecord:
32
33     ##
34     # Create a Geni Record
35     #
36     # @param name if !=None, assign the name of the record
37     # @param gid if !=None, assign the gid of the record
38     # @param type one of user | sa | ma | slice | component
39     # @param pointer is a pointer to a PLC record
40     # @param dict if !=None, then fill in this record from the dictionary
41
42     def __init__(self, name=None, gid=None, type=None, pointer=None, dict=None, string=None):
43         self.dirty = True
44         self.pl_info = None
45         self.geni_info = None
46         self.name = None
47         self.gid = None
48         self.type = None
49         self.pointer = None
50         if name:
51             self.set_name(name)
52         if gid:
53             self.set_gid(gid)
54         if type:
55             self.set_type(type)
56         if pointer:
57             self.set_pointer(pointer)
58         if dict:
59             self.load_from_dict(dict)
60         if string:
61             self.load_from_string(string)
62
63     ##
64     # Set the name of the record
65     #
66     # @param name is a string containing the HRN
67
68     def set_name(self, name):
69         self.name = name
70         self.dirty = True
71
72     ##
73     # Set the GID of the record
74     #
75     # @param gid is a GID object or the string representation of a GID object
76
77     def set_gid(self, gid):
78         if isinstance(gid, str):
79             self.gid = gid
80         else:
81             self.gid = gid.save_to_string(save_parents=True)
82         self.dirty = True
83
84     ##
85     # Set the type of the record
86     #
87     # @param type is a string: user | sa | ma | slice | component
88
89     def set_type(self, type):
90         self.type = type
91         self.dirty = True
92
93     ##
94     # Set the pointer of the record
95     #
96     # @param pointer is an integer containing the ID of a PLC record
97
98     def set_pointer(self, pointer):
99         self.pointer = pointer
100         self.dirty = True
101
102     ##
103     # Set the PLC info of the record
104     #
105     # @param pl_info is a dictionary containing planetlab info
106
107     def set_pl_info(self, pl_info):
108         self.pl_info = pl_info
109         self.dirty = True
110
111     ##
112     # Set the geni info the record
113     #
114     # @param geni_info is a dictionary containing geni info
115
116     def set_geni_info(self, geni_info):
117         self.geni_info = geni_info
118         self.dirty = True
119
120     ##
121     # Return the pl_info of the record, or an empty dictionary if none exists
122
123     def get_pl_info(self):
124         if self.pl_info:
125             return self.pl_info
126         else:
127             return {}
128
129     ##
130     # Return the geni_info of the record, or an empty dictionary if none exists
131
132     def get_geni_info(self):
133         if self.geni_info:
134             return self.geni_info
135         else:
136             return {}
137
138     ##
139     # Return the name (HRN) of the record
140
141     def get_name(self):
142         return self.name
143
144     ##
145     # Return the type of the record
146
147     def get_type(self):
148         return self.type
149
150     ##
151     # Return the pointer of the record. The pointer is an integer that may be
152     # used to look up the record in the PLC database. The evaluation of pointer
153     # depends on the type of the record
154
155     def get_pointer(self):
156         return self.pointer
157
158     ##
159     # Return the GID of the record, in the form of a GID object
160     # TODO: not the best name for the function, because we have things called
161     # gidObjects in the Cred
162
163     def get_gid_object(self):
164         return GID(string=self.gid)
165
166     ##
167     # Return a key that uniquely identifies this record among all records in
168     # Geni. This key is used to uniquely identify the record in the Geni
169     # database.
170
171     def get_key(self):
172         return self.name + "#" + self.type
173
174     ##
175     # Returns a list of field names in this record. pl_info, geni_info are not
176     # included because they are not part of the record that is stored in the
177     # database, but are rather computed values from other entities
178
179     def get_field_names(self):
180         return ["name", "gid", "type", "pointer"]
181
182     ##
183     # Given a field name ("name", "gid", ...) return the value of that field.
184     #
185     # @param name is the name of field to be returned
186
187     def get_field_value_string(self, fieldname):
188         if fieldname == "key":
189             val = self.get_key()
190         else:
191             val = getattr(self, fieldname)
192         if isinstance(val, str):
193             return "'" + str(val) + "'"
194         else:
195             return str(val)
196
197     ##
198     # Given a list of field names, return a list of values for those fields.
199     #
200     # @param fieldnames is a list of field names
201
202     def get_field_value_strings(self, fieldnames):
203         strs = []
204         for fieldname in fieldnames:
205             strs.append(self.get_field_value_string(fieldname))
206         return strs
207
208     ##
209     # Return the record in the form of a dictionary
210
211     def as_dict(self):
212         dict = {}
213         names = self.get_field_names()
214         for name in names:
215             dict[name] = getattr(self, name)
216
217         if self.pl_info:
218             dict['pl_info'] = self.pl_info
219
220         if self.geni_info:
221             dict['geni_info'] = self.geni_info
222
223         return dict
224
225     ##
226     # Load the record from a dictionary
227     #
228     # @param dict dictionary to load record fields from
229
230     def load_from_dict(self, dict):
231         self.set_name(dict['name'])
232
233         gidstr = dict.get("gid", None)
234         if gidstr:
235             self.set_gid(dict['gid'])
236
237         self.set_type(dict['type'])
238         self.set_pointer(dict['pointer'])
239         if "pl_info" in dict:
240            self.set_pl_info(dict["pl_info"])
241         if "geni_info" in dict:
242            self.set_geni_info(dict["geni_info"])
243
244     ##
245     # Save the record to a string. The string contains an XML representation of
246     # the record.
247
248     def save_to_string(self):
249         dict = self.as_dict()
250         str = xmlrpclib.dumps((dict,), allow_none=True)
251         return str
252
253     ##
254     # Load the record from a string. The string is assumed to contain an XML
255     # representation of the record.
256
257     def load_from_string(self, str):
258         dict = xmlrpclib.loads(str)[0][0]
259         self.load_from_dict(dict)
260
261     ##
262     # Dump the record to stdout
263     #
264     # @param dump_parents if true, then the parents of the GID will be dumped
265
266     def dump(self, dump_parents=False):
267         print "RECORD", self.name
268         print "        hrn:", self.name
269         print "       type:", self.type
270         print "        gid:"
271         if (not self.gid):
272             print "        None"
273         else:
274             self.get_gid_object().dump(8, dump_parents)
275         print "    pointer:", self.pointer
276
277         print "  geni_info:"
278         geni_info = getattr(self, "geni_info", {})
279         if geni_info:
280             for key in geni_info.keys():
281                 print "       ", key, ":", geni_info[key]
282
283         print "    pl_info:"
284         pl_info = getattr(self, "pl_info", {})
285         if pl_info:
286
287             for key in pl_info.keys():
288                 print "       ", key, ":", pl_info[key]
289
290
291     def getdict(self):
292         info = {'hrn': self.name, 'type': self.type, 'gid': self.gid}
293         info.update(getattr(self, "geni_info", {}))
294         info.update(getattr(self, "pl_info", {}))
295         return info