Skip to content

Development environment

The process of developing a ZenPack can be made much faster and easier by starting with a good development environment. A good development environment should do the following.

  • Isolate your changes from other users changes or a production systems.
  • Allow you to quickly see the result of changes for faster iteration.
  • Allow you to easily troubleshoot when changes do not have the desired effect.

The following recommendations are a good starting point for anyone wanting to develop ZenPacks for Collection Zone or Resource Manager deployments.

Installing

You must have Collection Zone or Resource Manager installed to develop ZenPacks. Zenoss recommends using a dedicated Resource Manager instance for development. Start by following the normal installation instructions available at docs.zenoss.com with the following notes.

  • System requirements for development can be lower. See below.
  • Use a single-host installation.
  • Any supported operating system can be used. This guide assumes Linux.
  • Verify that Zenoss has been deployed and its web interface is working.

System requirements

A development system will usually have system requirements lower than those of a production system. This is because it likely will not be storing as much data, supporting as many web users, or even performing continual monitoring. Your development system should have at least the following resources.

  • 4 CPU cores
  • 20 GB memory
  • 75 GB storage

Configuring the system

To improve productivity, make the following changes to your development system. Each change will be detailed in subsequent sections.

  • Add a zenoss user to the host that matches the same user in containers.
  • Create a /z directory on the host to share with containers.
  • Configure serviced to automatically share /z with all containers.

First make sure that you have Zenoss.resmgr service deployed and running, and that you are able to login to its web interface. All commands in the following sections should be run as root or through sudo unless otherwise noted.

Add a zenoss user

To make development easier we're going to be sharing files between the host and docker containers running on the host. We can create a zenoss user on the host that matches the UID (user ID) and GID (group ID) of the zenoss user in the containers to avoid having to worry about permissions problems with those shared files.

groupadd --gid=1206 zenoss
adduser --uid=1337 --gid=1206 zenoss

The zenoss user should be able to use sudo and docker commands, which you enable by adding the user to the wheel and docker groups, respectively.

usermod -a -G wheel zenoss
usermod -a -G docker zenoss

Also, add the user to the serviced group as well, in order to interact with Control Center containers.

usermod -a -G serviced zenoss

Helper aliases and functions

Many commands must be run inside Zope containers. To reduce toil, add the following lines to the .bashrc file of the zenoss user:

/home/zenoss/.bashrc
## ZenPack development helpers.
alias zope='serviced service attach zope su zenoss -l'
alias zenhub='serviced service attach zenhub su zenoss -l'
z () { serviced service attach zope su zenoss -l -c "cd /z;$*"; }
zenbatchload () { z zenbatchload $*; }
zendisc () { z zendisc $*; }
zendmd () { z zendmd $*; }
zenmib () { z zenmib $*; }
zenmodeler () { z zenmodeler $*; }
zenpack () { z zenpack $*; }
zenpacklib () { z zenpacklib $*; }
zenpython () { z zenpython $*; }

The preceding declarations enable the following shortcuts:

  • zope - Start a shell in a Zope container as the zenoss user.
  • zenhub - Start a shell in the zenhub container as the zenoss user.
  • z - Run any command as the zenoss user in a Zope container.
    • zendisc - Discover new devices
    • zendmd - Open the zendmd console
    • zenmib - Import SNMP MIB files
    • zenmodeler - Remodel existing devices
    • zenpack - Install and remove ZenPacks
    • zenpacklib - Run zenpacklib commands

Authenticating as zenoss

You will likely want to login to the system as the zenoss user after getting the system configured. That way you won’t have to switch (su) to the user to make sure files you create have the right permissions. Either set a password for the user or add your public key to the user’s authorized_keys file to support this.

Optionally set the zenoss user’s password:

passwd zenoss

Optionally add your SSH public key to the zenoss user’s authorized_keys file to login without a password:

mkdir -p /home/zenoss/.ssh
chmod 700 /home/zenoss/.ssh
cat >> /home/zenoss/.ssh/authorized_keys
... paste your public key, enter, ctrl-D ...
chmod 600 /home/zenoss/.ssh/authorized_keys
chown -R zenoss:zenoss /home/zenoss/.ssh

Create a /z directory

Now we can create a directory to share that the zenoss user on the host and in the container will be able to use. The specific path of this directory isn’t particularly important, but I like using /z because it’s as short as possible.

mkdir -p /z
chown -R zenoss:zenoss /z

Mount /z into all containers

Now we can configure serviced to automatically share (bind mount) the host’s /z directory into every container it starts. This will let us use the same files on the host and in containers using the exact same path.

Edit /etc/default/serviced. Find the existing SERVICED_OPTS line. It will likely be commented out (with a #) and look like the following.

/etc/default/serviced
## Arbitrary serviced daemon args
## SERVICED_OPTS=

Uncomment it, and add the bind mount configuration as follows.

/etc/default/serviced

/etc/default/serviced
## Arbitrary serviced daemon args
SERVICED_OPTS="--mount *,/z,/z"

You must then restart serviced.

systemctl restart serviced

Test /z sharing

Now you can verify that both the host and containers can read and write files in /z.

On the host:

su - zenoss # becomes zenoss user on host
touch /z/host
serviced service attach zenhub # attach to a container
su - zenoss # becomes zenoss user in container
rm /z/host
touch /z/container
exit # back to container root user
exit # back to host zenoss user
rm /z/container
exit # back to host root user

Configuring Zenoss services

There are some optional tweaks you can make to Zenoss service definitions to make development faster and easier. We’ll go through the following here.

  • Reducing Zope to a single instance so breakpoints can be used.
  • Setting unnecessary services to not automatically launch.

Reducing Zope to a single instance

Out of the box, Zope is configured to run a minimum of two instances. This is problematic when you insert a breakpoint (pdb.set_trace()) in code run by Zope because you can’t be sure the breakpoint will occur in the instance of Zope you happen to be running in the foreground.

Run the following command to edit the Zope service definition. This will open vi with Zope’s JSON service definition.

serviced service edit Zope

Search this file for “Instances” with the quotes. You should see a section that looks something like the following. Change Instances, Min, and Default to 1. Then save and quit.

"Instances": 6,
"InstanceLimits": {
  "Min": 2,
  "Max": 0,
  "Default": 6
},

Run the following command to restart Zope and effect the change.

serviced service restart Zope

Setting services to manual launch

The default Zenoss service templates are configured to launch almost all services they contain automatically. When developing ZenPacks it’s usually unnecessary to have all of the collector process such as zenping running. These services are consuming memory, CPU, and may need to be restarted frequently as you’re making code changes. To avoid all of that you can configure some services to not launch automatically when you start the service.

Run the following command to edit zenping’s service definition to make it not automatically launch.

serviced service edit zenping

Search this file for “Launch” with the quotes. You should see a section that looks like the following. Change auto to manual. Then save and quit.

"Launch": "auto",

This won’t stop zenping if it was already running, but it will prevent it from starting up next time you start Zenoss.resmgr.

Here’s the base list of services you should consider setting to the manual launch mode.

  • zencommand
  • zenjmx
  • zenmodeler
  • zenperfsnmp
  • zenping
  • zenprocess
  • zenpython
  • zenstatus
  • zensyslog
  • zentrap

Here are some additional services that could be set to manual.

  • zenjserver
  • zenpropertymonitor
  • zenucsevents
  • zenvsphere

You may have more or less services on your system depending on what ZenPacks are installed. The rule of thumb should be that any services under the Collection tree can be set to manual except for zenhub, zenhubworker, MetricShipper, collectorredis, and zminion.