Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit. Got the cookbook in place with no changes yet. THIS W…

…ILL NOT WORK!
  • Loading branch information...
commit 618b53b8ac6566838f800cf9564cdfed491695dd 0 parents
Crowbar User authored
Showing with 1,581 additions and 0 deletions.
  1. +26 −0 README.txt
  2. +21 −0 bin/crowbar_zenoss
  3. +104 −0 chef/cookbooks/zenoss/CHANGELOG.md
  4. +162 −0 chef/cookbooks/zenoss/README.md
  5. +56 −0 chef/cookbooks/zenoss/attributes/default.rb
  6. +8 −0 chef/cookbooks/zenoss/data_bags/Zenoss_Readonly_User.json
  7. +11 −0 chef/cookbooks/zenoss/data_bags/Zenoss_User.json
  8. +71 −0 chef/cookbooks/zenoss/metadata.rb
  9. +83 −0 chef/cookbooks/zenoss/providers/zenbatchload.rb
  10. +129 −0 chef/cookbooks/zenoss/providers/zendmd.rb
  11. +75 −0 chef/cookbooks/zenoss/providers/zenpack.rb
  12. +14 −0 chef/cookbooks/zenoss/providers/zenpatch.rb
  13. +58 −0 chef/cookbooks/zenoss/recipes/client.rb
  14. +21 −0 chef/cookbooks/zenoss/recipes/default.rb
  15. +245 −0 chef/cookbooks/zenoss/recipes/server.rb
  16. +5 −0 chef/cookbooks/zenoss/resources/zenbatchload.rb
  17. +11 −0 chef/cookbooks/zenoss/resources/zendmd.rb
  18. +7 −0 chef/cookbooks/zenoss/resources/zenpack.rb
  19. +4 −0 chef/cookbooks/zenoss/resources/zenpatch.rb
  20. +38 −0 chef/cookbooks/zenoss/roles/Class_Server-SSH-Linux-MySQL.rb
  21. +24 −0 chef/cookbooks/zenoss/roles/Class_Server-SSH-Linux.rb
  22. +10 −0 chef/cookbooks/zenoss/roles/Location_Austin.rb
  23. +10 −0 chef/cookbooks/zenoss/roles/Location_Seattle.rb
  24. +28 −0 chef/cookbooks/zenoss/roles/ZenossServer.rb
  25. +26 −0 chef/data_bags/crowbar/bc-template-zenoss.json
  26. +71 −0 chef/data_bags/crowbar/bc-template-zenoss.schema
  27. +9 −0 chef/roles/zenoss-server.rb
  28. +153 −0 crowbar.yml
  29. +21 −0 crowbar_framework/app/controllers/zenoss_controller.rb
  30. +60 −0 crowbar_framework/app/models/zenoss_service.rb
  31. +10 −0 crowbar_framework/app/views/barclamp/zenoss/_edit_attributes.html.haml
  32. +10 −0 crowbar_framework/app/views/barclamp/zenoss/_edit_deployment.html.haml
26 README.txt
@@ -0,0 +1,26 @@
+Welcome to a Barclamp for the Crowbar Framework project
+=======================================================
+_Copyright 2011, Keith Hudgins_
+
+The code and documentation is distributed under the Apache 2 license (http://www.apache.org/licenses/LICENSE-2.0.html). Contributions back to the source are encouraged.
+
+The Crowbar Framework (https://github.com/dellcloudedge/crowbar) was developed by the Dell CloudEdge Solutions Team (http://dell.com/openstack) as a OpenStack installer (http://OpenStack.org) but has evolved as a much broader function tool.
+A Barclamp is a module component that implements functionality for Crowbar. Core barclamps operate the essential functions of the Crowbar deployment mechanics while other barclamps extend the system for specific applications.
+
+* This functonality of this barclamp DOES NOT stand alone, the Crowbar Framework is required *
+
+About this Zenoss
+-------------------------------------
+
+Information for this barclamp is maintained on the Crowbar Framework Wiki: https://github.com/dellcloudedge/crowbar/wiki
+
+
+
+
+Legals
+-------------------------------------
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
21 bin/crowbar_zenoss
@@ -0,0 +1,21 @@
+#!/usr/bin/env ruby
+# Copyright 2011, Keith Hudgins
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+require File.join(File.expand_path(File.dirname(__FILE__)), "barclamp_lib")
+@barclamp = "zenoss"
+
+main
104 chef/cookbooks/zenoss/CHANGELOG.md
@@ -0,0 +1,104 @@
+This is the current, previous and future development milestones and contains the features backlog.
+
+0.1
+===
+mostly documentation
+zenoss::client depends on openssh
+
+0.2
+===
+zenoss::server installs itself via apt
+
+0.3
+===
+$ZENHOME is an attribute
+zenoss_zenpack LWRP with :install :remove
+install linux monitor ZenPack
+zenoss_zendmd LWRP with :run
+sets the admin password via attribute
+
+0.4
+===
+checks for already installed zenpacks, apt repos
+hash of installed_zenpacks as key->package, value->version: server attribute
+single attributes/default.rb file since there's no differentiation
+zenoss::server generate SSH keys for the zenoss user and writes it to an attribute
+zenoss::client get the SSH keys via the attribute writes it to /home/zenoss/.ssh/authorized_keys
+
+0.5
+===
+LWRP for 3.0.3 zenpatches (http://dev.zenoss.com/trac/report/6 is the basis)
+Roles will be used for Device Classes, Groups and Locations
+Recipes will be used for Systems
+server will insert devices
+devices get added to zenoss::server that implement the zenoss::client recipe
+zenoss::clients will have attributes for any particular properties they need set
+
+0.6
+===
+check search in client.rb to negate use of [0]
+in metadata.rb, you should add recipes http://wiki.opscode.com/display/chef/Metadata#Metadata-recipe
+move restart to server.rb for zenpack installation
+skips new install wizard
+create a random admin password (in mysql cookbook)
+user manage_home true
+document use of external IP addresses
+include the search zenpack
+zendmd use debug for commands
+load_current_resource for zenpack installation
+zenoss::client server move self to /Server/SSH/Linux instead of /Server/Linux
+monitoring server should have a default role ('monitoring' is used in Nagios)
+document enabling ping through the security group in EC2
+add additional users via zendmd (extend zendmd LWRP for user-management)
+use the "sysadmins" data bag to populate the users
+provide example data_bag files for loading users
+
+0.6.2
+===
+add support for Zenoss 3.1.0
+
+0.7 *CURRENT*
+===
+yum cookbook dependency
+CentOS 5.6 and Scientific Linux 5.5 support via yum_repository LWRP
+
+
+0.8
+mysql::server dependency for rpm installs
+notify zendmd at end of run to load everything (before zenbatchload)
+optimize creation of device classes, systems and groups by using hashes instead of individual calls or by comparing against previous values
+diff previous zenbatchload run
+clients request specific ZenPacks (or Device Class roles?)
+AWS ZenPack and Role for Device Class
+
+
+BACKLOG:
+Chef Client ZenPack
+configure mail settings
+sysadmin_email - default notification email.
+sysadmin_sms_email - default notification sms.
+encrypted data bags for storing passwords
+nodes not in "production" environment could map to other production states ("preproduction", "decommissioned", etc.")
+make zenoss server receive syslog
+install nagios plugins
+templates for the configuration? (http://community.zenoss.org/docs/DOC-8511)
+other configuration/tuning options exposed as attributes?
+configure zope.conf
+distributed collectors
+disable some of the daemons that are unused
+other types of things to monitor could be added by search (ie. apache::server or mysql::server)
+anything useful for the zLink?
+LDAP logins
+snmpd cookbook
+ERB template for monitoring via Zenoss that exposes the basics in a secure fashion
+change default community string to "cookbook"
+
+CHEF SERVER ZENPACK
+list of managed nodes
+link back to Chef server/platform in zLink
+zlinked and any stats available
+any reports
+AMQP message queue event listener
+anything worth pushing to the Chef Server with Knife?
+is there any additional monitoring data available from Chef Server worth exposing
+
162 chef/cookbooks/zenoss/README.md
@@ -0,0 +1,162 @@
+Description
+===========
+Installs and configures a Zenoss server with the `zenoss::server` recipe. Devices can be added to the Zenoss server by using the `zenoss::client` recipe and utilizing Chef roles to map to Zenoss Device Classes, Locations and Groups. LWRPs are available for installing ZenPacks, zenpatches, loading devices and users and running zendmd commands.
+
+CHANGELOG.md covers history and planned features
+
+Requirements
+============
+Written with Chef 0.10.0.rc.0 and uses fairly recent search capabilities of roles.
+
+The example roles in the `zenoss/roles` directory should be loaded for use, refer to the Roles subsection.
+
+Testing
+-------
+Tested on Ubuntu 10.04 and 10.10 and tested with Chef 0.9.12.
+Tested on CentOS 5.6 and Scientific Linux 5.5 and tested with Chef 0.10.0.rc.0.
+
+Attributes
+==========
+Attributes under the `zenoss` namespace.
+
+* `["zenoss"]["device"]["device_class"]` - Device Class for the device, "/Discovered" is the default and may be overwritten at the Role or Node.
+* `["zenoss"]["device"]["location"]` - Location for the device, may be set at the Role or Node.
+* `["zenoss"]["device"]["modeler_plugins"]` - Modeler Plugins used by the device, may be set at the Role or Node.
+* `["zenoss"]["device"]["properties"]` - Configuration Properties used by the device, may be set at the Role or Node.
+* `["zenoss"]["device"]["templates"]` - Monitoring Templates used by the device, may be set at the Role or Node.
+* `["zenoss"]["server"]["admin_password"]` - Password for the `admin` account, default is `chefzenoss`
+* `["zenoss"]["server"]["installed_zenpacks"]` - Hash of ZenPacks and their versions, defaults are `"ZenPacks.zenoss.LinuxMonitor" => "1.1.5", "ZenPacks.community.MySQLSSH" => "0.4"`
+* `["zenoss"]["server"]["zenhome"]` - Directory of the Zenoss server installation, default is `/usr/local/zenoss/zenoss` for Debian/Ubuntu and `/opt/zenoss` for CentOS/RHEL/Scientific Linux.
+* `["zenoss"]["server"]["zenoss_pubkey"]` - Public key for the `zenoss` user used for monitoring. Set on the server automatically if it does not exist.
+* `["zenoss"]["server"]["zenpatches"]` - Hash of patches and the tickets providing the patches, defaults are `"23716" => "http://dev.zenoss.com/trac/ticket/7485", "23833" => "http://dev.zenoss.com/trac/ticket/6959"`
+
+Resources/Providers
+===================
+zenbatchload
+------------
+This LWRP builds a list of devices, their Device Classes, Systems, Groups, Locations and their properties and populates the `zenoss::server` with them.
+
+zendmd
+------
+This LWRP takes a command to be executed by the `zendmd` command on the Zenoss server. Examples include setting passwords and other changes to the Zope object database.
+
+zenpack
+-------
+Installs ZenPacks on the `zenoss::server` for use for extending the base functionality.
+
+zenpatch
+--------
+Installs patches on the `zenoss::server` based on the number referenced in the ticket.
+
+Recipes
+=======
+Default
+-------
+The default recipe passes through to `zenoss::client`.
+
+Client
+------
+The client includes the `openssh` recipe and adds the device to the Zenoss server for monitoring.
+
+Server
+------
+The server includes the `openssh` and `apt` recipes. The server recipe installs Zenoss from the .deb stack installer via the `apt` cookbook, handling and configuring all the dependencies.
+
+The recipe does the following:
+
+1. Installs Zenoss per the Zenoss Installation Guide.
+2. Applies post-3.1.0 patches from closed tickets.
+3. Starts server.
+4. Sets the `admin` password.
+5. Adds any other users to the proper Zenoss roles.
+6. Creates a `zenoss` user for running Zenoss and monitoring clients via SSH.
+7. Installs ZenPacks required for monitoring.
+8. Creates Device Classes, Groups and Locations based on Chef roles containing custom settings.
+9. Adds Systems to the server based on which recipes are used within Chef.
+10. Adds itself to be monitored.
+11. Searches for members of the `sysadmins` group by searching through `users` data bag and adds them to the server.
+12. Finds all nodes implementing `zenoss::client` and adds them for monitoring and places them in the proper Device Classes, Groups, Systems and Locations and any node-specific settings as well.
+
+Data Bags
+=========
+Create a `users` data bag that will contain the users that will be able to log into the Zenoss server (members of the 'sysadmin' group). The admin user is automatically provided. Zenoss-specific information is stored in the `zenoss` hash. Passwords may be set or left out. Multiple roles may be set; the choices with Zenoss Core are Manager, ZenManager, ZenUser or empty. Users may belong to User Groups within Zenoss (listing them here will create them). Example user data bag item:
+
+ {
+ "id": "zenossadmin",
+ "groups": "sysadmin",
+ "zenoss": {
+ "password": "abc",
+ "roles": ["Manager", "ZenUser"],
+ "user_groups": ["managers"],
+ "pager": "zpager@example.com",
+ "email": "zemail@example.com"
+ }
+ }
+
+Two example data bags are provided and may be loaded like this:
+
+ knife data bag create users
+ knife data bag from file users cookbooks/zenoss/data_bags/Zenoss_User.json
+ knife data bag from file users cookbooks/zenoss/data_bags/Zenoss_Readonly_User.json
+
+Roles
+=====
+This cookbook provides a number of example roles for mapping attributes to Zenoss' Device Classes, Groups and Locations. There is also a role called "ZenossServer" that may be used to configure the Zenoss server for convenience. These roles may be loaded like this:
+
+ knife role from file cookbooks/zenoss/roles/Class_Server-SSH-Linux.rb
+
+Device Class Roles
+------------------
+* Roles intended to map to Device Classes set the attribute `[:zenoss][:device][:device_class]`. This is an override_attribute on the role.
+* Roles may set default attributes for `[:zenoss][:device][:modeler_plugins]`, `[:zenoss][:device][:templates]` and `[:zenoss][:device][:properties]` to be applied to the Device Class.
+* The `name` for the role is unused by Zenoss.
+* Nodes may only belong to a single Device Class, nodes that belong to multiple Device Class roles will have non-determinant membership in a single Device Class.
+
+Location Roles
+--------------
+* Roles intended to map to Locations set the attribute `[:zenoss][:device][:location]`. This is an override_attribute on the role.
+* Location roles may set the have `[:zenoss][:device][:address]` attribute for the Google map address. If you are using a newline, make sure it is entered as `\\n` in the role. This is an override_attribute on the role.
+* The `name` and the `description` for the role map to the name and description of the Location.
+* Nodes may only belong to a single Location, nodes that belong to multiple Location roles will have non-determinant membership in a single Location.
+
+Group Roles
+-----------
+* The roles in organization will populate the Groups on the Zenoss server.
+* The Device Class and Location roles will not be added to Groups.
+
+Usage
+=====
+For a Zenoss server add the following recipe to the run_list:
+
+ recipe[zenoss::server]
+
+This will allow device nodes to search for the server by this role. Devices are currently added by their external IP addresses, which is effective in hybrid clouds but you may want to modify this for environments in a single platform (ie. EC2-only). Check the `providers/zenbatchload.rb` for this setting. Running `chef-client --log_level debug` on the server node will show the calls for zendmd and zenbatchload commands.
+
+To register a device for monitoring with Zenoss on a client node:
+
+ include_recipe "zenoss::client"
+
+Any Properties that need to be set are exposed as attributes on the node and the Roles used by this cookbook.
+
+Zenoss has the concept of Devices, which belong to a single Device Class and Location. Chef nodes implementing the `zenoss::client` recipe become Zenoss Devices and the Device Class and Location roles may be used for placing in the proper organizers. Zenoss also has Groups and Systems which are essentially ways of tagging and organizing devices (and devices may belong to multiple Groups and Systems). Searches for nodes that belong to other roles will populate the Groups. Searches for nodes applying recipes are used to populate the Systems.
+
+If you are monitoring devices running on Amazon's EC2 with Zenoss, you will need to allow ICMP ping from your Zenoss server.
+
+License and Author
+==================
+Author:: Matt Ray <matt@opscode.com>
+
+Copyright:: 2010, Zenoss, Inc
+Copyright:: 2010, 2011 Opscode, Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
56 chef/cookbooks/zenoss/attributes/default.rb
@@ -0,0 +1,56 @@
+#
+# Author:: Matt Ray <matt@opscode.com>
+# Cookbook Name:: zenoss
+# Attributes:: default
+#
+# Copyright 2010, Zenoss, Inc
+# Copyright 2010, 2011 Opscode, Inc
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+::Chef::Node.send(:include, Opscode::OpenSSL::Password)
+
+set_unless[:zenoss][:server][:admin_password] = secure_password
+
+default[:zenoss][:device][:device_class] = "/Discovered" #overwritten by roles or on nodes
+default[:zenoss][:device][:location] = "" #overwritten by roles or on nodes
+default[:zenoss][:device][:modeler_plugins] = [] #overwritten by roles or on nodes
+default[:zenoss][:device][:properties] = {} #overwritten by roles or on nodes
+default[:zenoss][:device][:templates] = [] #overwritten by roles or on nodes
+default[:zenoss][:server][:version] = "3.1.0-0"
+default[:zenoss][:server][:zenoss_pubkey] = "" #gets set in the server recipe, read by clients
+case node['platform']
+when "ubuntu","debian"
+ default[:zenoss][:server][:zenhome] = "/usr/local/zenoss/zenoss" #RPM is different
+when "redhat","centos","scientific"
+ default[:zenoss][:server][:zenhome] = "/opt/zenoss" #RPM is different
+end
+
+#it might matter that these get ordered eventually
+default[:zenoss][:server][:installed_zenpacks] = {
+ "ZenPacks.zenoss.DeviceSearch" => "1.0.0",
+ "ZenPacks.zenoss.LinuxMonitor" => "1.1.5",
+ "ZenPacks.community.MySQLSSH" => "0.4",
+}
+
+#it might matter that these get ordered eventually as well
+default[:zenoss][:server][:zenpatches] = {
+ "25711" => "http://dev.zenoss.com/trac/ticket/7497",
+ "25814" => "http://dev.zenoss.com/trac/ticket/7772",
+ "25902" => "http://dev.zenoss.com/trac/ticket/7591",
+ "25926" => "http://dev.zenoss.com/trac/ticket/7802",
+ "25963" => "http://dev.zenoss.com/trac/ticket/7114",
+ "26025" => "http://dev.zenoss.com/trac/ticket/7813",
+ "26059" => "http://dev.zenoss.com/trac/ticket/7820",
+}
8 chef/cookbooks/zenoss/data_bags/Zenoss_Readonly_User.json
@@ -0,0 +1,8 @@
+{
+ "id": "readonly",
+ "groups": "sysadmin",
+ "zenoss": {
+ "password": "readonly",
+ "roles": ["ZenUser"]
+ }
+}
11 chef/cookbooks/zenoss/data_bags/Zenoss_User.json
@@ -0,0 +1,11 @@
+{
+ "id": "zenossadmin",
+ "groups": "sysadmin",
+ "zenoss": {
+ "password": "abc",
+ "roles": ["Manager","ZenUser"],
+ "user_groups": ["sysadmin"],
+ "pager": "zenossadmin_pager@example.com",
+ "email": "zenossadmin@example.com"
+ }
+}
71 chef/cookbooks/zenoss/metadata.rb
@@ -0,0 +1,71 @@
+maintainer "Opscode, Inc."
+maintainer_email "cookbooks@opscode.com"
+license "Apache 2.0"
+description "Installs and configures Zenoss and registers nodes as devices"
+version "0.7.1"
+depends "apt"
+depends "openssh"
+depends "openssl"
+depends "yum"
+recipe "zenoss", "Defaults to the client recipe."
+recipe "zenoss::client", "Includes the `openssh` recipe and adds the device to the Zenoss server for monitoring."
+recipe "zenoss::server", "Installs Zenoss, handling and configuring all the dependencies while adding Device Classes, Groups, Systems and Locations. All nodes using the `zenoss::client` recipe are added for monitoring."
+
+#start with just the .deb, perhaps switch to stack installer and/or .rpm
+%w{ debian ubuntu redhat centos scientific }.each do |os|
+ supports os
+end
+
+attribute "zenoss/device/device_class",
+ :display_name => "Device Class for the node.",
+ :description => "Device Class for the node. May be overridden by the Role.",
+ :default => "/Discovered"
+
+attribute "zenoss/device/location",
+ :display_name => "Location for the node.",
+ :description => "Location for the node. May be overridden by the Role."
+
+attribute "zenoss/device/modeler_plugins",
+ :display_name => "List of modeler plugins for the node.",
+ :description => "List of modeler plugins for the node. Node takes precendence over the Role if set.",
+ :type => "array"
+
+attribute "zenoss/device/properties",
+ :display_name => "Hash of configuration properties for the node.",
+ :description => "Hash of configuration properties for the node. Node takes precendence over the Role if set.",
+ :type => "hash"
+
+attribute "zenoss/device/templates",
+ :display_name => "List of templates for the node.",
+ :description => "List of templates for the node. Node takes precendence over the Role if set.",
+ :type => "array"
+
+attribute "zenoss/server/admin_password",
+ :display_name => "Zenoss Admin Password",
+ :description => "Randomly generated password for the admin user",
+ :default => "randomly generated"
+
+attribute "zenoss/server/version",
+ :display_name => "Zenoss Version",
+ :default => "3.0.3-0"
+
+attribute "zenoss/server/zenhome",
+ :display_name => "Environment variable $ZENHOME",
+ :description => "$ZENHOME environment variable, directory where Zenoss is installed.",
+ :default => "/usr/local/zenoss/zenoss"
+
+attribute "zenoss/server/zenoss_pubkey",
+ :display_name => "zenoss user's public key",
+ :description => "zenoss user's public key on the server for use with SSH monitoring.",
+ :type => "string"
+
+attribute "zenoss/server/installed_zenpacks",
+ :display_name => "Hash of ZenPacks to install.",
+ :description => "Hash of ZenPacks to install. Key/value of Name/Version.",
+ :type => "hash"
+
+attribute "zenoss/server/zenpatches",
+ :display_name => "zenpatch patches",
+ :description => "Hash of patches to install with zenpatch. Key/value of patch number/ticket url",
+ :type => "hash"
+
83 chef/cookbooks/zenoss/providers/zenbatchload.rb
@@ -0,0 +1,83 @@
+#loads the hash into a file for zenbatchload and loads it
+action :run do
+ devices = new_resource.devices
+ locations = new_resource.locations
+ groups = new_resource.groups
+ batch = ""
+ Chef::Log.debug "zenbatchload devices:#{devices}"
+ Chef::Log.debug "zenbatchload locations:#{locations}"
+ Chef::Log.debug "zenbatchload groups:#{groups}"
+ #sort the hash and construct the batchload file
+ devices.keys.sort!.each do |dclass|
+ batch += "#{dclass}\n"
+ devices[dclass].sort_by {|n| n.ipaddress}.each do |device|
+ #set for hybrid clouds
+ if device.attribute["cloud"] and device.attribute["cloud"]["public_ips"]
+ batch += "#{device.cloud.public_ips[0]} "
+ else
+ batch += "#{device.ipaddress} "
+ end
+ #set the ID to the ec2 public name or fqdn
+ if device.attribute["ec2"]
+ batch += "setTitle='#{device["ec2"]["public_hostname"]}', "
+ else
+ batch += "setTitle='#{device["fqdn"]}', "
+ end
+ #set the Location & Groups
+ devlocation = ""
+ devgroups = "setGroups=[["
+ device.roles.each do |role|
+ if locations.member?(role)
+ devlocation = "setLocation='#{role}', "
+ elsif groups.member?(role)
+ devgroups += "'#{role}',"
+ end
+ #ignore deviceclass roles
+ end
+ devgroups += "]], "
+ batch += "#{devlocation}#{devgroups}"
+ #set the Systems
+ devsystems = "setSystems=[["
+ systems = device.expand!.recipes
+ systems.collect! {|sys| sys.gsub('::', '/')}
+ systems.each {|sys| devsystems += "'#{sys}',"}
+ devsystems += "]], "
+ batch += "#{devsystems}"
+ #only use device.attribute["zenoss"]["device"].current_normal for node-specific templates, modeler_plugins and properties
+ if node.attribute["zenoss"] and node.attribute["zenoss"]["device"] and node.attribute["zenoss"]["device"].current_normal
+ if node.attribute["zenoss"]["device"].current_normal["modeler_plugins"]
+ plugins = node.attribute["zenoss"]["device"].current_normal["modeler_plugins"]
+ batch += "zCollectorPlugins=#{plugins}, "
+ end
+ if node.attribute["zenoss"]["device"].current_normal["templates"]
+ templates = node.attribute["zenoss"]["device"].current_normal["templates"]
+ batch += "zDeviceTemplates=#{templates}, "
+ end
+ if node.attribute["zenoss"]["device"].current_normal["properties"]
+ node.attribute["zenoss"]["device"].current_normal["properties"].each {|k, v| batch += "#{k}='#{v}', " }
+ end
+ end
+ batch += "\n"
+ end
+ end
+ Chef::Log.debug batch
+ #write the content to a temp file
+ file "/tmp/chefzenbatch.batch" do
+ owner "zenoss"
+ mode "0600"
+ content batch
+ action :create
+ end
+ #run the command as the zenoss user
+ execute "zenbatchload" do
+ user "zenoss"
+ environment ({
+ 'LD_LIBRARY_PATH' => "#{node[:zenoss][:server][:zenhome]}/lib",
+ 'PYTHONPATH' => "#{node[:zenoss][:server][:zenhome]}/lib/python",
+ 'ZENHOME' => node[:zenoss][:server][:zenhome]
+ })
+ command "#{node[:zenoss][:server][:zenhome]}/bin/zenbatchload /tmp/chefzenbatch.batch"
+ action :run
+ end
+end
+
129 chef/cookbooks/zenoss/providers/zendmd.rb
@@ -0,0 +1,129 @@
+#runs a command via zendmd
+action :run do
+ Chef::Log.info "zenoss_zendmd:#{new_resource.name}"
+ Chef::Log.debug "#{new_resource.command}"
+ #write the content to a temp file
+ dmdscript = "#{rand(1000000)}.dmd"
+ file "/tmp/#{dmdscript}" do
+ backup false
+ owner "zenoss"
+ mode "0600"
+ content new_resource.command
+ action :create
+ end
+ #run the command as the zenoss user
+ execute "zendmd" do
+ user "zenoss"
+ cwd "/tmp"
+ environment ({
+ 'LD_LIBRARY_PATH' => "#{node[:zenoss][:server][:zenhome]}/lib",
+ 'PYTHONPATH' => "#{node[:zenoss][:server][:zenhome]}/lib/python",
+ 'ZENHOME' => node[:zenoss][:server][:zenhome]
+ })
+ command "#{node[:zenoss][:server][:zenhome]}/bin/zendmd --commit --script=#{dmdscript}"
+ action :run
+ end
+ #remove the temp file
+ file "/tmp/#{dmdscript}" do
+ action :delete
+ end
+end
+
+#based on Device Class roles
+action :deviceclass do
+ dclass = new_resource.name
+ command = "dmd.Devices.createOrganizer('#{dclass}')\n"
+ dmdpath = "dmd.Devices"+dclass.gsub('/', '.')
+ command += "#{dmdpath}.description='#{new_resource.description}'\n"
+ plugins = new_resource.modeler_plugins
+ if plugins and (plugins.length > 0)
+ pluginscommand = "#{dmdpath}.setZenProperty('zCollectorPlugins', ("
+ plugins.each {|p| pluginscommand += "'#{p}',"}
+ pluginscommand += "))\n"
+ command += pluginscommand
+ end
+ templates = new_resource.templates
+ if templates and (templates.length > 0)
+ templatescommand = "#{dmdpath}.setZenProperty('zDeviceTemplates', ["
+ templates.each {|t| templatescommand += "'#{t}',"}
+ templatescommand += "])\n"
+ command += templatescommand
+ end
+ properties = new_resource.properties
+ if properties
+ properties.each {|p, v| command += "#{dmdpath}.setZenProperty('#{p}','#{v}')\n"}
+ end
+ zenoss_zendmd "Setting Device Class #{dclass}" do
+ command command
+ action :run
+ end
+end
+
+#based on Location roles
+action :location do
+ location = new_resource.location
+ command = "dmd.Locations.createOrganizer('#{location}')\n"
+ dmdpath = "dmd.Locations" + location.gsub('/', '.')
+ command += "#{dmdpath}.name='#{new_resource.name}'\n"
+ command += "#{dmdpath}.description='#{new_resource.description}'\n"
+ command += "#{dmdpath}.address='#{new_resource.address}'\n"
+ zenoss_zendmd "Setting Location #{location}" do
+ command command
+ action :run
+ end
+end
+
+#all non Device Class or Location roles
+action :group do
+ name = new_resource.name
+ command = "dmd.Groups.createOrganizer('#{name}')\n"
+ command += "dmd.Groups.#{name}.description='#{new_resource.description}'\n"
+ zenoss_zendmd "Setting Group #{name}" do
+ command command
+ action :run
+ end
+end
+
+#based on recipes used by nodes
+action :system do
+ name = new_resource.name
+ command = "dmd.Systems.createOrganizer('#{name}')\n"
+ zenoss_zendmd "Setting System #{name}" do
+ command command
+ action :run
+ end
+end
+
+action :users do
+ command = ""
+ new_resource.users.each do |user|
+ userid = user.id
+ if user.has_key?("zenoss")
+ password = user['zenoss']['password']
+ pager = user['zenoss']['pager']
+ email = user['zenoss']['email']
+ roles = user['zenoss']['roles']
+ user_groups = user['zenoss']['user_groups']
+ end
+ command += "dmd.ZenUsers.manage_addUser('#{userid}'"
+ command += ", '#{password}'" if password
+ command += ", email='#{email}'" if email
+ command += ", pager='#{pager}'" if pager
+ if roles and (roles.length > 0)
+ command += ", roles=("
+ roles.each {|r| command += "'#{r}',"}
+ command += ")"
+ end
+ command += ")\n"
+ if user_groups and (user_groups.length > 0)
+ user_groups.each {|g| command += "dmd.ZenUsers.manage_addGroup('#{g}')\n"}
+ command += "dmd.ZenUsers.manage_addUsersToGroups('#{userid}', ("
+ user_groups.each {|g| command += "'#{g}',"}
+ command += "))\n"
+ end
+ end
+ zenoss_zendmd "Creating users and user groups" do
+ command command
+ action :run
+ end
+end
75 chef/cookbooks/zenoss/providers/zenpack.rb
@@ -0,0 +1,75 @@
+#
+# Author:: Matt Ray <matt@opscode.com>
+# Cookbook Name:: zenoss
+# Provider:: zenpack
+#
+# Copyright 2010, 2011 Opscode, Inc <legal@opscode.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/mixin/shell_out'
+require 'chef/mixin/language'
+include Chef::Mixin::ShellOut
+
+action :install do
+ unless @zenpack.exists
+ zpfile = "#{new_resource.package}-#{new_resource.version}-#{new_resource.py_version}.egg"
+ Chef::Log.info "Installing the #{zpfile} ZenPack."
+ #download the ZenPack
+ remote_file "/tmp/#{zpfile}" do
+ source "http://dev.zenoss.com/zenpacks/#{zpfile}"
+ mode "0644"
+ action :create
+ end
+ #install the ZenPack
+ execute "zenpack --install" do
+ user "zenoss"
+ cwd "/tmp"
+ environment ({
+ 'LD_LIBRARY_PATH' => "#{node[:zenoss][:server][:zenhome]}/lib",
+ 'PYTHONPATH' => "#{node[:zenoss][:server][:zenhome]}/lib/python",
+ 'ZENHOME' => node[:zenoss][:server][:zenhome]
+ })
+ command "#{node[:zenoss][:server][:zenhome]}/bin/zenpack --install=#{zpfile}"
+ action :run
+ end
+ new_resource.updated_by_last_action(true)
+ end
+end
+
+action :remove do
+ if @zenpack.exists
+ Chef::Log.info "Removing the #{new_resource.package} ZenPack."
+ execute "zenpack --remove" do
+ user "zenoss"
+ environment ({
+ 'LD_LIBRARY_PATH' => "#{node[:zenoss][:server][:zenhome]}/lib",
+ 'PYTHONPATH' => "#{node[:zenoss][:server][:zenhome]}/lib/python",
+ 'ZENHOME' => node[:zenoss][:server][:zenhome]
+ })
+ command "#{node[:zenoss][:server][:zenhome]}/bin/zenpack --remove=#{new_resource.package}"
+ action :run
+ end
+ new_resource.updated_by_last_action(true)
+ end
+end
+
+#check if the zenpack is already installed
+def load_current_resource
+ @zenpack = Chef::Resource::ZenossZenpack.new(new_resource.package)
+ Chef::Log.debug("Checking for ZenPack #{new_resource.name}")
+ zp = shell_out("sudo -u zenoss -i #{node[:zenoss][:server][:zenhome]}/bin/zenpack --list")
+ exists = zp.stdout.include?(new_resource.package)
+ @zenpack.exists(exists)
+end
14 chef/cookbooks/zenoss/providers/zenpatch.rb
@@ -0,0 +1,14 @@
+action :install do
+ patch = new_resource.svnpatch
+ #check if the patch is already applied
+ unless ::File.exists?("#{node[:zenoss][:server][:zenhome]}/Products/r#{patch}.patch")
+ Chef::Log.info "Applying patch #{patch} from ticket #{new_resource.ticket}."
+ #apply the patch
+ execute "#{node[:zenoss][:server][:zenhome]}/bin/zenpatch #{patch}" do
+ user "zenoss"
+ environment ({'ZENHOME' => node[:zenoss][:server][:zenhome]})
+ action :run
+ end
+ end
+end
+
58 chef/cookbooks/zenoss/recipes/client.rb
@@ -0,0 +1,58 @@
+#
+# Author:: Matt Ray <matt@opscode.com>
+# Cookbook Name:: zenoss
+# Recipe:: client
+#
+# Copyright 2010, Zenoss, Inc
+# Copyright 2010, Opscode, Inc
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "openssh"
+
+#create a 'zenoss' user for monitoring
+user "zenoss" do
+ comment "Zenoss monitoring account"
+ home "/home/zenoss"
+ supports :manage_home => true
+ shell "/bin/bash"
+ action :create
+end
+
+#create a home directory for them
+directory "/home/zenoss/.ssh" do
+ owner "zenoss"
+ mode "0700"
+ action :create
+end
+
+#get the zenoss user public key via search
+server = search(:node, 'recipes:zenoss\:\:server') || []
+if server.length > 0
+ zenoss = server[0]["zenoss"]
+ if zenoss["server"] and zenoss["server"]["zenoss_pubkey"]
+ pubkey = zenoss["server"]["zenoss_pubkey"]
+ file "/home/zenoss/.ssh/authorized_keys" do
+ backup false
+ owner "zenoss"
+ mode "0600"
+ content pubkey
+ action :create
+ end
+ else
+ Chef::Log.info("No Zenoss server found, device is unmonitored.")
+ end
+else
+ Chef::Log.info("No Zenoss server found, device is unmonitored.")
+end
21 chef/cookbooks/zenoss/recipes/default.rb
@@ -0,0 +1,21 @@
+#
+# Author:: Matt Ray <matt@opscode.com>
+# Cookbook Name:: zenoss
+# Recipe:: default
+#
+# Copyright 2010, Opscode, Inc
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "zenoss::client"
245 chef/cookbooks/zenoss/recipes/server.rb
@@ -0,0 +1,245 @@
+#
+# Author:: Matt Ray <matt@opscode.com>
+# Cookbook Name:: zenoss
+# Recipe:: server
+#
+# Copyright 2010, Zenoss, Inc
+# Copyright 2010, 2011 Opscode, Inc
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "zenoss::client"
+
+case node[:platform]
+when "centos","redhat","scientific"
+ include_recipe "yum"
+
+ yum_key "RPM-GPG-KEY-zenoss" do
+ url "http://dev.zenoss.com/yum/RPM-GPG-KEY-zenoss"
+ action :add
+ end
+
+ yum_repository "zenoss" do
+ description "Zenoss Stable repo"
+ key "RPM-GPG-KEY-zenoss"
+ url "http://dev.zenoss.com/yum/stable/"
+ failovermethod "priority"
+ action :add
+ end
+
+ packages = %w{mysql-server net-snmp net-snmp-utils gmp libgomp libgcj liberation-fonts}
+ packages.each do |pkg|
+ yum_package pkg do
+ action :install
+ end
+ end
+
+ #mysql setup from the installation guide, this should be replaced with proper use of mysql::server
+ service "mysqld" do
+ action [:enable, :start]
+ end
+
+ execute "/usr/bin/mysqladmin -u root password ''"
+ execute "/usr/bin/mysqladmin -u root -h localhost password ''"
+
+ #from the install guide, would be worthwhile to configure properly
+ service "iptables" do
+ action [:stop, :disable]
+ end
+
+ yum_package "zenoss" do
+ action :install
+ end
+
+ #end redhat/centos/scientific block
+when "debian","ubuntu"
+ include_recipe "apt"
+
+ apt_repository "zenoss" do
+ uri "http://dev.zenoss.org/deb"
+ distribution "main"
+ components ["stable"]
+ action :add
+ end
+
+ packages = %w{ttf-liberation ttf-linux-libertine}
+ packages.each do |pkg|
+ apt_package pkg do
+ action :install
+ end
+ end
+
+ #Zenoss hasn't signed their repository http://dev.zenoss.org/trac/ticket/7421
+ apt_package "zenoss-stack" do
+ version node["zenoss"]["server"]["version"]
+ options "--allow-unauthenticated"
+ action :install
+ end
+ #end of debian/ubuntu
+end
+
+
+#apply post 3.1.0 patches from http://dev.zenoss.com/trac/report/6 marked 'closed'
+node["zenoss"]["server"]["zenpatches"].each do |patch, url|
+ zenoss_zenpatch patch do
+ ticket url
+ action :install
+ end
+end
+
+#the Zenoss installer puts the service in place, just start it
+service "zenoss" do
+ case node["platform"]
+ when "debian", "ubuntu"
+ service_name "zenoss-stack"
+ when "redhat", "centos", "scientific"
+ service_name "zenoss"
+ end
+ action [:enable, :start ]
+end
+
+#skip the new install Wizard.
+zenoss_zendmd "skip setup wizard" do
+ command "dmd._rq = True"
+ action :run
+end
+
+#use zendmd to set the admin password
+zenoss_zendmd "set admin pass" do
+ command "app.acl_users.userManager.updateUserPassword('admin', '#{node[:zenoss][:server][:admin_password]}')"
+ action :run
+end
+
+#search the 'users' databag and pull out sysadmins for users and groups
+begin
+ admins = search(:users, 'groups:sysadmin') || []
+rescue
+ admins = []
+end
+zenoss_zendmd "add users" do
+ users admins
+ action :users
+end
+
+#put public key in an attribute
+ruby_block "zenoss public key" do
+ block do
+ pubkey = IO.read("/home/zenoss/.ssh/id_dsa.pub")
+ node.set["zenoss"]["server"]["zenoss_pubkey"] = pubkey
+ node.save
+ #write out the authorized_keys for the zenoss user
+ ak = File.new("/home/zenoss/.ssh/authorized_keys", "w+")
+ ak.puts pubkey
+ ak.chown(File.stat("/home/zenoss/.ssh/id_dsa.pub").uid,File.stat("/home/zenoss/.ssh/id_dsa.pub").gid)
+ end
+ action :nothing
+end
+
+#generate SSH key for the zenoss user
+execute "ssh-keygen -q -t dsa -f /home/zenoss/.ssh/id_dsa -N \"\" " do
+ user "zenoss"
+ action :run
+ not_if {File.exists?("/home/zenoss/.ssh/id_dsa.pub")}
+ notifies :create, resources(:ruby_block => "zenoss public key"), :immediate
+end
+
+#this list should get appended by other recipes
+node["zenoss"]["server"]["installed_zenpacks"].each do |package, zpversion|
+ zenoss_zenpack "#{package}" do
+ version zpversion
+ action :install
+ notifies :restart, resources(:service => "zenoss"), :immediate
+ end
+end
+
+#find the roles and push their settings in via zendmd
+deviceclasslist = []
+locationlist = []
+grouplist = []
+search(:role, "*:*").each do |role|
+ if role.override_attributes["zenoss"] and role.override_attributes["zenoss"]["device"]
+ if role.override_attributes["zenoss"]["device"]["device_class"]
+ #add the role as a Device Class
+ deviceclasslist.push(role.name)
+ zenoss_zendmd role.override_attributes["zenoss"]["device"]["device_class"] do
+ description role.description
+ modeler_plugins role.default_attributes["zenoss"]["device"]["modeler_plugins"]
+ templates role.default_attributes["zenoss"]["device"]["templates"]
+ properties role.default_attributes["zenoss"]["device"]["properties"]
+ action :deviceclass
+ end
+ elsif role.override_attributes["zenoss"]["device"]["location"]
+ #add the role as a Location
+ locationlist.push(role.name)
+ zenoss_zendmd role.name do
+ location role.override_attributes["zenoss"]["device"]["location"]
+ description role.description
+ address role.override_attributes["zenoss"]["device"]["address"]
+ action :location
+ end
+ end
+ else
+ #create Groups for the rest of the roles
+ grouplist.push(role.name)
+ zenoss_zendmd role.name do
+ description role.description
+ action :group
+ end
+ end
+end
+
+#move the localhost to SSH monitoring since we're not using SNMP
+zenoss_zendmd "move Zenoss server" do
+ batch = "dmd.Devices.moveDevices('/Server/SSH/Linux/MySQL', '#{node[:fqdn]}')\n"
+ batch += "dev = dmd.Devices.findDevice('#{node[:fqdn]}')\n"
+ batch += "dev.setManageIp('#{node[:ipaddress]}')"
+ command batch
+ action :run
+end
+
+#all nodes (for now, until pick a role or other flag to standardize on)
+nodes = search(:node, 'zenoss:device*') || []
+#find the recipes and create Systems for them
+systems = []
+nodes.each {|node| systems.push(node.expand!.recipes)}
+systems.flatten!
+systems.uniq!
+#make suborganizers with recipes
+systems.collect! {|sys| sys.gsub('::', '/')}
+systems.each do |system|
+ zenoss_zendmd system do
+ action :system
+ end
+end
+#using the nodes list, write out a zenbatchload
+#find all the device classes and the devices each one has.
+devices = {}
+nodes.each do |node|
+ if node.attribute["zenoss"] and node.attribute["zenoss"]["device"]
+ dclass = node.attribute["zenoss"]["device"]["device_class"]
+ if devices.has_key?(dclass)
+ devices[dclass].push(node)
+ else
+ devices[dclass] = [node]
+ end
+ end
+end
+zenoss_zenbatchload "zenbatchloading devices" do
+ devices devices
+ locations locationlist
+ groups grouplist
+ action :run
+end
+
+#keep the previous zenbatchload run, diff it against the new list and only load the results of the diff.
5 chef/cookbooks/zenoss/resources/zenbatchload.rb
@@ -0,0 +1,5 @@
+actions :run
+
+attribute :devices, :kind_of => Hash, :default => {}
+attribute :locations, :kind_of => Array, :default => []
+attribute :groups, :kind_of => Array, :default => []
11 chef/cookbooks/zenoss/resources/zendmd.rb
@@ -0,0 +1,11 @@
+actions :run, :deviceclass, :group, :system, :location, :users
+
+attribute :name, :kind_of => String, :name_attribute => true
+attribute :command, :kind_of => String #command to run via zendmd
+attribute :description, :kind_of => String
+attribute :modeler_plugins, :kind_of => Array, :default => []
+attribute :templates, :kind_of => Array, :default => []
+attribute :properties, :kind_of => Hash, :default => {}
+attribute :location, :kind_of => String
+attribute :address, :kind_of => String
+attribute :users, :kind_of => Array, :default => []
7 chef/cookbooks/zenoss/resources/zenpack.rb
@@ -0,0 +1,7 @@
+actions :install, :remove
+
+#package name of the zenpack
+attribute :package, :kind_of => String, :name_attribute => true
+attribute :version, :kind_of => String
+attribute :py_version, :kind_of =>String, :default => "py2.6"
+attribute :exists, :default => false
4 chef/cookbooks/zenoss/resources/zenpatch.rb
@@ -0,0 +1,4 @@
+actions :install
+
+attribute :svnpatch, :kind_of => String, :name_attribute => true
+attribute :ticket, :kind_of => String
38 chef/cookbooks/zenoss/roles/Class_Server-SSH-Linux-MySQL.rb
@@ -0,0 +1,38 @@
+name "ServerSSHLinuxMySQL"
+description "Linux & MySQL monitoring via SSH"
+default_attributes(
+ "zenoss" => {
+ "device" => {
+ "properties" => {
+ "zCommandUsername" => "zenoss",
+ "zKeyPath" => "/home/zenoss/.ssh/id_dsa",
+ "zMySqlPassword" => "zenoss",
+ "zMySqlUsername" => "zenoss"
+ }
+ # "modeler_plugins" => [
+ # "zenoss.cmd.uname",
+ # "zenoss.cmd.uname_a",
+ # "zenoss.cmd.df",
+ # "zenoss.cmd.linux.cpuinfo",
+ # "zenoss.cmd.linux.memory",
+ # "zenoss.cmd.linux.ifconfig",
+ # "zenoss.cmd.linux.netstat_an",
+ # "zenoss.cmd.linux.netstat_rn",
+ # ],
+ # "templates" => ['Device']
+ }
+ }
+ )
+
+override_attributes(
+ "zenoss" => {
+ "device" => {
+ "device_class" => "/Server/SSH/Linux/MySQL"
+ }
+ }
+ )
+
+#this could change to zenoss::client_mysqlssh or something eventually
+run_list(
+ "recipe[zenoss::client]"
+ )
24 chef/cookbooks/zenoss/roles/Class_Server-SSH-Linux.rb
@@ -0,0 +1,24 @@
+name "ServerSSHLinux"
+description "Linux monitoring via SSH"
+#use the default modeler_plugins and templates for the device class
+default_attributes(
+ "zenoss" => {
+ "device" => {
+ "properties" => {
+ "zCommandUsername" => "zenoss",
+ "zKeyPath" => "/home/zenoss/.ssh/id_dsa"
+ }
+ }
+ }
+ )
+
+override_attributes(
+ "zenoss" => {
+ "device" => {
+ "device_class" => "/Server/SSH/Linux",
+ }
+ }
+ )
+run_list(
+ "recipe[zenoss::client]"
+ )
10 chef/cookbooks/zenoss/roles/Location_Austin.rb
@@ -0,0 +1,10 @@
+name "Austin"
+description "Opscode Austin"
+override_attributes(
+ "zenoss" => {
+ "device" => {
+ "address" => "1005 W 38th Street\\nAustin, TX 78705",
+ "location" => "/Austin"
+ }
+ }
+ )
10 chef/cookbooks/zenoss/roles/Location_Seattle.rb
@@ -0,0 +1,10 @@
+name "Seattle"
+description "Opscode HQ"
+override_attributes(
+ "zenoss" => {
+ "device" => {
+ "address" => "1008 Western Ave\\nSeattle WA 98104",
+ "location" => "/Seattle"
+ }
+ }
+ )
28 chef/cookbooks/zenoss/roles/ZenossServer.rb
@@ -0,0 +1,28 @@
+name "ZenossServer"
+description "Role to use as basis for configuring Zenoss Server"
+#a number of server attributes are available for customization
+#you may want to set the [:zenoss][:server][:admin_password]
+default_attributes(
+ "zenoss" => {
+ "device" => {
+ "properties" => {
+ "zCommandUsername" => "zenoss",
+ "zKeyPath" => "/home/zenoss/.ssh/id_dsa",
+ "zMySqlPassword" => "zenoss",
+ "zMySqlUsername" => "zenoss"
+ }
+ }
+ }
+ )
+
+override_attributes(
+ "zenoss" => {
+ "device" => {
+ "device_class" => "/Server/SSH/Linux/MySQL"
+ }
+ }
+ )
+
+run_list(
+ "recipe[zenoss::server]"
+ )
26 chef/data_bags/crowbar/bc-template-zenoss.json
@@ -0,0 +1,26 @@
+{
+ "id": "bc-template-zenoss",
+ "description": "Installation for Zenoss",
+ "attributes": {
+ "zenoss": {
+ "foo": "bar"
+ }
+ },
+ "deployment": {
+ "zenoss": {
+ "crowbar-revision": 0,
+ "elements": {},
+ "element_order": [
+ [ "zenoss-server" ]
+ ],
+ "config": {
+ "environment": "zenoss-base-config",
+ "mode": "full",
+ "transitions": false,
+ "transition_list": [
+ ]
+ }
+ }
+ }
+}
+
71 chef/data_bags/crowbar/bc-template-zenoss.schema
@@ -0,0 +1,71 @@
+{
+ "type": "map",
+ "required": true,
+ "mapping": {
+ "id": { "type": "str", "required": true, "pattern": "/^bc-zenoss-|^bc-template-zenoss$/" },
+ "description": { "type": "str", "required": true },
+ "attributes": {
+ "type": "map",
+ "required": true,
+ "mapping": {
+ "zenoss": {
+ "type": "map",
+ "required": true,
+ "mapping": {
+ "foo": { "type": "str", "required": true }
+ }
+ }
+ }
+ },
+ "deployment": {
+ "type": "map",
+ "required": true,
+ "mapping": {
+ "zenoss": {
+ "type": "map",
+ "required": true,
+ "mapping": {
+ "crowbar-revision": { "type": "int", "required": true },
+ "crowbar-committing": { "type": "bool" },
+ "crowbar-queued": { "type": "bool" },
+ "crowbar-status": { "type": "str" },
+ "crowbar-failed": { "type": "str" },
+ "elements": {
+ "type": "map",
+ "required": true,
+ "mapping": {
+ = : {
+ "type": "seq",
+ "required": true,
+ "sequence": [ { "type": "str" } ]
+ }
+ }
+ },
+ "element_order": {
+ "type": "seq",
+ "required": true,
+ "sequence": [ {
+ "type": "seq",
+ "sequence": [ { "type": "str" } ]
+ } ]
+ },
+ "config": {
+ "type": "map",
+ "required": true,
+ "mapping": {
+ "environment": { "type": "str", "required": true },
+ "mode": { "type": "str", "required": true },
+ "transitions": { "type": "bool", "required": true },
+ "transition_list": {
+ "type": "seq",
+ "required": true,
+ "sequence": [ { "type": "str" } ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
9 chef/roles/zenoss-server.rb
@@ -0,0 +1,9 @@
+name "zenoss-server"
+description "Zenoss Server Role"
+run_list(
+ "recipe[zenoss::api]",
+ "recipe[zenoss::monitor]"
+)
+default_attributes()
+override_attributes()
+
153 crowbar.yml
@@ -0,0 +1,153 @@
+# Copyright 2011, Keith Hudgins
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Author: RobHirschfeld
+#
+# This file directs the installation of the barclamp by the Crowbar Framework
+# The major compoents are
+# barclamp: detalis about the barclamp
+# crowbar: installation instructions
+# nav: (optional) injects items into the Crowbar UI menu
+# debs/rpms/gems: components needs by the barclamp
+
+barclamp:
+ name: zenoss
+ display: Zenoss
+ description: A way to maximize awesomeness for Zenoss
+ proposal_schema_version: 1
+ version: 0
+ # Requires allows you to declare that this barclamp relies on
+ # another barclamp to provide some of its functionality.
+ # All barclamps implicitly rely on the crowbar barclamp.
+ requires:
+ - another-barclamp # rely on a single other barclamp
+ - @barclamp-group # rely on another group of barclamps.
+ # Member allows you to declare that this barclamp is a member
+ # of a group of related barclamp. A barclamp can be a member of
+ # muliple groups, and a group name can be used instead of a barclamp
+ # in a requires: clause by prefixing it with an @ sign.
+ member:
+ - barclamp-group
+ - another-barclamp-group
+ # Os_support allows you to declare that this barclamp only supports
+ # specific operating systems. If you don't have an os_support
+ # section, Crowbar will assume the barclamp works on all the operating
+ # systems it supports.
+ os_support:
+ - redhat-5.6
+ - ubuntu-10.10
+
+crowbar:
+ layout: 1
+ order: 1000
+ proposal_schema_version: 2
+
+nav:
+ barclamps:
+ zenoss: barclamp_modules_path(:id=>'zenoss')
+
+# debs, gems, rpms and extra_files allow you declare the OS packages,
+# gems, and raw files that this barclamp needs.
+
+# debs allows you to declare extra repositories to pull packages from
+# and delare that packages that you need for systems that use Debian-style
+# packaging.
+debs:
+ # repos allows you to add an apt repository that the build system
+ # should pull packages from. Each entry is formatted in the standard
+ # sources.list format.
+ repos:
+ # pull from internet:
+ # - deb http://www.rabbitmq.com/debian/ testing main
+ # ppas allows you to declare Ubuntu personal package archives that
+ # the build should try to pull from.
+ ppas:
+ - ppa_username/ppa_name
+ # pkgs is a list of extra packages that the build system will try to pull
+ # and cache on the crowbar iso image. You only have to list top-level
+ # packages here -- if apt-get install gets all the dependencies, you do not
+ # need to list them here.
+ pkgs:
+ # put your packages here
+ # - mod_fcgid
+ # raw_pkgs is a list of URLs to .deb packages that the build system will try
+ # to download and add to the iso. It does not do dependency checking, and
+ # it uses curl to handle the actual download process.
+ raw_pkgs:
+ - http://your_site/your_special_deb.deb
+ # You can have multiple OS specific sections as well. You can declare
+ # dependencies for repos, ppas, pkgs, and raw_pkgs here, and they will
+ # be picked up when building Crowbar on that OS.
+ os-token:
+ repos:
+ ppas:
+ pkgs:
+ raw_pkgs:
+
+# rpms does the same thing that debs does, except for RPM-based systems.
+rpms:
+ repos:
+ # rpm repos allow you to declare that you want to use a repo that
+ # is set up using an RPM. EPEL is a good example of such a repo.
+ - rpm http://repo_addr/repo.rpm
+ # bare allows you to declare that you want to use a repository that
+ # does not allow easy installation via rpm.
+ # It has a slightly more complex declaration:
+ # bare repo_name numeric_repo_priority repo_url
+ - bare epel5-nagios3 10 http://repos.fedorapeople.org/repos/peter/nagios3/epel-5/x86_64/
+ pkgs:
+ # put your rpms here
+ # - httpd
+ raw_pkgs:
+ - http://your_site/your_special_rpm.rpm
+
+# gems allows you to declare the gems you need.
+# Unlike the other package types, you can ask for a specific version of a gem
+# The build system will solve dependencies as best it can, but if a gem you have
+# requires extra packages to install you will need to add them to the appropriate
+# build_pkgs section of rpms and debs above.
+gems:
+ pkgs:
+ # put your gems here.
+ - i18n
+ - rails-2.3.12 # Will try and pull rails-2.3.12 exactly.
+
+# extra_files downloads and saves a file to be slipstreamed on to the
+# crowbar .iso in the extra/files directory (or a subdirectory thereof).
+# The build system will try to extract the .rpm files from
+# anything that looks like an Oracle java rpm.bin and treat the extracted
+# .rpm files as if they were provided by raw_pkgs.
+extra_files:
+ # will place file into extra/files
+ - http://some/file
+ # will place file into extra/files/foo
+ - http://some/file foo
+ # will place image.tar.gz in extra/files/ami.
+ # For backwards compatibility, it will also be available at /ami
+ - http://some/amazon/image.tar.gz ami
+ # Will download a java package and try to install its RPMS
+ # if bulding Crowbar staged on Redhat.
+ - http://java.oracle.com/java-version-x64-rpm.bin java
+
+
+locale_additions:
+ en:
+ nav:
+ zenoss: Zenoss
+ barclamp:
+ zenoss_edit_attributes:
+ attributes: Attributes
+ foo: Comic Choice
+ zenoss_edit_deployment:
+ deployment: Deployment
21 crowbar_framework/app/controllers/zenoss_controller.rb
@@ -0,0 +1,21 @@
+# Copyright 2011, Keith Hudgins
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+class ZenossController < BarclampController
+ def initialize
+ @service_object = ZenossService.new logger
+ end
+end
+
60 crowbar_framework/app/models/zenoss_service.rb
@@ -0,0 +1,60 @@
+# Copyright 2011, Keith Hudgins
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+class ZenossService < ServiceObject
+
+ def initialize(thelogger)
+ @bc_name = "zenoss"
+ @logger = thelogger
+ end
+
+ #if barclamp allows multiple proposals OVERRIDE
+ # def self.allow_multiple_proposals?
+
+ def create_proposal
+ @logger.debug("Zenoss create_proposal: entering")
+ base = super
+
+ nodes = NodeObject.all
+ nodes.delete_if { |n| n.nil? or n.admin? }
+ if nodes.size >= 1
+ base["deployment"]["zenoss"]["elements"] = {
+ "zenoss-server" => [ nodes.first[:fqdn] ]
+ }
+ end
+
+ @logger.debug("Zenoss create_proposal: exiting")
+ base
+ end
+
+ def apply_role_pre_chef_call(old_role, role, all_nodes)
+ @logger.debug("Zenoss apply_role_pre_chef_call: entering #{all_nodes.inspect}")
+ return if all_nodes.empty?
+
+ # Make sure the bind hosts are in the admin network
+ all_nodes.each do |n|
+ node = NodeObject.find_node_by_name n
+
+ admin_address = node.get_network_by_type("admin")["address"]
+ node.crowbar[:zenoss] = {} if node.crowbar[:zenoss].nil?
+ node.crowbar[:zenoss][:api_bind_host] = admin_address
+
+ node.save
+ end
+ @logger.debug("Zenoss apply_role_pre_chef_call: leaving")
+ end
+
+end
+
10 crowbar_framework/app/views/barclamp/zenoss/_edit_attributes.html.haml
@@ -0,0 +1,10 @@
+
+%input#proposal_attributes{:type => "hidden", :name => "proposal_attributes", :value => @proposal.raw_data['attributes'][@proposal.barclamp].to_json}
+%p
+ %label{:for => "proposal_attributes"}= t('.attributes')
+ = link_to t('raw'), proposal_barclamp_path(:id => @proposal.name, :controller => @proposal.barclamp, :dep_raw => @dep_raw, :attr_raw => true), :style => "float: right;"
+ %div.container
+ %p
+ %label{ :for => :backing_type }= t('.foo')
+ = select_tag :backing_type, options_for_select([['XKCD','xkcd'], ['Dilbert', 'dilbert']], @proposal.raw_data['attributes'][@proposal.barclamp]["foo"]), :onchange => "update_value('foo', 'foo', 'string')"
+
10 crowbar_framework/app/views/barclamp/zenoss/_edit_deployment.html.haml
@@ -0,0 +1,10 @@
+
+%p
+ = render :partial => "barclamp/node_selector"
+
+:javascript
+ $(document).ready(function(){
+ var constraints = { "zenoss-server": { "unique": false, "count": 1 } };
+ node_selector($('#drag_drop'), constraints);
+ });
+
Please sign in to comment.
Something went wrong with that request. Please try again.