Package Products :: Package ZenEvents :: Package events2 :: Module proxy
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenEvents.events2.proxy

  1  ############################################################################## 
  2  #  
  3  # Copyright (C) Zenoss, Inc. 2010, all rights reserved. 
  4  #  
  5  # This content is made available according to terms specified in 
  6  # License.zenoss under the directory where your Zenoss product is installed. 
  7  #  
  8  ############################################################################## 
  9   
 10   
 11  from itertools import imap 
 12  from Products.ZenUtils.Time import LocalDateTimeFromMilli 
 13  from Products.ZenEvents.events2.fields import EventField, EventSummaryField, ZepRawEventField 
 14  from zenoss.protocols.protobufs.model_pb2 import DEVICE, COMPONENT 
 15  from zenoss.protocols.protobufs.zep_pb2 import ( 
 16      STATUS_NEW, 
 17      STATUS_ACKNOWLEDGED, 
 18      STATUS_SUPPRESSED, 
 19      STATUS_CLOSED, 
 20      STATUS_CLEARED, 
 21      STATUS_DROPPED, 
 22      STATUS_AGED, 
 23      SEVERITY_CLEAR, 
 24      EventTag, 
 25      EventDetail 
 26  ) 
 27  from zenoss.protocols.jsonformat import to_dict 
 28   
 29  import logging 
 30  log = logging.getLogger('zen.%s' % __name__) 
31 32 -class EventTagProxy(object):
33 """ 34 A proxy for a tag UUID dictionary. Maps org.zenoss.protocols.zep.EventTag 35 to a dictionary. 36 """
37 - def __init__(self, eventProtobufWithTags):
38 self._eventProtobuf = eventProtobufWithTags 39 self._tags = {} 40 self._load()
41
42 - def _load(self):
43 for tag in self._eventProtobuf.tags: 44 tag_uuids = self._tags.get(tag.type) 45 if not tag_uuids: 46 self._tags[tag.type] = tag_uuids = set() 47 for tagUuid in tag.uuid: 48 tag_uuids.add(tagUuid)
49
50 - def add(self, type, uuid):
51 tag_uuids = self._tags.get(type) 52 if not tag_uuids: 53 self._tags[type] = tag_uuids = set() 54 55 if not uuid in tag_uuids: 56 tag_uuids.add(uuid) 57 58 event_tag = None 59 for tag in self._eventProtobuf.tags: 60 if tag.type == type: 61 event_tag = tag 62 break 63 else: 64 event_tag = self._eventProtobuf.tags.add() 65 event_tag.type = type 66 67 event_tag.uuid.append(uuid)
68
69 - def addAll(self, type, uuids):
70 for uuid in uuids: 71 self.add(type, uuid)
72
73 - def getByType(self, type):
74 return self._tags.get(type, ())
75
76 - def clearType(self, removetype):
77 # accept a single type or a list of types - if a single value given, make it a 1-element list 78 79 # if a generator was given, consume it into a temporary list 80 if hasattr(removetype, 'next'): 81 removetype = list(removetype) 82 83 # make single value into a temporary list 84 if not hasattr(removetype, '__iter__'): 85 removetype = [removetype] 86 87 # remove all entries from mapping 88 for typ in removetype: 89 if typ in self._tags: 90 del self._tags[typ] 91 92 # clear values from protobuf tags by assigning new list comprehension into 93 # protobuf tags list in place (using [:] slice would be a lot easier, but not implemented) 94 95 # This doesn't work - see http://code.google.com/p/protobuf/issues/detail?id=286 96 #saveTags = [tag for tag in self._eventProtobuf.tags if tag.type not in removetype] 97 saveTags = [] 98 for tag in self._eventProtobuf.tags: 99 if tag.type not in removetype: 100 cloned = EventTag() 101 cloned.MergeFrom(tag) 102 saveTags.append(cloned) 103 104 del self._eventProtobuf.tags[:] 105 self._eventProtobuf.tags.extend(saveTags)
106
107 108 -class EventDetailProxy(object):
109 """ 110 A proxy for a details dictionary. Maps org.zenoss.protocols.zep.EventDetail 111 to a dictionary. 112 """
113 - def __init__(self, eventProtobuf):
114 self.__dict__['_eventProtobuf'] = eventProtobuf 115 self.__dict__['_map'] = {} 116 117 for detail in self._eventProtobuf.details: 118 self._map[detail.name] = detail
119
120 - def __getattr__(self, name):
121 try: 122 return self[name] 123 except KeyError: 124 raise AttributeError(name)
125
126 - def __setattr__(self, name, value):
127 self[name] = value
128
129 - def __delitem__(self, key):
130 if key in self._map: 131 item = self._map.pop(key) 132 # This doesn't work - see http://code.google.com/p/protobuf/issues/detail?id=286 133 #savedetails = [det for det in self._eventProtobuf.details if det is not item] 134 savedetails = [] 135 for det in self._eventProtobuf.details: 136 if det.name != item.name: 137 cloned = EventDetail() 138 cloned.MergeFrom(det) 139 savedetails.append(cloned) 140 self._map[cloned.name] = cloned 141 del self._eventProtobuf.details[:] 142 self._eventProtobuf.details.extend(savedetails)
143
144 - def __getitem__(self, key):
145 item = self._map[key] 146 # Details are expected to be single values, 147 # we'll just have to do our best to make it so 148 if len(item.value) == 0: 149 return None 150 if len(item.value) == 1: 151 return item.value[0] 152 else: 153 raise Exception('Detail %s has more than one value but the old event system expects only one: %s' % (item.name, item.value))
154
155 - def __setitem__(self, key, value):
156 # Prep the field 157 if value: 158 if not key in self._map: 159 item = self._eventProtobuf.details.add() 160 item.name = key 161 self._map[key] = item 162 item = self._map[key] 163 item.ClearField(EventField.Detail.VALUE) 164 # Assume multivalue details 165 if not isinstance(value, (set, list, tuple)): 166 value = (value,) 167 # Set each detail if it exists 168 for val in imap(str, value): 169 if val: 170 item.value.append(val)
171
172 - def __contains__(self, key):
173 return key in self._map
174
175 - def __len__(self):
176 return len(self._map)
177
178 - def get(self, key, default=None):
179 try: 180 return self[key] 181 except KeyError: 182 return default
183
184 - def set(self, key, value):
185 self[key] = value
186
187 - def getAll(self, key, default=None):
188 """ 189 The normal __getitem__ and get() methods throw an exception for multi-valued details. This one specifically 190 allows multi-valued details. 191 """ 192 try: 193 return self._map[key].value 194 except KeyError: 195 return default
196
197 -class ProtobufWrapper(object):
198 """ 199 Conveinence wrapper for protobufs to make sure fields 200 are actually set. 201 """
202 - def __init__(self, pb):
203 self.__dict__['_pb'] = pb
204
205 - def get(self, key, default=None):
206 if self._pb.HasField(key): 207 return getattr(self._pb, key) 208 else: 209 return default
210
211 - def set(self, key, value):
212 setattr(self.__dict__['_pb'], key, value)
213
214 - def __getattr__(self, name):
215 return getattr(self._pb, name)
216
217 - def __setattr__(self, name, value):
218 self.set(name, value)
219
220 - def __delattr__(self, name):
221 self._pb.ClearField(name)
222
223 - def HasField(self, name):
224 return self._pb.HasField(name)
225
226 -class EventProxy(object):
227 """ 228 Wraps an org.zenoss.protobufs.zep.Event 229 and makes it look like an old style Event. 230 """ 231 232 DEVICE_PRIORITY_DETAIL_KEY = "zenoss.device.priority" 233 PRODUCTION_STATE_DETAIL_KEY = "zenoss.device.production_state" 234 DEVICE_IP_ADDRESS_DETAIL_KEY = 'zenoss.device.ip_address' 235 DEVICE_SYSTEMS_DETAIL_KEY = 'zenoss.device.systems' 236 DEVICE_GROUPS_DETAIL_KEY = 'zenoss.device.groups' 237 DEVICE_LOCATION_DETAIL_KEY = 'zenoss.device.location' 238 DEVICE_CLASS_DETAIL_KEY = 'zenoss.device.device_class' 239
240 - def __init__(self, eventProtobuf):
241 self.__dict__['_event'] = ProtobufWrapper(eventProtobuf) 242 self.__dict__['_clearClasses'] = set() 243 self.__dict__['_readOnly'] = {} 244 self.__dict__['details'] = EventDetailProxy(self._event) 245 self.__dict__['_tags'] = EventTagProxy(self._event)
246
247 - def updateFromDict(self, data):
248 for key, value in data.iteritems(): 249 setattr(self, key, value)
250 251 @property
252 - def created(self):
253 t = self._event.get(EventField.CREATED_TIME) 254 if t: 255 return t / 1000
256 @property
257 - def agent(self):
258 return self._event.get(EventField.AGENT)
259 260 @agent.setter
261 - def agent(self, val):
262 self._event.set(EventField.AGENT, val)
263 264 @property
265 - def severity(self):
266 return self._event.get(EventField.SEVERITY)
267 268 @severity.setter
269 - def severity(self, val):
270 self._event.set(EventField.SEVERITY, int(val))
271 272 @property
273 - def device(self):
274 return self._event.actor.element_identifier
275 276 @device.setter
277 - def device(self, val):
278 self._event.actor.element_identifier = val 279 self._event.actor.element_type_id = DEVICE 280 self._event.actor.ClearField(EventField.Actor.ELEMENT_UUID)
281 282 @property
283 - def component(self):
284 return self._event.actor.element_sub_identifier
285 286 @component.setter
287 - def component(self, val):
288 self._event.actor.element_sub_identifier = val 289 self._event.actor.element_sub_type_id = COMPONENT 290 self._event.actor.ClearField(EventField.Actor.ELEMENT_SUB_UUID)
291 292 @property
293 - def eventClass(self):
294 eventClassValue = self._event.get(EventField.EVENT_CLASS) 295 if isinstance( eventClassValue, unicode ): 296 eventClassValue = str( eventClassValue ) 297 return eventClassValue
298 299 @eventClass.setter
300 - def eventClass(self, val):
301 self._event.set(EventField.EVENT_CLASS, val)
302 303 @property
304 - def prodState(self):
305 state = self.details.get(EventProxy.PRODUCTION_STATE_DETAIL_KEY) 306 if state: 307 return int(state)
308 309 @prodState.setter
310 - def prodState(self, val):
311 self.details.set(EventProxy.PRODUCTION_STATE_DETAIL_KEY, int(val))
312 313 @property
314 - def summary(self):
315 return self._event.get(EventField.SUMMARY)
316 317 @summary.setter
318 - def summary(self, val):
319 self._event.set(EventField.SUMMARY, val)
320 321 @property
322 - def message(self):
323 return self._event.get(EventField.MESSAGE)
324 325 @message.setter
326 - def message(self, val):
327 self._event.set(EventField.MESSAGE, val)
328 329 @property
330 - def facility(self):
331 return self._event.get(EventField.SYSLOG_FACILITY)
332 333 @facility.setter
334 - def facility(self, val):
335 self._event.set(EventField.SYSLOG_FACILITY, val)
336 337 @property
338 - def eventClassKey(self):
339 return self._event.get(EventField.EVENT_CLASS_KEY)
340 341 @eventClassKey.setter
342 - def eventClassKey(self, val):
343 self._event.set(EventField.EVENT_CLASS_KEY, val)
344 345 @property
346 - def dedupid(self):
347 return self._event.get(EventField.FINGERPRINT)
348 349 @dedupid.setter
350 - def dedupid(self, val):
351 self._event.set(EventField.FINGERPRINT, val)
352 353 @property
354 - def monitor(self):
355 return self._event.get(EventField.MONITOR)
356 357 @monitor.setter
358 - def monitor(self, val):
359 self._event.set(EventField.MONITOR, val)
360 361 @property
362 - def ntevid(self):
363 return self._event.get(EventField.NT_EVENT_CODE)
364 365 @ntevid.setter
366 - def ntevid(self, val):
367 self._event.set(EventField.NT_EVENT_CODE, val)
368 369 @property
370 - def DevicePriority(self):
371 priority = self.details.get(EventProxy.DEVICE_PRIORITY_DETAIL_KEY) 372 if priority: 373 return int(priority)
374 375 @DevicePriority.setter
376 - def DevicePriority(self, val):
377 self.details.set(EventProxy.DEVICE_PRIORITY_DETAIL_KEY, int(val))
378 379 @property
380 - def priority(self):
381 return self._event.get(EventField.SYSLOG_PRIORITY)
382 383 @priority.setter
384 - def priority(self, val):
385 self._event.set(EventField.SYSLOG_PRIORITY, val)
386 387 @property
388 - def evid(self):
389 return self._event.get(EventField.UUID)
390 391 @property
392 - def eventKey(self):
393 return self._event.get(EventField.EVENT_KEY)
394 395 @eventKey.setter
396 - def eventKey(self, val):
397 self._event.set(EventField.EVENT_KEY, val)
398 399 @property
400 - def eventGroup(self):
401 return self._event.get(EventField.EVENT_GROUP)
402 403 @eventGroup.setter
404 - def eventGroup(self, val):
405 self._event.set(EventField.EVENT_GROUP, val)
406 407 @property
408 - def ipAddress(self):
409 return self.details.get(EventProxy.DEVICE_IP_ADDRESS_DETAIL_KEY)
410 411 @ipAddress.setter
412 - def ipAddress(self, val):
414 415 @property
416 - def DeviceClass(self):
417 return self.details.get(EventProxy.DEVICE_CLASS_DETAIL_KEY)
418 419 @DeviceClass.setter
420 - def DeviceClass(self, val):
421 self.details.set(EventProxy.DEVICE_CLASS_DETAIL_KEY, val)
422 423 @property
424 - def eventState(self):
425 return self._event.get(EventSummaryField.STATUS, STATUS_NEW)
426 427 @eventState.setter
428 - def eventState(self, val):
429 self._event.set(EventSummaryField.STATUS, val)
430 431 @property
432 - def tags(self):
433 return self._tags
434 435 @property
436 - def Location(self):
437 return self.details.get(EventProxy.DEVICE_LOCATION_DETAIL_KEY)
438 439 @property
440 - def Systems(self):
441 values = self.details.getAll(EventProxy.DEVICE_SYSTEMS_DETAIL_KEY) 442 if values: 443 return '|' + '|'.join(values)
444 445 @property
446 - def DeviceGroups(self):
447 values = self.details.getAll(EventProxy.DEVICE_GROUPS_DETAIL_KEY) 448 if values: 449 return '|' + '|'.join(values)
450
451 - def setReadOnly(self, name, value):
452 """ 453 Adds a read only attribute for transforms to read. 454 These properties are not sent with the event to the queue. 455 """ 456 self._readOnly[name] = value
457
458 - def resetReadOnly(self, name):
459 """ 460 Clears a read only attribute so it can be updated. 461 """ 462 self._readOnly.pop(name, None)
463 464 # Just put everything else in the details
465 - def __getattr__(self, name):
466 if name in self._readOnly: 467 return self._readOnly[name] 468 469 try: 470 return self.__dict__['details'][name] 471 except KeyError: 472 raise AttributeError(name)
473
474 - def __setattr__(self, name, value):
475 if hasattr(self.__class__, name): 476 object.__setattr__(self, name, value) 477 else: 478 self.__dict__['details'][name] = value
479
480 -class EventSummaryProxy(EventProxy):
481 """ 482 Wraps an org.zenoss.protobufs.zep.EventSummary 483 484 and makes it look like an old style Event. 485 """
486 - def __init__(self, eventSummaryProtobuf):
487 self.__dict__['_eventSummary'] = ProtobufWrapper(eventSummaryProtobuf) 488 if not self._eventSummary.occurrence: 489 self._eventSummary.occurrence.add() 490 491 event = self._eventSummary.occurrence[0] 492 EventProxy.__init__(self, event)
493 494 @property
495 - def evid(self):
496 return self._eventSummary.get(EventSummaryField.UUID)
497 498 @property
499 - def stateChange(self):
500 t = self._eventSummary.get(EventSummaryField.STATUS_CHANGE_TIME) 501 if t: 502 return LocalDateTimeFromMilli(t)
503 504 @property
505 - def clearid(self):
506 return self._eventSummary.get(EventSummaryField.CLEARED_BY_EVENT_UUID)
507 508 @clearid.setter
509 - def clearid(self, val):
510 self._eventSummary.set(EventSummaryField.CLEARED_BY_EVENT_UUID, val)
511 512 @property
513 - def firstTime(self):
514 t = self._eventSummary.get(EventSummaryField.FIRST_SEEN_TIME) 515 if t: 516 return LocalDateTimeFromMilli(t)
517 518 @property
519 - def lastTime(self):
520 t = self._eventSummary.get(EventSummaryField.LAST_SEEN_TIME) 521 if t: 522 return LocalDateTimeFromMilli(t)
523 524 @property
525 - def count(self):
526 return self._eventSummary.get(EventSummaryField.COUNT, 0)
527 528 @property
529 - def ownerid(self):
530 return self._eventSummary.get(EventSummaryField.CURRENT_USER_NAME)
531 532 @ownerid.setter
533 - def ownerid(self, val):
534 self._eventSummary.set(EventSummaryField.CURRENT_USER_NAME, val)
535 536 @property
537 - def eventState(self):
538 return self._eventSummary.get(EventSummaryField.STATUS, STATUS_NEW)
539 540 @eventState.setter
541 - def eventState(self, val):
542 self._eventSummary.set(EventSummaryField.STATUS, val)
543
544 -class ZepRawEventProxy(EventProxy):
545 """ 546 Wraps an org.zenoss.protobufs.zep.ZepRawEvent and makes it look like 547 an old style Event. It is the proper event proxy to use for transforms 548 since transforms use _action and _clearClasses. 549 """ 550 ACTION_HISTORY = 'history' 551 ACTION_DROP = 'drop' 552 ACTION_STATUS = 'status' 553 ACTION_HEARTBEAT = 'heartbeat' 554 ACTION_LOG = 'log' 555 ACTION_ALERT_STATE = 'alert_state' 556 ACTION_DETAIL = 'detail' 557 558 ACTION_STATUS_MAP = { 559 ACTION_HISTORY : STATUS_CLOSED, 560 ACTION_STATUS : STATUS_NEW, 561 ACTION_DROP : STATUS_DROPPED, 562 None : STATUS_NEW, 563 } 564 565 STATUS_ACTION_MAP = { 566 STATUS_NEW : ACTION_STATUS, 567 STATUS_ACKNOWLEDGED : ACTION_STATUS, 568 STATUS_SUPPRESSED : ACTION_STATUS, 569 STATUS_CLOSED : ACTION_HISTORY, 570 STATUS_CLEARED : ACTION_HISTORY, 571 STATUS_DROPPED : ACTION_DROP, 572 STATUS_AGED : ACTION_HISTORY, 573 None : ACTION_STATUS, 574 } 575
576 - def __init__(self, zepRawEvent):
577 self.__dict__['_zepRawEvent'] = ProtobufWrapper(zepRawEvent) 578 EventProxy.__init__(self, self._zepRawEvent.event) 579 580 classes = [] 581 if self._zepRawEvent.clear_event_class: 582 classes = list(self._zepRawEvent.clear_event_class) 583 584 self.__dict__['_clearClassesSet'] = set(classes) 585 self._refreshClearClasses()
586
587 - def __str__(self):
588 return "{_zepRawEvent:%s}" % str(to_dict(self._zepRawEvent))
589
590 - def _refreshClearClasses(self):
591 # Add this dynamically in case severity or event_class changes 592 if self._event.severity == SEVERITY_CLEAR and self._event.get(EventField.EVENT_CLASS): 593 self._clearClassesSet.add(self._event.event_class) 594 595 del self._zepRawEvent.clear_event_class 596 for eventClass in self._clearClassesSet: 597 self._zepRawEvent.clear_event_class.append(eventClass)
598 599 @property
600 - def _clearClasses(self):
601 return list(self._clearClassesSet)
602 603 @_clearClasses.setter
604 - def _clearClasses(self, val):
605 self._clearClassesSet.clear() 606 self._clearClassesSet.update(val) 607 self._refreshClearClasses()
608 609 @property
610 - def _action(self):
611 return self.STATUS_ACTION_MAP.get(self.eventState, self.STATUS_ACTION_MAP[None])
612 613 @_action.setter
614 - def _action(self, val):
615 current_status = self.STATUS_ACTION_MAP.get(self.eventState) 616 if current_status != val: 617 self.eventState = self.ACTION_STATUS_MAP.get(val, self.ACTION_STATUS_MAP[None])
618 619 @property
620 - def eventClassMapping(self):
621 return self.details.get('eventClassMapping', '')
622 623 @eventClassMapping.setter
624 - def eventClassMapping(self, val):
625 # TODO: event_class_mapping_uuid needs to be set separately to avoid 626 # duplicate lookups 627 self.details['eventClassMapping'] = val
628 629 630 # add lists to introspect valid fields for types 631 for typ in (EventProxy, EventSummaryProxy): 632 typ.FIELDS = [name for name in dir(typ) if isinstance(getattr(typ,name), property)] 633