1# _entity.py
2#
3# openipmi GUI handling for entities
4#
5# Author: MontaVista Software, Inc.
6#         Corey Minyard <minyard@mvista.com>
7#         source@mvista.com
8#
9# Copyright 2005 MontaVista Software Inc.
10#
11#  This program is free software; you can redistribute it and/or
12#  modify it under the terms of the GNU Lesser General Public License
13#  as published by the Free Software Foundation; either version 2 of
14#  the License, or (at your option) any later version.
15#
16#
17#  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
18#  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19#  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20#  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21#  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22#  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23#  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24#  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
25#  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
26#  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27#
28#  You should have received a copy of the GNU Lesser General Public
29#  License along with this program; if not, write to the Free
30#  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31#
32
33import OpenIPMI
34from openipmigui import _oi_logging
35from openipmigui import _sensor
36from openipmigui import _control
37from openipmigui import _fru
38from openipmigui import gui_popup
39from openipmigui import gui_setdialog
40
41class EntityOp:
42    def __init__(self, e, func):
43        self.e = e
44        self.func = func
45        return
46
47    def DoOp(self):
48        rv = self.e.entity_id.to_entity(self)
49        if (rv == 0):
50            rv = self.rv
51            pass
52        return rv;
53
54    def entity_cb(self, entity):
55        self.rv = getattr(entity, self.func)(self.e)
56        return
57
58    pass
59
60class EntityFruViewer:
61    def __init__(self, e):
62        self.e = e
63        self.e.entity_id.to_entity(self)
64        return
65
66    def entity_cb(self, entity):
67        fru = entity.get_fru()
68        if (fru == None):
69            return
70        _fru.FruInfoDisplay(fru, str(self.e))
71        return
72
73    pass
74
75class ActivationTimeSetter:
76    def __init__(self, e, name, func):
77        self.e = e
78        self.name = name
79        self.func = func
80
81        self.err = 0
82        rv = e.entity_id.to_entity(self)
83        if (rv == 0):
84            rv = self.err
85            pass
86        if (rv):
87            _oi_logging.error("Error doing entity cb in activation time setter: "
88                          + str(rv))
89            pass
90
91        return
92
93    def ok(self, val):
94        self.acttime = int(val)
95        rv = self.e.entity_id.to_entity(self)
96        if (rv == 0):
97            rv = self.err
98            pass
99        if (rv != 0):
100            return ("Error setting activation time: "
101                    + OpenIPMI.get_error_string(rv))
102        return
103
104    def entity_cb(self, entity):
105        if (self.setting):
106            self.err = getattr(entity, 'set_' + self.func)(None)
107        else:
108            self.err = getattr(entity, 'get_' + self.func)(self)
109            pass
110        return
111
112    def entity_hot_swap_get_time_cb(self, entity, err, time):
113        if (err):
114            _oi_logging.error("Error getting activation time: " + str(err))
115            return
116        gui_setdialog.SetDialog("Set " + self.name + " for " + str(self.e),
117                                [ time ],
118                                1,
119                                self)
120        return
121
122    pass
123
124class Entity:
125    def __init__(self, d, entity):
126        self.d = d
127        self.ui = d.ui
128        self.name = entity.get_name()
129        self.entity_id = entity.get_id()
130        self.entity_id_str = entity.get_entity_id_string()
131        self.sensors = { }
132        self.controls = { }
133        self.children = { }
134        entity.add_presence_handler(self)
135        entity.add_hot_swap_handler(self)
136        entity.add_sensor_update_handler(self)
137        entity.add_control_update_handler(self)
138
139        d.entities[self.name] = self
140
141        self.destroyed = False
142
143        # Find my parent and put myself in that hierarchy
144        self.parent_id = None
145        self.parent = None
146        self.eeop = "fparent"
147        entity.iterate_parents(self)
148        self.ui.add_entity(self.d, self, parent=self.parent)
149        if (self.parent != None):
150            self.parent.children[self.name] = self.name
151            self.parent_name = self.parent.name
152            pass
153        else:
154            self.parent_name = None
155            pass
156        self.parent = None # Don't leave circular reference
157
158        self.hot_swap = 'No'
159        self.hot_swap_state = ''
160        self.create_my_items()
161
162        self.Changed(entity)
163        return
164
165    def create_my_items(self):
166        self.ui.append_item(self, 'Entity ID', self.entity_id_str)
167        self.typeitem = self.ui.append_item(self, 'Type', None)
168        self.idstringitem = self.ui.append_item(self, 'ID String', None)
169        self.psatitem = self.ui.append_item(self,
170                                            'Presence Sensor Always There',
171                                            None)
172        self.slotnumitem = self.ui.append_item(self, 'Slot Number', None)
173        self.mcitem = self.ui.append_item(self, 'MC', None)
174        self.hotswapitem = self.ui.append_item(self, 'Hot Swap', self.hot_swap)
175        return
176
177    def __str__(self):
178        return self.name
179
180    def HandleMenu(self, event):
181        if (self.impt_data == None):
182            menul = [ [ "Add to watch values", self.add_impt ] ]
183            pass
184        else:
185            menul = [ [ "Remove from watch values", self.remove_impt ] ]
186            pass
187        if (self.is_fru):
188            menul.append(["View FRU Data", self.ViewFruData])
189            pass
190
191        if (self.hot_swap == "Managed"):
192            menul.append(["Request Activation", self.RequestActivation])
193            menul.append(["Activate", self.Activate])
194            menul.append(["Deactivate", self.Deactivate])
195            if (self.supports_auto_activate):
196                menul.append(["Set Auto-activate Time", self.SetAutoActTime])
197                pass
198            if (self.supports_auto_deactivate):
199                menul.append(["Set Auto-deactivate Time",
200                              self.SetAutoDeactTime])
201                pass
202            pass
203
204        if (len(menul) > 0):
205            gui_popup.popup(self.d.ui, event, menul)
206            pass
207        return
208
209    def add_impt(self, event):
210        self.ui.add_impt_data("entity", str(self), self)
211        return
212
213    def remove_impt(self, event):
214        self.ui.remove_impt_data(self.impt_data)
215        return
216
217    def RequestActivation(self, event):
218        oper = EntityOp(self, "set_activation_requested")
219        rv = oper.DoOp()
220        if (rv != 0):
221            _oi_logging.error("entity set activation failed: " + str(rv))
222            pass
223        return
224
225    def Activate(self, event):
226        oper = EntityOp(self, "activate")
227        rv = oper.DoOp()
228        if (rv != 0):
229            _oi_logging.error("entity activation failed: " + str(rv))
230            pass
231        return
232
233    def Deactivate(self, event):
234        oper = EntityOp(self, "deactivate")
235        rv = oper.DoOp()
236        if (rv != 0):
237            _oi_logging.error("entity deactivation failed: " + str(rv))
238            pass
239        return
240
241    def SetAutoActTime(self, event):
242        ActivationTimeSetter(self, "Activation Time", "auto_activate_time")
243        return
244
245    def SetAutoDeactTime(self, event):
246        ActivationTimeSetter(self, "Deactivation Time", "auto_deactivate_time")
247        return
248
249    def ViewFruData(self, event):
250        EntityFruViewer(self)
251        return
252
253    def entity_activate_cb(self, entity, err):
254        if (err != 0):
255            _oi_logging.error("entity activate operation failed: " + str(err))
256            pass
257        return
258
259    def Changed(self, entity):
260        # Reparent first, in case parent has changed.
261        old_parent_id = self.parent_id
262        reparent = False
263        self.parent_id = None
264        self.parent = None
265        self.eeop = "fparent"
266        entity.iterate_parents(self)
267        if (self.parent_id != None):
268            if (old_parent_id == None):
269                reparent = True
270                pass
271            elif (self.parent_id.cmp(old_parent_id) != 0):
272                reparent = True
273                pass
274            pass
275        else:
276            if (old_parent_id != None):
277                reparent = True
278                pass
279            pass
280
281        if (reparent):
282            old_treeroot = self.treeroot
283            self.eop = "deleted"
284            entity.iterate_sensors(self)
285            entity.iterate_controls(self)
286
287            if (self.parent_name):
288                oparent = self.d.find_entity_byname(self.parent_name)
289                if (oparent):
290                    del oparent.children[self.name]
291                pass
292            self.ui.reparent_entity(self.d, self, self.parent)
293            if (self.parent != None):
294                self.parent.children[self.name] = self.name
295                self.parent_name = self.parent.name
296                pass
297            else:
298                self.parent_name = None
299                pass
300            self.create_my_items()
301
302            # Reparent children
303            self.eeop = "repch"
304            entity.iterate_children(self);
305
306            self.eop = "added"
307            entity.iterate_sensors(self)
308            entity.iterate_controls(self)
309
310            if (entity.is_present()):
311                self.ui.set_item_active(self.treeroot);
312                pass
313            else:
314                self.ui.set_item_inactive(self.treeroot);
315                pass
316
317            self.eop = None
318            self.ui.remove_entity(old_treeroot)
319            pass
320
321        self.parent = None # Kill circular reference
322
323
324        self.is_fru = entity.is_fru()
325
326        self.id_str = entity.get_id_string()
327        eid = self.id_str
328        if (eid == None):
329            eid = self.entity_id_str
330            pass
331        if (eid != None):
332            self.ui.set_item_text(self.treeroot, eid)
333            pass
334
335        self.entity_type = entity.get_type()
336        self.slot_number = entity.get_physical_slot_num()
337        if (self.slot_number < 0):
338            self.slot_number = None
339            pass
340
341        self.mc_id = entity.get_mc_id()
342        self.mc_name = None
343        if (self.mc_id != None):
344            self.mc_id.to_mc(self);
345            pass
346
347        if entity.is_hot_swappable():
348            if entity.supports_managed_hot_swap():
349                hot_swap = "Managed"
350            else:
351                hot_swap = "Simple"
352                pass
353        else:
354            hot_swap = "No"
355            pass
356        if (hot_swap != self.hot_swap):
357            self.hot_swap = hot_swap
358            if (hot_swap != "No"):
359                entity.get_hot_swap_state(self)
360            else:
361                self.hot_swap_state = ''
362                pass
363            pass
364
365        self.supports_auto_activate = entity.supports_auto_activate_time()
366        self.supports_auto_deactivate = entity.supports_auto_deactivate_time()
367
368        # Fill in the various value in the GUI
369        self.ui.set_item_text(self.typeitem, self.entity_type)
370        self.ui.set_item_text(self.idstringitem, self.id_str)
371        self.ui.set_item_text(self.psatitem,
372                           str(entity.get_presence_sensor_always_there() != 0))
373        if (self.slot_number != None):
374            self.ui.set_item_text(self.slotnumitem, str(self.slot_number))
375            pass
376        self.ui.set_item_text(self.mcitem, self.mc_name)
377        self.ui.set_item_text(self.hotswapitem,
378                              self.hot_swap + ' ' + self.hot_swap_state)
379        return
380
381    def entity_hot_swap_update_cb(self, entity, old_state, new_state, event):
382        if (self.destroyed):
383            return
384        self.hot_swap_state = new_state
385        self.ui.set_item_text(self.hotswapitem,
386                              self.hot_swap + ' ' + self.hot_swap_state)
387        return OpenIPMI.EVENT_NOT_HANDLED
388
389    def entity_hot_swap_cb(self, entity, err, state):
390        if (self.destroyed):
391            return
392        if (err):
393            _oi_logging.error("Error getting entity hot-swap state: " + str(err))
394            return
395        self.hot_swap_state = state
396        self.ui.set_item_text(self.hotswapitem,
397                              self.hot_swap + ' ' + self.hot_swap_state)
398        return
399
400    def mc_cb(self, mc):
401        self.mc_name = mc.get_name()
402        return
403
404    def entity_iter_entities_cb(self, e1, e2):
405        if (self.eeop == "fparent"):
406            self.parent_id = e2.get_id()
407            self.parent = self.d.find_or_create_entity(e2)
408            pass
409        elif (self.eeop == "repch"):
410            ch_e = self.d.find_entity_byname(e2.get_name())
411            if (ch_e):
412                ch_e.parent_id = None
413                ch_e.Changed(e2)
414                pass
415            pass
416        return
417
418    def entity_iter_sensors_cb(self, entity, sensor):
419        self.entity_sensor_update_cb(self.eop, entity, sensor)
420        return
421
422    def entity_iter_controls_cb(self, entity, control):
423        self.entity_control_update_cb(self.eop, entity, control)
424        return
425
426    def remove(self):
427        self.d.entities.pop(self.name)
428        self.ui.remove_entity(self)
429        self.destroyed = True
430        self.d = None
431        self.ui = None
432        return
433
434    def entity_sensor_update_cb(self, op, entity, sensor):
435        if (self.destroyed):
436            return
437        if (op == "added"):
438            if (sensor.get_name() not in self.sensors):
439                e = _sensor.Sensor(self, sensor)
440                pass
441            pass
442        elif (op == "deleted"):
443            if (sensor.get_name() in self.sensors):
444                self.sensors[sensor.get_name()].remove()
445                pass
446            pass
447        return
448
449    def entity_control_update_cb(self, op, entity, control):
450        if (self.destroyed):
451            return
452        if (op == "added"):
453            if (control.get_name() not in self.controls):
454                e = _control.Control(self, control)
455                pass
456            pass
457        elif (op == "deleted"):
458            if (control.get_name() in self.controls):
459                self.controls[control.get_name()].remove()
460                pass
461            pass
462        return
463
464    def entity_presence_cb(self, entity, present, event):
465        if (self.destroyed):
466            return
467        if (present):
468            self.ui.set_item_active(self.treeroot)
469        else:
470            self.ui.set_item_inactive(self.treeroot)
471            pass
472        return
473
474    def entity_fru_update_werr_cb(self, op, err, entity, fru):
475        if (self.destroyed):
476            return
477        if (op == "error"):
478            _oi_logging.error("Error getting entity fru: " + str(err))
479        return
480
481    pass
482