<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>zenpacks on Andrés Álvarez</title>
    <link>https://aalvrz.me/tags/zenpacks/</link>
    <description>Recent content in zenpacks on Andrés Álvarez</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Tue, 27 Jun 2017 00:00:00 +0000</lastBuildDate>
    
	<atom:link href="https://aalvrz.me/tags/zenpacks/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Extending Device Python Classes From Other ZenPacks</title>
      <link>https://aalvrz.me/posts/extending-device-python-classes-from-other-zenpacks/</link>
      <pubDate>Tue, 27 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>https://aalvrz.me/posts/extending-device-python-classes-from-other-zenpacks/</guid>
      <description>&lt;p&gt;Recently I was struggling with trying to make two custom ZenPacks work together with device objects in the Zenoss database. My issue was that a main ZenPack (which would be installed first) would create a custom class that inherits from &lt;code&gt;Device&lt;/code&gt;. This ZenPack would add a lot of properties and relationships with custom components. Then, a second optional ZenPack could be installed which would extend this same class with an additional property that would work along with a &lt;a href=&#34;https://aalvrz.me/posts/working-with-zenoss-python-data-sources.html&#34;&gt;Python data source&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;zenpack.yaml&lt;/code&gt; file for the first and main ZenPack would look something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# ZenPack1&lt;/span&gt;

classes&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
  SpecialServer&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
    base&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;[&lt;/span&gt;zenpacklib.Device&lt;span style=&#34;color:#111&#34;&gt;]&lt;/span&gt;
    label&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; Special Server

  SpecialComponent&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
    base&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;[&lt;/span&gt;zenpacklib.Component&lt;span style=&#34;color:#111&#34;&gt;]&lt;/span&gt;
    label&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; Special Component
    properties&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
      &lt;span style=&#34;color:#75715e&#34;&gt;# ...&lt;/span&gt;

  AmazingComponent&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
    base&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;[&lt;/span&gt;zenpacklib.Component&lt;span style=&#34;color:#111&#34;&gt;]&lt;/span&gt;
    label&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; Amazing Component
    properties&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
      &lt;span style=&#34;color:#75715e&#34;&gt;# ...&lt;/span&gt;

class_relationships&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
  - SpecialServer &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;MC SpecialComponent
  - SpecialServer &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;MC AmazingComponent
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Overriding Default Zenoss Pages</title>
      <link>https://aalvrz.me/posts/overriding-default-zenoss-pages/</link>
      <pubDate>Fri, 17 Mar 2017 00:00:00 +0000</pubDate>
      
      <guid>https://aalvrz.me/posts/overriding-default-zenoss-pages/</guid>
      <description>&lt;p&gt;While testing the &lt;a href=&#34;https://github.com/zenoss/ZenPacks.zenoss.Layer2&#34;&gt;Layer 2 ZenPack&lt;/a&gt;, I noticed that the network map provided by the ZenPack was placed in the same page of the old default Zenoss&#39;s network map, replacing the latter which was made using Flash. After the ZenPack is installed, when you click on the &lt;em&gt;Network Map&lt;/em&gt; secondary link in the Infrastructure page, you will get the new map instead.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://aalvrz.me/posts/overriding-default-zenoss-pages/map_link.jpg&#34; alt=&#34;Network Map link&#34;&gt;&lt;/p&gt;
&lt;p&gt;This seemed pretty nice, and I was curious how they achieved this, so I started browsing around the source code. It turns out that this overriding is done in a file called &lt;code&gt;overrides.zcml&lt;/code&gt;, which is placed in the ZenPack&#39;s top directory.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Working With Zenoss Python Data Source Plugins</title>
      <link>https://aalvrz.me/posts/working-with-zenoss-python-data-sources/</link>
      <pubDate>Thu, 23 Feb 2017 00:00:00 +0000</pubDate>
      
      <guid>https://aalvrz.me/posts/working-with-zenoss-python-data-sources/</guid>
      <description>&lt;p&gt;Using Python data source plugins in Zenoss is a great way to collect data, and probably a better way than using &lt;a href=&#34;https://aalvrz.me/posts/ssh-monitoring-in-zenpacks.html&#34;&gt;command datasources&lt;/a&gt;. Python data sources come with the introduction of the &lt;a href=&#34;https://www.zenoss.com/product/zenpacks/pythoncollector&#34;&gt;PythonCollector ZenPack&lt;/a&gt;, so this ZenPack is required in order to start using Python data sources in our own ZenPacks.&lt;/p&gt;
&lt;p&gt;Python data source plugins work exceptionally great in replacing data collection logic in &lt;a href=&#34;https://aalvrz.me/posts/creating-zenoss-zenpack-daemons.html&#34;&gt;custom daemons&lt;/a&gt; written in Python. This means that the ZenPacks&#39;s code is greatly reduced because we do not have to create configuration service, and custom daemon code.&lt;/p&gt;
&lt;p&gt;Moreover, while Python data source plugins are Python-based, we can still execute shell commands within the plugin.&lt;/p&gt;
&lt;h2 id=&#34;example-scenario-bmc-power-status&#34;&gt;Example Scenario: BMC Power Status&lt;/h2&gt;
&lt;p&gt;For this post, I will be using an example where we will be executing an &lt;a href=&#34;https://aalvrz.me/posts/ipmi-baseboard-management-controllers.html&#34;&gt;ipmitool command&lt;/a&gt; to check the power chassis status of a &lt;a href=&#34;https://aalvrz.me/posts/ipmi-baseboard-management-controllers.html&#34;&gt;BMC device&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If I run the following command from my shell:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ipmitool -H $BMC_IP -I lanplus -U admin -P admin power status
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I get the following output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Chassis Power is on
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What we want is our data source plugin to periodically and continuously execute this command and obtain the value. Our ZenPack will then proceed to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Map the value into a boolean property of a custon zenpacklib class.&lt;/li&gt;
&lt;li&gt;Create a CRITICAL event if the power status is off or if the command fails. Create a CLEAR event if the power status is on.&lt;/li&gt;
&lt;li&gt;Update the device model with the new property value.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://aalvrz.me/posts/modifying-the-zenoss-device-detail-bar.html&#34;&gt;Display the property&#39;s value in the device detail bar using JavaScript&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
    
    <item>
      <title>Processing Nova Live Migration Events in Zenoss</title>
      <link>https://aalvrz.me/posts/processing-nova-live-migration-events-in-zenoss/</link>
      <pubDate>Mon, 23 Jan 2017 00:00:00 +0000</pubDate>
      
      <guid>https://aalvrz.me/posts/processing-nova-live-migration-events-in-zenoss/</guid>
      <description>&lt;p&gt;When monitoring OpenStack using the OpenStack Infrastructure ZenPack integrated with Ceilometer, it is possible to get fast virtual machine state changes (on/off powering, etc.) by receiving events sent from Ceilometer to Zenoss.&lt;/p&gt;
&lt;p&gt;However I discovered that when trying to get the same effect for &lt;strong&gt;live migration&lt;/strong&gt; (live migrating a virtual machine from one compute node to another) scenarios, this would not work. I proceeded to investigate why.&lt;/p&gt;
&lt;h2 id=&#34;ceilometer-dispatcher-live-migration-events&#34;&gt;Ceilometer Dispatcher Live Migration Events&lt;/h2&gt;
&lt;p&gt;I decided that the first thing to check was if the &lt;a href=&#34;https://github.com/zenoss/ceilometer_zenoss&#34;&gt;Zenoss Ceilometer dispatcher&lt;/a&gt; was &lt;strong&gt;capturing&lt;/strong&gt; and &lt;strong&gt;sending&lt;/strong&gt; the live migration events to Zenoss. Indeed, the logs can be found in Ceilometer under &lt;code&gt;/var/log/ceilometer/ceilometer-collector.log&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2017-01-23 14:22:02.593 25667 INFO ceilometer_zenoss.dispatcher.zenoss [-] record_events called (events=[&amp;lt;Event: 3538a01c-ab8d-4e64-b0ff-6e8fe270e06a, compute.instance.live_migration.post.dest.start, 2017-01-23 06:22:02.584049, &amp;lt;Trait: state_description 1 migrating&amp;gt; &amp;lt;Trait: memory_mb 2 512&amp;gt; &amp;lt;Trait: ephemeral_gb 2 0&amp;gt; &amp;lt;Trait: fixed_ips 1 [{u&#39;version&#39;: 4, u&#39;vif_mac&#39;: u&#39;fa:16:3e:6e:02:e9&#39;, u&#39;floating_ips&#39;: [], u&#39;label&#39;: u&#39;admin-net&#39;, u&#39;meta&#39;: {}, u&#39;address&#39;: u&#39;192.168.0.15&#39;, u&#39;type&#39;: u&#39;fixed&#39;}]&amp;gt; &amp;lt;Trait: user_id 1 6d581c230c86475abf70cce41440e8a1&amp;gt; &amp;lt;Trait: service 1 compute&amp;gt; &amp;lt;Trait: priority 1 info&amp;gt; &amp;lt;Trait: state 1 active&amp;gt; &amp;lt;Trait: launched_at 4 2017-01-23 05:06:41&amp;gt; &amp;lt;Trait: flavor_name 1 m1.tiny&amp;gt; &amp;lt;Trait: disk_gb 2 1&amp;gt; &amp;lt;Trait: display_name 1 pdcmtest&amp;gt; &amp;lt;Trait: root_gb 2 1&amp;gt; &amp;lt;Trait: tenant_id 1 10296907e44248d2a707689f77d59ef6&amp;gt; &amp;lt;Trait: instance_id 1 87be4b45-e214-4ca3-8f5c-1bd31159f9e4&amp;gt; &amp;lt;Trait: vcpus 2 1&amp;gt; &amp;lt;Trait: host_name 1 ndc27-3222&amp;gt; &amp;lt;Trait: request_id 1 req-d4c27d06-6329-4ce0-adb5-370b8ca83a22&amp;gt;&amp;gt;])

2017-01-23 14:22:02.771 25667 INFO ceilometer_zenoss.dispatcher.zenoss [-] record_events called (events=[&amp;lt;Event: 8db64329-606c-4184-9b5b-eb815166cb17, compute.instance.live_migration.post.dest.end, 2017-01-23 06:22:02.761138, &amp;lt;Trait: state_description 1 &amp;gt; &amp;lt;Trait: memory_mb 2 512&amp;gt; &amp;lt;Trait: ephemeral_gb 2 0&amp;gt; &amp;lt;Trait: fixed_ips 1 [{u&#39;version&#39;: 4, u&#39;vif_mac&#39;: u&#39;fa:16:3e:6e:02:e9&#39;, u&#39;floating_ips&#39;: [], u&#39;label&#39;: u&#39;admin-net&#39;, u&#39;meta&#39;: {}, u&#39;address&#39;: u&#39;192.168.0.15&#39;, u&#39;type&#39;: u&#39;fixed&#39;}]&amp;gt; &amp;lt;Trait: user_id 1 6d581c230c86475abf70cce41440e8a1&amp;gt; &amp;lt;Trait: service 1 compute&amp;gt; &amp;lt;Trait: priority 1 info&amp;gt; &amp;lt;Trait: state 1 active&amp;gt; &amp;lt;Trait: launched_at 4 2017-01-23 05:06:41&amp;gt; &amp;lt;Trait: flavor_name 1 m1.tiny&amp;gt; &amp;lt;Trait: disk_gb 2 1&amp;gt; &amp;lt;Trait: display_name 1 pdcmtest&amp;gt; &amp;lt;Trait: root_gb 2 1&amp;gt; &amp;lt;Trait: tenant_id 1 10296907e44248d2a707689f77d59ef6&amp;gt; &amp;lt;Trait: instance_id 1 87be4b45-e214-4ca3-8f5c-1bd31159f9e4&amp;gt; &amp;lt;Trait: vcpus 2 1&amp;gt; &amp;lt;Trait: host_name 1 ndc27-3222&amp;gt; &amp;lt;Trait: request_id 1 req-d4c27d06-6329-4ce0-adb5-370b8ca83a22&amp;gt;&amp;gt;])

2017-01-23 14:22:02.782 25667 INFO ceilometer_zenoss.dispatcher.zenoss [-] record_events called (events=[&amp;lt;Event: d0dc4f4a-454a-42c5-b767-386dc3e0d1f3, compute.instance.live_migration._post.end, 2017-01-23 06:22:02.776665, &amp;lt;Trait: state_description 1 migrating&amp;gt; &amp;lt;Trait: memory_mb 2 512&amp;gt; &amp;lt;Trait: ephemeral_gb 2 0&amp;gt; &amp;lt;Trait: fixed_ips 1 [{u&#39;version&#39;: 4, u&#39;vif_mac&#39;: u&#39;fa:16:3e:6e:02:e9&#39;, u&#39;floating_ips&#39;: [], u&#39;label&#39;: u&#39;admin-net&#39;, u&#39;meta&#39;: {}, u&#39;address&#39;: u&#39;192.168.0.15&#39;, u&#39;type&#39;: u&#39;fixed&#39;}]&amp;gt; &amp;lt;Trait: user_id 1 6d581c230c86475abf70cce41440e8a1&amp;gt; &amp;lt;Trait: service 1 compute&amp;gt; &amp;lt;Trait: priority 1 info&amp;gt; &amp;lt;Trait: state 1 active&amp;gt; &amp;lt;Trait: launched_at 4 2017-01-23 05:06:41&amp;gt; &amp;lt;Trait: flavor_name 1 m1.tiny&amp;gt; &amp;lt;Trait: disk_gb 2 1&amp;gt; &amp;lt;Trait: display_name 1 pdcmtest&amp;gt; &amp;lt;Trait: root_gb 2 1&amp;gt; &amp;lt;Trait: tenant_id 1 10296907e44248d2a707689f77d59ef6&amp;gt; &amp;lt;Trait: instance_id 1 87be4b45-e214-4ca3-8f5c-1bd31159f9e4&amp;gt; &amp;lt;Trait: vcpus 2 1&amp;gt; &amp;lt;Trait: host_name 1 ndc27-3205&amp;gt; &amp;lt;Trait: request_id 1 req-d4c27d06-6329-4ce0-adb5-370b8ca83a22&amp;gt;&amp;gt;])
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Notice the &lt;code&gt;live_migration.post.dest.start&lt;/code&gt; and &lt;code&gt;live_migration.post.dest.end&lt;/code&gt; logs.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Appending Modeler Plugins in ZenPacks</title>
      <link>https://aalvrz.me/posts/appending-modeler-plugins-in-zenpacks/</link>
      <pubDate>Fri, 20 Jan 2017 00:00:00 +0000</pubDate>
      
      <guid>https://aalvrz.me/posts/appending-modeler-plugins-in-zenpacks/</guid>
      <description>&lt;p&gt;When creating ZenPacks using zenpacklib, assigning modeler plugins to device classes will cause all the device class&#39;s modeler plugins to be &lt;strong&gt;replaced&lt;/strong&gt; by the new modeler plugins assigned by the ZenPack. Obviously most of the time this is not the behaviour we want. What we really want is that the new modeler plugins are simply &lt;em&gt;added&lt;/em&gt; to the device class&#39;s list of modeler plugins.&lt;/p&gt;
&lt;p&gt;In a previous post I explained how we can &lt;a href=&#34;https://aalvrz.me/posts/customizing-the-zenpack-installation-process.html&#34;&gt;customize the ZenPacks installation process&lt;/a&gt; to perform additional tasks. The way to append new modeler plugins to a device class follows this concept.&lt;/p&gt;
&lt;p&gt;Let&#39;s assume that we have the &lt;a href=&#34;http://wiki.zenoss.org/ZenPack:OpenStack_(Provider_View)&#34;&gt;OpenStack Infrastructure ZenPack&lt;/a&gt; installed in our Zenoss Core. This ZenPack adds some custom modeler plugins to the &lt;code&gt;/Server/SSH/Linux/NovaHost&lt;/code&gt; device class. We want our custom ZenPack to add &lt;em&gt;new&lt;/em&gt; modeler plugins to this device class without replacing the ones added by the OpenStack ZenPack.&lt;/p&gt;
&lt;p&gt;This will be done upon installation (like in the previous post) inside the &lt;code&gt;__init__.py&lt;/code&gt; file in the ZenPack top directory. This is how the code looks like:&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Customizing the ZenPack Installation Process</title>
      <link>https://aalvrz.me/posts/customizing-the-zenpack-installation-process/</link>
      <pubDate>Tue, 17 Jan 2017 00:00:00 +0000</pubDate>
      
      <guid>https://aalvrz.me/posts/customizing-the-zenpack-installation-process/</guid>
      <description>&lt;p&gt;There are some circumstances where we need to perform certain tasks in our ZenPack the moment it is installed. We can achieve this using Python by placing this logic inside the ZenPack&#39;s top directory&#39;s &lt;code&gt;__init__.py&lt;/code&gt; file. When creating a fresh ZenPack using &lt;strong&gt;zenpacklib&lt;/strong&gt;, this &lt;code&gt;__init__.py&lt;/code&gt; file will contain the following contents:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;zenpacklib&lt;/span&gt;

&lt;span style=&#34;color:#111&#34;&gt;CFG&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;zenpacklib&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;load_yaml&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To add custom functionality that gets executed when the ZenPack is installed, we need to extend the &lt;code&gt;install&lt;/code&gt; method of the &lt;code&gt;ZenPack&lt;/code&gt; class. Below the original code, we can proceed to do so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;color:#00a8c8&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#75af00&#34;&gt;ZenPack&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;schema&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;ZenPack&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
    &lt;span style=&#34;color:#00a8c8&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#75af00&#34;&gt;install&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;app&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
        &lt;span style=&#34;color:#75715e&#34;&gt;# Our custom logic here&lt;/span&gt;

        &lt;span style=&#34;color:#111&#34;&gt;super&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;ZenPack&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;install&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;app&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;No other imports are necessary. Notice the last line of the &lt;code&gt;install&lt;/code&gt; method, this is where the ZenPack gets installed.&lt;/p&gt;
&lt;p&gt;For the purpuse of giving an example, Let&#39;s say that our ZenPack creates two new &lt;a href=&#34;https://zenpack-sdk.zenoss.com/en/latest/yaml-zProperties.html&#34;&gt;zProperties&lt;/a&gt;, one property to store an API key, and the other one to store a URL. Moreover let&#39;s say that we obtain these values from somewhere and we want to assign them &lt;strong&gt;automatically&lt;/strong&gt; to the properties upon the installation of the ZenPack.&lt;/p&gt;
&lt;p&gt;These two new properties are defined in &lt;code&gt;zenpack.yaml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;name&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; ZenPacks.aalvarez.MyZenPack

zProperties&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
  zMyApiUrl&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
    category&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; MyApi
    type&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; string

  zMyApiKey&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
    category&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; MyApi
    type&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; string
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Custom Pages in Zenoss</title>
      <link>https://aalvrz.me/posts/custom-pages-in-zenoss/</link>
      <pubDate>Mon, 26 Dec 2016 00:00:00 +0000</pubDate>
      
      <guid>https://aalvrz.me/posts/custom-pages-in-zenoss/</guid>
      <description>&lt;p&gt;In a &lt;a href=&#34;https://aalvrz.me/posts/extending-zenoss-navigations.html&#34;&gt;previous post&lt;/a&gt; I talked about how to create custom navigation links in Zenoss using a ZenPack. However we didn&#39;t get to creating the custom pages that these links would link to. This is what we will learn today.&lt;/p&gt;
&lt;h2 id=&#34;page-viewlets&#34;&gt;Page Viewlets&lt;/h2&gt;
&lt;p&gt;Previously we created navigation item viewlets, this time we will be creating &lt;strong&gt;page&lt;/strong&gt; viewlets. These type of viewlets allow us to create and insert new custom pages into Zenoss where we can display custom content. To create a new page, we add the following code to &lt;code&gt;browser/configure.zcml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;browser:page&lt;/span&gt;
  &lt;span style=&#34;color:#75af00&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;secondaryPage&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#75af00&#34;&gt;for=&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#75af00&#34;&gt;permission=&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;zenoss.View&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#75af00&#34;&gt;template=&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;templates/my_template.pt&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is important that the &lt;strong&gt;name&lt;/strong&gt; attribute matches the URL of the navigation link we created previously. Another important attribute is the &lt;strong&gt;template&lt;/strong&gt; attribute, this is a special file that will represent the base markup of the page using a combination of HTML, TAL, and &lt;a href=&#34;http://old.zope.org/Members/tone/METAL&#34;&gt;METAL&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also let&#39;s not forget to create a necessary python init file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;touch browser/__init__.py
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    <item>
      <title>Extending Zenoss Navigation Bars</title>
      <link>https://aalvrz.me/posts/extending-zenoss-navigations/</link>
      <pubDate>Wed, 21 Dec 2016 00:00:00 +0000</pubDate>
      
      <guid>https://aalvrz.me/posts/extending-zenoss-navigations/</guid>
      <description>&lt;p&gt;It is possible to extend the functionality of Zenoss&#39;s navigations from within our custom ZenPacks. This means that we can add or remove links to the navigation bars we frequently use to access the infrastructure page or event console.&lt;/p&gt;
&lt;h2 id=&#34;configurezcml&#34;&gt;configure.zcml&lt;/h2&gt;
&lt;p&gt;Zenoss ZenPacks can contain a file in the ZenPack top directory called &lt;code&gt;configure.zcml&lt;/code&gt;. I&#39;ve mentioned and talked about this particular file in previous posts. This file basically acts as a configuration glue between back-end functions and front-end components.&lt;/p&gt;
&lt;p&gt;It is in this file where we will declare and create new navigational links from our ZenPack.&lt;/p&gt;
&lt;p&gt;~&amp;gt; In this post we assume that the ZenPack is created using &lt;a href=&#34;https://zenpacklib.zenoss.com/en/latest/&#34;&gt;zenpacklib&lt;/a&gt;, which is a Python library that makes creating ZenPacks much easier. Zenpacklib also makes the integration between the back-end and front-end much easier as well.&lt;/p&gt;
&lt;p&gt;Usually this file begins with some required boilerplate code:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;configure.zcml&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;utf-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;configure&lt;/span&gt;
  &lt;span style=&#34;color:#75af00&#34;&gt;xmlns=&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;http://namespaces.zope.org/zope&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#75af00&#34;&gt;xmlns:browser=&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;http://namespaces.zope.org/browser&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#75af00&#34;&gt;xmlns:zcml=&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;http://namespaces.zope.org/zcml&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;

  &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;!--&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; Our custom code here &lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;--&amp;gt;&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;include&lt;/span&gt; &lt;span style=&#34;color:#75af00&#34;&gt;package=&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;.browser&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/configure&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Custom Zenoss API Endpoints</title>
      <link>https://aalvrz.me/posts/custom-zenoss-api-endpoints/</link>
      <pubDate>Tue, 20 Dec 2016 00:00:00 +0000</pubDate>
      
      <guid>https://aalvrz.me/posts/custom-zenoss-api-endpoints/</guid>
      <description>&lt;p&gt;In a &lt;a href=&#34;https://aalvrz.me/posts/the-zenoss-json-api.html&#34;&gt;previous post&lt;/a&gt; I went over the Zenoss JSON API and how it works inside the Zenoss Core. In this post we will apply the concepts learned in that post in order to create custom API endpoints within Zenoss, which can be accessed by the JavaScript front-end, &lt;em&gt;curl&lt;/em&gt;, API clients, etc. All this new functionality added from a basic ZenPack.&lt;/p&gt;
&lt;h2 id=&#34;creating-an-endpoint&#34;&gt;Creating an Endpoint&lt;/h2&gt;
&lt;p&gt;Assuming that we are starting with a new and fresh ZenPack created with &lt;a href=&#34;https://zenpacklib.zenoss.com/en/latest/&#34;&gt;zenpacklib&lt;/a&gt;, we will proceed to create a simple endpoint.&lt;/p&gt;
&lt;p&gt;Let&#39;s go ahead and create a file named &lt;code&gt;api.py&lt;/code&gt; (can be any name) under the ZenPack&#39;s top directory. In this file we will import necessary modules, implement interfaces, and define our &lt;strong&gt;routers&lt;/strong&gt; and &lt;strong&gt;facades&lt;/strong&gt;. If you still don&#39;t know what routers and facades are and what they do, I suggest you first take a look at &lt;a href=&#34;https://aalvrz.me/posts/the-zenoss-json-api.html&#34;&gt;The Zenoss JSON API&lt;/a&gt; post.&lt;/p&gt;
&lt;p&gt;First, let&#39;s take a quick look at the imports:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;os.path&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;urlparse&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;urlparse&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;subprocess&lt;/span&gt;

&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;zope.event&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;notify&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;zope.interface&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;implements&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;ZODB.transact&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;transact&lt;/span&gt;

&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;Products.ZenUtils.Ext&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;DirectRouter&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;DirectResponse&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;Products&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;Zuul&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;Products.Zuul.catalog.events&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;IndexingEvent&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;Products.Zuul.facades&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;ZuulFacade&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;Products.Zuul.interfaces&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;IFacade&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;Products.Zuul.utils&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;ZuulMessageFactory&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;_t&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;Products.ZenUtils.Utils&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;zenPath&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Some imports are probably not needed, but the ones that are of our interest are imports such as &lt;code&gt;DirectRouter&lt;/code&gt; and &lt;code&gt;DirectResponse&lt;/code&gt;, which you might remember from the previous post. Additionally we are also importing the necessary facade, events, and interfaces imports.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>SSH Monitoring in ZenPacks</title>
      <link>https://aalvrz.me/posts/ssh-monitoring-in-zenpacks/</link>
      <pubDate>Wed, 14 Dec 2016 00:00:00 +0000</pubDate>
      
      <guid>https://aalvrz.me/posts/ssh-monitoring-in-zenpacks/</guid>
      <description>&lt;p&gt;Zenoss usually monitors and collects information using &lt;strong&gt;SNMP&lt;/strong&gt; and &lt;strong&gt;SSH&lt;/strong&gt; methods. A good example of is the &lt;a href=&#34;http://wiki.zenoss.org/ZenPack:Linux_Monitor&#34;&gt;linux monitor ZenPack&lt;/a&gt; which can collect information such as hard disks, interfaces, and file systems using &lt;strong&gt;both&lt;/strong&gt; methods.&lt;/p&gt;
&lt;p&gt;SNMP works by installing and configuring an SNMP agent on the machine we want to monitor. This agent will poll the machine for data, and this data can be retrieved by Zenoss using &lt;strong&gt;&lt;a href=&#34;http://www.net-snmp.org/&#34;&gt;net-snmp&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;On the other hand, SSH works by configuring a username and password or a path to an SSH key zProperties. This will allow Zenoss to remotely access the host using SSH and execute the corresponding commands and return the corresponding information.&lt;/p&gt;
&lt;p&gt;When developing ZenPacks, data collection using SNMP is a relatively common practice. There is even a very good tutorial on &lt;a href=&#34;https://zenpacklib.zenoss.com/en/latest/tutorial-snmp-device/index.html&#34;&gt;SNMP monitoring using zenpacklib&lt;/a&gt;. When using SNMP, the modeler plugins are &lt;code&gt;SnmpPlugin&lt;/code&gt; plugins that typically work using a set of &lt;a href=&#34;http://www.dpstele.com/snmp/what-does-oid-network-elements.php&#34;&gt;OIDs&lt;/a&gt; to determine exactly which data is to be modeled.&lt;/p&gt;
&lt;h2 id=&#34;ssh-in-modeler-plugins&#34;&gt;SSH in Modeler Plugins&lt;/h2&gt;
&lt;p&gt;In order to make a modeler plugin utilize SSH as it&#39;s polling method we need to use a different type of plugin, the &lt;code&gt;CommandPlugin&lt;/code&gt; plugin. The structure of this type of plugin is very similar to the &lt;code&gt;SnmpPlugin&lt;/code&gt;, however there is one critical variable that must be implemented.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Modifying the Zenoss Infrastructure Grid</title>
      <link>https://aalvrz.me/posts/modifying-the-zenoss-infrastructure-grid/</link>
      <pubDate>Thu, 10 Nov 2016 00:00:00 +0000</pubDate>
      
      <guid>https://aalvrz.me/posts/modifying-the-zenoss-infrastructure-grid/</guid>
      <description>&lt;p&gt;Continuing from my previous post, where I explained &lt;a href=&#34;https://aalvrz.me/posts/modifying-the-zenoss-device-detail-bar.html&#34;&gt;how to modify the device detail bar from a ZenPack using ExtJS&lt;/a&gt;, in this post I will explain how we can modify the device list grid shown in the infrastructure page.&lt;/p&gt;
&lt;h2 id=&#34;the-infrastructure-grid&#34;&gt;The Infrastructure Grid&lt;/h2&gt;
&lt;p&gt;This is the table in the infrastructure page that shows all devices being monitored by Zenoss. Default columns include &lt;em&gt;device name&lt;/em&gt;, &lt;em&gt;device class&lt;/em&gt;, &lt;em&gt;IP address&lt;/em&gt;, &lt;em&gt;production state&lt;/em&gt;, and &lt;em&gt;events&lt;/em&gt;, as shown in the image below:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://aalvrz.me/posts/modifying-the-zenoss-infrastructure-grid/zenoss_device_grid.png&#34; alt=&#34;Zenoss Infrastructure Grid&#34;&gt;&lt;/p&gt;
&lt;p&gt;However it would be nice to also include the power status we added to the device detail bar in the previous post, maybe even add the ping status as well (why Zenoss doesn&#39;t do this by default is beyond me).&lt;/p&gt;
&lt;h2 id=&#34;devicepanelsjs&#34;&gt;DevicePanels.js&lt;/h2&gt;
&lt;p&gt;The source code for the grid is found in &lt;code&gt;$ZENHOME/Products/ZenUI/browser/resources/js/zenoss/DevicePanels.js&lt;/code&gt;. A quick glance at it and you will quickly find the definitions of the columns I mentioned earlier, defined in an array called &lt;code&gt;deviceColumns&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Modifying the Zenoss Device Detail Bar</title>
      <link>https://aalvrz.me/posts/modifying-the-zenoss-device-detail-bar/</link>
      <pubDate>Tue, 08 Nov 2016 00:00:00 +0000</pubDate>
      
      <guid>https://aalvrz.me/posts/modifying-the-zenoss-device-detail-bar/</guid>
      <description>&lt;p&gt;The Zenoss Core &lt;a href=&#34;https://www.sencha.com/products/extjs/&#34;&gt;&lt;strong&gt;ExtJS&lt;/strong&gt;&lt;/a&gt; graphic user interface is divided into many different components. In this post I will go over on how we can modify the device detail bar to display additional custom information for devices, by creating a custom ZenPack.&lt;/p&gt;
&lt;p&gt;Zenoss Core 4 uses ExtJS 4 JavaScript framework to manage all the user interface components. These components can be found in &lt;code&gt;$ZENHOME/Products/ZenUI3/browser/resources/js/zenoss&lt;/code&gt;, and as you would expect, the device detail bar component is also located there.&lt;/p&gt;
&lt;h2 id=&#34;the-device-detail-bar&#34;&gt;The Device Detail Bar&lt;/h2&gt;
&lt;p&gt;This is the detail bar located on the device view page which shows the device&#39;s icon, name, events, status, production state, and priority. The JavaScript source code for this component can be found in &lt;code&gt;DeviceDetailBar.js&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://aalvrz.me/posts/modifying-the-zenoss-device-detail-bar/device_detail_bar.png&#34; alt=&#34;Device Detail Bar&#34;&gt;&lt;/p&gt;
&lt;p&gt;However since we are going to &lt;strong&gt;&lt;em&gt;extend&lt;/em&gt;&lt;/strong&gt; this component through a ZenPack, we will not modify that source. Instead, we will add new code to use ExtJS to add our custom data displays.&lt;/p&gt;
&lt;h2 id=&#34;extending-the-component-through-zenpacks&#34;&gt;Extending The Component, Through ZenPacks&lt;/h2&gt;
&lt;p&gt;Let&#39;s assume we are starting with a freshly created ZenPack, which adds a new &lt;code&gt;power_status&lt;/code&gt; integer field to certain devices, according to its &lt;code&gt;zenpack.yaml&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# ...&lt;/span&gt;

classes&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
  CustomDevice&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
    base&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;[&lt;/span&gt;zenpacklib.Device&lt;span style=&#34;color:#111&#34;&gt;]&lt;/span&gt;
    label&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; Custom Device
    properties&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
      power_status&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
        type&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; boolean

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What we want is to display this value in the device&#39;s detail bar, similar to the device&#39;s ping status display.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Creating Zenoss ZenPack Daemons</title>
      <link>https://aalvrz.me/posts/creating-zenoss-zenpack-daemons/</link>
      <pubDate>Mon, 07 Nov 2016 00:00:00 +0000</pubDate>
      
      <guid>https://aalvrz.me/posts/creating-zenoss-zenpack-daemons/</guid>
      <description>&lt;p&gt;ZenPacks are powerful custom add-ons that can help us extend Zenoss&#39;s functionality. In this post I will go over on how to create a ZenPack that adds a custom daemon to the existing Zenoss daemons and runs on a configured cycle time to perform custom tasks. We will achieve this by creating the ZenPack using &lt;a href=&#34;http://zenpacklib.zenoss.com/en/latest/index.html&#34;&gt;&lt;strong&gt;zenpacklib&lt;/strong&gt;&lt;/a&gt;, but it is also possible to create it from the Zenoss user interface.&lt;/p&gt;
&lt;h2 id=&#34;about-zenpacklib&#34;&gt;About zenpacklib&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;zenpacklib&lt;/strong&gt; is a Python library developed by the Zenoss team to facilitate the process of creating ZenPacks, specially ZenPacks that deal with modeling and monitoring devices and components. Most of the newer ZenPacks that are being released are now being built with zenpacklib.&lt;/p&gt;
&lt;p&gt;We can obtain zenpacklib by running the following commands:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wget http://zenpacklib.zenoss.com/zenpacklib.py
chmod 755 zenpacklib.py
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will download the zenpacklib Python library and give it executable permissions.&lt;/p&gt;
&lt;h2 id=&#34;creating-the-zenpack&#34;&gt;Creating the ZenPack&lt;/h2&gt;
&lt;p&gt;Using the zenpacklib file we just downloaded, we proceed to create a new fresh ZenPack:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;./zenpacklib.py create ZenPacks.&amp;lt;your_namespace&amp;gt;.&amp;lt;zenpack_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will create the ZenPack base directory with the necessary base files.&lt;/p&gt;
&lt;p&gt;Now we go into this directory to begin.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd ZenPacks.&amp;lt;your_namespace&amp;gt;.&amp;lt;zenpack_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;creating-the-zenpack-daemon&#34;&gt;Creating the ZenPack Daemon&lt;/h2&gt;
&lt;p&gt;Our custom daemon declaration will be located in a directory named &lt;code&gt;daemons&lt;/code&gt;, inside our ZenPack directory:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir ZenPacks.&amp;lt;your_namespace&amp;gt;.&amp;lt;zenpack_name&amp;gt;/&amp;lt;your_namespace&amp;gt;/&amp;lt;zenpack_name&amp;gt;/daemons
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here we will create a new Bashscript file with the name of our daemon. In this case we will name it &lt;code&gt;mydaemon&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#! /usr/bin/env bash
&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;
&lt;span style=&#34;color:#111&#34;&gt;DAEMON_NAME&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;mydaemon&amp;#34;&lt;/span&gt;

. &lt;span style=&#34;color:#111&#34;&gt;$ZENHOME&lt;/span&gt;/bin/zenfunctions

&lt;span style=&#34;color:#111&#34;&gt;MYPATH&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;`&lt;/span&gt;python -c &lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;import os.path; print os.path.realpath(&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;$0&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#39;)&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;THISDIR&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;`&lt;/span&gt;dirname &lt;span style=&#34;color:#111&#34;&gt;$MYPATH&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;PRGHOME&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;`&lt;/span&gt;dirname &lt;span style=&#34;color:#111&#34;&gt;$THISDIR&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;PRGNAME&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;$DAEMON_NAME&lt;/span&gt;.py &lt;span style=&#34;color:#111&#34;&gt;CFGFILE&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;$CFGDIR&lt;/span&gt;/&lt;span style=&#34;color:#111&#34;&gt;$DAEMON_NAME&lt;/span&gt;.conf

generic &lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;$@&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once the ZenPack is installed, files under this &lt;code&gt;daemons&lt;/code&gt; directory will become executable (&lt;code&gt;chmod 0755&lt;/code&gt;), a symlink to the file will be created in &lt;code&gt;$ZENHOME/bin&lt;/code&gt;, and a configuration file will be generated in &lt;code&gt;$ZENHOME/etc/&amp;lt;daemon_name&amp;gt;.conf&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; If you created your ZenPack using the Zenoss user interface, the &lt;code&gt;daemons&lt;/code&gt; directory will also be automatically created, and will contain an example daemon file named &lt;code&gt;zenexample&lt;/code&gt; with code similar to the one above. In this case you should simply replace the necessary values.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Zenoss Renderers</title>
      <link>https://aalvrz.me/posts/zenoss-renderers/</link>
      <pubDate>Thu, 27 Oct 2016 00:00:00 +0000</pubDate>
      
      <guid>https://aalvrz.me/posts/zenoss-renderers/</guid>
      <description>&lt;p&gt;Zenoss makes use of some very interesting graphical components called renderers. These are used to manipulate the way data is shown in the Zenoss user interface.&lt;/p&gt;
&lt;p&gt;For example, a value of &lt;em&gt;total bytes used&lt;/em&gt; could be 6080626688 in bytes, which is a very high number and doesn&#39;t really convey much meaning. However, we can use a built-in Zenoss renderer called &lt;code&gt;bytesString&lt;/code&gt; which will convert this value in bytes to the closest representation:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://aalvrz.me/posts/zenoss-renderers/zenoss_renderers.png&#34; alt=&#34;Zenoss Renderers&#34;&gt;&lt;/p&gt;
&lt;p&gt;As we can see, this is a much better and meaningful way of displaying the data.&lt;/p&gt;
&lt;p&gt;The built-in Zenoss renderers and source code can be found in &lt;code&gt;$ZENHOME/Products/ZenUI3/browser/resources/js/zenoss/Renderers.js&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;They are a list of registered Javascript functions that can be assigned in our YAML definitions file by adding the &lt;code&gt;renderer&lt;/code&gt; property. For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;HardDisk&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
  base&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;[&lt;/span&gt;zenpacklib.Component&lt;span style=&#34;color:#111&#34;&gt;]&lt;/span&gt;
  label&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; Hard Disk
  properties&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
     location&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
        label&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; Location

     capacity&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
        label&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; Capacity

     raid_name&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
        label&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; Raid Name

     raid_level&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
        label&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; Raid Level

     status&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
        label&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; Status
        renderer&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; Zenoss.render.pingStatus
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Zenoss.render.pingStatus&lt;/code&gt; is one of the default renderers that come built-in within Zenoss Core 4, similar to &lt;code&gt;Zenoss.render.bytesString&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Changing Zenoss Dashboard Portlets Using CLI</title>
      <link>https://aalvrz.me/posts/changing-zenoss-dashboard-portlets-using-cli/</link>
      <pubDate>Wed, 26 Oct 2016 00:00:00 +0000</pubDate>
      
      <guid>https://aalvrz.me/posts/changing-zenoss-dashboard-portlets-using-cli/</guid>
      <description>&lt;p&gt;The Zenoss &lt;a href=&#34;http://wiki.zenoss.org/ZenPack:Dashboard&#34;&gt;ZenPacks.zenoss.Dashboard&lt;/a&gt; ZenPack adds a very nice and new dashboard to our Zenoss Core 4 deployment, replacing the old default dashboard that comes with the installation.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;http://wiki.zenoss.org/images/0/01/Separate_dashboard.png&#34; alt=&#34;ZenPack Dashboard&#34;&gt;&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>