![]() |
![]() |
Subject: | Modeling and Component Creation in SDK |
Author: | Austin Culbertson |
Posted: | 2018-10-04 13:53 |
Using Zenoss 4.2.5, with access to zenpacklib.
Using the Zenoss-SDK (Device Modeling - ZenPack SDK 2.1.1 documentation), I am trying to figure out how I can write a modeler plugin to be added to an existing device that will collect an IP address from an ipmitool command - This is primarily so I can store this IP on a per-machine basis and monitor the status of the device's IPMI URL using other methods with which I'm more familiar.
I'm struggling to get the component added, however. I have 'stitched together' the ExampleCMD.py.example and what I've found on the SDK URL to get the following:
# Module-level documentation will automatically be shown as additional # information for the modeler plugin in the web interface. """ ExampleCMD An example plugin that illustrates how to model devices using SSH. """ # This is an example of an CMD-based modeler plugin. It won't be recognized by # Zenoss as an available modeler plugin unless the .example extension is # removed. # When configuring modeler plugins for a device or device class, this plugin's # name would be community.snmp.ExampleCMD because its filesystem path within # the ZenPack is modeler/plugins/community/snmp/ExampleCMD.py. The name of the # class within this file must match the filename. import re # CommandPlugin is the base class that provides lots of help in modeling data # that's available by connecting to a remote machine, running command line # tools, and parsing their results. from Products.DataCollector.plugins.CollectorPlugin import CommandPlugin # Classes we'll need for returning proper results from our modeler plugin's # process method. from Products.DataCollector.plugins.DataMaps import ObjectMap, RelationshipMap class BMCIP(CommandPlugin): # The command to run. command = "/usr/bin/ipmitool lan print" relname = "ribbonBMCIPs" modname = 'ZenPacks.Bandwidth.SBCBMCMonitor.BMCIP' # Modeler plugins can optionally implement the "condition" method. This # allows your plugin to determine if it should be run by looking at the # configuration of the device that's about to be modeled. Return True if # you want the modeler plugin to execute and False if you do not. # # The default is to return True. So ordinarily you wouldn't even implement # the method if you were just going to blindly return True like this # example. def condition(self, device, log): return True def process(self, device, results, log): log.info("Modeler %s processing data for device %s", self.name(), device.id) objectmaps = [] # For CommandPlugin, the results parameter to the process method will # be a string containing all output from the command defined above. # results contents.. # major minor #blocks name # # 8 0 41943040 sda # 8 1 104391 sda1 # 8 2 41833260 sda2 # 253 0 41091072 dm-0 # 253 1 720896 dm-1 rm = self.relMap() log.info("rm is %s", rm) matcher = re.compile(r'^IP Address\s+:\s(\d+.\d+.\d+.\d+)') for line in results.split('\n'): line = line.strip() # match = matcher.search(line) match = re.match('IP Address\s+:\s(\d+.\d+.\d+.\d+)', line) if match: # objectmaps.append(ObjectMap({ # 'id': self.prepId(match.group(0)), # 'description': match.group(0), # })) rm.append(self.objectMap({ 'id': self.prepId(match.group(1)), 'description': match.group(1), 'bmcip': match.group(1), })) log.info("Found IP Address: %s", match.group(1)) # Return a RelationshipMap that describes the component, relationship # on that component, and the module name for the created objects. Pass # in the previously built list of ObjectMaps that will be used to # populate the relationship. # return RelationshipMap( # compname="bMCIP", relname="bMCIP", # modname='ZenPacks.Bandwidth.SBCBMCMonitor.BMCIP', # objmaps=objectmaps) log.info("rm is %s", rm) return rm
At present, my zenpack.yaml looks like this:
name: ZenPacks.Bandwidth.SBCBMCMonitor classes: RibbonSBCDevice: base: [zenpacklib.Device] label: Ribbon SBC Device RibbonBMCIP: base: [zenpacklib.Component] label: BMCIP_Label properties: bmcip: label: BMC IP class_relationships: - RibbonSBCDevice 1:MC RibbonBMCIP
Debugging shows that we are running the command and finding the information:
2018-10-04 17:47:33,374 DEBUG zen.ZenModeler: Plugin BMCIP.BMCIP results = Set in [snip] IP Address Source : Static Address IP Address : 192.168.125.6 [/snip] 2018-10-04 17:47:33,374 INFO zen.ZenModeler: Modeler BMCIP.BMCIP processing data for device 192.168.125.22 2018-10-04 17:47:33,374 INFO zen.ZenModeler: rm is <RelationshipMap []> 2018-10-04 17:47:33,375 INFO zen.ZenModeler: Found IP Address: 192.168.125.6 2018-10-04 17:47:33,375 INFO zen.ZenModeler: rm is <RelationshipMap [<ObjectMap {'bmcip': '192.168.125.6', 'classname': '', 'compname': '', 'description': '192.168.125.6', 'id': '192.168.125.6', 'modname': 'ZenPacks.Bandwidth.SBCBMCMonitor.BMCIP'}>]>
I think this might have something to do with the fact that there is no compname here. However, I don't see this field ever being referenced in the Zenoss SDK documentation.
I'm certain I'm missing something, but I just don't know what. Is creating my own component not achieved in this way? Am I using a resource that doesn't apply to my version of Zenoss?
Subject: | RE: Modeling and Component Creation in SDK |
Author: | Patrick McMahon |
Posted: | 2018-10-04 17:23 |
Subject: | RE: Modeling and Component Creation in SDK |
Author: | Patrick McMahon |
Posted: | 2018-10-05 08:10 |
Subject: | RE: Modeling and Component Creation in SDK |
Author: | Austin Culbertson |
Posted: | 2018-10-05 12:27 |
In the PythonCollector documentation it indicates:
# An ObjectMap with no compname or relname will be
# applied to the device.
ObjectMap({'rackSlot': 'near-the-top'}),
# An ObjectMap with a compname, but no relname will be
# applied to a static object that's always a child of the
# device. For example: hw and os.
ObjectMap({
'compname': 'hw',
'totalMemory': 45097156608}),
What does 'it will be applied to the device' entail? Does that mean that, if I'm in zendmd, and it's properly 'added', I can do something like:
dev = find('192.168.125.22') dev.bmcip OR dev.ribbonBMCip[0]
Or something like that? I'm not quite 100% certain on what the implications of this are, in-so-far as how it translate to what I might see in the GUI (if anything). Likewise, what does it mean to be 'a static object that is always a child of the device'?
------------------------------
Austin Culbertson
NOC Monitoring Engineer
------------------------------
Using Zenoss 4.2.5, with access to zenpacklib.
Using the Zenoss-SDK (Device Modeling - ZenPack SDK 2.1.1 documentation), I am trying to figure out how I can write a modeler plugin to be added to an existing device that will collect an IP address from an ipmitool command - This is primarily so I can store this IP on a per-machine basis and monitor the status of the device's IPMI URL using other methods with which I'm more familiar.
I'm struggling to get the component added, however. I have 'stitched together' the ExampleCMD.py.example and what I've found on the SDK URL to get the following:
# Module-level documentation will automatically be shown as additional # information for the modeler plugin in the web interface. """ ExampleCMD An example plugin that illustrates how to model devices using SSH. """ # This is an example of an CMD-based modeler plugin. It won't be recognized by # Zenoss as an available modeler plugin unless the .example extension is # removed. # When configuring modeler plugins for a device or device class, this plugin's # name would be community.snmp.ExampleCMD because its filesystem path within # the ZenPack is modeler/plugins/community/snmp/ExampleCMD.py. The name of the # class within this file must match the filename. import re # CommandPlugin is the base class that provides lots of help in modeling data # that's available by connecting to a remote machine, running command line # tools, and parsing their results. from Products.DataCollector.plugins.CollectorPlugin import CommandPlugin # Classes we'll need for returning proper results from our modeler plugin's # process method. from Products.DataCollector.plugins.DataMaps import ObjectMap, RelationshipMap class BMCIP(CommandPlugin): # The command to run. command = "/usr/bin/ipmitool lan print" relname = "ribbonBMCIPs" modname = 'ZenPacks.Bandwidth.SBCBMCMonitor.BMCIP' # Modeler plugins can optionally implement the "condition" method. This # allows your plugin to determine if it should be run by looking at the # configuration of the device that's about to be modeled. Return True if # you want the modeler plugin to execute and False if you do not. # # The default is to return True. So ordinarily you wouldn't even implement # the method if you were just going to blindly return True like this # example. def condition(self, device, log): return True def process(self, device, results, log): log.info("Modeler %s processing data for device %s", self.name(), device.id) objectmaps = [] # For CommandPlugin, the results parameter to the process method will # be a string containing all output from the command defined above. # results contents.. # major minor #blocks name # # 8 0 41943040 sda # 8 1 104391 sda1 # 8 2 41833260 sda2 # 253 0 41091072 dm-0 # 253 1 720896 dm-1 rm = self.relMap() log.info("rm is %s", rm) matcher = re.compile(r'^IP Address\s+:\s(\d+.\d+.\d+.\d+)') for line in results.split('\n'): line = line.strip() # match = matcher.search(line) match = re.match('IP Address\s+:\s(\d+.\d+.\d+.\d+)', line) if match: # objectmaps.append(ObjectMap({ # 'id': self.prepId(match.group(0)), # 'description': match.group(0), # })) rm.append(self.objectMap({ 'id': self.prepId(match.group(1)), 'description': match.group(1), 'bmcip': match.group(1), })) log.info("Found IP Address: %s", match.group(1)) # Return a RelationshipMap that describes the component, relationship # on that component, and the module name for the created objects. Pass # in the previously built list of ObjectMaps that will be used to # populate the relationship. # return RelationshipMap( # compname="bMCIP", relname="bMCIP", # modname='ZenPacks.Bandwidth.SBCBMCMonitor.BMCIP', # objmaps=objectmaps) log.info("rm is %s", rm) return rm
At present, my zenpack.yaml looks like this:
name: ZenPacks.Bandwidth.SBCBMCMonitor classes: RibbonSBCDevice: base: [zenpacklib.Device] label: Ribbon SBC Device RibbonBMCIP: base: [zenpacklib.Component] label: BMCIP_Label properties: bmcip: label: BMC IP class_relationships: - RibbonSBCDevice 1:MC RibbonBMCIP
Debugging shows that we are running the command and finding the information:
2018-10-04 17:47:33,374 DEBUG zen.ZenModeler: Plugin BMCIP.BMCIP results = Set in [snip] IP Address Source : Static Address IP Address : 192.168.125.6 [/snip] 2018-10-04 17:47:33,374 INFO zen.ZenModeler: Modeler BMCIP.BMCIP processing data for device 192.168.125.22 2018-10-04 17:47:33,374 INFO zen.ZenModeler: rm is <RelationshipMap []> 2018-10-04 17:47:33,375 INFO zen.ZenModeler: Found IP Address: 192.168.125.6 2018-10-04 17:47:33,375 INFO zen.ZenModeler: rm is <RelationshipMap [<ObjectMap {'bmcip': '192.168.125.6', 'classname': '', 'compname': '', 'description': '192.168.125.6', 'id': '192.168.125.6', 'modname': 'ZenPacks.Bandwidth.SBCBMCMonitor.BMCIP'}>]>
I think this might have something to do with the fact that there is no compname here. However, I don't see this field ever being referenced in the Zenoss SDK documentation.
I'm certain I'm missing something, but I just don't know what. Is creating my own component not achieved in this way? Am I using a resource that doesn't apply to my version of Zenoss?
Subject: | RE: Modeling and Component Creation in SDK |
Author: | Patrick McMahon |
Posted: | 2018-10-05 17:17 |
device_classes: /NetBotz: zProperties: zPythonClass: ZenPacks.training.NetBotz.NetBotzDeviceWhen your running your modeler plugin in the context of some Device Class, the zPythonClass zProperty in that Device Class tells the modeler plugin what Device to create or attach to relations to. By default I think it's Products.ZenModel.Device.Device (may be a shorter form) and you did not define a relation to Device for your component RibbonBMCIP so that may be the issue.
Subject: | RE: Modeling and Component Creation in SDK |
Author: | Austin Culbertson |
Posted: | 2018-10-09 16:36 |
I got this to work by manually defining the zPythonClass of the group that I wanted to be 'RibbonSBCDevices' and moving existing devices out of and back to the groups in Zenoss to get the RibbonSBCDevice class to be applied to them.
My next question is this: Is it possible to 'Extend' or augment an existing device class? i.e. if I change zenpack.yaml to define the device as 'LinuxDevice', is it going to 'extend' or 'overwrite' the LinuxDevice class?
device_classes: /NetBotz: zProperties: zPythonClass: ZenPacks.training.NetBotz.NetBotzDeviceWhen your running your modeler plugin in the context of some Device Class, the zPythonClass zProperty in that Device Class tells the modeler plugin what Device to create or attach to relations to. By default I think it's Products.ZenModel.Device.Device (may be a shorter form) and you did not define a relation to Device for your component RibbonBMCIP so that may be the issue.
In the PythonCollector documentation it indicates:
# An ObjectMap with no compname or relname will be
# applied to the device.
ObjectMap({'rackSlot': 'near-the-top'}),
# An ObjectMap with a compname, but no relname will be
# applied to a static object that's always a child of the
# device. For example: hw and os.
ObjectMap({
'compname': 'hw',
'totalMemory': 45097156608}),
What does 'it will be applied to the device' entail? Does that mean that, if I'm in zendmd, and it's properly 'added', I can do something like:
dev = find('192.168.125.22') dev.bmcip OR dev.ribbonBMCip[0]
Or something like that? I'm not quite 100% certain on what the implications of this are, in-so-far as how it translate to what I might see in the GUI (if anything). Likewise, what does it mean to be 'a static object that is always a child of the device'?
------------------------------
Austin Culbertson
NOC Monitoring Engineer
Using Zenoss 4.2.5, with access to zenpacklib.
Using the Zenoss-SDK (Device Modeling - ZenPack SDK 2.1.1 documentation), I am trying to figure out how I can write a modeler plugin to be added to an existing device that will collect an IP address from an ipmitool command - This is primarily so I can store this IP on a per-machine basis and monitor the status of the device's IPMI URL using other methods with which I'm more familiar.
I'm struggling to get the component added, however. I have 'stitched together' the ExampleCMD.py.example and what I've found on the SDK URL to get the following:
# Module-level documentation will automatically be shown as additional # information for the modeler plugin in the web interface. """ ExampleCMD An example plugin that illustrates how to model devices using SSH. """ # This is an example of an CMD-based modeler plugin. It won't be recognized by # Zenoss as an available modeler plugin unless the .example extension is # removed. # When configuring modeler plugins for a device or device class, this plugin's # name would be community.snmp.ExampleCMD because its filesystem path within # the ZenPack is modeler/plugins/community/snmp/ExampleCMD.py. The name of the # class within this file must match the filename. import re # CommandPlugin is the base class that provides lots of help in modeling data # that's available by connecting to a remote machine, running command line # tools, and parsing their results. from Products.DataCollector.plugins.CollectorPlugin import CommandPlugin # Classes we'll need for returning proper results from our modeler plugin's # process method. from Products.DataCollector.plugins.DataMaps import ObjectMap, RelationshipMap class BMCIP(CommandPlugin): # The command to run. command = "/usr/bin/ipmitool lan print" relname = "ribbonBMCIPs" modname = 'ZenPacks.Bandwidth.SBCBMCMonitor.BMCIP' # Modeler plugins can optionally implement the "condition" method. This # allows your plugin to determine if it should be run by looking at the # configuration of the device that's about to be modeled. Return True if # you want the modeler plugin to execute and False if you do not. # # The default is to return True. So ordinarily you wouldn't even implement # the method if you were just going to blindly return True like this # example. def condition(self, device, log): return True def process(self, device, results, log): log.info("Modeler %s processing data for device %s", self.name(), device.id) objectmaps = [] # For CommandPlugin, the results parameter to the process method will # be a string containing all output from the command defined above. # results contents.. # major minor #blocks name # # 8 0 41943040 sda # 8 1 104391 sda1 # 8 2 41833260 sda2 # 253 0 41091072 dm-0 # 253 1 720896 dm-1 rm = self.relMap() log.info("rm is %s", rm) matcher = re.compile(r'^IP Address\s+:\s(\d+.\d+.\d+.\d+)') for line in results.split('\n'): line = line.strip() # match = matcher.search(line) match = re.match('IP Address\s+:\s(\d+.\d+.\d+.\d+)', line) if match: # objectmaps.append(ObjectMap({ # 'id': self.prepId(match.group(0)), # 'description': match.group(0), # })) rm.append(self.objectMap({ 'id': self.prepId(match.group(1)), 'description': match.group(1), 'bmcip': match.group(1), })) log.info("Found IP Address: %s", match.group(1)) # Return a RelationshipMap that describes the component, relationship # on that component, and the module name for the created objects. Pass # in the previously built list of ObjectMaps that will be used to # populate the relationship. # return RelationshipMap( # compname="bMCIP", relname="bMCIP", # modname='ZenPacks.Bandwidth.SBCBMCMonitor.BMCIP', # objmaps=objectmaps) log.info("rm is %s", rm) return rm
At present, my zenpack.yaml looks like this:
name: ZenPacks.Bandwidth.SBCBMCMonitor classes: RibbonSBCDevice: base: [zenpacklib.Device] label: Ribbon SBC Device RibbonBMCIP: base: [zenpacklib.Component] label: BMCIP_Label properties: bmcip: label: BMC IP class_relationships: - RibbonSBCDevice 1:MC RibbonBMCIP
Debugging shows that we are running the command and finding the information:
2018-10-04 17:47:33,374 DEBUG zen.ZenModeler: Plugin BMCIP.BMCIP results = Set in [snip] IP Address Source : Static Address IP Address : 192.168.125.6 [/snip] 2018-10-04 17:47:33,374 INFO zen.ZenModeler: Modeler BMCIP.BMCIP processing data for device 192.168.125.22 2018-10-04 17:47:33,374 INFO zen.ZenModeler: rm is <RelationshipMap []> 2018-10-04 17:47:33,375 INFO zen.ZenModeler: Found IP Address: 192.168.125.6 2018-10-04 17:47:33,375 INFO zen.ZenModeler: rm is <RelationshipMap [<ObjectMap {'bmcip': '192.168.125.6', 'classname': '', 'compname': '', 'description': '192.168.125.6', 'id': '192.168.125.6', 'modname': 'ZenPacks.Bandwidth.SBCBMCMonitor.BMCIP'}>]>
I think this might have something to do with the fact that there is no compname here. However, I don't see this field ever being referenced in the Zenoss SDK documentation.
I'm certain I'm missing something, but I just don't know what. Is creating my own component not achieved in this way? Am I using a resource that doesn't apply to my version of Zenoss?
Subject: | RE: Modeling and Component Creation in SDK |
Author: | Jane Curry |
Posted: | 2018-10-11 06:00 |
Subject: | RE: Modeling and Component Creation in SDK |
Author: | Austin Culbertson |
Posted: | 2018-11-08 14:28 |
Thank you all for your help so far - I've got this working now when creating my own new device.
I've tried tying this onto the ZenPacks.zenoss.LinuxMonitor.LinuxDevice type, but zenpacklib doesn't seem to like this:
Here is my attempted configuration:
name: ZenPacks.Bandwidth.RibbonSBCMonitor
classes:
RibbonSBCDevice:
base: [zenpacklib.Device]
meta_type: RibbonSBCDevice
label: Ribbon SBC Device
BMCIP:
base: [zenpacklib.Component]
meta_type: BMCIP
label: BMC IP
properties:
ipmiIP:
type: string
label: IP Address
short_label: IP
label_width: 30
class_relationships:
#- RibbonSBCDevice 1:MC BMCIP
- ZenPacks.zenoss.LinuxMonitor.LinuxDevice 1:MC BMCIP
Here is the error:
[zenoss@zenoss-03.lab1 zenpack-testing]$ zenpacklib --lint ZenPacks.Bandwidth.RibbonSBCMonitor/ZenPacks/Bandwidth/RibbonSBCMonitor/zenpack.yaml
ERROR:ZenPacks.Bandwidth.RibbonSBCMonitor:Failed to import class ZenPacks.zenoss.LinuxMonitor.LinuxDevice from ZenPacks.zenoss.LinuxMonitor (Failed while importing class LinuxMonitor from module ZenPacks.zenoss.LinuxMonitor)
2018-11-08 19:19:59,061 [ZenPacks.Bandwidth.RibbonSBCMonitor] ERROR Failed to import class ZenPacks.zenoss.LinuxMonitor.LinuxDevice from ZenPacks.zenoss.LinuxMonitor (Failed while importing class LinuxMonitor from module ZenPacks.zenoss.LinuxMonitor)
ERROR:ZenPacks.Bandwidth.RibbonSBCMonitor:Failed to add relationship (bmcips) to imported class (ZenPacks.zenoss.LinuxMonitor.LinuxDevice).
2018-11-08 19:19:59,062 [ZenPacks.Bandwidth.RibbonSBCMonitor] ERROR Failed to add relationship (bmcips) to imported class (ZenPacks.zenoss.LinuxMonitor.LinuxDevice).
Is this a path issue, or some type of issue surrounding 'private' device types?
I got this to work by manually defining the zPythonClass of the group that I wanted to be 'RibbonSBCDevices' and moving existing devices out of and back to the groups in Zenoss to get the RibbonSBCDevice class to be applied to them.
My next question is this: Is it possible to 'Extend' or augment an existing device class? i.e. if I change zenpack.yaml to define the device as 'LinuxDevice', is it going to 'extend' or 'overwrite' the LinuxDevice class?
device_classes: /NetBotz: zProperties: zPythonClass: ZenPacks.training.NetBotz.NetBotzDeviceWhen your running your modeler plugin in the context of some Device Class, the zPythonClass zProperty in that Device Class tells the modeler plugin what Device to create or attach to relations to. By default I think it's Products.ZenModel.Device.Device (may be a shorter form) and you did not define a relation to Device for your component RibbonBMCIP so that may be the issue.
In the PythonCollector documentation it indicates:
# An ObjectMap with no compname or relname will be
# applied to the device.
ObjectMap({'rackSlot': 'near-the-top'}),
# An ObjectMap with a compname, but no relname will be
# applied to a static object that's always a child of the
# device. For example: hw and os.
ObjectMap({
'compname': 'hw',
'totalMemory': 45097156608}),
What does 'it will be applied to the device' entail? Does that mean that, if I'm in zendmd, and it's properly 'added', I can do something like:
dev = find('192.168.125.22') dev.bmcip OR dev.ribbonBMCip[0]
Or something like that? I'm not quite 100% certain on what the implications of this are, in-so-far as how it translate to what I might see in the GUI (if anything). Likewise, what does it mean to be 'a static object that is always a child of the device'?
------------------------------
Austin Culbertson
NOC Monitoring Engineer
Using Zenoss 4.2.5, with access to zenpacklib.
Using the Zenoss-SDK (Device Modeling - ZenPack SDK 2.1.1 documentation), I am trying to figure out how I can write a modeler plugin to be added to an existing device that will collect an IP address from an ipmitool command - This is primarily so I can store this IP on a per-machine basis and monitor the status of the device's IPMI URL using other methods with which I'm more familiar.
I'm struggling to get the component added, however. I have 'stitched together' the ExampleCMD.py.example and what I've found on the SDK URL to get the following:
# Module-level documentation will automatically be shown as additional # information for the modeler plugin in the web interface. """ ExampleCMD An example plugin that illustrates how to model devices using SSH. """ # This is an example of an CMD-based modeler plugin. It won't be recognized by # Zenoss as an available modeler plugin unless the .example extension is # removed. # When configuring modeler plugins for a device or device class, this plugin's # name would be community.snmp.ExampleCMD because its filesystem path within # the ZenPack is modeler/plugins/community/snmp/ExampleCMD.py. The name of the # class within this file must match the filename. import re # CommandPlugin is the base class that provides lots of help in modeling data # that's available by connecting to a remote machine, running command line # tools, and parsing their results. from Products.DataCollector.plugins.CollectorPlugin import CommandPlugin # Classes we'll need for returning proper results from our modeler plugin's # process method. from Products.DataCollector.plugins.DataMaps import ObjectMap, RelationshipMap class BMCIP(CommandPlugin): # The command to run. command = "/usr/bin/ipmitool lan print" relname = "ribbonBMCIPs" modname = 'ZenPacks.Bandwidth.SBCBMCMonitor.BMCIP' # Modeler plugins can optionally implement the "condition" method. This # allows your plugin to determine if it should be run by looking at the # configuration of the device that's about to be modeled. Return True if # you want the modeler plugin to execute and False if you do not. # # The default is to return True. So ordinarily you wouldn't even implement # the method if you were just going to blindly return True like this # example. def condition(self, device, log): return True def process(self, device, results, log): log.info("Modeler %s processing data for device %s", self.name(), device.id) objectmaps = [] # For CommandPlugin, the results parameter to the process method will # be a string containing all output from the command defined above. # results contents.. # major minor #blocks name # # 8 0 41943040 sda # 8 1 104391 sda1 # 8 2 41833260 sda2 # 253 0 41091072 dm-0 # 253 1 720896 dm-1 rm = self.relMap() log.info("rm is %s", rm) matcher = re.compile(r'^IP Address\s+:\s(\d+.\d+.\d+.\d+)') for line in results.split('\n'): line = line.strip() # match = matcher.search(line) match = re.match('IP Address\s+:\s(\d+.\d+.\d+.\d+)', line) if match: # objectmaps.append(ObjectMap({ # 'id': self.prepId(match.group(0)), # 'description': match.group(0), # })) rm.append(self.objectMap({ 'id': self.prepId(match.group(1)), 'description': match.group(1), 'bmcip': match.group(1), })) log.info("Found IP Address: %s", match.group(1)) # Return a RelationshipMap that describes the component, relationship # on that component, and the module name for the created objects. Pass # in the previously built list of ObjectMaps that will be used to # populate the relationship. # return RelationshipMap( # compname="bMCIP", relname="bMCIP", # modname='ZenPacks.Bandwidth.SBCBMCMonitor.BMCIP', # objmaps=objectmaps) log.info("rm is %s", rm) return rm
At present, my zenpack.yaml looks like this:
name: ZenPacks.Bandwidth.SBCBMCMonitor classes: RibbonSBCDevice: base: [zenpacklib.Device] label: Ribbon SBC Device RibbonBMCIP: base: [zenpacklib.Component] label: BMCIP_Label properties: bmcip: label: BMC IP class_relationships: - RibbonSBCDevice 1:MC RibbonBMCIP
Debugging shows that we are running the command and finding the information:
2018-10-04 17:47:33,374 DEBUG zen.ZenModeler: Plugin BMCIP.BMCIP results = Set in [snip] IP Address Source : Static Address IP Address : 192.168.125.6 [/snip] 2018-10-04 17:47:33,374 INFO zen.ZenModeler: Modeler BMCIP.BMCIP processing data for device 192.168.125.22 2018-10-04 17:47:33,374 INFO zen.ZenModeler: rm is <RelationshipMap []> 2018-10-04 17:47:33,375 INFO zen.ZenModeler: Found IP Address: 192.168.125.6 2018-10-04 17:47:33,375 INFO zen.ZenModeler: rm is <RelationshipMap [<ObjectMap {'bmcip': '192.168.125.6', 'classname': '', 'compname': '', 'description': '192.168.125.6', 'id': '192.168.125.6', 'modname': 'ZenPacks.Bandwidth.SBCBMCMonitor.BMCIP'}>]>
I think this might have something to do with the fact that there is no compname here. However, I don't see this field ever being referenced in the Zenoss SDK documentation.
I'm certain I'm missing something, but I just don't know what. Is creating my own component not achieved in this way? Am I using a resource that doesn't apply to my version of Zenoss?
Subject: | RE: Modeling and Component Creation in SDK |
Author: | Patrick McMahon |
Posted: | 2018-11-09 09:35 |
Subject: | RE: Modeling and Component Creation in SDK |
Author: | Austin Culbertson |
Posted: | 2018-11-09 11:40 |
< |
Previous Unable to get >1000 events from API query |
Next How to execute command on Noviflow Switch |
> |