Package Products :: Package ZenModel :: Module actions
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenModel.actions

  1  ############################################################################## 
  2  #  
  3  # Copyright (C) Zenoss, Inc. 2007, 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  import re 
 12  from socket import getaddrinfo 
 13  from traceback import format_exc 
 14  from zope.interface import implements 
 15  from zope.component import getUtilitiesFor 
 16   
 17  from pynetsnmp import netsnmp 
 18   
 19  from twisted.internet.protocol import ProcessProtocol 
 20   
 21  from email.MIMEText import MIMEText 
 22  from email.MIMEMultipart import MIMEMultipart 
 23  from email.Utils import formatdate 
 24   
 25  from zenoss.protocols.protobufs import zep_pb2 
 26  from Products.ZenEvents.events2.proxy import EventSummaryProxy 
 27  from Products.ZenUtils.Utils import sendEmail 
 28  from Products.Zuul.interfaces.actions import IEmailActionContentInfo, IPageActionContentInfo, ICommandActionContentInfo, ISnmpTrapActionContentInfo 
 29  from Products.Zuul.form.interfaces import IFormBuilder 
 30  from Products.ZenModel.UserSettings import GroupSettings 
 31  from Products.ZenModel.interfaces import IAction, IProvidesEmailAddresses, IProvidesPagerAddresses, IProcessSignal, INotificationContextProvider 
 32  from Products.ZenModel.NotificationSubscription import NotificationEventContextWrapper 
 33  from Products.ZenEvents.Event import Event 
 34  from Products.ZenUtils import Utils 
 35  from Products.ZenUtils.guid.guid import GUIDManager 
 36  from Products.ZenUtils.ProcessQueue import ProcessQueue 
 37  from Products.ZenEvents.ZenEventClasses import Warning as SEV_WARNING 
 38  from Products.ZenUtils.ZenTales import talEval 
 39   
 40  import logging 
 41   
 42  log = logging.getLogger("zen.actions") 
 43   
 44   
 45   
 46   
47 -class ActionExecutionException(Exception): pass
48 49
50 -class ActionMissingException(Exception): pass
51 52
53 -class TargetableActionException(ActionExecutionException):
54 - def __init__(self, action, notification, exceptionTargets):
55 self.action = action 56 self.notificationId = notification.id 57 self.exceptionTargets = exceptionTargets
58 - def __str__(self):
59 return "Failed {action} for notification {notification} on targets {targets}".format( 60 action=self.action.name, 61 notification=self.notificationId, 62 targets = ','.join(self.exceptionTargets) 63 )
64
65 -def processTalSource(source, **kwargs):
66 """ 67 This function is used to parse fields made available to actions that allow 68 for TAL expressions. 69 """ 70 sourceStr = source 71 context = kwargs.get('here', {}) 72 context.update(kwargs) 73 return talEval(sourceStr, context, kwargs)
74 75
76 -def _signalToContextDict(signal, zopeurl, notification=None, guidManager=None):
77 summary = signal.event 78 # build basic event context wrapper for notifications 79 if signal.clear: 80 # aged and closed events have clear == True, but they don't have an associated clear event 81 # spoof a clear event in those cases, so the notification messages contain useful info 82 if summary.status == zep_pb2.STATUS_AGED: 83 occur = signal.clear_event.occurrence.add() 84 occur.summary = "Event aging task aged out the event." 85 summary.cleared_by_event_uuid = "Event aging task" 86 elif summary.status == zep_pb2.STATUS_CLOSED: 87 occur = signal.clear_event.occurrence.add() 88 occur.summary = "User '" + summary.current_user_name + "' closed the event in the Zenoss event console." 89 summary.cleared_by_event_uuid = "User action" 90 data = NotificationEventContextWrapper(summary, signal.clear_event) 91 else: 92 data = NotificationEventContextWrapper(summary) 93 94 # add urls to event context 95 data['urls']['eventUrl'] = getEventUrl(zopeurl, summary.uuid) 96 data['urls']['ackUrl'] = getAckUrl(zopeurl, summary.uuid) 97 data['urls']['closeUrl'] = getCloseUrl(zopeurl, summary.uuid) 98 proxy = EventSummaryProxy(summary) 99 data['urls']['deviceUrl'] = _getBaseDeviceUrl(zopeurl, proxy.DeviceClass, proxy.device) 100 data['urls']['eventsUrl'] = getEventsUrl(zopeurl, proxy.DeviceClass, proxy.device) 101 data['urls']['reopenUrl'] = getReopenUrl(zopeurl, summary.uuid) 102 data['urls']['baseUrl'] = zopeurl 103 # now process all custom processors that might be registered to enhance 104 # the event context 105 for key, processor in getUtilitiesFor(IProcessSignal): 106 data[key] = processor.process(signal) 107 108 # Process INotificationContextProvider 109 for key, contextProvider in getUtilitiesFor(INotificationContextProvider): 110 contextProvider.updateContext(signal, data) 111 112 # Add trigger and notification info 113 if notification: 114 data['notification']['name'] = notification.titleOrId() 115 if guidManager: 116 trigger = guidManager.getObject(signal.trigger_uuid) 117 if trigger: 118 data['trigger']['name'] = trigger.titleOrId() 119 120 return data
121 122
123 -def _getBaseUrl(zopeurl):
124 if not zopeurl: 125 zopeurl = Utils.getDefaultZopeUrl() 126 return '%s/zport/dmd' % zopeurl
127 128
129 -def _getBaseEventUrl(zopeurl):
130 return '%s/Events' % _getBaseUrl(zopeurl)
131 132
133 -def _getBaseDeviceUrl(zopeurl, device_class, device_name):
134 """ 135 Builds the URL for a device. 136 Example: "http://.../Devices/Server/Linux/devices/localhost/devicedetail" 137 """ 138 return '%s/Devices%s/devices/%s/devicedetail' % (_getBaseUrl(zopeurl), device_class, device_name)
139 140
141 -def getEventUrl(zopeurl, evid):
142 return "%s/viewDetail?evid=%s" % (_getBaseEventUrl(zopeurl), evid)
143 144
145 -def getEventsUrl(zopeurl, device_class=None, device_name=None):
146 if device_class and device_name: 147 # events for a specific device 148 return "%s#deviceDetailNav:device_events" % _getBaseDeviceUrl(zopeurl, device_class, device_name) 149 else: 150 #events on all devices 151 return "%s/viewEvents" % _getBaseUrl(zopeurl)
152 153
154 -def getAckUrl(zopeurl, evid):
155 return "%s/manage_ackEvents?evids=%s&zenScreenName=viewEvents" %\ 156 (_getBaseEventUrl(zopeurl), evid)
157 158
159 -def getCloseUrl(zopeurl, evid):
160 return "%s/manage_deleteEvents?evids=%s&zenScreenName=viewHistoryEvents" %\ 161 (_getBaseEventUrl(zopeurl), evid)
162 163
164 -def getReopenUrl(zopeurl, evid):
165 return "%s/manage_undeleteEvents?evids=%s&zenScreenName=viewEvents" %\ 166 (_getBaseEventUrl(zopeurl), evid)
167 168
169 -class IActionBase(object):
170 """ 171 Mixin class for provided some common, necessary, methods. 172 """ 173
174 - def configure(self, options):
175 self.options = options
176
177 - def getInfo(self, notification):
178 return self.actionContentInfo(notification)
179
180 - def generateJavascriptContent(self, notification):
181 content = self.getInfo(notification) 182 return IFormBuilder(content).render(fieldsets=False)
183
184 - def getDefaultData(self, dmd):
185 return {}
186 187
188 -class TargetableAction(object):
189 190 shouldExecuteInBatch = False 191
192 - def setupAction(self, dmd):
193 """ 194 Some actions need to configure themselves with properties from the dmd. 195 This is their opportunity to do so. 196 """ 197 pass
198
199 - def getTargets(self, notification):
200 targets = set() 201 for recipient in notification.recipients: 202 if recipient['type'] in ['group', 'user']: 203 guid = recipient['value'] 204 target_obj = self.guidManager.getObject(guid) 205 if target_obj: 206 for target in self.getActionableTargets(target_obj): 207 targets.add(target) 208 else: 209 targets.add(recipient['value']) 210 return targets
211
212 - def handleExecuteError(self, exception, notification, target):
213 # If there is an error executing this action on a target, 214 # we need to handle it, but we don't want to prevent other 215 # actions from executing on any other targets that may be 216 # about to be acted on. 217 msg = 'Error executing action {notification} on {target}'.format( 218 notification=notification.id, 219 target=target, 220 ) 221 log.error(exception) 222 log.error(msg) 223 traceback = format_exc() 224 event = Event(device="localhost", 225 eventClass="/App/Failed", 226 summary=msg, 227 message=traceback, 228 severity=SEV_WARNING, component="zenactiond") 229 notification.dmd.ZenEventManager.sendEvent(event)
230 231
232 - def executeBatch(self, notification, signal, targets):
233 raise NotImplemented()
234 235
236 - def execute(self, notification, signal):
237 self.setupAction(notification.dmd) 238 239 exceptionTargets = [] 240 targets = self.getTargets(notification) 241 if self.shouldExecuteInBatch: 242 try: 243 log.debug("Executing batch action for targets.") 244 self.executeBatch(notification, signal, targets) 245 except Exception, e: 246 self.handleExecuteError(e, notification, targets) 247 exceptionTargets.extend(targets) 248 else: 249 log.debug("Executing action serially for targets.") 250 for target in targets: 251 try: 252 self.executeOnTarget(notification, signal, target) 253 log.debug('Done executing action for target: %s' % target) 254 except Exception, e: 255 self.handleExecuteError(e, notification, target) 256 exceptionTargets.append(target) 257 258 if exceptionTargets: 259 raise TargetableActionException(self, notification, exceptionTargets)
260
261 -class EmailAction(IActionBase, TargetableAction):
262 implements(IAction) 263 id = 'email' 264 name = 'Email' 265 actionContentInfo = IEmailActionContentInfo 266 267 shouldExecuteInBatch = True 268
269 - def __init__(self):
270 super(EmailAction, self).__init__()
271
272 - def getDefaultData(self, dmd):
273 return dict(host=dmd.smtpHost, 274 port=dmd.smtpPort, 275 user=dmd.smtpUser, 276 password=dmd.smtpPass, 277 useTls=dmd.smtpUseTLS, 278 email_from=dmd.getEmailFrom())
279
280 - def setupAction(self, dmd):
281 self.guidManager = GUIDManager(dmd)
282
283 - def executeBatch(self, notification, signal, targets):
284 log.debug("Executing %s action for targets: %s", self.name, targets) 285 self.setupAction(notification.dmd) 286 287 data = _signalToContextDict(signal, self.options.get('zopeurl'), notification, self.guidManager) 288 if signal.clear: 289 log.debug('This is a clearing signal.') 290 subject = processTalSource(notification.content['clear_subject_format'], **data) 291 body = processTalSource(notification.content['clear_body_format'], **data) 292 else: 293 subject = processTalSource(notification.content['subject_format'], **data) 294 body = processTalSource(notification.content['body_format'], **data) 295 296 log.debug('Sending this subject: %s' % subject) 297 log.debug('Sending this body: %s' % body) 298 299 plain_body = MIMEText(self._stripTags(body)) 300 email_message = plain_body 301 302 if notification.content['body_content_type'] == 'html': 303 email_message = MIMEMultipart('related') 304 email_message_alternative = MIMEMultipart('alternative') 305 email_message_alternative.attach(plain_body) 306 307 html_body = MIMEText(body.replace('\n', '<br />\n')) 308 html_body.set_type('text/html') 309 email_message_alternative.attach(html_body) 310 311 email_message.attach(email_message_alternative) 312 313 host = notification.content['host'] 314 port = notification.content['port'] 315 user = notification.content['user'] 316 password = notification.content['password'] 317 useTls = notification.content['useTls'] 318 email_from = notification.content['email_from'] 319 320 email_message['Subject'] = subject 321 email_message['From'] = email_from 322 email_message['To'] = ','.join(targets) 323 email_message['Date'] = formatdate(None, True) 324 325 result, errorMsg = sendEmail( 326 email_message, 327 host, port, 328 useTls, 329 user, password 330 ) 331 332 if result: 333 log.debug("Notification '%s' sent emails to: %s", 334 notification.id, targets) 335 else: 336 raise ActionExecutionException( 337 "Notification '%s' FAILED to send emails to %s: %s" % 338 (notification.id, targets, errorMsg) 339 )
340
341 - def getActionableTargets(self, target):
342 """ 343 @param target: This is an object that implements the IProvidesEmailAddresses 344 interface. 345 @type target: UserSettings or GroupSettings. 346 """ 347 if IProvidesEmailAddresses.providedBy(target): 348 return target.getEmailAddresses()
349
350 - def _stripTags(self, data):
351 """A quick html => plaintext converter 352 that retains and displays anchor hrefs 353 354 stolen from the old zenactions. 355 @todo: needs to be updated for the new data structure? 356 """ 357 tags = re.compile(r'<(.|\n)+?>', re.I | re.M) 358 aattrs = re.compile(r'<a(.|\n)+?href=["\']([^"\']*)[^>]*?>([^<>]*?)</a>', re.I | re.M) 359 anchors = re.finditer(aattrs, data) 360 for x in anchors: data = data.replace(x.group(), "%s: %s" % (x.groups()[2], x.groups()[1])) 361 data = re.sub(tags, '', data) 362 return data
363
364 - def updateContent(self, content=None, data=None):
365 updates = dict() 366 updates['body_content_type'] = data.get('body_content_type', 'html') 367 368 properties = ['subject_format', 'body_format', 'clear_subject_format', 'clear_body_format'] 369 properties.extend(['host', 'port', 'user', 'password', 'useTls', 'email_from']) 370 for k in properties: 371 updates[k] = data.get(k) 372 373 content.update(updates)
374 375
376 -class PageAction(IActionBase, TargetableAction):
377 implements(IAction) 378 379 id = 'page' 380 name = 'Page' 381 actionContentInfo = IPageActionContentInfo 382
383 - def __init__(self):
384 super(PageAction, self).__init__()
385
386 - def setupAction(self, dmd):
387 self.guidManager = GUIDManager(dmd) 388 self.page_command = dmd.pageCommand
389
390 - def executeOnTarget(self, notification, signal, target):
391 """ 392 @TODO: handle the deferred parameter on the sendPage call. 393 """ 394 log.debug('Executing action: Page') 395 396 data = _signalToContextDict(signal, self.options.get('zopeurl'), notification, self.guidManager) 397 if signal.clear: 398 log.debug('This is a clearing signal.') 399 subject = processTalSource(notification.content['clear_subject_format'], **data) 400 else: 401 subject = processTalSource(notification.content['subject_format'], **data) 402 403 success, errorMsg = Utils.sendPage( 404 target, subject, self.page_command, 405 #deferred=self.options.cycle) 406 deferred=False) 407 408 if success: 409 log.debug("Notification '%s' sent page to %s." % (notification, target)) 410 else: 411 raise ActionExecutionException( 412 "Notification '%s' failed to send page to %s. (%s)" % (notification, target, errorMsg))
413
414 - def getActionableTargets(self, target):
415 """ 416 @param target: This is an object that implements the IProvidesPagerAddresses 417 interface. 418 @type target: UserSettings or GroupSettings. 419 """ 420 if IProvidesPagerAddresses.providedBy(target): 421 return target.getPagerAddresses()
422
423 - def updateContent(self, content=None, data=None):
424 updates = dict() 425 426 properties = ['subject_format', 'clear_subject_format', ] 427 for k in properties: 428 updates[k] = data.get(k) 429 430 content.update(updates)
431 432
433 -class EventCommandProtocol(ProcessProtocol):
434 - def __init__(self, cmd):
435 self.cmd = cmd 436 self.data = '' 437 self.error = ''
438
439 - def timedOut(self, value):
440 log.error("Command '%s' timed out" % self.cmd.id) 441 # FIXME: send an event or something? 442 return value
443
444 - def processEnded(self, reason):
445 log.debug("Command finished: '%s'" % reason.getErrorMessage())
446 447 # FIXME: send an event or something? 448 # 449 # code = 1 450 # try: 451 # code = reason.value.exitCode 452 # except AttributeError: 453 # pass 454 # code = reason.value.exitCode 455 # if code == 0: 456 # cmdData = self.data or "<command produced no output>" 457 # else: 458 # cmdError = self.error or "<command produced no output>" 459
460 - def outReceived(self, text):
461 self.data += text
462
463 - def errReceived(self, text):
464 self.error += text
465 466
467 -class CommandAction(IActionBase, TargetableAction):
468 implements(IAction) 469 470 id = 'command' 471 name = 'Command' 472 actionContentInfo = ICommandActionContentInfo 473 474 shouldExecuteInBatch = False 475
476 - def configure(self, options):
477 super(CommandAction, self).configure(options) 478 self.processQueue = ProcessQueue(options.get('maxCommands', 10)) 479 self.processQueue.start()
480
481 - def setupAction(self, dmd):
482 self.guidManager = GUIDManager(dmd) 483 self.dmd = dmd
484
485 - def execute(self, notification, signal):
486 # check to see if we have any targets 487 if notification.recipients: 488 return super(CommandAction, self).execute(notification, signal) 489 else: 490 self._execute(notification, signal)
491
492 - def executeOnTarget(self, notification, signal, target):
493 log.debug('Executing command action: %s on %s', self.name, target) 494 user_env_format = notification.content.get('user_env_format', '') 495 environ ={} 496 env = dict( envvar.split('=') for envvar in user_env_format.split(';') if '=' in envvar) 497 environ['env'] = env 498 environ['user'] = getattr(self.dmd.ZenUsers, target, None) 499 self._execute(notification, signal, environ)
500
501 - def _execute(self, notification, signal, extra_env= {}):
502 self.setupAction(notification.dmd) 503 log.debug('Executing command action: %s', self.name) 504 505 if signal.clear: 506 command = notification.content['clear_body_format'] 507 else: 508 command = notification.content['body_format'] 509 510 log.debug('Executing this command: %s', command) 511 512 actor = signal.event.occurrence[0].actor 513 device = None 514 if actor.element_uuid: 515 device = self.guidManager.getObject(actor.element_uuid) 516 517 component = None 518 if actor.element_sub_uuid: 519 component = self.guidManager.getObject(actor.element_sub_uuid) 520 521 environ = {'dev': device, 'component': component, 'dmd': notification.dmd, 'env':None} 522 data = _signalToContextDict(signal, self.options.get('zopeurl'), notification, self.guidManager) 523 environ.update(data) 524 525 if environ.get('evt', None): 526 environ['evt'] = self._escapeEvent(environ['evt']) 527 528 if environ.get('clearEvt', None): 529 environ['clearEvt'] = self._escapeEvent(environ['clearEvt']) 530 531 environ.update(extra_env) 532 try: 533 command = processTalSource(command, **environ) 534 except Exception: 535 raise ActionExecutionException('Unable to perform TALES evaluation on "%s" -- is there an unescaped $?' % command) 536 537 log.debug('Executing this compiled command: "%s"' % command) 538 _protocol = EventCommandProtocol(command) 539 540 log.debug('Queueing up command action process.') 541 self.processQueue.queueProcess( 542 '/bin/sh', 543 ('/bin/sh', '-c', command), 544 env=environ['env'], 545 processProtocol=_protocol, 546 timeout=int(notification.content['action_timeout']), 547 timeout_callback=_protocol.timedOut 548 )
549
550 - def getActionableTargets(self, target):
551 ids = [target.id] 552 if isinstance(target, GroupSettings): 553 ids = [x.id for x in target.getMemberUserSettings()] 554 return ids
555
556 - def updateContent(self, content=None, data=None):
557 updates = dict() 558 559 properties = ['body_format', 'clear_body_format', 'action_timeout', 'user_env_format'] 560 for k in properties: 561 updates[k] = data.get(k) 562 563 content.update(updates)
564
565 - def _escapeEvent(self, evt):
566 """ 567 Escapes the relavent fields of an event context for event commands. 568 """ 569 if evt.message: 570 evt.message = self._wrapInQuotes(evt.message) 571 if evt.summary: 572 evt.summary = self._wrapInQuotes(evt.summary) 573 return evt
574
575 - def _wrapInQuotes(self, msg):
576 """ 577 Wraps the message in quotes, escaping any existing quote. 578 579 Before: How do you pronounce "Zenoss"? 580 After: "How do you pronounce \"Zenoss\"?" 581 """ 582 QUOTE = '"' 583 BACKSLASH = '\\' 584 return ''.join((QUOTE, msg.replace(QUOTE, BACKSLASH + QUOTE), QUOTE))
585
586 -class SNMPTrapAction(IActionBase):
587 implements(IAction) 588 589 id = 'trap' 590 name = 'SNMP Trap' 591 actionContentInfo = ISnmpTrapActionContentInfo 592 593 _sessions = {} 594
595 - def setupAction(self, dmd):
596 self.guidManager = GUIDManager(dmd)
597
598 - def execute(self, notification, signal):
599 """ 600 Send out an SNMP trap according to the definition in ZENOSS-MIB. 601 """ 602 log.debug('Processing SNMP Trap action.') 603 self.setupAction(notification.dmd) 604 data = _signalToContextDict(signal, self.options.get('zopeurl'), notification, self.guidManager) 605 self._sendTrap(notification, data, data['eventSummary']) 606 if signal.clear: 607 if 'clearEvt' in data and data['clearEvt'].severity is not None: 608 self._sendTrap(notification, data, data['clearEvt'])
609
610 - def _sendTrap(self, notification, data, event):
611 actor = getattr(event, "actor", None) 612 details = event.details 613 baseOID = '1.3.6.1.4.1.14296.1.100' 614 615 fields = { 616 'uuid' : ( 1, event), 617 'fingerprint' : ( 2, event), 618 'element_identifier' : ( 3, actor), 619 'element_sub_identifier' : ( 4, actor), 620 'event_class' : ( 5, event), 621 'event_key' : ( 6, event), 622 'summary' : ( 7, event), 623 'message' : ( 8, event), 624 'severity' : ( 9, event), 625 'status' : (10, event), 626 'event_class_key' : (11, event), 627 'event_group' : (12, event), 628 'state_change_time' : (13, event), 629 'first_seen_time' : (14, event), 630 'last_seen_time' : (15, event), 631 'count' : (16, event), 632 'zenoss.device.production_state':(17, details), 633 'agent': (20, event), 634 'zenoss.device.device_class': (21, details), 635 'zenoss.device.location' : (22, details), 636 'zenoss.device.systems' : (23, details), 637 'zenoss.device.groups' : (24, details), 638 'zenoss.device.ip_address': (25, details), 639 'syslog_facility' : (26, event), 640 'syslog_priority' : (27, event), 641 'nt_event_code' : (28, event), 642 'current_user_name' : (29, event), 643 'cleared_by_event_uuid' : (31, event), 644 'zenoss.device.priority' : (32, details), 645 'event_class_mapping_uuid': (33, event) 646 } 647 648 eventDict = self.createEventDict(fields, event) 649 self.processEventDict(eventDict, data, notification.dmd) 650 varbinds = self.makeVarBinds(baseOID, fields, eventDict) 651 652 session = self._getSession(notification.content) 653 654 for v in varbinds: 655 log.debug(v) 656 session.sendTrap(baseOID + '.0.0.1', varbinds=varbinds)
657
658 - def createEventDict(self, fields, event):
659 """ 660 Create an event dictionary suitable for Python evaluation. 661 """ 662 eventDict = {} 663 for field, oidspec in fields.items(): 664 i, source = oidspec 665 if source is event.details: 666 val = source.get(field, '') 667 else: 668 val = getattr(source, field, '') 669 eventDict[field] = val 670 return eventDict
671
672 - def processEventDict(self, eventDict, data, dmd):
673 """ 674 Integration hook 675 """ 676 pass
677
678 - def makeVarBinds(self, baseOID, fields, eventDict):
679 """ 680 Make the SNMP variable bindings in numeric order. 681 """ 682 intValues = (9, 10, 26, 27) 683 varbinds = [] 684 for field, oidspec in sorted(fields.items(), key=lambda x: x[1][0]): 685 i, source = oidspec 686 val = eventDict.get(field, '') 687 if isinstance(val, (list, tuple, set)): 688 val = '|'.join(val) 689 690 # Create the binding 691 oid = "%s.%d" % (baseOID, i) 692 oidType = 's' if i not in intValues else 'i' 693 # No matter what the OID data type, send in strings as that's what is expected 694 val = str(val) 695 696 varbinds.append( (oid, oidType, val) ) 697 return varbinds
698
699 - def updateContent(self, content=None, data=None):
700 content['action_destination'] = data.get('action_destination') 701 content['community'] = data.get('community') 702 content['version'] = data.get('version') 703 content['port'] = int(data.get('port'))
704
705 - def _getSession(self, content):
706 traphost = content['action_destination'] 707 port = content.get('port', 162) 708 destination = '%s:%s' % (traphost, port) 709 710 if not traphost or port <= 0: 711 log.error("%s: SNMP trap host information %s is incorrect ", destination) 712 return None 713 714 community = content.get('community', 'public') 715 version = content.get('version', 'v2c') 716 717 session = self._sessions.get(destination, None) 718 if session is None: 719 log.debug("Creating SNMP trap session to %s", destination) 720 721 # Test that the hostname and port are sane. 722 try: 723 getaddrinfo(traphost, port) 724 except Exception: 725 raise ActionExecutionException("The destination %s is not resolvable." % destination) 726 727 session = netsnmp.Session(( 728 '-%s' % version, 729 '-c', community, 730 destination) 731 ) 732 session.open() 733 self._sessions[destination] = session 734 735 return session
736