blob: 6d8493b175eed05a8cc0590dc000b0e235e8ff60 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake 'Event' implementation
5
6Classes and functions for manipulating 'events' in the
7BitBake build tools.
8"""
9
10# Copyright (C) 2003, 2004 Chris Larson
11#
12# This program is free software; you can redistribute it and/or modify
13# it under the terms of the GNU General Public License version 2 as
14# published by the Free Software Foundation.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License along
22# with this program; if not, write to the Free Software Foundation, Inc.,
23# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
25import os, sys
26import warnings
Patrick Williamsc0f7c042017-02-23 20:41:17 -060027import pickle
Patrick Williamsc124f4f2015-09-15 14:41:29 -050028import logging
29import atexit
30import traceback
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050031import ast
Patrick Williamsc0f7c042017-02-23 20:41:17 -060032import threading
33
Patrick Williamsc124f4f2015-09-15 14:41:29 -050034import bb.utils
35import bb.compat
36import bb.exceptions
37
38# This is the pid for which we should generate the event. This is set when
39# the runqueue forks off.
40worker_pid = 0
41worker_fire = None
42
43logger = logging.getLogger('BitBake.Event')
44
45class Event(object):
46 """Base class for events"""
47
48 def __init__(self):
49 self.pid = worker_pid
50
Brad Bishop6e60e8b2018-02-01 10:27:11 -050051
52class HeartbeatEvent(Event):
53 """Triggered at regular time intervals of 10 seconds. Other events can fire much more often
54 (runQueueTaskStarted when there are many short tasks) or not at all for long periods
55 of time (again runQueueTaskStarted, when there is just one long-running task), so this
56 event is more suitable for doing some task-independent work occassionally."""
57 def __init__(self, time):
58 Event.__init__(self)
59 self.time = time
60
Patrick Williamsc124f4f2015-09-15 14:41:29 -050061Registered = 10
62AlreadyRegistered = 14
63
64def get_class_handlers():
65 return _handlers
66
67def set_class_handlers(h):
68 global _handlers
69 _handlers = h
70
71def clean_class_handlers():
72 return bb.compat.OrderedDict()
73
74# Internal
75_handlers = clean_class_handlers()
76_ui_handlers = {}
77_ui_logfilters = {}
78_ui_handler_seq = 0
79_event_handler_map = {}
80_catchall_handlers = {}
81_eventfilter = None
82_uiready = False
Patrick Williamsc0f7c042017-02-23 20:41:17 -060083_thread_lock = threading.Lock()
84_thread_lock_enabled = False
85
86if hasattr(__builtins__, '__setitem__'):
87 builtins = __builtins__
88else:
89 builtins = __builtins__.__dict__
90
91def enable_threadlock():
92 global _thread_lock_enabled
93 _thread_lock_enabled = True
94
95def disable_threadlock():
96 global _thread_lock_enabled
97 _thread_lock_enabled = False
Patrick Williamsc124f4f2015-09-15 14:41:29 -050098
99def execute_handler(name, handler, event, d):
100 event.data = d
101 addedd = False
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600102 if 'd' not in builtins:
103 builtins['d'] = d
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500104 addedd = True
105 try:
106 ret = handler(event)
107 except (bb.parse.SkipRecipe, bb.BBHandledException):
108 raise
109 except Exception:
110 etype, value, tb = sys.exc_info()
111 logger.error("Execution of event handler '%s' failed" % name,
112 exc_info=(etype, value, tb.tb_next))
113 raise
114 except SystemExit as exc:
115 if exc.code != 0:
116 logger.error("Execution of event handler '%s' failed" % name)
117 raise
118 finally:
119 del event.data
120 if addedd:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600121 del builtins['d']
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500122
123def fire_class_handlers(event, d):
124 if isinstance(event, logging.LogRecord):
125 return
126
127 eid = str(event.__class__)[8:-2]
128 evt_hmap = _event_handler_map.get(eid, {})
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600129 for name, handler in list(_handlers.items()):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500130 if name in _catchall_handlers or name in evt_hmap:
131 if _eventfilter:
132 if not _eventfilter(name, handler, event, d):
133 continue
134 execute_handler(name, handler, event, d)
135
136ui_queue = []
137@atexit.register
138def print_ui_queue():
139 """If we're exiting before a UI has been spawned, display any queued
140 LogRecords to the console."""
141 logger = logging.getLogger("BitBake")
142 if not _uiready:
143 from bb.msg import BBLogFormatter
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600144 stdout = logging.StreamHandler(sys.stdout)
145 stderr = logging.StreamHandler(sys.stderr)
146 formatter = BBLogFormatter("%(levelname)s: %(message)s")
147 stdout.setFormatter(formatter)
148 stderr.setFormatter(formatter)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500149
150 # First check to see if we have any proper messages
151 msgprint = False
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600152 for event in ui_queue[:]:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500153 if isinstance(event, logging.LogRecord):
154 if event.levelno > logging.DEBUG:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600155 if event.levelno >= logging.WARNING:
156 logger.addHandler(stderr)
157 else:
158 logger.addHandler(stdout)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500159 logger.handle(event)
160 msgprint = True
161 if msgprint:
162 return
163
164 # Nope, so just print all of the messages we have (including debug messages)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600165 logger.addHandler(stdout)
166 for event in ui_queue[:]:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500167 if isinstance(event, logging.LogRecord):
168 logger.handle(event)
169
170def fire_ui_handlers(event, d):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600171 global _thread_lock
172 global _thread_lock_enabled
173
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500174 if not _uiready:
175 # No UI handlers registered yet, queue up the messages
176 ui_queue.append(event)
177 return
178
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600179 if _thread_lock_enabled:
180 _thread_lock.acquire()
181
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500182 errors = []
183 for h in _ui_handlers:
184 #print "Sending event %s" % event
185 try:
186 if not _ui_logfilters[h].filter(event):
187 continue
188 # We use pickle here since it better handles object instances
189 # which xmlrpc's marshaller does not. Events *must* be serializable
190 # by pickle.
191 if hasattr(_ui_handlers[h].event, "sendpickle"):
192 _ui_handlers[h].event.sendpickle((pickle.dumps(event)))
193 else:
194 _ui_handlers[h].event.send(event)
195 except:
196 errors.append(h)
197 for h in errors:
198 del _ui_handlers[h]
199
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600200 if _thread_lock_enabled:
201 _thread_lock.release()
202
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500203def fire(event, d):
204 """Fire off an Event"""
205
206 # We can fire class handlers in the worker process context and this is
207 # desired so they get the task based datastore.
208 # UI handlers need to be fired in the server context so we defer this. They
209 # don't have a datastore so the datastore context isn't a problem.
210
211 fire_class_handlers(event, d)
212 if worker_fire:
213 worker_fire(event, d)
214 else:
215 fire_ui_handlers(event, d)
216
217def fire_from_worker(event, d):
218 fire_ui_handlers(event, d)
219
220noop = lambda _: None
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500221def register(name, handler, mask=None, filename=None, lineno=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500222 """Register an Event handler"""
223
224 # already registered
225 if name in _handlers:
226 return AlreadyRegistered
227
228 if handler is not None:
229 # handle string containing python code
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600230 if isinstance(handler, str):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500231 tmp = "def %s(e):\n%s" % (name, handler)
232 try:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500233 code = bb.methodpool.compile_cache(tmp)
234 if not code:
235 if filename is None:
236 filename = "%s(e)" % name
237 code = compile(tmp, filename, "exec", ast.PyCF_ONLY_AST)
238 if lineno is not None:
239 ast.increment_lineno(code, lineno-1)
240 code = compile(code, filename, "exec")
241 bb.methodpool.compile_cache_add(tmp, code)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500242 except SyntaxError:
243 logger.error("Unable to register event handler '%s':\n%s", name,
244 ''.join(traceback.format_exc(limit=0)))
245 _handlers[name] = noop
246 return
247 env = {}
248 bb.utils.better_exec(code, env)
249 func = bb.utils.better_eval(name, env)
250 _handlers[name] = func
251 else:
252 _handlers[name] = handler
253
254 if not mask or '*' in mask:
255 _catchall_handlers[name] = True
256 else:
257 for m in mask:
258 if _event_handler_map.get(m, None) is None:
259 _event_handler_map[m] = {}
260 _event_handler_map[m][name] = True
261
262 return Registered
263
264def remove(name, handler):
265 """Remove an Event handler"""
266 _handlers.pop(name)
267
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600268def get_handlers():
269 return _handlers
270
271def set_handlers(handlers):
272 global _handlers
273 _handlers = handlers
274
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500275def set_eventfilter(func):
276 global _eventfilter
277 _eventfilter = func
278
279def register_UIHhandler(handler, mainui=False):
280 if mainui:
281 global _uiready
282 _uiready = True
283 bb.event._ui_handler_seq = bb.event._ui_handler_seq + 1
284 _ui_handlers[_ui_handler_seq] = handler
285 level, debug_domains = bb.msg.constructLogOptions()
286 _ui_logfilters[_ui_handler_seq] = UIEventFilter(level, debug_domains)
287 return _ui_handler_seq
288
289def unregister_UIHhandler(handlerNum):
290 if handlerNum in _ui_handlers:
291 del _ui_handlers[handlerNum]
292 return
293
294# Class to allow filtering of events and specific filtering of LogRecords *before* we put them over the IPC
295class UIEventFilter(object):
296 def __init__(self, level, debug_domains):
297 self.update(None, level, debug_domains)
298
299 def update(self, eventmask, level, debug_domains):
300 self.eventmask = eventmask
301 self.stdlevel = level
302 self.debug_domains = debug_domains
303
304 def filter(self, event):
305 if isinstance(event, logging.LogRecord):
306 if event.levelno >= self.stdlevel:
307 return True
308 if event.name in self.debug_domains and event.levelno >= self.debug_domains[event.name]:
309 return True
310 return False
311 eid = str(event.__class__)[8:-2]
312 if self.eventmask and eid not in self.eventmask:
313 return False
314 return True
315
316def set_UIHmask(handlerNum, level, debug_domains, mask):
317 if not handlerNum in _ui_handlers:
318 return False
319 if '*' in mask:
320 _ui_logfilters[handlerNum].update(None, level, debug_domains)
321 else:
322 _ui_logfilters[handlerNum].update(mask, level, debug_domains)
323 return True
324
325def getName(e):
326 """Returns the name of a class or class instance"""
327 if getattr(e, "__name__", None) == None:
328 return e.__class__.__name__
329 else:
330 return e.__name__
331
332class OperationStarted(Event):
333 """An operation has begun"""
334 def __init__(self, msg = "Operation Started"):
335 Event.__init__(self)
336 self.msg = msg
337
338class OperationCompleted(Event):
339 """An operation has completed"""
340 def __init__(self, total, msg = "Operation Completed"):
341 Event.__init__(self)
342 self.total = total
343 self.msg = msg
344
345class OperationProgress(Event):
346 """An operation is in progress"""
347 def __init__(self, current, total, msg = "Operation in Progress"):
348 Event.__init__(self)
349 self.current = current
350 self.total = total
351 self.msg = msg + ": %s/%s" % (current, total);
352
353class ConfigParsed(Event):
354 """Configuration Parsing Complete"""
355
356class RecipeEvent(Event):
357 def __init__(self, fn):
358 self.fn = fn
359 Event.__init__(self)
360
361class RecipePreFinalise(RecipeEvent):
362 """ Recipe Parsing Complete but not yet finialised"""
363
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500364class RecipeTaskPreProcess(RecipeEvent):
365 """
366 Recipe Tasks about to be finalised
367 The list of tasks should be final at this point and handlers
368 are only able to change interdependencies
369 """
370 def __init__(self, fn, tasklist):
371 self.fn = fn
372 self.tasklist = tasklist
373 Event.__init__(self)
374
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500375class RecipeParsed(RecipeEvent):
376 """ Recipe Parsing Complete """
377
378class StampUpdate(Event):
379 """Trigger for any adjustment of the stamp files to happen"""
380
381 def __init__(self, targets, stampfns):
382 self._targets = targets
383 self._stampfns = stampfns
384 Event.__init__(self)
385
386 def getStampPrefix(self):
387 return self._stampfns
388
389 def getTargets(self):
390 return self._targets
391
392 stampPrefix = property(getStampPrefix)
393 targets = property(getTargets)
394
395class BuildBase(Event):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500396 """Base class for bitbake build events"""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500397
398 def __init__(self, n, p, failures = 0):
399 self._name = n
400 self._pkgs = p
401 Event.__init__(self)
402 self._failures = failures
403
404 def getPkgs(self):
405 return self._pkgs
406
407 def setPkgs(self, pkgs):
408 self._pkgs = pkgs
409
410 def getName(self):
411 return self._name
412
413 def setName(self, name):
414 self._name = name
415
416 def getCfg(self):
417 return self.data
418
419 def setCfg(self, cfg):
420 self.data = cfg
421
422 def getFailures(self):
423 """
424 Return the number of failed packages
425 """
426 return self._failures
427
428 pkgs = property(getPkgs, setPkgs, None, "pkgs property")
429 name = property(getName, setName, None, "name property")
430 cfg = property(getCfg, setCfg, None, "cfg property")
431
432
433
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600434class BuildInit(BuildBase):
435 """buildFile or buildTargets was invoked"""
436 def __init__(self, p=[]):
437 name = None
438 BuildBase.__init__(self, name, p)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500439
440class BuildStarted(BuildBase, OperationStarted):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500441 """Event when builds start"""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500442 def __init__(self, n, p, failures = 0):
443 OperationStarted.__init__(self, "Building Started")
444 BuildBase.__init__(self, n, p, failures)
445
446class BuildCompleted(BuildBase, OperationCompleted):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500447 """Event when builds have completed"""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500448 def __init__(self, total, n, p, failures=0, interrupted=0):
449 if not failures:
450 OperationCompleted.__init__(self, total, "Building Succeeded")
451 else:
452 OperationCompleted.__init__(self, total, "Building Failed")
453 self._interrupted = interrupted
454 BuildBase.__init__(self, n, p, failures)
455
456class DiskFull(Event):
457 """Disk full case build aborted"""
458 def __init__(self, dev, type, freespace, mountpoint):
459 Event.__init__(self)
460 self._dev = dev
461 self._type = type
462 self._free = freespace
463 self._mountpoint = mountpoint
464
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500465class DiskUsageSample:
466 def __init__(self, available_bytes, free_bytes, total_bytes):
467 # Number of bytes available to non-root processes.
468 self.available_bytes = available_bytes
469 # Number of bytes available to root processes.
470 self.free_bytes = free_bytes
471 # Total capacity of the volume.
472 self.total_bytes = total_bytes
473
474class MonitorDiskEvent(Event):
475 """If BB_DISKMON_DIRS is set, then this event gets triggered each time disk space is checked.
476 Provides information about devices that are getting monitored."""
477 def __init__(self, disk_usage):
478 Event.__init__(self)
479 # hash of device root path -> DiskUsageSample
480 self.disk_usage = disk_usage
481
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500482class NoProvider(Event):
483 """No Provider for an Event"""
484
485 def __init__(self, item, runtime=False, dependees=None, reasons=None, close_matches=None):
486 Event.__init__(self)
487 self._item = item
488 self._runtime = runtime
489 self._dependees = dependees
490 self._reasons = reasons
491 self._close_matches = close_matches
492
493 def getItem(self):
494 return self._item
495
496 def isRuntime(self):
497 return self._runtime
498
499class MultipleProviders(Event):
500 """Multiple Providers"""
501
502 def __init__(self, item, candidates, runtime = False):
503 Event.__init__(self)
504 self._item = item
505 self._candidates = candidates
506 self._is_runtime = runtime
507
508 def isRuntime(self):
509 """
510 Is this a runtime issue?
511 """
512 return self._is_runtime
513
514 def getItem(self):
515 """
516 The name for the to be build item
517 """
518 return self._item
519
520 def getCandidates(self):
521 """
522 Get the possible Candidates for a PROVIDER.
523 """
524 return self._candidates
525
526class ParseStarted(OperationStarted):
527 """Recipe parsing for the runqueue has begun"""
528 def __init__(self, total):
529 OperationStarted.__init__(self, "Recipe parsing Started")
530 self.total = total
531
532class ParseCompleted(OperationCompleted):
533 """Recipe parsing for the runqueue has completed"""
534 def __init__(self, cached, parsed, skipped, masked, virtuals, errors, total):
535 OperationCompleted.__init__(self, total, "Recipe parsing Completed")
536 self.cached = cached
537 self.parsed = parsed
538 self.skipped = skipped
539 self.virtuals = virtuals
540 self.masked = masked
541 self.errors = errors
542 self.sofar = cached + parsed
543
544class ParseProgress(OperationProgress):
545 """Recipe parsing progress"""
546 def __init__(self, current, total):
547 OperationProgress.__init__(self, current, total, "Recipe parsing")
548
549
550class CacheLoadStarted(OperationStarted):
551 """Loading of the dependency cache has begun"""
552 def __init__(self, total):
553 OperationStarted.__init__(self, "Loading cache Started")
554 self.total = total
555
556class CacheLoadProgress(OperationProgress):
557 """Cache loading progress"""
558 def __init__(self, current, total):
559 OperationProgress.__init__(self, current, total, "Loading cache")
560
561class CacheLoadCompleted(OperationCompleted):
562 """Cache loading is complete"""
563 def __init__(self, total, num_entries):
564 OperationCompleted.__init__(self, total, "Loading cache Completed")
565 self.num_entries = num_entries
566
567class TreeDataPreparationStarted(OperationStarted):
568 """Tree data preparation started"""
569 def __init__(self):
570 OperationStarted.__init__(self, "Preparing tree data Started")
571
572class TreeDataPreparationProgress(OperationProgress):
573 """Tree data preparation is in progress"""
574 def __init__(self, current, total):
575 OperationProgress.__init__(self, current, total, "Preparing tree data")
576
577class TreeDataPreparationCompleted(OperationCompleted):
578 """Tree data preparation completed"""
579 def __init__(self, total):
580 OperationCompleted.__init__(self, total, "Preparing tree data Completed")
581
582class DepTreeGenerated(Event):
583 """
584 Event when a dependency tree has been generated
585 """
586
587 def __init__(self, depgraph):
588 Event.__init__(self)
589 self._depgraph = depgraph
590
591class TargetsTreeGenerated(Event):
592 """
593 Event when a set of buildable targets has been generated
594 """
595 def __init__(self, model):
596 Event.__init__(self)
597 self._model = model
598
599class ReachableStamps(Event):
600 """
601 An event listing all stamps reachable after parsing
602 which the metadata may use to clean up stale data
603 """
604
605 def __init__(self, stamps):
606 Event.__init__(self)
607 self.stamps = stamps
608
609class FilesMatchingFound(Event):
610 """
611 Event when a list of files matching the supplied pattern has
612 been generated
613 """
614 def __init__(self, pattern, matches):
615 Event.__init__(self)
616 self._pattern = pattern
617 self._matches = matches
618
619class CoreBaseFilesFound(Event):
620 """
621 Event when a list of appropriate config files has been generated
622 """
623 def __init__(self, paths):
624 Event.__init__(self)
625 self._paths = paths
626
627class ConfigFilesFound(Event):
628 """
629 Event when a list of appropriate config files has been generated
630 """
631 def __init__(self, variable, values):
632 Event.__init__(self)
633 self._variable = variable
634 self._values = values
635
636class ConfigFilePathFound(Event):
637 """
638 Event when a path for a config file has been found
639 """
640 def __init__(self, path):
641 Event.__init__(self)
642 self._path = path
643
644class MsgBase(Event):
645 """Base class for messages"""
646
647 def __init__(self, msg):
648 self._message = msg
649 Event.__init__(self)
650
651class MsgDebug(MsgBase):
652 """Debug Message"""
653
654class MsgNote(MsgBase):
655 """Note Message"""
656
657class MsgWarn(MsgBase):
658 """Warning Message"""
659
660class MsgError(MsgBase):
661 """Error Message"""
662
663class MsgFatal(MsgBase):
664 """Fatal Message"""
665
666class MsgPlain(MsgBase):
667 """General output"""
668
669class LogExecTTY(Event):
670 """Send event containing program to spawn on tty of the logger"""
671 def __init__(self, msg, prog, sleep_delay, retries):
672 Event.__init__(self)
673 self.msg = msg
674 self.prog = prog
675 self.sleep_delay = sleep_delay
676 self.retries = retries
677
678class LogHandler(logging.Handler):
679 """Dispatch logging messages as bitbake events"""
680
681 def emit(self, record):
682 if record.exc_info:
683 etype, value, tb = record.exc_info
684 if hasattr(tb, 'tb_next'):
685 tb = list(bb.exceptions.extract_traceback(tb, context=3))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500686 # Need to turn the value into something the logging system can pickle
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500687 record.bb_exc_info = (etype, value, tb)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600688 record.bb_exc_formatted = bb.exceptions.format_exception(etype, value, tb, limit=5)
689 value = str(value)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500690 record.exc_info = None
691 fire(record, None)
692
693 def filter(self, record):
694 record.taskpid = worker_pid
695 return True
696
697class RequestPackageInfo(Event):
698 """
699 Event to request package information
700 """
701
702class PackageInfo(Event):
703 """
704 Package information for GUI
705 """
706 def __init__(self, pkginfolist):
707 Event.__init__(self)
708 self._pkginfolist = pkginfolist
709
710class MetadataEvent(Event):
711 """
712 Generic event that target for OE-Core classes
713 to report information during asynchrous execution
714 """
715 def __init__(self, eventtype, eventdata):
716 Event.__init__(self)
717 self.type = eventtype
718 self._localdata = eventdata
719
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600720class ProcessStarted(Event):
721 """
722 Generic process started event (usually part of the initial startup)
723 where further progress events will be delivered
724 """
725 def __init__(self, processname, total):
726 Event.__init__(self)
727 self.processname = processname
728 self.total = total
729
730class ProcessProgress(Event):
731 """
732 Generic process progress event (usually part of the initial startup)
733 """
734 def __init__(self, processname, progress):
735 Event.__init__(self)
736 self.processname = processname
737 self.progress = progress
738
739class ProcessFinished(Event):
740 """
741 Generic process finished event (usually part of the initial startup)
742 """
743 def __init__(self, processname):
744 Event.__init__(self)
745 self.processname = processname
746
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500747class SanityCheck(Event):
748 """
749 Event to run sanity checks, either raise errors or generate events as return status.
750 """
751 def __init__(self, generateevents = True):
752 Event.__init__(self)
753 self.generateevents = generateevents
754
755class SanityCheckPassed(Event):
756 """
757 Event to indicate sanity check has passed
758 """
759
760class SanityCheckFailed(Event):
761 """
762 Event to indicate sanity check has failed
763 """
764 def __init__(self, msg, network_error=False):
765 Event.__init__(self)
766 self._msg = msg
767 self._network_error = network_error
768
769class NetworkTest(Event):
770 """
771 Event to run network connectivity tests, either raise errors or generate events as return status.
772 """
773 def __init__(self, generateevents = True):
774 Event.__init__(self)
775 self.generateevents = generateevents
776
777class NetworkTestPassed(Event):
778 """
779 Event to indicate network test has passed
780 """
781
782class NetworkTestFailed(Event):
783 """
784 Event to indicate network test has failed
785 """
786