mcollective

As adding support for mCollective is currently a work in progress http://projects.theforeman.org/projects/1/wiki/MCollective_integration and primarily focused around the smart-proxy, this how to can change at any time.

Mcollective 1.2.1, Foreman and Puppet PE

As puppet PE comes with mcollective it's fairly easy to make it work with the foreman smart proxy. Sam Kottler wrote a patch (https://github.com/theforeman/smart-proxy/pull/58/files) to integrate mcollective and foreman-proxy.

I assume you have followed the guide passenger on Puppet PE and use foreman as an ENC and reporting engine . If so you need to replace, create and edit the following files:

/usr/share/foreman-proxy/config/settings.yml 
/usr/share/foreman-proxy/lib/proxy/puppet.rb
/usr/share/foreman-proxy/lib/proxy/puppet/runner.rb
/usr/share/foreman-proxy/lib/puppet_api.rb

In /usr/share/foreman-proxy/config/settings add the following line after the puppet management entry:

# enable MCollective integration
:mcollective: true

Now your puppet pe / foreman installation is ready for a puppet run via foreman host page.

Then replace puppet.rb and puppet_api.rb

# rm -f /usr/share/foreman-proxy/lib/proxy/puppet.rb
# cd /usr/share/foreman-proxy/lib/proxy/
# wget https://raw.github.com/skottler/smart-proxy/2a7b5fbfcdb3a0e9a4b22d46a09d4bfa2aa0f765/lib/proxy/puppet.rb
# rm -f /usr/share/foreman-proxy/lib/puppet_api.rb
# cd /usr/share/foreman-proxy/lib/
# wget https://raw.github.com/skottler/smart-proxy/2a7b5fbfcdb3a0e9a4b22d46a09d4bfa2aa0f765/lib/puppet_api.rb

The 4th script runner.rb needs a little bit more attention. Puppet pe 2.7.2 does use mcollective 1.2 which means the agent puppet cannot be used. So we need to swap it with puppetd. Also to be able to query the hosts, all the mcollective commands need to be running in the peadmin user environment.

# cd /usr/share/foreman-proxy/lib/proxy/puppet/
# wget https://raw.github.com/skottler/smart-proxy/2a7b5fbfcdb3a0e9a4b22d46a09d4bfa2aa0f765/lib/proxy/puppet/runner.rb

Modify the runner.rb file on line 8 and line 16:

  1 module Proxy::Puppet
  2   class Mcollective
  3     extend Proxy::Util
  4
  5     def self.run(nodes)
  6       mco_search_path = ["/usr/bin", "/opt/puppet/bin"]
  7       sudo = which("sudo", "usr/bin")
  8       sudo = sudo << " -u peadmin" 
  9       mco = which("mco", mco_search_path)
 10
 11       unless sudo and mco
 12         logger.warn "sudo or the mco binary is missing." 
 13         return false
 14       end
 15
 16       mco << " puppetd runonce -I #{nodes}" 

Mcollective sudo

Create an mcollective sudoers file to allow the foreman proxy to execute mco commands.

Defaults:foreman-proxy !requiretty
foreman-proxy ALL=(peadmin) NOPASSWD: /opt/puppet/bin/mco *

Mcollective 1.2.1 / Foreman / Puppet Opensource

Installing mcollective on a opensource puppet host is slightly different than the above procedure as puppet enterprise comes with pre configured puppet modules which do most of the steps automatically which I show here manually. You could also download the puppet modules from puppet forge for mcollective and activemq and customize them for your needs. First we need to install mcollective and mcollective-client. The mcollective-client is only needed by the puppet master host. To be consistent with the above installation I choose the same version of mcollective as in puppet pe.

Install activemq / mcollecitve

To be able to install mcollective and activemq you need to install the puppetlabs repo.

$ sudo rpm -ivh sudo rpm -ivh http://yum.puppetlabs.com/el/6/products/i386/puppetlabs-release-6-7.noarch.rpm 

Install activemq and mcollective on the puppet server

$ sudo yum install mcollective-1.2.1-1.el6.noarch mcollective-common-1.2.1-1.el6.noarch mcollective-client-1.2.1-1.el6.noarch activemq-5.5.0-1.el6.noarch

Configure activemq first and edit the following lines in /etc/activemq/activemq.xml

109               <authenticationUser username="mcollective" password="marionette" groups="mcollective,everyone"/>
119                   <authorizationEntry topic="mcollective.>" write="mcollective" read="mcollective" admin="mcollective" />
120                   <authorizationEntry queue=">" write="mcollective" read="mcollective" admin="mcollective" />

Enable activemq to start on boot and start the service

# chkconfig activemq on
# service activemq start

Configure the server.cfg in /etc/mcollective/server.cfg

topicprefix = /topic/
main_collective = mcollective
collectives = mcollective
libdir = /usr/libexec/mcollective
logfile = /var/log/mcollective.log
loglevel = info
daemonize = 1

# Plugins
securityprovider = psk
plugin.psk = unset

connector = stomp
plugin.stomp.host = YOUR ACTIVEMQ HOST can be local host
plugin.stomp.port = 61613
plugin.stomp.user = mcollective
plugin.stomp.password = marionette

# Facts
factsource = yaml
plugin.yaml = /etc/mcollective/facts.yaml

# Puppet Classes
classesfile = /var/lib/puppet/classes.txt

# Puppet Agent plugin configuration
plugin.puppetd.puppetd   = /usr/sbin/puppetd
plugin.puppetd.lockfile  = /var/lib/puppet/state/puppetdlock
plugin.puppetd.statefile = /var/lib/puppet/state/state.yaml
plugin.puppetd.splaytime = 120
# Note the following two are "puppet" and not "puppetd" 
plugin.puppet.pidfile    = /var/run/puppet/agent.pid
plugin.puppet.summary    = /var/lib/puppet/state/last_run_summary.yaml

# Periodcally broadcast metdata for registration purposes.
# This registration plugin will broadcast current Facter fact values.
registration = Meta
# registerinterval is intentionally "long" to prevent systems from being overly
# chatty on the message bus by default.  If you want a higher frequency, this
# may be set to 300 (5 minutes)
registerinterval = 14400

# authorization
rpcauthorization = 1
rpcauthprovider = action_policy
plugin.actionpolicy.allow_unconfigured = 1

Configure the client.cfg in /etc/mcollective/client.cfg ( only for puppet server which runs the mcollective-client)

topicprefix = /topic/
main_collective = mcollective
collectives = mcollective
libdir = /usr/libexec/mcollective
logfile = /dev/null
loglevel = info

# Plugins
securityprovider = psk
plugin.psk = unset

connector = stomp
plugin.stomp.host = localhost
plugin.stomp.port = 61613
plugin.stomp.user = mcollective
plugin.stomp.password = marionette

# Facts
factsource = yaml
plugin.yaml = /etc/mcollective/facts.yaml

Install the mcollective plugins

Per default mcollective comes only with discovery and rpcutil as an agent. As we want to run puppet we need to get the puppetd agent and application. Please be aware that the puppetd agent is an old plugin. Its recommended to run puppet.rb from (https://github.com/puppetlabs/mcollective-puppet-agent.git) which does need mcollective >= 2.2.

To be consistent with the puppet pe env we are going to install the following additional agents / applications which you can get from here
git://github.com/puppetlabs/mcollective-plugins.git:

agents (/usr/libexec/mcollective/mcollective/agent): 
--- package.ddl
--- package.rb
--- puppetd.ddl
--- puppetd.rb
--- puppetral.ddl
--- puppetral.rb
--- service.ddl
--- service.rb

applications (/usr/libexec/mcollective/mcollective/application): 

--- package.rb
--- puppetd.rb
--- service.rb

and util (/usr/libexec/mcollective/mcollective/util):
--- actionpolicy.rb

Collect puppet facts for mcollective

If you look at the mcollective server.cfg you'll see that we mentioned the file /etc/mcollective/facts.yaml. This file is needed so that mcollective can query the host facts. There are 2 approaches to create the file. The first one was written by Jordan Sissel. He added a file resource to the mcollective module which creates the facts.yaml file each time puppet runs.

 
file { 
  "/etc/mcollective/facts.yaml": 
    ensure => file, 
    content => inline_template("<%= scope.to_hash.reject { |k,v| !( k.is_a?(String) && v.is_a?(String) ) }.to_yaml %>"), 
    require => Package["mcollective"]; 
} 

Another approach is to create a cron entry to update the facts every 15 minutes
0,15,30,45 * * * * /usr/sbin/refresh-mco-meta

Create the file refresh-mco-meta in /usr/sbin/ and add the following content

#! /bin/bash
/usr/bin/facter --puppet --yaml > /etc/mcollective/facts.yaml.new
mv /etc/mcollective/facts.yaml.new /etc/mcollective/facts.yaml

Starting the service mcollective and enable mcollective at boot

# service mcollective start
# chkconfig mcollective on 

Include the smart proxy mcollective function (only on the puppet server which runs the smart proxy)
As foreman 1.1 does not include the mcollective functionality we need to apply Sam Kottler patch (https://github.com/theforeman/smart-proxy/pull/58/files) to integrate mcollective and foreman-proxy.

Get the 4 files you need to replace from the above url and replace, create and edit the following files:

/usr/share/foreman-proxy/config/settings.yml 
/usr/share/foreman-proxy/lib/proxy/puppet.rb
/usr/share/foreman-proxy/lib/proxy/puppet/runner.rb
/usr/share/foreman-proxy/lib/puppet_api.rb

In /etc/foreman-proxy/setings.yml add the following line after the puppet management entry:

# enable MCollective integration
:mcollective: true

Then replace puppet.rb and puppet_api.rb

# rm -f /usr/share/foreman-proxy/lib/proxy/puppet.rb
# cd /usr/share/foreman-proxy/lib/proxy/
# wget https://raw.github.com/skottler/smart-proxy/2a7b5fbfcdb3a0e9a4b22d46a09d4bfa2aa0f765/lib/proxy/puppet.rb
# rm -f /usr/share/foreman-proxy/lib/puppet_api.rb
# cd /usr/share/foreman-proxy/lib/
# wget https://raw.github.com/skottler/smart-proxy/2a7b5fbfcdb3a0e9a4b22d46a09d4bfa2aa0f765/lib/puppet_api.rb

The 4th script runner.rb needs a little bit more attention. As we use mcollective 1.2 we need to use the agent puppetd.

# cd /usr/share/foreman-proxy/lib/proxy/puppet/
# wget https://raw.github.com/skottler/smart-proxy/2a7b5fbfcdb3a0e9a4b22d46a09d4bfa2aa0f765/lib/proxy/puppet/runner.rb

Modify the runner.rb file on line 8 and line 16:

  1 module Proxy::Puppet
  2   class Mcollective
  3     extend Proxy::Util
  4
  5     def self.run(nodes)
  6       mco_search_path = ["/usr/bin", "/opt/puppet/bin"]
  7       sudo = which("sudo", "usr/bin")
  8       sudo = sudo << " -u puppet" 
  9       mco = which("mco", mco_search_path)
 10
 11       unless sudo and mco
 12         logger.warn "sudo or the mco binary is missing." 
 13         return false
 14       end
 15
 16       mco << " puppetd runonce -I #{nodes}" 

Mcollective sudo

Create an mcollective sudoers file to allow the foreman proxy to execute mco commands.

Defaults:foreman-proxy !requiretty
foreman-proxy ALL=(puppet) NOPASSWD: /usr/bin/mco *

Run puppet periodically with mcollective

There is a nice script called puppetcommander which runs puppet for you every x minutes.

You can get the script from here:

http://projects.puppetlabs.com/projects/mcollective-plugins/wiki/ToolPuppetcommander

Installing mcollective on the puppet clients

The puppet client only needs the mcollective and mcollective-common package. Which means you can follow the steps for the puppet server and skip the section for activemq and mcollective client. The rest is the same.

Testing the the configuration

After installing mcollective on the server and clients, you should be able to fire the following command form the puppet server

#mco ping

You should get a response from each puppet client which is subscribed to the mcollective topic.