May 13, 2010 2:37 PM
Adding interface description to an event
-
Like (0)
I've tried two mechanisms that are described in the forum for adding an interface description to an event summary and am not getting anything to work. The two things I've tried are from the Event Transforms and Examples blog (docs/DOC-2554).
What I get now is below and contains a bunch of redundant information:
Router001 GigabitEthernet0/1 /Net/Link Interface GigabitEthernet0/1, changed state to down
What I'd like is to have interface down events display something like this:
Router001 GigabitEthernet0/1 /Net/Link DOWN: Link to Router002 Gig0/2
The first thing I tried was the section titled "Modify event down to specify which interface is down". It runs, but the resulting event says "No description", which is the text I used to denote that an interface had no description. I print the Index value and it is zero, which it shouldn't be for the interface in question.
The second thing I tried was in the section titled "Event Mapping based on Interface Description". It turns red when I enter it into the Transform section of editing a class, so I'm guessing that something has changed since this transform was first built.
Can I print things from within a Transform and see the output somewhere? Jane's paper on transforms says to look at zenaction.log, but it doesn't contain anything useful when debug is enabled.
Thanks!
When the Transform section turns red if means there is an error with the text/code in there. It needs to be Python I believe (i'm still learning). I have a working transform as follows that may help some.
evt.summary = 'LINK DOWN - Module: %s Port: %s to %s' % (evt.mcModulInx, evt.mcPortPortInx, evt.mcPortPortDesc)
which transforms like 'LINK DOWN - Module: 4 Port 2 to SwitchWhatever'
evt.xxxx are values pulled from the Trap, which will be a bunch of numbers if the Mibs are not installed for that device. So the above evt.xxx will not be the same for your device. These should work evt.device for the device name and evt.ifDescr may be description but thats a guess. I am sure that there are other programmatic statements you could use in the transform area but I am not that savy yet.
Thanks for the example with a trap. I'm keying off syslog messages. I think there may be a way to use the interface name and walk through all interfaces on a device to find the matching interface and look up its description. The example in the Transform blog uses the index, which is zero in test I've done.
Hmm. Maybe that's a hint that the transform example is for a trap and not a syslog and I need to think of using syslog data. Syslog only includes the interface name, not index.
I'm not having much success in getting the interface description into the event summary for a syslog event. Is there a way to print some diag info into a log file from within a transform so that I can figure out what's happening? Thanks!
I used the following transform to start to debug why it isn't working. It modifies the Summary field and I use that as my print output. Crude and not very flexible for output formatting.
descr = '|'
if device:
for iface in device.os.interfaces():
descr = descr + iface.description + '|'
evt.summary = '%s DOWN: %s' % (device,descr)
It produced the output:
summary None DOWN: |
So now I see that the variable 'device' isn't being set. Why that's not being set is a new challenge.
try evt.device it should give you the device the event is linked to
I already tried using 'evt.device'. It is a text string, not a device object, so there's no way to reference evt.device.os.interfaces(), which is what I need to identify the interface. So I need to learn how to lookup the device object if I know the device name. Once I have the device object, I should be able to iterate through the interfaces to find the one that matches the interface name in the syslog message. I can then lookup the interface description.
here is something I found that looks through the interfaces to match an index. Maybe it will work if you replace ifindex with interfaceName or description.
for obj in device.os.interfaces.objectItems():
if obj[1].ifindex == index:
blah blah...
The sub-reference helps some. Here's what I have, which works in zendmd, but not in a transform:
>>> devname = '406-router-01'
>>> intname = 'GigabitEthernet0/1'
>>>
>>> descr = ''
>>> dev=device.findDevice(devname)
>>> for iface in dev.os.interfaces.objectItems():
... if iface[1].name() == intname:
... descr = iface[1].description
...
>>> summary = 'DOWN: %s Int: %s (%s)' % (devname, intname, descr)
>>> print summary
DOWN: 406-router-01 Int: GigabitEthernet0/1 (Lab testing)
In a transform, I get the following error in zenhub.log:
2010-05-17 13:11:33,047 INFO zen.ZenHub: Worker reports 2010-05-17 13:11:33,045 ERROR zen.Events: Error processing transform/mapping on Event Class /zport/dmd/Events/Net/Link/instances/LINK-3-UPDOWN
Traceback (most recent call last):
File "/opt/zenoss/zenoss/Products/ZenEvents/EventClassInst.py", line 96, in applyTransform
exec(eventclass.transform, variables_and_funcs)
File "<string>", line 5, in ?
NameError: name 'findDevice' is not defined
I need a way to lookup the device object given the device name. I guess I could have it walk the list of all devices (for dev in devices...), but it would be much better to have a lookup that does it more efficiently, if such a thing exists.
The problem seems to be that an SNMP event has the object 'device' defined, so a transform that uses:
dev = device.findDevice(evt.device)
will work correctly. However, for syslog messages, it looks to me like 'device' is a string that contains the device name, so the object method 'findDevice()' doesn't exist. That's why the error:
2010-05-17 15:45:44,556 INFO zen.ZenHub: Worker reports 2010-05-17 15:45:44,556 ERROR zen.Events: Error processing transform/mapping on Event Class /zport/dmd/Events/Net/Link/instances/LINK-3-UPDOWN
Traceback (most recent call last):
File "/opt/zenoss/zenoss/Products/ZenEvents/EventClassInst.py", line 96, in applyTransform
exec(eventclass.transform, variables_and_funcs)
File "<string>", line 2, in ?
AttributeError: 'NoneType' object has no attribute 'findDevice'
on the transform:
descr = device
dev = device.findDevice(evt.device)
evt.summary = 'DOWN: %s\t%s\t(%s)' % (evt.device, evt.component, descr)
It looks to me like the variable 'device' being a text string is a bug and that it should really be a device object.
Though I have not tested it. I had thought that using 'device' in an event transform always refered to the device in which the event was linked so you would not have to search for the device itself in the transform. If it is just a string and you are unable to use device.whatever it is certainly an inconvience. Wish I was more familier with the code to tell, but I would just take out the dev=device.findDevice statement and see if that works. If not there must be some other magic statement we have not found.
Below is my analysis. It basically is a breakdown of what homework I've done. I agree that 'device' should reference the device info.
Well, the code in MySqlSendEvent.py contains the following, which looks to me like it should set 'device' to the device object which generated the event. The code in applyDeviceContext() below shows the device object's context being referenced.
# Look for the device by name, then IP 'globally'
# and then from the /Network class
device = None
if getattr(evt, 'device', None):
device = devices.findDevice(evt.device)
if not device and getattr(evt, 'ipAddress', None):
device = devices.findDevice(evt.ipAddress)
if not device and getattr(evt, 'device', None):
device = self._findByIp(evt.device, networks)
if not device and getattr(evt, 'ipAddress', None):
device = self._findByIp(evt.ipAddress, networks)
if device:
evt.device = device.id
log.debug("Found device %s and adding device-specific"
" data", evt.device)
evt = self.applyDeviceContext(device, evt)
evtclass = events.lookup(evt, device)
if evtclass:
evt = evtclass.applyExtraction(evt)
evt = evtclass.applyValues(evt)
evt = evtclass.applyTransform(evt, device)
if evt._action == "drop":
log.debug("Dropping event")
return None
return evt
def applyDeviceContext(self, device, evt):
"""
Apply event attributes from device context.
@param device: device from DMD
@type device: device object
@param evt: event
@type evt: Event class
@return: updated event
@rtype: Event class
"""
if not hasattr(evt, 'ipAddress'): evt.ipAddress = device.manageIp
evt.prodState = device.productionState
evt.Location = device.getLocationName()
evt.DeviceClass = device.getDeviceClassName()
evt.DeviceGroups = "|"+"|".join(device.getDeviceGroupNames())
evt.Systems = "|"+"|".join(device.getSystemNames())
evt.DevicePriority = device.getPriority()
return evt
But when I try it from within this transform:
devname = evt.device
intname = evt.component
dev = device
for iface in dev.os.interfaces.objectItems():
if iface[1].name() == intname:
descr = iface[1].description
summary = 'DOWN: %s\t%s\t(%s)' % (devname, intname, descr)
evt.summary = summary
it generates the following error:
2010-05-17 17:06:05,352 INFO zen.ZenHub: Worker reports 2010-05-17 17:06:05,351 ERROR zen.Events: Error processing transform/mapping on Event Class /zport/dmd/Events/Net/Link/instances/LINK-3-UPDOWN
Traceback (most recent call last):
File "/opt/zenoss/zenoss/Products/ZenEvents/EventClassInst.py", line 96, in applyTransform
exec(eventclass.transform, variables_and_funcs)
File "<string>", line 4, in ?
AttributeError: 'NoneType' object has no attribute 'os'
I'm interpreting this as 'device' is a 'NoneType' object (line 4 is "for iface in dev.os.interfaces.objectItems():") .
I enabled debugging to make sure that no other transforms were being applied in the class path to this transform. This is the only match.
I'm running out of things to try. It just doesn't make sense to me, though I'm just learning Python, so there's a very good probability that I'm missing something subtle in the language.
I finally have something working. Here's the transform. It could be condensed; I used several temporary variables to aid my troubleshooting process. The device object as well as the event object are both passed to the transform. If the device was not found by the zenhub processing, then 'device' will be None and the transform will fail and the result will be the default event summary message.
devname = evt.device
intname = evt.component
descr = ''
log.debug('Transform= device:%s evt.device:%s' % (device, evt.device))
for iface in device.os.interfaces.objectItems():
if iface[1].name() == intname:
descr = iface[1].description
summary = 'DOWN: %s\t%s\t(%s)' % (devname, intname, descr)
evt.summary = summary
The event summary that results is:
DOWN: 406-router-06 FastEthernet0/6 (Netlink to 406-router-01)
which I find more useful than the default summary:
Interface FastEthernet0/19, changed state to down
One of the problems I encountered was using the 'client.py' script to generate test syslog messages. The source IP address of the syslog is 'localhost', which confused zensyslog, even though I have the 'parsehost' setting enabled (set to True). Other messages that are being forwarded by our syslog-ng server are working.
A more condensed version of the same transform:
descr = ''
log.debug('Transform= device:%s evt.device:%s' % (device, evt.device))
for iface in device.os.interfaces.objectItems():
if iface[1].name() == evt.component:
descr = iface[1].description
evt.summary = 'DOWN: %s\t%s\t(%s)' % (evt.device, evt.component, descr)
In the Event Console, it doesn't look like the tabs in the summary are of any benefit, so I may change them to a couple of spaces. I was hoping to get a more columnar display of device name, interface name, and description.
Follow Us On Twitter »
|
Latest from the Zenoss Blog » | Community | Products | Services Resources | Customers Partners | About Us | ||
Copyright © 2005-2011 Zenoss, Inc.
|
||||||||