xref: /OK3568_Linux_fs/yocto/poky/bitbake/lib/bb/event.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun"""
2*4882a593SmuzhiyunBitBake 'Event' implementation
3*4882a593Smuzhiyun
4*4882a593SmuzhiyunClasses and functions for manipulating 'events' in the
5*4882a593SmuzhiyunBitBake build tools.
6*4882a593Smuzhiyun"""
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun# Copyright (C) 2003, 2004  Chris Larson
9*4882a593Smuzhiyun#
10*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only
11*4882a593Smuzhiyun#
12*4882a593Smuzhiyun
13*4882a593Smuzhiyunimport ast
14*4882a593Smuzhiyunimport atexit
15*4882a593Smuzhiyunimport collections
16*4882a593Smuzhiyunimport logging
17*4882a593Smuzhiyunimport pickle
18*4882a593Smuzhiyunimport sys
19*4882a593Smuzhiyunimport threading
20*4882a593Smuzhiyunimport traceback
21*4882a593Smuzhiyun
22*4882a593Smuzhiyunimport bb.exceptions
23*4882a593Smuzhiyunimport bb.utils
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun# This is the pid for which we should generate the event. This is set when
26*4882a593Smuzhiyun# the runqueue forks off.
27*4882a593Smuzhiyunworker_pid = 0
28*4882a593Smuzhiyunworker_fire = None
29*4882a593Smuzhiyun
30*4882a593Smuzhiyunlogger = logging.getLogger('BitBake.Event')
31*4882a593Smuzhiyun
32*4882a593Smuzhiyunclass Event(object):
33*4882a593Smuzhiyun    """Base class for events"""
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun    def __init__(self):
36*4882a593Smuzhiyun        self.pid = worker_pid
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun
39*4882a593Smuzhiyunclass HeartbeatEvent(Event):
40*4882a593Smuzhiyun    """Triggered at regular time intervals of 10 seconds. Other events can fire much more often
41*4882a593Smuzhiyun       (runQueueTaskStarted when there are many short tasks) or not at all for long periods
42*4882a593Smuzhiyun       of time (again runQueueTaskStarted, when there is just one long-running task), so this
43*4882a593Smuzhiyun       event is more suitable for doing some task-independent work occasionally."""
44*4882a593Smuzhiyun    def __init__(self, time):
45*4882a593Smuzhiyun        Event.__init__(self)
46*4882a593Smuzhiyun        self.time = time
47*4882a593Smuzhiyun
48*4882a593SmuzhiyunRegistered        = 10
49*4882a593SmuzhiyunAlreadyRegistered = 14
50*4882a593Smuzhiyun
51*4882a593Smuzhiyundef get_class_handlers():
52*4882a593Smuzhiyun    return _handlers
53*4882a593Smuzhiyun
54*4882a593Smuzhiyundef set_class_handlers(h):
55*4882a593Smuzhiyun    global _handlers
56*4882a593Smuzhiyun    _handlers = h
57*4882a593Smuzhiyun
58*4882a593Smuzhiyundef clean_class_handlers():
59*4882a593Smuzhiyun    return collections.OrderedDict()
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun# Internal
62*4882a593Smuzhiyun_handlers = clean_class_handlers()
63*4882a593Smuzhiyun_ui_handlers = {}
64*4882a593Smuzhiyun_ui_logfilters = {}
65*4882a593Smuzhiyun_ui_handler_seq = 0
66*4882a593Smuzhiyun_event_handler_map = {}
67*4882a593Smuzhiyun_catchall_handlers = {}
68*4882a593Smuzhiyun_eventfilter = None
69*4882a593Smuzhiyun_uiready = False
70*4882a593Smuzhiyun_thread_lock = threading.Lock()
71*4882a593Smuzhiyun_thread_lock_enabled = False
72*4882a593Smuzhiyun
73*4882a593Smuzhiyunif hasattr(__builtins__, '__setitem__'):
74*4882a593Smuzhiyun    builtins = __builtins__
75*4882a593Smuzhiyunelse:
76*4882a593Smuzhiyun    builtins = __builtins__.__dict__
77*4882a593Smuzhiyun
78*4882a593Smuzhiyundef enable_threadlock():
79*4882a593Smuzhiyun    global _thread_lock_enabled
80*4882a593Smuzhiyun    _thread_lock_enabled = True
81*4882a593Smuzhiyun
82*4882a593Smuzhiyundef disable_threadlock():
83*4882a593Smuzhiyun    global _thread_lock_enabled
84*4882a593Smuzhiyun    _thread_lock_enabled = False
85*4882a593Smuzhiyun
86*4882a593Smuzhiyundef execute_handler(name, handler, event, d):
87*4882a593Smuzhiyun    event.data = d
88*4882a593Smuzhiyun    addedd = False
89*4882a593Smuzhiyun    if 'd' not in builtins:
90*4882a593Smuzhiyun        builtins['d'] = d
91*4882a593Smuzhiyun        addedd = True
92*4882a593Smuzhiyun    try:
93*4882a593Smuzhiyun        ret = handler(event)
94*4882a593Smuzhiyun    except (bb.parse.SkipRecipe, bb.BBHandledException):
95*4882a593Smuzhiyun        raise
96*4882a593Smuzhiyun    except Exception:
97*4882a593Smuzhiyun        etype, value, tb = sys.exc_info()
98*4882a593Smuzhiyun        logger.error("Execution of event handler '%s' failed" % name,
99*4882a593Smuzhiyun                        exc_info=(etype, value, tb.tb_next))
100*4882a593Smuzhiyun        raise
101*4882a593Smuzhiyun    except SystemExit as exc:
102*4882a593Smuzhiyun        if exc.code != 0:
103*4882a593Smuzhiyun            logger.error("Execution of event handler '%s' failed" % name)
104*4882a593Smuzhiyun        raise
105*4882a593Smuzhiyun    finally:
106*4882a593Smuzhiyun        del event.data
107*4882a593Smuzhiyun        if addedd:
108*4882a593Smuzhiyun            del builtins['d']
109*4882a593Smuzhiyun
110*4882a593Smuzhiyundef fire_class_handlers(event, d):
111*4882a593Smuzhiyun    if isinstance(event, logging.LogRecord):
112*4882a593Smuzhiyun        return
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun    eid = str(event.__class__)[8:-2]
115*4882a593Smuzhiyun    evt_hmap = _event_handler_map.get(eid, {})
116*4882a593Smuzhiyun    for name, handler in list(_handlers.items()):
117*4882a593Smuzhiyun        if name in _catchall_handlers or name in evt_hmap:
118*4882a593Smuzhiyun            if _eventfilter:
119*4882a593Smuzhiyun                if not _eventfilter(name, handler, event, d):
120*4882a593Smuzhiyun                    continue
121*4882a593Smuzhiyun            if d is not None and not name in (d.getVar("__BBHANDLERS_MC") or set()):
122*4882a593Smuzhiyun                continue
123*4882a593Smuzhiyun            execute_handler(name, handler, event, d)
124*4882a593Smuzhiyun
125*4882a593Smuzhiyunui_queue = []
126*4882a593Smuzhiyun@atexit.register
127*4882a593Smuzhiyundef print_ui_queue():
128*4882a593Smuzhiyun    global ui_queue
129*4882a593Smuzhiyun    """If we're exiting before a UI has been spawned, display any queued
130*4882a593Smuzhiyun    LogRecords to the console."""
131*4882a593Smuzhiyun    logger = logging.getLogger("BitBake")
132*4882a593Smuzhiyun    if not _uiready:
133*4882a593Smuzhiyun        from bb.msg import BBLogFormatter
134*4882a593Smuzhiyun        # Flush any existing buffered content
135*4882a593Smuzhiyun        try:
136*4882a593Smuzhiyun            sys.stdout.flush()
137*4882a593Smuzhiyun        except:
138*4882a593Smuzhiyun            pass
139*4882a593Smuzhiyun        try:
140*4882a593Smuzhiyun            sys.stderr.flush()
141*4882a593Smuzhiyun        except:
142*4882a593Smuzhiyun            pass
143*4882a593Smuzhiyun        stdout = logging.StreamHandler(sys.stdout)
144*4882a593Smuzhiyun        stderr = logging.StreamHandler(sys.stderr)
145*4882a593Smuzhiyun        formatter = BBLogFormatter("%(levelname)s: %(message)s")
146*4882a593Smuzhiyun        stdout.setFormatter(formatter)
147*4882a593Smuzhiyun        stderr.setFormatter(formatter)
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun        # First check to see if we have any proper messages
150*4882a593Smuzhiyun        msgprint = False
151*4882a593Smuzhiyun        msgerrs = False
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun        # Should we print to stderr?
154*4882a593Smuzhiyun        for event in ui_queue[:]:
155*4882a593Smuzhiyun            if isinstance(event, logging.LogRecord) and event.levelno >= logging.WARNING:
156*4882a593Smuzhiyun                msgerrs = True
157*4882a593Smuzhiyun                break
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun        if msgerrs:
160*4882a593Smuzhiyun            logger.addHandler(stderr)
161*4882a593Smuzhiyun        else:
162*4882a593Smuzhiyun            logger.addHandler(stdout)
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun        for event in ui_queue[:]:
165*4882a593Smuzhiyun            if isinstance(event, logging.LogRecord):
166*4882a593Smuzhiyun                if event.levelno > logging.DEBUG:
167*4882a593Smuzhiyun                    logger.handle(event)
168*4882a593Smuzhiyun                    msgprint = True
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun        # Nope, so just print all of the messages we have (including debug messages)
171*4882a593Smuzhiyun        if not msgprint:
172*4882a593Smuzhiyun            for event in ui_queue[:]:
173*4882a593Smuzhiyun                if isinstance(event, logging.LogRecord):
174*4882a593Smuzhiyun                    logger.handle(event)
175*4882a593Smuzhiyun        if msgerrs:
176*4882a593Smuzhiyun            logger.removeHandler(stderr)
177*4882a593Smuzhiyun        else:
178*4882a593Smuzhiyun            logger.removeHandler(stdout)
179*4882a593Smuzhiyun        ui_queue = []
180*4882a593Smuzhiyun
181*4882a593Smuzhiyundef fire_ui_handlers(event, d):
182*4882a593Smuzhiyun    global _thread_lock
183*4882a593Smuzhiyun    global _thread_lock_enabled
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun    if not _uiready:
186*4882a593Smuzhiyun        # No UI handlers registered yet, queue up the messages
187*4882a593Smuzhiyun        ui_queue.append(event)
188*4882a593Smuzhiyun        return
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun    if _thread_lock_enabled:
191*4882a593Smuzhiyun        _thread_lock.acquire()
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun    errors = []
194*4882a593Smuzhiyun    for h in _ui_handlers:
195*4882a593Smuzhiyun        #print "Sending event %s" % event
196*4882a593Smuzhiyun        try:
197*4882a593Smuzhiyun             if not _ui_logfilters[h].filter(event):
198*4882a593Smuzhiyun                 continue
199*4882a593Smuzhiyun             # We use pickle here since it better handles object instances
200*4882a593Smuzhiyun             # which xmlrpc's marshaller does not. Events *must* be serializable
201*4882a593Smuzhiyun             # by pickle.
202*4882a593Smuzhiyun             if hasattr(_ui_handlers[h].event, "sendpickle"):
203*4882a593Smuzhiyun                _ui_handlers[h].event.sendpickle((pickle.dumps(event)))
204*4882a593Smuzhiyun             else:
205*4882a593Smuzhiyun                _ui_handlers[h].event.send(event)
206*4882a593Smuzhiyun        except:
207*4882a593Smuzhiyun            errors.append(h)
208*4882a593Smuzhiyun    for h in errors:
209*4882a593Smuzhiyun        del _ui_handlers[h]
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun    if _thread_lock_enabled:
212*4882a593Smuzhiyun        _thread_lock.release()
213*4882a593Smuzhiyun
214*4882a593Smuzhiyundef fire(event, d):
215*4882a593Smuzhiyun    """Fire off an Event"""
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun    # We can fire class handlers in the worker process context and this is
218*4882a593Smuzhiyun    # desired so they get the task based datastore.
219*4882a593Smuzhiyun    # UI handlers need to be fired in the server context so we defer this. They
220*4882a593Smuzhiyun    # don't have a datastore so the datastore context isn't a problem.
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun    fire_class_handlers(event, d)
223*4882a593Smuzhiyun    if worker_fire:
224*4882a593Smuzhiyun        worker_fire(event, d)
225*4882a593Smuzhiyun    else:
226*4882a593Smuzhiyun        # If messages have been queued up, clear the queue
227*4882a593Smuzhiyun        global _uiready, ui_queue
228*4882a593Smuzhiyun        if _uiready and ui_queue:
229*4882a593Smuzhiyun            for queue_event in ui_queue:
230*4882a593Smuzhiyun                fire_ui_handlers(queue_event, d)
231*4882a593Smuzhiyun            ui_queue = []
232*4882a593Smuzhiyun        fire_ui_handlers(event, d)
233*4882a593Smuzhiyun
234*4882a593Smuzhiyundef fire_from_worker(event, d):
235*4882a593Smuzhiyun    fire_ui_handlers(event, d)
236*4882a593Smuzhiyun
237*4882a593Smuzhiyunnoop = lambda _: None
238*4882a593Smuzhiyundef register(name, handler, mask=None, filename=None, lineno=None, data=None):
239*4882a593Smuzhiyun    """Register an Event handler"""
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun    if data is not None and data.getVar("BB_CURRENT_MC"):
242*4882a593Smuzhiyun        mc = data.getVar("BB_CURRENT_MC")
243*4882a593Smuzhiyun        name = '%s%s' % (mc.replace('-', '_'), name)
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun    # already registered
246*4882a593Smuzhiyun    if name in _handlers:
247*4882a593Smuzhiyun        if data is not None:
248*4882a593Smuzhiyun            bbhands_mc = (data.getVar("__BBHANDLERS_MC") or set())
249*4882a593Smuzhiyun            bbhands_mc.add(name)
250*4882a593Smuzhiyun            data.setVar("__BBHANDLERS_MC", bbhands_mc)
251*4882a593Smuzhiyun        return AlreadyRegistered
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun    if handler is not None:
254*4882a593Smuzhiyun        # handle string containing python code
255*4882a593Smuzhiyun        if isinstance(handler, str):
256*4882a593Smuzhiyun            tmp = "def %s(e):\n%s" % (name, handler)
257*4882a593Smuzhiyun            try:
258*4882a593Smuzhiyun                code = bb.methodpool.compile_cache(tmp)
259*4882a593Smuzhiyun                if not code:
260*4882a593Smuzhiyun                    if filename is None:
261*4882a593Smuzhiyun                        filename = "%s(e)" % name
262*4882a593Smuzhiyun                    code = compile(tmp, filename, "exec", ast.PyCF_ONLY_AST)
263*4882a593Smuzhiyun                    if lineno is not None:
264*4882a593Smuzhiyun                        ast.increment_lineno(code, lineno-1)
265*4882a593Smuzhiyun                    code = compile(code, filename, "exec")
266*4882a593Smuzhiyun                    bb.methodpool.compile_cache_add(tmp, code)
267*4882a593Smuzhiyun            except SyntaxError:
268*4882a593Smuzhiyun                logger.error("Unable to register event handler '%s':\n%s", name,
269*4882a593Smuzhiyun                             ''.join(traceback.format_exc(limit=0)))
270*4882a593Smuzhiyun                _handlers[name] = noop
271*4882a593Smuzhiyun                return
272*4882a593Smuzhiyun            env = {}
273*4882a593Smuzhiyun            bb.utils.better_exec(code, env)
274*4882a593Smuzhiyun            func = bb.utils.better_eval(name, env)
275*4882a593Smuzhiyun            _handlers[name] = func
276*4882a593Smuzhiyun        else:
277*4882a593Smuzhiyun            _handlers[name] = handler
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun        if not mask or '*' in mask:
280*4882a593Smuzhiyun            _catchall_handlers[name] = True
281*4882a593Smuzhiyun        else:
282*4882a593Smuzhiyun            for m in mask:
283*4882a593Smuzhiyun                if _event_handler_map.get(m, None) is None:
284*4882a593Smuzhiyun                    _event_handler_map[m] = {}
285*4882a593Smuzhiyun                _event_handler_map[m][name] = True
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun        if data is not None:
288*4882a593Smuzhiyun            bbhands_mc = (data.getVar("__BBHANDLERS_MC") or set())
289*4882a593Smuzhiyun            bbhands_mc.add(name)
290*4882a593Smuzhiyun            data.setVar("__BBHANDLERS_MC", bbhands_mc)
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun        return Registered
293*4882a593Smuzhiyun
294*4882a593Smuzhiyundef remove(name, handler, data=None):
295*4882a593Smuzhiyun    """Remove an Event handler"""
296*4882a593Smuzhiyun    if data is not None:
297*4882a593Smuzhiyun        if data.getVar("BB_CURRENT_MC"):
298*4882a593Smuzhiyun            mc = data.getVar("BB_CURRENT_MC")
299*4882a593Smuzhiyun            name = '%s%s' % (mc.replace('-', '_'), name)
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun    _handlers.pop(name)
302*4882a593Smuzhiyun    if name in _catchall_handlers:
303*4882a593Smuzhiyun        _catchall_handlers.pop(name)
304*4882a593Smuzhiyun    for event in _event_handler_map.keys():
305*4882a593Smuzhiyun        if name in _event_handler_map[event]:
306*4882a593Smuzhiyun            _event_handler_map[event].pop(name)
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun    if data is not None:
309*4882a593Smuzhiyun        bbhands_mc = (data.getVar("__BBHANDLERS_MC") or set())
310*4882a593Smuzhiyun        if name in bbhands_mc:
311*4882a593Smuzhiyun            bbhands_mc.remove(name)
312*4882a593Smuzhiyun            data.setVar("__BBHANDLERS_MC", bbhands_mc)
313*4882a593Smuzhiyun
314*4882a593Smuzhiyundef get_handlers():
315*4882a593Smuzhiyun    return _handlers
316*4882a593Smuzhiyun
317*4882a593Smuzhiyundef set_handlers(handlers):
318*4882a593Smuzhiyun    global _handlers
319*4882a593Smuzhiyun    _handlers = handlers
320*4882a593Smuzhiyun
321*4882a593Smuzhiyundef set_eventfilter(func):
322*4882a593Smuzhiyun    global _eventfilter
323*4882a593Smuzhiyun    _eventfilter = func
324*4882a593Smuzhiyun
325*4882a593Smuzhiyundef register_UIHhandler(handler, mainui=False):
326*4882a593Smuzhiyun    bb.event._ui_handler_seq = bb.event._ui_handler_seq + 1
327*4882a593Smuzhiyun    _ui_handlers[_ui_handler_seq] = handler
328*4882a593Smuzhiyun    level, debug_domains = bb.msg.constructLogOptions()
329*4882a593Smuzhiyun    _ui_logfilters[_ui_handler_seq] = UIEventFilter(level, debug_domains)
330*4882a593Smuzhiyun    if mainui:
331*4882a593Smuzhiyun        global _uiready
332*4882a593Smuzhiyun        _uiready = _ui_handler_seq
333*4882a593Smuzhiyun    return _ui_handler_seq
334*4882a593Smuzhiyun
335*4882a593Smuzhiyundef unregister_UIHhandler(handlerNum, mainui=False):
336*4882a593Smuzhiyun    if mainui:
337*4882a593Smuzhiyun        global _uiready
338*4882a593Smuzhiyun        _uiready = False
339*4882a593Smuzhiyun    if handlerNum in _ui_handlers:
340*4882a593Smuzhiyun        del _ui_handlers[handlerNum]
341*4882a593Smuzhiyun    return
342*4882a593Smuzhiyun
343*4882a593Smuzhiyundef get_uihandler():
344*4882a593Smuzhiyun    if _uiready is False:
345*4882a593Smuzhiyun        return None
346*4882a593Smuzhiyun    return _uiready
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun# Class to allow filtering of events and specific filtering of LogRecords *before* we put them over the IPC
349*4882a593Smuzhiyunclass UIEventFilter(object):
350*4882a593Smuzhiyun    def __init__(self, level, debug_domains):
351*4882a593Smuzhiyun        self.update(None, level, debug_domains)
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun    def update(self, eventmask, level, debug_domains):
354*4882a593Smuzhiyun        self.eventmask = eventmask
355*4882a593Smuzhiyun        self.stdlevel = level
356*4882a593Smuzhiyun        self.debug_domains = debug_domains
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun    def filter(self, event):
359*4882a593Smuzhiyun        if isinstance(event, logging.LogRecord):
360*4882a593Smuzhiyun            if event.levelno >= self.stdlevel:
361*4882a593Smuzhiyun                return True
362*4882a593Smuzhiyun            if event.name in self.debug_domains and event.levelno >= self.debug_domains[event.name]:
363*4882a593Smuzhiyun                return True
364*4882a593Smuzhiyun            return False
365*4882a593Smuzhiyun        eid = str(event.__class__)[8:-2]
366*4882a593Smuzhiyun        if self.eventmask and eid not in self.eventmask:
367*4882a593Smuzhiyun            return False
368*4882a593Smuzhiyun        return True
369*4882a593Smuzhiyun
370*4882a593Smuzhiyundef set_UIHmask(handlerNum, level, debug_domains, mask):
371*4882a593Smuzhiyun    if not handlerNum in _ui_handlers:
372*4882a593Smuzhiyun        return False
373*4882a593Smuzhiyun    if '*' in mask:
374*4882a593Smuzhiyun        _ui_logfilters[handlerNum].update(None, level, debug_domains)
375*4882a593Smuzhiyun    else:
376*4882a593Smuzhiyun        _ui_logfilters[handlerNum].update(mask, level, debug_domains)
377*4882a593Smuzhiyun    return True
378*4882a593Smuzhiyun
379*4882a593Smuzhiyundef getName(e):
380*4882a593Smuzhiyun    """Returns the name of a class or class instance"""
381*4882a593Smuzhiyun    if getattr(e, "__name__", None) is None:
382*4882a593Smuzhiyun        return e.__class__.__name__
383*4882a593Smuzhiyun    else:
384*4882a593Smuzhiyun        return e.__name__
385*4882a593Smuzhiyun
386*4882a593Smuzhiyunclass OperationStarted(Event):
387*4882a593Smuzhiyun    """An operation has begun"""
388*4882a593Smuzhiyun    def __init__(self, msg = "Operation Started"):
389*4882a593Smuzhiyun        Event.__init__(self)
390*4882a593Smuzhiyun        self.msg = msg
391*4882a593Smuzhiyun
392*4882a593Smuzhiyunclass OperationCompleted(Event):
393*4882a593Smuzhiyun    """An operation has completed"""
394*4882a593Smuzhiyun    def __init__(self, total, msg = "Operation Completed"):
395*4882a593Smuzhiyun        Event.__init__(self)
396*4882a593Smuzhiyun        self.total = total
397*4882a593Smuzhiyun        self.msg = msg
398*4882a593Smuzhiyun
399*4882a593Smuzhiyunclass OperationProgress(Event):
400*4882a593Smuzhiyun    """An operation is in progress"""
401*4882a593Smuzhiyun    def __init__(self, current, total, msg = "Operation in Progress"):
402*4882a593Smuzhiyun        Event.__init__(self)
403*4882a593Smuzhiyun        self.current = current
404*4882a593Smuzhiyun        self.total = total
405*4882a593Smuzhiyun        self.msg = msg + ": %s/%s" % (current, total);
406*4882a593Smuzhiyun
407*4882a593Smuzhiyunclass ConfigParsed(Event):
408*4882a593Smuzhiyun    """Configuration Parsing Complete"""
409*4882a593Smuzhiyun
410*4882a593Smuzhiyunclass MultiConfigParsed(Event):
411*4882a593Smuzhiyun    """Multi-Config Parsing Complete"""
412*4882a593Smuzhiyun    def __init__(self, mcdata):
413*4882a593Smuzhiyun        self.mcdata = mcdata
414*4882a593Smuzhiyun        Event.__init__(self)
415*4882a593Smuzhiyun
416*4882a593Smuzhiyunclass RecipeEvent(Event):
417*4882a593Smuzhiyun    def __init__(self, fn):
418*4882a593Smuzhiyun        self.fn = fn
419*4882a593Smuzhiyun        Event.__init__(self)
420*4882a593Smuzhiyun
421*4882a593Smuzhiyunclass RecipePreFinalise(RecipeEvent):
422*4882a593Smuzhiyun    """ Recipe Parsing Complete but not yet finalised"""
423*4882a593Smuzhiyun
424*4882a593Smuzhiyunclass RecipePostKeyExpansion(RecipeEvent):
425*4882a593Smuzhiyun    """ Recipe Parsing Complete but not yet finalised"""
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun
428*4882a593Smuzhiyunclass RecipeTaskPreProcess(RecipeEvent):
429*4882a593Smuzhiyun    """
430*4882a593Smuzhiyun    Recipe Tasks about to be finalised
431*4882a593Smuzhiyun    The list of tasks should be final at this point and handlers
432*4882a593Smuzhiyun    are only able to change interdependencies
433*4882a593Smuzhiyun    """
434*4882a593Smuzhiyun    def __init__(self, fn, tasklist):
435*4882a593Smuzhiyun        self.fn = fn
436*4882a593Smuzhiyun        self.tasklist = tasklist
437*4882a593Smuzhiyun        Event.__init__(self)
438*4882a593Smuzhiyun
439*4882a593Smuzhiyunclass RecipeParsed(RecipeEvent):
440*4882a593Smuzhiyun    """ Recipe Parsing Complete """
441*4882a593Smuzhiyun
442*4882a593Smuzhiyunclass BuildBase(Event):
443*4882a593Smuzhiyun    """Base class for bitbake build events"""
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun    def __init__(self, n, p, failures = 0):
446*4882a593Smuzhiyun        self._name = n
447*4882a593Smuzhiyun        self._pkgs = p
448*4882a593Smuzhiyun        Event.__init__(self)
449*4882a593Smuzhiyun        self._failures = failures
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun    def getPkgs(self):
452*4882a593Smuzhiyun        return self._pkgs
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun    def setPkgs(self, pkgs):
455*4882a593Smuzhiyun        self._pkgs = pkgs
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun    def getName(self):
458*4882a593Smuzhiyun        return self._name
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun    def setName(self, name):
461*4882a593Smuzhiyun        self._name = name
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun    def getFailures(self):
464*4882a593Smuzhiyun        """
465*4882a593Smuzhiyun        Return the number of failed packages
466*4882a593Smuzhiyun        """
467*4882a593Smuzhiyun        return self._failures
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun    pkgs = property(getPkgs, setPkgs, None, "pkgs property")
470*4882a593Smuzhiyun    name = property(getName, setName, None, "name property")
471*4882a593Smuzhiyun
472*4882a593Smuzhiyunclass BuildInit(BuildBase):
473*4882a593Smuzhiyun    """buildFile or buildTargets was invoked"""
474*4882a593Smuzhiyun    def __init__(self, p=[]):
475*4882a593Smuzhiyun        name = None
476*4882a593Smuzhiyun        BuildBase.__init__(self, name, p)
477*4882a593Smuzhiyun
478*4882a593Smuzhiyunclass BuildStarted(BuildBase, OperationStarted):
479*4882a593Smuzhiyun    """Event when builds start"""
480*4882a593Smuzhiyun    def __init__(self, n, p, failures = 0):
481*4882a593Smuzhiyun        OperationStarted.__init__(self, "Building Started")
482*4882a593Smuzhiyun        BuildBase.__init__(self, n, p, failures)
483*4882a593Smuzhiyun
484*4882a593Smuzhiyunclass BuildCompleted(BuildBase, OperationCompleted):
485*4882a593Smuzhiyun    """Event when builds have completed"""
486*4882a593Smuzhiyun    def __init__(self, total, n, p, failures=0, interrupted=0):
487*4882a593Smuzhiyun        if not failures:
488*4882a593Smuzhiyun            OperationCompleted.__init__(self, total, "Building Succeeded")
489*4882a593Smuzhiyun        else:
490*4882a593Smuzhiyun            OperationCompleted.__init__(self, total, "Building Failed")
491*4882a593Smuzhiyun        self._interrupted = interrupted
492*4882a593Smuzhiyun        BuildBase.__init__(self, n, p, failures)
493*4882a593Smuzhiyun
494*4882a593Smuzhiyunclass DiskFull(Event):
495*4882a593Smuzhiyun    """Disk full case build halted"""
496*4882a593Smuzhiyun    def __init__(self, dev, type, freespace, mountpoint):
497*4882a593Smuzhiyun        Event.__init__(self)
498*4882a593Smuzhiyun        self._dev = dev
499*4882a593Smuzhiyun        self._type = type
500*4882a593Smuzhiyun        self._free = freespace
501*4882a593Smuzhiyun        self._mountpoint = mountpoint
502*4882a593Smuzhiyun
503*4882a593Smuzhiyunclass DiskUsageSample:
504*4882a593Smuzhiyun    def __init__(self, available_bytes, free_bytes, total_bytes):
505*4882a593Smuzhiyun        # Number of bytes available to non-root processes.
506*4882a593Smuzhiyun        self.available_bytes = available_bytes
507*4882a593Smuzhiyun        # Number of bytes available to root processes.
508*4882a593Smuzhiyun        self.free_bytes = free_bytes
509*4882a593Smuzhiyun        # Total capacity of the volume.
510*4882a593Smuzhiyun        self.total_bytes = total_bytes
511*4882a593Smuzhiyun
512*4882a593Smuzhiyunclass MonitorDiskEvent(Event):
513*4882a593Smuzhiyun    """If BB_DISKMON_DIRS is set, then this event gets triggered each time disk space is checked.
514*4882a593Smuzhiyun       Provides information about devices that are getting monitored."""
515*4882a593Smuzhiyun    def __init__(self, disk_usage):
516*4882a593Smuzhiyun        Event.__init__(self)
517*4882a593Smuzhiyun        # hash of device root path -> DiskUsageSample
518*4882a593Smuzhiyun        self.disk_usage = disk_usage
519*4882a593Smuzhiyun
520*4882a593Smuzhiyunclass NoProvider(Event):
521*4882a593Smuzhiyun    """No Provider for an Event"""
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun    def __init__(self, item, runtime=False, dependees=None, reasons=None, close_matches=None):
524*4882a593Smuzhiyun        Event.__init__(self)
525*4882a593Smuzhiyun        self._item = item
526*4882a593Smuzhiyun        self._runtime = runtime
527*4882a593Smuzhiyun        self._dependees = dependees
528*4882a593Smuzhiyun        self._reasons = reasons
529*4882a593Smuzhiyun        self._close_matches = close_matches
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun    def getItem(self):
532*4882a593Smuzhiyun        return self._item
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun    def isRuntime(self):
535*4882a593Smuzhiyun        return self._runtime
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun    def __str__(self):
538*4882a593Smuzhiyun        msg = ''
539*4882a593Smuzhiyun        if self._runtime:
540*4882a593Smuzhiyun            r = "R"
541*4882a593Smuzhiyun        else:
542*4882a593Smuzhiyun            r = ""
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun        extra = ''
545*4882a593Smuzhiyun        if not self._reasons:
546*4882a593Smuzhiyun            if self._close_matches:
547*4882a593Smuzhiyun                extra = ". Close matches:\n  %s" % '\n  '.join(sorted(set(self._close_matches)))
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun        if self._dependees:
550*4882a593Smuzhiyun            msg = "Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)%s" % (r, self._item, ", ".join(self._dependees), r, extra)
551*4882a593Smuzhiyun        else:
552*4882a593Smuzhiyun            msg = "Nothing %sPROVIDES '%s'%s" % (r, self._item, extra)
553*4882a593Smuzhiyun        if self._reasons:
554*4882a593Smuzhiyun            for reason in self._reasons:
555*4882a593Smuzhiyun                msg += '\n' + reason
556*4882a593Smuzhiyun        return msg
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun
559*4882a593Smuzhiyunclass MultipleProviders(Event):
560*4882a593Smuzhiyun    """Multiple Providers"""
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun    def  __init__(self, item, candidates, runtime = False):
563*4882a593Smuzhiyun        Event.__init__(self)
564*4882a593Smuzhiyun        self._item = item
565*4882a593Smuzhiyun        self._candidates = candidates
566*4882a593Smuzhiyun        self._is_runtime = runtime
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun    def isRuntime(self):
569*4882a593Smuzhiyun        """
570*4882a593Smuzhiyun        Is this a runtime issue?
571*4882a593Smuzhiyun        """
572*4882a593Smuzhiyun        return self._is_runtime
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun    def getItem(self):
575*4882a593Smuzhiyun        """
576*4882a593Smuzhiyun        The name for the to be build item
577*4882a593Smuzhiyun        """
578*4882a593Smuzhiyun        return self._item
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun    def getCandidates(self):
581*4882a593Smuzhiyun        """
582*4882a593Smuzhiyun        Get the possible Candidates for a PROVIDER.
583*4882a593Smuzhiyun        """
584*4882a593Smuzhiyun        return self._candidates
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun    def __str__(self):
587*4882a593Smuzhiyun        msg = "Multiple providers are available for %s%s (%s)" % (self._is_runtime and "runtime " or "",
588*4882a593Smuzhiyun                            self._item,
589*4882a593Smuzhiyun                            ", ".join(self._candidates))
590*4882a593Smuzhiyun        rtime = ""
591*4882a593Smuzhiyun        if self._is_runtime:
592*4882a593Smuzhiyun            rtime = "R"
593*4882a593Smuzhiyun        msg += "\nConsider defining a PREFERRED_%sPROVIDER entry to match %s" % (rtime, self._item)
594*4882a593Smuzhiyun        return msg
595*4882a593Smuzhiyun
596*4882a593Smuzhiyunclass ParseStarted(OperationStarted):
597*4882a593Smuzhiyun    """Recipe parsing for the runqueue has begun"""
598*4882a593Smuzhiyun    def __init__(self, total):
599*4882a593Smuzhiyun        OperationStarted.__init__(self, "Recipe parsing Started")
600*4882a593Smuzhiyun        self.total = total
601*4882a593Smuzhiyun
602*4882a593Smuzhiyunclass ParseCompleted(OperationCompleted):
603*4882a593Smuzhiyun    """Recipe parsing for the runqueue has completed"""
604*4882a593Smuzhiyun    def __init__(self, cached, parsed, skipped, masked, virtuals, errors, total):
605*4882a593Smuzhiyun        OperationCompleted.__init__(self, total, "Recipe parsing Completed")
606*4882a593Smuzhiyun        self.cached = cached
607*4882a593Smuzhiyun        self.parsed = parsed
608*4882a593Smuzhiyun        self.skipped = skipped
609*4882a593Smuzhiyun        self.virtuals = virtuals
610*4882a593Smuzhiyun        self.masked = masked
611*4882a593Smuzhiyun        self.errors = errors
612*4882a593Smuzhiyun        self.sofar = cached + parsed
613*4882a593Smuzhiyun
614*4882a593Smuzhiyunclass ParseProgress(OperationProgress):
615*4882a593Smuzhiyun    """Recipe parsing progress"""
616*4882a593Smuzhiyun    def __init__(self, current, total):
617*4882a593Smuzhiyun        OperationProgress.__init__(self, current, total, "Recipe parsing")
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun
620*4882a593Smuzhiyunclass CacheLoadStarted(OperationStarted):
621*4882a593Smuzhiyun    """Loading of the dependency cache has begun"""
622*4882a593Smuzhiyun    def __init__(self, total):
623*4882a593Smuzhiyun        OperationStarted.__init__(self, "Loading cache Started")
624*4882a593Smuzhiyun        self.total = total
625*4882a593Smuzhiyun
626*4882a593Smuzhiyunclass CacheLoadProgress(OperationProgress):
627*4882a593Smuzhiyun    """Cache loading progress"""
628*4882a593Smuzhiyun    def __init__(self, current, total):
629*4882a593Smuzhiyun        OperationProgress.__init__(self, current, total, "Loading cache")
630*4882a593Smuzhiyun
631*4882a593Smuzhiyunclass CacheLoadCompleted(OperationCompleted):
632*4882a593Smuzhiyun    """Cache loading is complete"""
633*4882a593Smuzhiyun    def __init__(self, total, num_entries):
634*4882a593Smuzhiyun        OperationCompleted.__init__(self, total, "Loading cache Completed")
635*4882a593Smuzhiyun        self.num_entries = num_entries
636*4882a593Smuzhiyun
637*4882a593Smuzhiyunclass TreeDataPreparationStarted(OperationStarted):
638*4882a593Smuzhiyun    """Tree data preparation started"""
639*4882a593Smuzhiyun    def __init__(self):
640*4882a593Smuzhiyun        OperationStarted.__init__(self, "Preparing tree data Started")
641*4882a593Smuzhiyun
642*4882a593Smuzhiyunclass TreeDataPreparationProgress(OperationProgress):
643*4882a593Smuzhiyun    """Tree data preparation is in progress"""
644*4882a593Smuzhiyun    def __init__(self, current, total):
645*4882a593Smuzhiyun        OperationProgress.__init__(self, current, total, "Preparing tree data")
646*4882a593Smuzhiyun
647*4882a593Smuzhiyunclass TreeDataPreparationCompleted(OperationCompleted):
648*4882a593Smuzhiyun    """Tree data preparation completed"""
649*4882a593Smuzhiyun    def __init__(self, total):
650*4882a593Smuzhiyun        OperationCompleted.__init__(self, total, "Preparing tree data Completed")
651*4882a593Smuzhiyun
652*4882a593Smuzhiyunclass DepTreeGenerated(Event):
653*4882a593Smuzhiyun    """
654*4882a593Smuzhiyun    Event when a dependency tree has been generated
655*4882a593Smuzhiyun    """
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun    def __init__(self, depgraph):
658*4882a593Smuzhiyun        Event.__init__(self)
659*4882a593Smuzhiyun        self._depgraph = depgraph
660*4882a593Smuzhiyun
661*4882a593Smuzhiyunclass TargetsTreeGenerated(Event):
662*4882a593Smuzhiyun    """
663*4882a593Smuzhiyun    Event when a set of buildable targets has been generated
664*4882a593Smuzhiyun    """
665*4882a593Smuzhiyun    def __init__(self, model):
666*4882a593Smuzhiyun        Event.__init__(self)
667*4882a593Smuzhiyun        self._model = model
668*4882a593Smuzhiyun
669*4882a593Smuzhiyunclass ReachableStamps(Event):
670*4882a593Smuzhiyun    """
671*4882a593Smuzhiyun    An event listing all stamps reachable after parsing
672*4882a593Smuzhiyun    which the metadata may use to clean up stale data
673*4882a593Smuzhiyun    """
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun    def __init__(self, stamps):
676*4882a593Smuzhiyun        Event.__init__(self)
677*4882a593Smuzhiyun        self.stamps = stamps
678*4882a593Smuzhiyun
679*4882a593Smuzhiyunclass StaleSetSceneTasks(Event):
680*4882a593Smuzhiyun    """
681*4882a593Smuzhiyun    An event listing setscene tasks which are 'stale' and will
682*4882a593Smuzhiyun    be rerun. The metadata may use to clean up stale data.
683*4882a593Smuzhiyun    tasks is a mapping of tasks and matching stale stamps.
684*4882a593Smuzhiyun    """
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun    def __init__(self, tasks):
687*4882a593Smuzhiyun        Event.__init__(self)
688*4882a593Smuzhiyun        self.tasks = tasks
689*4882a593Smuzhiyun
690*4882a593Smuzhiyunclass FilesMatchingFound(Event):
691*4882a593Smuzhiyun    """
692*4882a593Smuzhiyun    Event when a list of files matching the supplied pattern has
693*4882a593Smuzhiyun    been generated
694*4882a593Smuzhiyun    """
695*4882a593Smuzhiyun    def __init__(self, pattern, matches):
696*4882a593Smuzhiyun        Event.__init__(self)
697*4882a593Smuzhiyun        self._pattern = pattern
698*4882a593Smuzhiyun        self._matches = matches
699*4882a593Smuzhiyun
700*4882a593Smuzhiyunclass ConfigFilesFound(Event):
701*4882a593Smuzhiyun    """
702*4882a593Smuzhiyun    Event when a list of appropriate config files has been generated
703*4882a593Smuzhiyun    """
704*4882a593Smuzhiyun    def __init__(self, variable, values):
705*4882a593Smuzhiyun        Event.__init__(self)
706*4882a593Smuzhiyun        self._variable = variable
707*4882a593Smuzhiyun        self._values = values
708*4882a593Smuzhiyun
709*4882a593Smuzhiyunclass ConfigFilePathFound(Event):
710*4882a593Smuzhiyun    """
711*4882a593Smuzhiyun    Event when a path for a config file has been found
712*4882a593Smuzhiyun    """
713*4882a593Smuzhiyun    def __init__(self, path):
714*4882a593Smuzhiyun        Event.__init__(self)
715*4882a593Smuzhiyun        self._path = path
716*4882a593Smuzhiyun
717*4882a593Smuzhiyunclass MsgBase(Event):
718*4882a593Smuzhiyun    """Base class for messages"""
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun    def __init__(self, msg):
721*4882a593Smuzhiyun        self._message = msg
722*4882a593Smuzhiyun        Event.__init__(self)
723*4882a593Smuzhiyun
724*4882a593Smuzhiyunclass MsgDebug(MsgBase):
725*4882a593Smuzhiyun    """Debug Message"""
726*4882a593Smuzhiyun
727*4882a593Smuzhiyunclass MsgNote(MsgBase):
728*4882a593Smuzhiyun    """Note Message"""
729*4882a593Smuzhiyun
730*4882a593Smuzhiyunclass MsgWarn(MsgBase):
731*4882a593Smuzhiyun    """Warning Message"""
732*4882a593Smuzhiyun
733*4882a593Smuzhiyunclass MsgError(MsgBase):
734*4882a593Smuzhiyun    """Error Message"""
735*4882a593Smuzhiyun
736*4882a593Smuzhiyunclass MsgFatal(MsgBase):
737*4882a593Smuzhiyun    """Fatal Message"""
738*4882a593Smuzhiyun
739*4882a593Smuzhiyunclass MsgPlain(MsgBase):
740*4882a593Smuzhiyun    """General output"""
741*4882a593Smuzhiyun
742*4882a593Smuzhiyunclass LogExecTTY(Event):
743*4882a593Smuzhiyun    """Send event containing program to spawn on tty of the logger"""
744*4882a593Smuzhiyun    def __init__(self, msg, prog, sleep_delay, retries):
745*4882a593Smuzhiyun        Event.__init__(self)
746*4882a593Smuzhiyun        self.msg = msg
747*4882a593Smuzhiyun        self.prog = prog
748*4882a593Smuzhiyun        self.sleep_delay = sleep_delay
749*4882a593Smuzhiyun        self.retries = retries
750*4882a593Smuzhiyun
751*4882a593Smuzhiyunclass LogHandler(logging.Handler):
752*4882a593Smuzhiyun    """Dispatch logging messages as bitbake events"""
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun    def emit(self, record):
755*4882a593Smuzhiyun        if record.exc_info:
756*4882a593Smuzhiyun            etype, value, tb = record.exc_info
757*4882a593Smuzhiyun            if hasattr(tb, 'tb_next'):
758*4882a593Smuzhiyun                tb = list(bb.exceptions.extract_traceback(tb, context=3))
759*4882a593Smuzhiyun            # Need to turn the value into something the logging system can pickle
760*4882a593Smuzhiyun            record.bb_exc_info = (etype, value, tb)
761*4882a593Smuzhiyun            record.bb_exc_formatted = bb.exceptions.format_exception(etype, value, tb, limit=5)
762*4882a593Smuzhiyun            value = str(value)
763*4882a593Smuzhiyun            record.exc_info = None
764*4882a593Smuzhiyun        fire(record, None)
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun    def filter(self, record):
767*4882a593Smuzhiyun        record.taskpid = worker_pid
768*4882a593Smuzhiyun        return True
769*4882a593Smuzhiyun
770*4882a593Smuzhiyunclass MetadataEvent(Event):
771*4882a593Smuzhiyun    """
772*4882a593Smuzhiyun    Generic event that target for OE-Core classes
773*4882a593Smuzhiyun    to report information during asynchronous execution
774*4882a593Smuzhiyun    """
775*4882a593Smuzhiyun    def __init__(self, eventtype, eventdata):
776*4882a593Smuzhiyun        Event.__init__(self)
777*4882a593Smuzhiyun        self.type = eventtype
778*4882a593Smuzhiyun        self._localdata = eventdata
779*4882a593Smuzhiyun
780*4882a593Smuzhiyunclass ProcessStarted(Event):
781*4882a593Smuzhiyun    """
782*4882a593Smuzhiyun    Generic process started event (usually part of the initial startup)
783*4882a593Smuzhiyun    where further progress events will be delivered
784*4882a593Smuzhiyun    """
785*4882a593Smuzhiyun    def __init__(self, processname, total):
786*4882a593Smuzhiyun        Event.__init__(self)
787*4882a593Smuzhiyun        self.processname = processname
788*4882a593Smuzhiyun        self.total = total
789*4882a593Smuzhiyun
790*4882a593Smuzhiyunclass ProcessProgress(Event):
791*4882a593Smuzhiyun    """
792*4882a593Smuzhiyun    Generic process progress event (usually part of the initial startup)
793*4882a593Smuzhiyun    """
794*4882a593Smuzhiyun    def __init__(self, processname, progress):
795*4882a593Smuzhiyun        Event.__init__(self)
796*4882a593Smuzhiyun        self.processname = processname
797*4882a593Smuzhiyun        self.progress = progress
798*4882a593Smuzhiyun
799*4882a593Smuzhiyunclass ProcessFinished(Event):
800*4882a593Smuzhiyun    """
801*4882a593Smuzhiyun    Generic process finished event (usually part of the initial startup)
802*4882a593Smuzhiyun    """
803*4882a593Smuzhiyun    def __init__(self, processname):
804*4882a593Smuzhiyun        Event.__init__(self)
805*4882a593Smuzhiyun        self.processname = processname
806*4882a593Smuzhiyun
807*4882a593Smuzhiyunclass SanityCheck(Event):
808*4882a593Smuzhiyun    """
809*4882a593Smuzhiyun    Event to run sanity checks, either raise errors or generate events as return status.
810*4882a593Smuzhiyun    """
811*4882a593Smuzhiyun    def __init__(self, generateevents = True):
812*4882a593Smuzhiyun        Event.__init__(self)
813*4882a593Smuzhiyun        self.generateevents = generateevents
814*4882a593Smuzhiyun
815*4882a593Smuzhiyunclass SanityCheckPassed(Event):
816*4882a593Smuzhiyun    """
817*4882a593Smuzhiyun    Event to indicate sanity check has passed
818*4882a593Smuzhiyun    """
819*4882a593Smuzhiyun
820*4882a593Smuzhiyunclass SanityCheckFailed(Event):
821*4882a593Smuzhiyun    """
822*4882a593Smuzhiyun    Event to indicate sanity check has failed
823*4882a593Smuzhiyun    """
824*4882a593Smuzhiyun    def __init__(self, msg, network_error=False):
825*4882a593Smuzhiyun        Event.__init__(self)
826*4882a593Smuzhiyun        self._msg = msg
827*4882a593Smuzhiyun        self._network_error = network_error
828*4882a593Smuzhiyun
829*4882a593Smuzhiyunclass NetworkTest(Event):
830*4882a593Smuzhiyun    """
831*4882a593Smuzhiyun    Event to run network connectivity tests, either raise errors or generate events as return status.
832*4882a593Smuzhiyun    """
833*4882a593Smuzhiyun    def __init__(self, generateevents = True):
834*4882a593Smuzhiyun        Event.__init__(self)
835*4882a593Smuzhiyun        self.generateevents = generateevents
836*4882a593Smuzhiyun
837*4882a593Smuzhiyunclass NetworkTestPassed(Event):
838*4882a593Smuzhiyun    """
839*4882a593Smuzhiyun    Event to indicate network test has passed
840*4882a593Smuzhiyun    """
841*4882a593Smuzhiyun
842*4882a593Smuzhiyunclass NetworkTestFailed(Event):
843*4882a593Smuzhiyun    """
844*4882a593Smuzhiyun    Event to indicate network test has failed
845*4882a593Smuzhiyun    """
846*4882a593Smuzhiyun
847*4882a593Smuzhiyunclass FindSigInfoResult(Event):
848*4882a593Smuzhiyun    """
849*4882a593Smuzhiyun    Event to return results from findSigInfo command
850*4882a593Smuzhiyun    """
851*4882a593Smuzhiyun    def __init__(self, result):
852*4882a593Smuzhiyun        Event.__init__(self)
853*4882a593Smuzhiyun        self.result = result
854