Update code from https://github.com/dmi-try/marionette-collective
authorDmitry Burmistrov <dburmistrov@mirantis.com>
Tue, 15 Oct 2013 13:55:40 +0000 (17:55 +0400)
committerDmitry Burmistrov <dburmistrov@mirantis.com>
Tue, 15 Oct 2013 19:30:25 +0000 (23:30 +0400)
Change-Id: Iaf781af6b59d3932ffca234751ae014da2aea5af

98 files changed:
Rakefile
debian/control
debian/mcollective.init
debian/patches/conffile.dpatch
debian/patches/pluginsdir.dpatch
doc/.do-not-remove [new file with mode: 0644]
doc/mcollective/COPYING [deleted file]
doc/mcollective/README [deleted file]
etc/client.cfg.dist
etc/server.cfg.dist
ext/activemq/examples/multi-broker/broker1-activemq.xml
ext/activemq/examples/multi-broker/broker2-activemq.xml
ext/activemq/examples/multi-broker/broker3-activemq.xml
ext/activemq/examples/single-broker/activemq.xml
ext/debian/patches/conffile.dpatch
ext/debian/patches/pluginsdir.dpatch
ext/openbsd/port-files/mcollective/patches/patch-etc_server_cfg_dist
ext/redhat/mcollective.spec
ext/solaris11/README.md
lib/mcollective.rb
lib/mcollective/application.rb
lib/mcollective/config.rb
lib/mcollective/data/base.rb
lib/mcollective/data/result.rb
lib/mcollective/ddl/base.rb
lib/mcollective/locales/en.yml
plugins/mcollective/agent/discovery.rb
plugins/mcollective/application/rpc.rb
plugins/mcollective/connector/activemq.rb
plugins/mcollective/connector/rabbitmq.rb
spec/unit/application_spec.rb
spec/unit/config_spec.rb
spec/unit/data/base_spec.rb
spec/unit/data/result_spec.rb
spec/unit/data_spec.rb
spec/unit/plugins/mcollective/connector/rabbitmq_spec.rb
spec/unit/plugins/mcollective/data/agent_data_spec.rb
spec/unit/plugins/mcollective/data/fstat_data_spec.rb
spec/unit/security/base_spec.rb
website/changelog.md
website/configure/server.md [new file with mode: 0644]
website/deploy/middleware/activemq.md [new file with mode: 0644]
website/deploy/middleware/activemq_keystores.md [new file with mode: 0644]
website/index.md
website/messages/PLMC1.md
website/messages/PLMC10.md
website/messages/PLMC11.md
website/messages/PLMC12.md
website/messages/PLMC13.md
website/messages/PLMC14.md
website/messages/PLMC15.md
website/messages/PLMC16.md
website/messages/PLMC17.md
website/messages/PLMC18.md
website/messages/PLMC19.md
website/messages/PLMC2.md
website/messages/PLMC20.md
website/messages/PLMC21.md
website/messages/PLMC22.md
website/messages/PLMC23.md
website/messages/PLMC24.md
website/messages/PLMC25.md
website/messages/PLMC26.md
website/messages/PLMC27.md
website/messages/PLMC28.md
website/messages/PLMC29.md
website/messages/PLMC3.md
website/messages/PLMC30.md
website/messages/PLMC31.md
website/messages/PLMC32.md
website/messages/PLMC33.md
website/messages/PLMC34.md
website/messages/PLMC35.md
website/messages/PLMC36.md
website/messages/PLMC37.md
website/messages/PLMC38.md
website/messages/PLMC39.md
website/messages/PLMC4.md
website/messages/PLMC5.md
website/messages/PLMC6.md
website/messages/PLMC7.md
website/messages/PLMC8.md
website/messages/PLMC9.md
website/reference/basic/configuration.md
website/reference/basic/gettingstarted.md
website/reference/basic/gettingstarted_debian.md
website/reference/basic/gettingstarted_redhat.md
website/reference/basic/subcollectives.md
website/reference/integration/activemq_clusters.md
website/reference/integration/activemq_security.md
website/reference/integration/activemq_ssl.md
website/reference/plugins/connector_activemq.md
website/reference/plugins/connector_rabbitmq.md
website/reference/plugins/connector_stomp.md
website/reference/plugins/data.md
website/reference/ui/nodereports.md
website/releasenotes.md
website/simplerpc/authorization.md

index c1020d06d74060fa98e7b06faf5248a458488fe2..4a6f8f92bfdb4217440a2d4afc849d9d53da9faf 100644 (file)
--- a/Rakefile
+++ b/Rakefile
@@ -129,21 +129,23 @@ task :rpm => [:clean, :doc, :package] do
   specsdir = `rpm --eval '%_specdir'`.chomp
   srpmsdir = `rpm --eval '%_srcrpmdir'`.chomp
   rpmdir = `rpm --eval '%_rpmdir'`.chomp
-  lsbdistrel = `lsb_release -r -s | cut -d . -f1`.chomp
-  lsbdistro = `lsb_release -i -s`.chomp
+  rpmdist = ''
+
+  `which lsb_release`
+  if $?.success?
+    lsbdistrel = `lsb_release -r -s | cut -d . -f1`.chomp
+    lsbdistro = `lsb_release -i -s`.chomp
+    case lsbdistro
+    when 'CentOS'
+      rpmdist = ".el#{lsbdistrel}"
+    when 'Fedora'
+      rpmdist = ".fc#{lsbdistrel}"
+    end
+  end
 
   `which rpmbuild-md5`
   rpmcmd = $?.success? ? 'rpmbuild-md5' : 'rpmbuild'
 
-  case lsbdistro
-  when 'CentOS'
-    rpmdist = ".el#{lsbdistrel}"
-  when 'Fedora'
-    rpmdist = ".fc#{lsbdistrel}"
-  else
-    rpmdist = ""
-  end
-
   safe_system %{cp build/#{PROJ_NAME}-#{CURRENT_VERSION}.tgz #{sourcedir}}
   safe_system %{cat ext/redhat/#{PROJ_NAME}.spec|sed -e s/%{rpm_release}/#{CURRENT_RELEASE}/g | sed -e s/%{version}/#{CURRENT_VERSION}/g > #{specsdir}/#{PROJ_NAME}.spec}
 
@@ -153,9 +155,9 @@ task :rpm => [:clean, :doc, :package] do
     safe_system %{#{rpmcmd} -D 'version #{CURRENT_VERSION}' -D 'rpm_release #{CURRENT_RELEASE}' -D 'dist #{rpmdist}' -D 'use_lsb 0' -ba #{specsdir}/#{PROJ_NAME}.spec}
   end
 
-  safe_system %{cp #{srpmsdir}/#{PROJ_NAME}-#{CURRENT_VERSION}-#{CURRENT_RELEASE}#{rpmdist}.src.rpm build/}
+  safe_system %{cp #{srpmsdir}/#{PROJ_NAME}-#{CURRENT_VERSION}-#{CURRENT_RELEASE}*.src.rpm build/}
 
-  safe_system %{cp #{rpmdir}/*/#{PROJ_NAME}*-#{CURRENT_VERSION}-#{CURRENT_RELEASE}#{rpmdist}.*.rpm build/}
+  safe_system %{cp #{rpmdir}/*/#{PROJ_NAME}*-#{CURRENT_VERSION}-#{CURRENT_RELEASE}*.rpm build/}
 end
 
 desc "Create the .debs"
@@ -224,9 +226,6 @@ task :update_msgweb do
       md.puts "toc: false"
       md.puts "---"
       md.puts
-      md.puts "Detail for Marionette Collective message %s" % msg_code
-      md.puts "==========================================="
-      md.puts
       md.puts "Example Message"
       md.puts "---------------"
       md.puts
index 7fb71de9437d2733b1f71d6dc889db682017f2be..7a0ada2954e0c31b5421f9d795db183e97b2a178 100644 (file)
@@ -31,12 +31,12 @@ Description: build server orchestration or parallel job execution systems
  .
  Common files for mcollective packages.
 
-Package: mcollective-doc
-Architecture: all
-Section: doc
-Description: Documentation for mcollective
- The Marionette Collective aka. mcollective is a framework 
- to build server orchestration or parallel job execution systems.
- .
- Documentation package.
+#Package: mcollective-doc
+#Architecture: all
+#Section: doc
+#Description: Documentation for mcollective
+# The Marionette Collective aka. mcollective is a framework 
+# to build server orchestration or parallel job execution systems.
+# .
+# Documentation package.
 
index f599f4a8b5a6010ed0559bcf0de085ac7b82b59e..6fb229b0c1cc0397018eff095951ea090380706e 100755 (executable)
@@ -24,11 +24,11 @@ uid=`id -u`
 
 
 # PID directory
-pidfile="/var/run/mcollectived.pid"
+pidfile="/var/run/mcollective.pid"
 
 name="mcollective"
 mcollectived=/usr/sbin/mcollectived
-daemonopts="--pid=${pidfile}  --config=/etc/mcollective/server.cfg"
+daemonopts="--config=/etc/mcollective/server.cfg"
 
 
 # Source function library.
@@ -41,22 +41,30 @@ then
     exit 5
 fi
 
-# create pid file if it does not exist
-[ ! -f ${pidfile} ] && { touch ${pidfile} ; }
-
 # See how we were called.
 case "$1" in
     start)
         echo "Starting daemon: " $name
         # start the program
-        start-stop-daemon -S -p ${pidfile} --oknodo -q -a ${mcollectived} -- ${daemonopts}
-        [ $? = 0 ] && { exit 0 ; } || { exit 1 ; }
+       if [ -f $pidfile ]; then
+               if [ -f "$(cat /proc/$(cat $pidfile)/exe > /dev/null)" ] ; then
+                       echo MCollective appears to be running
+                       exit 1
+               else
+                       /sbin/start-stop-daemon --start -b --quiet --oknodo -m --pidfile $pidfile --exec $mcollectived -- $daemonopts
+               [ $? = 0 ] && { exit 0 ; } || { exit 1 ; }
+               fi
+       else
+               /sbin/start-stop-daemon --start -b --quiet --oknodo -m --pidfile $pidfile --exec $mcollectived -- $daemonopts
+       fi
         log_success_msg "mcollective started"
-        touch $lock
         ;;
     stop)
         echo "Stopping daemon: " $name
-        start-stop-daemon -K -R 5 -s "TERM" --oknodo -q -p ${pidfile}
+        /sbin/start-stop-daemon --stop -q --pidfile $pidfile
+       if [ -f $pidfile ]; then
+               rm -f $pidfile
+       fi
         [ $? = 0 ] && { exit 0 ; } || { exit 1 ; }
         log_success_msg "mcollective stopped"
         ;;
@@ -67,14 +75,6 @@ case "$1" in
         $0 start
         [ $? = 0 ] && { echo "mcollective restarted" ; exit 0 ; }
         ;;
-    condrestart)
-        if [ -f $lock ]; then
-            $0 stop
-            # avoid race
-            sleep 2
-            $0 start
-        fi
-        ;;
     status)
         status_of_proc -p ${pidfile} ${mcollectived} ${name} && exit 0 || exit $?
         ;;
index 07ba476ecc6a031f3bd53caf3f9214e66eaf6821..499ae7c683e6d21a97f12c74d27e60310ea937bc 100755 (executable)
@@ -9,7 +9,6 @@ diff -urNad mcollective-0.4.1~/etc/client.cfg mcollective-0.4.1/etc/client.cfg
 --- mcollective-0.4.1~/etc/client.cfg  1970-01-01 00:00:00.000000000 +0000
 +++ mcollective-0.4.1/etc/client.cfg   2010-01-06 14:37:24.000000000 +0000
 @@ -0,0 +1,19 @@
-+topicprefix = /topic/mcollective
 +libdir = /usr/share/mcollective/plugins
 +logger_type = console
 +loglevel = warn
@@ -33,7 +32,6 @@ diff -urNad mcollective-0.4.1~/etc/client.cfg.dist mcollective-0.4.1/etc/client.
 --- mcollective-0.4.1~/etc/client.cfg.dist     2010-01-02 14:54:25.000000000 +0000
 +++ mcollective-0.4.1/etc/client.cfg.dist      1970-01-01 00:00:00.000000000 +0000
 @@ -1,19 +0,0 @@
--topicprefix = /topic/mcollective
 -libdir = /usr/libexec/mcollective
 -logger_type = console
 -loglevel = warn
@@ -68,7 +66,6 @@ diff -urNad mcollective-0.4.1~/etc/server.cfg mcollective-0.4.1/etc/server.cfg
 --- mcollective-0.4.1~/etc/server.cfg  1970-01-01 00:00:00.000000000 +0000
 +++ mcollective-0.4.1/etc/server.cfg   2010-01-06 14:37:50.000000000 +0000
 @@ -0,0 +1,20 @@
-+topicprefix = /topic/mcollective
 +libdir = /usr/share/mcollective/plugins
 +logfile = /var/log/mcollective.log
 +loglevel = info
@@ -93,7 +90,6 @@ diff -urNad mcollective-0.4.1~/etc/server.cfg.dist mcollective-0.4.1/etc/server.
 --- mcollective-0.4.1~/etc/server.cfg.dist     2010-01-02 14:54:25.000000000 +0000
 +++ mcollective-0.4.1/etc/server.cfg.dist      1970-01-01 00:00:00.000000000 +0000
 @@ -1,20 +0,0 @@
--topicprefix = /topic/mcollective
 -libdir = /usr/libexec/mcollective
 -logfile = /var/log/mcollective.log
 -loglevel = info
index ef569279bb4a1a35e9e35ea36ba4a94c666024c1..843c716009dd64b67e0576a13ca6a4b040304771 100755 (executable)
@@ -8,20 +8,18 @@
 diff -urNad mcollective-1.1.4~/etc/client.cfg.dist mcollective-1.1.4/etc/client.cfg.dist
 --- mcollective-1.1.4~/etc/client.cfg.dist  2011-04-06 14:13:08.829462165 -0700
 +++ mcollective-1.1.4/etc/client.cfg.dist 2011-04-06 14:12:53.129384114 -0700
-@@ -1,7 +1,7 @@
- topicprefix = /topic/
+@@ -1,6 +1,6 @@
  main_collective = mcollective
  collectives = mcollective
 -libdir = /usr/libexec/mcollective
 +libdir = /usr/share/mcollective/plugins
  logger_type = console
  loglevel = warn
+
 diff -urNad mcollective-1.1.4~/etc/server.cfg.dist mcollective-1.1.4/etc/server.cfg.dist
 --- mcollective-1.1.4~/etc/server.cfg.dist  2011-04-06 14:12:30.889527230 -0700
 +++ mcollective-1.1.4/etc/server.cfg.dist 2011-04-06 14:12:23.779407065 -0700
-@@ -1,7 +1,7 @@
- topicprefix = /topic/
+@@ -1,6 +1,6 @@
  main_collective = mcollective
  collectives = mcollective
 -libdir = /usr/libexec/mcollective
diff --git a/doc/.do-not-remove b/doc/.do-not-remove
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/doc/mcollective/COPYING b/doc/mcollective/COPYING
deleted file mode 100644 (file)
index 375d1c8..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright 2010, 2011 Puppet Labs
-
-   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.
diff --git a/doc/mcollective/README b/doc/mcollective/README
deleted file mode 100644 (file)
index 8db05de..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-The Marionette Collective
-=========================
-
-The Marionette Collective aka. mcollective is a framework to build server orchestration or parallel job execution systems.
-
-For full information, wikis, ticketing and downloads please see http://marionette-collective.org/
index 514c1a59ac727a60885a3b0bdb1a57eb395f504a..1acffeef592647f4743f8663f82d273d34ce1075 100644 (file)
@@ -1,4 +1,3 @@
-topicprefix = /topic/
 main_collective = mcollective
 collectives = mcollective
 libdir = /usr/libexec/mcollective
index beed021fbeea4675cdba0e647dd1f3ede4475044..20383249c8e5153e719f34f7721a7e1ef6003505 100644 (file)
@@ -1,4 +1,3 @@
-topicprefix = /topic/
 main_collective = mcollective
 collectives = mcollective
 libdir = /usr/libexec/mcollective
index a910b3d1439a3cb0c1179c601a82a4ca75ee759a..bc7fe078bde7e6a399b1ddd52a0986e5a93ce2bc 100755 (executable)
         </property>
     </bean>
 
+    <!--
+      For more information about what MCollective requires in this file,
+      see http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html
+    -->
+
+    <!--
+      WARNING: The elements that are direct children of <broker> MUST BE IN
+      ALPHABETICAL ORDER. This is fixed in ActiveMQ 5.6.0, but affects
+      previous versions back to 5.4.
+      https://issues.apache.org/jira/browse/AMQ-3570
+    -->
+
+    <!-- In a network of brokers, the brokerName attribute must be unique. -->
     <broker xmlns="http://activemq.apache.org/schema/core" brokerName="broker1" useJmx="true" schedulePeriodForDestinationPurge="60000">
+        <!--
+          MCollective generally expects producer flow control to be turned off.
+          It will also generate a limitless number of single-use reply queues,
+          which should be garbage-collected after about five minutes to conserve
+          memory.
+
+          For more information, see:
+          http://activemq.apache.org/producer-flow-control.html
+        -->
         <destinationPolicy>
           <policyMap>
             <policyEntries>
             <managementContext createConnector="false"/>
         </managementContext>
 
+        <!--
+          Configure network connectors for a network of brokers. The
+          MCollective ActiveMQ connector uses TWO bi-directional
+          connectors per link, because the short-lived reply queues
+          require conduitSubscriptions be set to false.
+
+          In this config, broker1 connects to both other brokers; neither
+          of the other two have a <networkConnectors> element.
+        -->
         <networkConnectors>
           <!-- broker1 -> broker2 -->
           <networkConnector
                 name="broker1-broker2-topics"
-                uri="static:(tcp://broker2:6166)"
+                uri="static:(tcp://broker2:61616)"
                 userName="amq"
                 password="secret"
                 duplex="true"
@@ -43,7 +74,7 @@
           </networkConnector>
           <networkConnector
                 name="broker1-broker2-queues"
-                uri="static:(tcp://broker2:6166)"
+                uri="static:(tcp://broker2:61616)"
                 userName="amq"
                 password="secret"
                 duplex="true"
@@ -59,7 +90,7 @@
           <!-- broker1 -> broker3 -->
           <networkConnector
                 name="broker1-broker3-topics"
-                uri="static:(tcp://broker3:6166)"
+                uri="static:(tcp://broker3:61616)"
                 userName="amq"
                 password="secret"
                 duplex="true"
           </networkConnector>
           <networkConnector
                 name="broker1-broker3-queues"
-                uri="static:(tcp://broker3:6166)"
+                uri="static:(tcp://broker3:61616)"
                 userName="amq"
                 password="secret"
                 duplex="true"
           </networkConnector>
         </networkConnectors>
 
+        <!--
+          Configure message persistence for the broker. MCollective only
+          requires this in a network of brokers, where it's used to prevent
+          duplicate messages.
+
+          The default persistence mechanism is the KahaDB store (identified by
+          the kahaDB tag). For more information, see:
+
+          http://activemq.apache.org/persistence.html
+        -->
+        <persistenceAdapter>
+            <kahaDB directory="${activemq.base}/data/kahadb"/>
+        </persistenceAdapter>
+
         <plugins>
           <statisticsBrokerPlugin/>
+
+          <!--
+            This configures the users and groups used by this broker. Groups
+            are referenced below, in the write/read/admin attributes
+            of each authorizationEntry element.
+          -->
           <simpleAuthenticationPlugin>
             <users>
               <authenticationUser username="amq" password="secret" groups="admins,everyone"/>
               <authenticationUser username="mcollective" password="marionette" groups="mcollective,everyone"/>
-              <authenticationUser username="admin" password="secret" groups="mcollective,admin,everyone"/>
+              <authenticationUser username="admin" password="secret" groups="mcollective,admins,everyone"/>
             </users>
           </simpleAuthenticationPlugin>
+
+          <!--
+            Configure which users are allowed to read and write where. Permissions
+            are organized by group; groups are configured above, in the
+            authentication plugin.
+
+            With the rules below, both servers and admin users belong to group
+            mcollective, which can both issue and respond to commands. For an
+            example that splits permissions and doesn't allow servers to issue
+            commands, see:
+            http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html#detailed-restrictions
+          -->
           <authorizationPlugin>
             <map>
               <authorizationMap>
                   <authorizationEntry topic=">" write="admins" read="admins" admin="admins" />
                   <authorizationEntry topic="mcollective.>" write="mcollective" read="mcollective" admin="mcollective" />
                   <authorizationEntry queue="mcollective.>" write="mcollective" read="mcollective" admin="mcollective" />
+                  <!--
+                    The advisory topics are part of ActiveMQ, and all users need access to them.
+                    The "everyone" group is not special; you need to ensure every user is a member.
+                  -->
                   <authorizationEntry topic="ActiveMQ.Advisory.>" read="everyone" write="everyone" admin="everyone"/>
                 </authorizationEntries>
               </authorizationMap>
           </authorizationPlugin>
         </plugins>
 
+        <!--
+          The systemUsage controls the maximum amount of space the broker will
+          use for messages. For more information, see:
+          http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html#memory-and-temp-usage-for-messages-systemusage
+        -->
         <systemUsage>
             <systemUsage>
                 <memoryUsage>
             </systemUsage>
         </systemUsage>
 
+        <!--
+          The transport connectors allow ActiveMQ to listen for connections over
+          a given protocol. MCollective uses Stomp, and other ActiveMQ brokers
+          use OpenWire. You'll need different URLs depending on whether you are
+          using TLS. For more information, see:
+
+          http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html#transport-connectors
+        -->
         <transportConnectors>
-            <transportConnector name="openwire" uri="tcp://0.0.0.0:6166"/>
-            <transportConnector name="stomp" uri="stomp://0.0.0.0:6163"/>
+            <transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/>
+            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613"/>
         </transportConnectors>
     </broker>
+
+    <!--
+      Enable web consoles, REST and Ajax APIs and demos.
+      It also includes Camel (with its web console); see ${ACTIVEMQ_HOME}/conf/camel.xml for more info.
+
+      See ${ACTIVEMQ_HOME}/conf/jetty.xml for more details.
+    -->
     <import resource="jetty.xml"/>
 </beans>
index 163cf36ba8cfe4636bec329efd00ab2f0814ee61..5f1d027dd59c6a1f9e2df0e2c8704cf3375d6948 100755 (executable)
         </property>
     </bean>
 
+    <!--
+      For more information about what MCollective requires in this file,
+      see http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html
+    -->
+
+    <!--
+      WARNING: The elements that are direct children of <broker> MUST BE IN
+      ALPHABETICAL ORDER. This is fixed in ActiveMQ 5.6.0, but affects
+      previous versions back to 5.4.
+      https://issues.apache.org/jira/browse/AMQ-3570
+    -->
+
+    <!-- In a network of brokers, the brokerName attribute must be unique. -->
     <broker xmlns="http://activemq.apache.org/schema/core" brokerName="broker2" useJmx="true" schedulePeriodForDestinationPurge="60000">
+        <!--
+          MCollective generally expects producer flow control to be turned off.
+          It will also generate a limitless number of single-use reply queues,
+          which should be garbage-collected after about five minutes to conserve
+          memory.
+
+          For more information, see:
+          http://activemq.apache.org/producer-flow-control.html
+        -->
         <destinationPolicy>
           <policyMap>
             <policyEntries>
             <managementContext createConnector="false"/>
         </managementContext>
 
+        <!--
+          Configure message persistence for the broker. MCollective only
+          requires this in a network of brokers, where it's used to prevent
+          duplicate messages.
+
+          The default persistence mechanism is the KahaDB store (identified by
+          the kahaDB tag). For more information, see:
+
+          http://activemq.apache.org/persistence.html
+        -->
+        <persistenceAdapter>
+            <kahaDB directory="${activemq.base}/data/kahadb"/>
+        </persistenceAdapter>
+
         <plugins>
           <statisticsBrokerPlugin/>
+
+          <!--
+            This configures the users and groups used by this broker. Groups
+            are referenced below, in the write/read/admin attributes
+            of each authorizationEntry element.
+          -->
           <simpleAuthenticationPlugin>
             <users>
               <authenticationUser username="amq" password="secret" groups="admins,everyone"/>
               <authenticationUser username="mcollective" password="marionette" groups="mcollective,everyone"/>
-              <authenticationUser username="admin" password="secret" groups="mcollective,admin,everyone"/>
+              <authenticationUser username="admin" password="secret" groups="mcollective,admins,everyone"/>
             </users>
           </simpleAuthenticationPlugin>
+
+          <!--
+            Configure which users are allowed to read and write where. Permissions
+            are organized by group; groups are configured above, in the
+            authentication plugin.
+
+            With the rules below, both servers and admin users belong to group
+            mcollective, which can both issue and respond to commands. For an
+            example that splits permissions and doesn't allow servers to issue
+            commands, see:
+            http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html#detailed-restrictions
+          -->
           <authorizationPlugin>
             <map>
               <authorizationMap>
                   <authorizationEntry topic=">" write="admins" read="admins" admin="admins" />
                   <authorizationEntry topic="mcollective.>" write="mcollective" read="mcollective" admin="mcollective" />
                   <authorizationEntry queue="mcollective.>" write="mcollective" read="mcollective" admin="mcollective" />
+                  <!--
+                    The advisory topics are part of ActiveMQ, and all users need access to them.
+                    The "everyone" group is not special; you need to ensure every user is a member.
+                  -->
                   <authorizationEntry topic="ActiveMQ.Advisory.>" read="everyone" write="everyone" admin="everyone"/>
                 </authorizationEntries>
               </authorizationMap>
           </authorizationPlugin>
         </plugins>
 
+        <!--
+          The systemUsage controls the maximum amount of space the broker will
+          use for messages. For more information, see:
+          http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html#memory-and-temp-usage-for-messages-systemusage
+        -->
         <systemUsage>
             <systemUsage>
                 <memoryUsage>
             </systemUsage>
         </systemUsage>
 
+        <!--
+          The transport connectors allow ActiveMQ to listen for connections over
+          a given protocol. MCollective uses Stomp, and other ActiveMQ brokers
+          use OpenWire. You'll need different URLs depending on whether you are
+          using TLS. For more information, see:
+
+          http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html#transport-connectors
+        -->
         <transportConnectors>
-            <transportConnector name="openwire" uri="tcp://0.0.0.0:6166"/>
-            <transportConnector name="stomp" uri="stomp://0.0.0.0:6163"/>
+            <transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/>
+            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613"/>
         </transportConnectors>
     </broker>
+
+    <!--
+      Enable web consoles, REST and Ajax APIs and demos.
+      It also includes Camel (with its web console); see ${ACTIVEMQ_HOME}/conf/camel.xml for more info.
+
+      See ${ACTIVEMQ_HOME}/conf/jetty.xml for more details.
+    -->
     <import resource="jetty.xml"/>
 </beans>
index d118852317900709e22fc8b1584c30076eb35a48..b9366fc10910899023c696dafc30d13db49967a1 100755 (executable)
         </property>
     </bean>
 
+    <!--
+      For more information about what MCollective requires in this file,
+      see http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html
+    -->
+
+    <!--
+      WARNING: The elements that are direct children of <broker> MUST BE IN
+      ALPHABETICAL ORDER. This is fixed in ActiveMQ 5.6.0, but affects
+      previous versions back to 5.4.
+      https://issues.apache.org/jira/browse/AMQ-3570
+    -->
+
+    <!-- In a network of brokers, the brokerName attribute must be unique. -->
     <broker xmlns="http://activemq.apache.org/schema/core" brokerName="broker3" useJmx="true" schedulePeriodForDestinationPurge="60000">
+        <!--
+          MCollective generally expects producer flow control to be turned off.
+          It will also generate a limitless number of single-use reply queues,
+          which should be garbage-collected after about five minutes to conserve
+          memory.
+
+          For more information, see:
+          http://activemq.apache.org/producer-flow-control.html
+        -->
         <destinationPolicy>
           <policyMap>
             <policyEntries>
             <managementContext createConnector="false"/>
         </managementContext>
 
+        <!--
+          Configure message persistence for the broker. MCollective only
+          requires this in a network of brokers, where it's used to prevent
+          duplicate messages.
+
+          The default persistence mechanism is the KahaDB store (identified by
+          the kahaDB tag). For more information, see:
+
+          http://activemq.apache.org/persistence.html
+        -->
+        <persistenceAdapter>
+            <kahaDB directory="${activemq.base}/data/kahadb"/>
+        </persistenceAdapter>
+
         <plugins>
           <statisticsBrokerPlugin/>
+
+          <!--
+            This configures the users and groups used by this broker. Groups
+            are referenced below, in the write/read/admin attributes
+            of each authorizationEntry element.
+          -->
           <simpleAuthenticationPlugin>
             <users>
               <authenticationUser username="amq" password="secret" groups="admins,everyone"/>
               <authenticationUser username="mcollective" password="marionette" groups="mcollective,everyone"/>
-              <authenticationUser username="admin" password="secret" groups="mcollective,admin,everyone"/>
+              <authenticationUser username="admin" password="secret" groups="mcollective,admins,everyone"/>
             </users>
           </simpleAuthenticationPlugin>
+
+          <!--
+            Configure which users are allowed to read and write where. Permissions
+            are organized by group; groups are configured above, in the
+            authentication plugin.
+
+            With the rules below, both servers and admin users belong to group
+            mcollective, which can both issue and respond to commands. For an
+            example that splits permissions and doesn't allow servers to issue
+            commands, see:
+            http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html#detailed-restrictions
+          -->
           <authorizationPlugin>
             <map>
               <authorizationMap>
                   <authorizationEntry topic=">" write="admins" read="admins" admin="admins" />
                   <authorizationEntry topic="mcollective.>" write="mcollective" read="mcollective" admin="mcollective" />
                   <authorizationEntry queue="mcollective.>" write="mcollective" read="mcollective" admin="mcollective" />
+                  <!--
+                    The advisory topics are part of ActiveMQ, and all users need access to them.
+                    The "everyone" group is not special; you need to ensure every user is a member.
+                  -->
                   <authorizationEntry topic="ActiveMQ.Advisory.>" read="everyone" write="everyone" admin="everyone"/>
                 </authorizationEntries>
               </authorizationMap>
           </authorizationPlugin>
         </plugins>
 
+        <!--
+          The systemUsage controls the maximum amount of space the broker will
+          use for messages. For more information, see:
+          http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html#memory-and-temp-usage-for-messages-systemusage
+        -->
         <systemUsage>
             <systemUsage>
                 <memoryUsage>
             </systemUsage>
         </systemUsage>
 
+        <!--
+          The transport connectors allow ActiveMQ to listen for connections over
+          a given protocol. MCollective uses Stomp, and other ActiveMQ brokers
+          use OpenWire. You'll need different URLs depending on whether you are
+          using TLS. For more information, see:
+
+          http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html#transport-connectors
+        -->
         <transportConnectors>
-            <transportConnector name="openwire" uri="tcp://0.0.0.0:6166"/>
-            <transportConnector name="stomp" uri="stomp://0.0.0.0:6163"/>
+            <transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/>
+            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613"/>
         </transportConnectors>
     </broker>
+
+    <!--
+      Enable web consoles, REST and Ajax APIs and demos.
+      It also includes Camel (with its web console); see ${ACTIVEMQ_HOME}/conf/camel.xml for more info.
+
+      See ${ACTIVEMQ_HOME}/conf/jetty.xml for more details.
+    -->
     <import resource="jetty.xml"/>
 </beans>
index bb9ea1b74dac4a4021c66f196e4089ae09e63b3b..7f9e9f833815bcea67c2679c2fe58e9f6b9d0e05 100644 (file)
         </property>
     </bean>
 
+    <!--
+      For more information about what MCollective requires in this file,
+      see http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html
+    -->
+
+    <!--
+      WARNING: The elements that are direct children of <broker> MUST BE IN
+      ALPHABETICAL ORDER. This is fixed in ActiveMQ 5.6.0, but affects
+      previous versions back to 5.4.
+      https://issues.apache.org/jira/browse/AMQ-3570
+    -->
     <broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" useJmx="true" schedulePeriodForDestinationPurge="60000">
+        <!--
+          MCollective generally expects producer flow control to be turned off.
+          It will also generate a limitless number of single-use reply queues,
+          which should be garbage-collected after about five minutes to conserve
+          memory.
+
+          For more information, see:
+          http://activemq.apache.org/producer-flow-control.html
+        -->
         <destinationPolicy>
           <policyMap>
             <policyEntries>
 
         <plugins>
           <statisticsBrokerPlugin/>
+
+          <!--
+            This configures the users and groups used by this broker. Groups
+            are referenced below, in the write/read/admin attributes
+            of each authorizationEntry element.
+          -->
           <simpleAuthenticationPlugin>
             <users>
               <authenticationUser username="mcollective" password="marionette" groups="mcollective,everyone"/>
-              <authenticationUser username="admin" password="secret" groups="mcollective,admin,everyone"/>
+              <authenticationUser username="admin" password="secret" groups="mcollective,admins,everyone"/>
             </users>
           </simpleAuthenticationPlugin>
+
+          <!--
+            Configure which users are allowed to read and write where. Permissions
+            are organized by group; groups are configured above, in the
+            authentication plugin.
+
+            With the rules below, both servers and admin users belong to group
+            mcollective, which can both issue and respond to commands. For an
+            example that splits permissions and doesn't allow servers to issue
+            commands, see:
+            http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html#detailed-restrictions
+          -->
           <authorizationPlugin>
             <map>
               <authorizationMap>
                   <authorizationEntry topic=">" write="admins" read="admins" admin="admins" />
                   <authorizationEntry topic="mcollective.>" write="mcollective" read="mcollective" admin="mcollective" />
                   <authorizationEntry queue="mcollective.>" write="mcollective" read="mcollective" admin="mcollective" />
+                  <!--
+                    The advisory topics are part of ActiveMQ, and all users need access to them.
+                    The "everyone" group is not special; you need to ensure every user is a member.
+                  -->
                   <authorizationEntry topic="ActiveMQ.Advisory.>" read="everyone" write="everyone" admin="everyone"/>
                 </authorizationEntries>
               </authorizationMap>
           </authorizationPlugin>
         </plugins>
 
+        <!--
+          The systemUsage controls the maximum amount of space the broker will
+          use for messages. For more information, see:
+          http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html#memory-and-temp-usage-for-messages-systemusage
+        -->
         <systemUsage>
             <systemUsage>
                 <memoryUsage>
             </systemUsage>
         </systemUsage>
 
+        <!--
+          The transport connectors allow ActiveMQ to listen for connections over
+          a given protocol. MCollective uses Stomp, and other ActiveMQ brokers
+          use OpenWire. You'll need different URLs depending on whether you are
+          using TLS. For more information, see:
+
+          http://docs.puppetlabs.com/mcollective/deploy/middleware/activemq.html#transport-connectors
+        -->
         <transportConnectors>
-            <transportConnector name="openwire" uri="tcp://0.0.0.0:6166"/>
-            <transportConnector name="stomp" uri="stomp://0.0.0.0:6163"/>
+            <transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/>
+            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613"/>
         </transportConnectors>
     </broker>
+
+    <!--
+      Enable web consoles, REST and Ajax APIs and demos.
+      It also includes Camel (with its web console); see ${ACTIVEMQ_HOME}/conf/camel.xml for more info.
+
+      See ${ACTIVEMQ_HOME}/conf/jetty.xml for more details.
+    -->
     <import resource="jetty.xml"/>
 </beans>
index 07ba476ecc6a031f3bd53caf3f9214e66eaf6821..499ae7c683e6d21a97f12c74d27e60310ea937bc 100755 (executable)
@@ -9,7 +9,6 @@ diff -urNad mcollective-0.4.1~/etc/client.cfg mcollective-0.4.1/etc/client.cfg
 --- mcollective-0.4.1~/etc/client.cfg  1970-01-01 00:00:00.000000000 +0000
 +++ mcollective-0.4.1/etc/client.cfg   2010-01-06 14:37:24.000000000 +0000
 @@ -0,0 +1,19 @@
-+topicprefix = /topic/mcollective
 +libdir = /usr/share/mcollective/plugins
 +logger_type = console
 +loglevel = warn
@@ -33,7 +32,6 @@ diff -urNad mcollective-0.4.1~/etc/client.cfg.dist mcollective-0.4.1/etc/client.
 --- mcollective-0.4.1~/etc/client.cfg.dist     2010-01-02 14:54:25.000000000 +0000
 +++ mcollective-0.4.1/etc/client.cfg.dist      1970-01-01 00:00:00.000000000 +0000
 @@ -1,19 +0,0 @@
--topicprefix = /topic/mcollective
 -libdir = /usr/libexec/mcollective
 -logger_type = console
 -loglevel = warn
@@ -68,7 +66,6 @@ diff -urNad mcollective-0.4.1~/etc/server.cfg mcollective-0.4.1/etc/server.cfg
 --- mcollective-0.4.1~/etc/server.cfg  1970-01-01 00:00:00.000000000 +0000
 +++ mcollective-0.4.1/etc/server.cfg   2010-01-06 14:37:50.000000000 +0000
 @@ -0,0 +1,20 @@
-+topicprefix = /topic/mcollective
 +libdir = /usr/share/mcollective/plugins
 +logfile = /var/log/mcollective.log
 +loglevel = info
@@ -93,7 +90,6 @@ diff -urNad mcollective-0.4.1~/etc/server.cfg.dist mcollective-0.4.1/etc/server.
 --- mcollective-0.4.1~/etc/server.cfg.dist     2010-01-02 14:54:25.000000000 +0000
 +++ mcollective-0.4.1/etc/server.cfg.dist      1970-01-01 00:00:00.000000000 +0000
 @@ -1,20 +0,0 @@
--topicprefix = /topic/mcollective
 -libdir = /usr/libexec/mcollective
 -logfile = /var/log/mcollective.log
 -loglevel = info
index ef569279bb4a1a35e9e35ea36ba4a94c666024c1..843c716009dd64b67e0576a13ca6a4b040304771 100755 (executable)
@@ -8,20 +8,18 @@
 diff -urNad mcollective-1.1.4~/etc/client.cfg.dist mcollective-1.1.4/etc/client.cfg.dist
 --- mcollective-1.1.4~/etc/client.cfg.dist  2011-04-06 14:13:08.829462165 -0700
 +++ mcollective-1.1.4/etc/client.cfg.dist 2011-04-06 14:12:53.129384114 -0700
-@@ -1,7 +1,7 @@
- topicprefix = /topic/
+@@ -1,6 +1,6 @@
  main_collective = mcollective
  collectives = mcollective
 -libdir = /usr/libexec/mcollective
 +libdir = /usr/share/mcollective/plugins
  logger_type = console
  loglevel = warn
+
 diff -urNad mcollective-1.1.4~/etc/server.cfg.dist mcollective-1.1.4/etc/server.cfg.dist
 --- mcollective-1.1.4~/etc/server.cfg.dist  2011-04-06 14:12:30.889527230 -0700
 +++ mcollective-1.1.4/etc/server.cfg.dist 2011-04-06 14:12:23.779407065 -0700
-@@ -1,7 +1,7 @@
- topicprefix = /topic/
+@@ -1,6 +1,6 @@
  main_collective = mcollective
  collectives = mcollective
 -libdir = /usr/libexec/mcollective
index 61bf822fcb34bf0fec1ae81da55cc30273f1b9b9..acf348b710c3a398aeb449d60aa56cf5f918f2f9 100644 (file)
@@ -2,9 +2,8 @@ $OpenBSD$
 --- etc/server.cfg.dist.orig   Thu Jun 24 15:57:17 2010
 +++ etc/server.cfg.dist        Thu Jun 24 15:57:25 2010
 @@ -1,5 +1,5 @@
- topicprefix = /topic/mcollective
 -libdir = /usr/libexec/mcollective
-+libdir = ${PREFIX}/share/mcollective/plugins 
++libdir = ${PREFIX}/share/mcollective/plugins
  logfile = /var/log/mcollective.log
  loglevel = info
  daemonize = 1
index d11def7cf4ed71f7594f5e6ed7feab780c5fbdd5..2eb54fc35a7937d1750820d9166d97c504bb76de 100644 (file)
@@ -10,8 +10,6 @@ License: ASL 2.0
 URL: http://puppetlabs.com/mcollective/introduction/
 Source0: http://downloads.puppetlabs.com/mcollective/%{name}-%{version}.tgz
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-BuildRequires: ruby
-BuildRequires: ruby(abi) >= 1.8
 Requires: mcollective-common = %{version}-%{release}
 Packager: R.I.Pienaar <rip@devco.net>
 BuildArch: noarch
index 17d70e9e79f932b56ceb065a87dc0fd0ca902088..cd0df717b3235f8ea3fd7bfbac4e31642fcddb56 100644 (file)
@@ -74,7 +74,6 @@ Configuration
 There is no packaged configuration; you can use the following example:
 
     # cat > /etc/mcollective/client.cfg << "EOF"
-    topicprefix = /topic/
     main_collective = mcollective
     collectives = mcollective
     libdir = /usr/share/mcollective/plugins
index 8b376df0191add43fa2a66e3c14abffedd54c0e2..8b1431fe9cbdd7d4cb860fcf736d1565434b0649 100644 (file)
@@ -7,6 +7,7 @@ require 'singleton'
 require 'socket'
 require 'erb'
 require 'shellwords'
+require 'stringio'
 require 'rbconfig'
 require 'tempfile'
 require 'tmpdir'
index 66751e03e3db6a0c53bc99b4b67ab4e5a1266ff6..85f57ebf0e3de82f0f6f37c6aa310e3c1e3b5c3e 100644 (file)
@@ -319,46 +319,31 @@ module MCollective
       exit 1
     end
 
+    def halt_code(stats)
+      request_stats = {:discoverytime => 0,
+                       :discovered => 0,
+                       :okcount => 0,
+                       :failcount => 0}.merge(stats.to_hash)
+
+      return 4 if request_stats[:discoverytime] == 0 && request_stats[:responses] == 0
+      return 3 if request_stats[:discovered] > 0 && request_stats[:responses] == 0
+      return 2 if request_stats[:discovered] > 0 && request_stats[:failcount] > 0
+      return 1 if request_stats[:discovered] == 0
+      return 0 if request_stats[:discoverytime] == 0 && request_stats[:discovered] == request_stats[:okcount]
+      return 0 if request_stats[:discovered] == request_stats[:okcount]
+    end
+
     # A helper that creates a consistent exit code for applications by looking at an
     # instance of MCollective::RPC::Stats
     #
     # Exit with 0 if nodes were discovered and all passed
-    # Exit with 0 if no discovery were done and > 0 responses were received
+    # Exit with 0 if no discovery were done and > 0 responses were received, all ok
     # Exit with 1 if no nodes were discovered
     # Exit with 2 if nodes were discovered but some RPC requests failed
-    # Exit with 3 if nodes were discovered, but not responses received
+    # Exit with 3 if nodes were discovered, but no responses received
     # Exit with 4 if no discovery were done and no responses were received
     def halt(stats)
-      request_stats = {:discoverytime => 0,
-                       :discovered => 0,
-                       :failcount => 0}.merge(stats.to_hash)
-
-      # was discovery done?
-      if request_stats[:discoverytime] != 0
-        # was any nodes discovered
-        if request_stats[:discovered] == 0
-          exit 1
-
-        # nodes were discovered, did we get responses
-        elsif request_stats[:responses] == 0
-          exit 3
-
-        else
-          # we got responses and discovery was done, no failures
-          if request_stats[:failcount] == 0
-            exit 0
-          else
-            exit 2
-          end
-        end
-      else
-        # discovery wasnt done and we got no responses
-        if request_stats[:responses] == 0
-          exit 4
-        else
-          exit 0
-        end
-      end
+      exit(halt_code(stats))
     end
 
     # Wrapper around MC::RPC#rpcclient that forcably supplies our options hash
index 8b5e4091ae8acd6efa9e57d399b6812e57597c3b..7ce3a26714cdf4fc6ed08c224532ed4a923ca30c 100644 (file)
@@ -5,16 +5,16 @@ module MCollective
 
     attr_accessor :mode
 
-    attr_reader :topicprefix, :daemonize, :pluginconf, :libdir, :configured
+    attr_reader :daemonize, :pluginconf, :libdir, :configured
     attr_reader :logfile, :keeplogs, :max_log_size, :loglevel, :logfacility
     attr_reader :identity, :daemonize, :connector, :securityprovider, :factsource
-    attr_reader :registration, :registerinterval, :topicsep, :classesfile
+    attr_reader :registration, :registerinterval, :classesfile
     attr_reader :rpcauditprovider, :rpcaudit, :configdir, :rpcauthprovider
     attr_reader :rpcauthorization, :color, :configfile, :rpchelptemplate
     attr_reader :rpclimitmethod, :logger_type, :fact_cache_time, :collectives
     attr_reader :main_collective, :ssl_cipher, :registration_collective
     attr_reader :direct_addressing, :direct_addressing_threshold, :ttl, :helptemplatedir
-    attr_reader :queueprefix, :default_discovery_method, :default_discovery_options
+    attr_reader :default_discovery_method, :default_discovery_options
 
     def initialize
       @configured = false
@@ -24,7 +24,7 @@ module MCollective
       set_config_defaults(configfile)
 
       if File.exists?(configfile)
-        File.open(configfile, "r").each do |line|
+        File.readlines(configfile).each do |line|
 
           # strip blank spaces, tabs etc off the end of all lines
           line.gsub!(/\s*$/, "")
@@ -35,8 +35,6 @@ module MCollective
               val = $2
 
               case key
-                when "topicsep"
-                  @topicsep = val
                 when "registration"
                   @registration = val.capitalize
                 when "registration_collective"
@@ -47,10 +45,6 @@ module MCollective
                   @collectives = val.split(",").map {|c| c.strip}
                 when "main_collective"
                   @main_collective = val
-                when "topicprefix"
-                  @topicprefix = val
-                when "queueprefix"
-                  @queueprefix = val
                 when "logfile"
                   @logfile = val
                 when "keeplogs"
@@ -74,7 +68,7 @@ module MCollective
                 when "identity"
                   @identity = val
                 when "direct_addressing"
-                  val =~ /^1|y/i ? @direct_addressing = true : @direct_addressing = false
+                  @direct_addressing = false unless val =~ /^1|y/i
                 when "direct_addressing_threshold"
                   @direct_addressing_threshold = val.to_i
                 when "color"
@@ -124,6 +118,8 @@ module MCollective
           end
         end
 
+        raise('The %s config file does not specify a libdir setting, cannot continue' % configfile) if @libdir.empty?
+
         I18n.load_path = Dir[File.expand_path(File.join(File.dirname(__FILE__), "locales", "*.yml"))]
         I18n.locale = :en
 
@@ -163,9 +159,6 @@ module MCollective
       @registration = "Agentlist"
       @registerinterval = 0
       @registration_collective = nil
-      @topicsep = "."
-      @topicprefix = "/topic/"
-      @queueprefix = "/queue/"
       @classesfile = "/var/lib/puppet/state/classes.txt"
       @rpcaudit = false
       @rpcauditprovider = ""
@@ -185,7 +178,7 @@ module MCollective
       @collectives = ["mcollective"]
       @main_collective = @collectives.first
       @ssl_cipher = "aes-256-cbc"
-      @direct_addressing = false
+      @direct_addressing = true
       @direct_addressing_threshold = 10
       @default_discovery_method = "mc"
       @default_discovery_options = []
index 3ff8213d6b6cc93b576d8c241be5e19b6250439e..fdfecee52fd02c2e4c216da99d78285a44bbaf23 100644 (file)
@@ -13,7 +13,7 @@ module MCollective
       def initialize
         @name = self.class.to_s.split("::").last.downcase
         @ddl = DDL.new(@name, :data)
-        @result = Result.new
+        @result = Result.new(@ddl.dataquery_interface[:output])
         @timeout = @ddl.meta[:timeout] || 1
 
         startup_hook
index e19a652ffa8b10a6c21dacf1735b62acae39ee0f..8ffe4d2f34861d8ddd9f347cf63f628f13f5bb81 100644 (file)
@@ -6,8 +6,12 @@ module MCollective
       # method_missing lookup strategy
       undef :type if method_defined?(:type)
 
-      def initialize
+      def initialize(outputs)
         @data = {}
+
+        outputs.keys.each do |output|
+          @data[output] = outputs[output].fetch(:default, nil)
+        end
       end
 
       def include?(key)
index d526755ace6e4f6b26f56753798fe32b8e0e2b10..b4e524d44898df8e4b8355f2e0a322bd73ee3d08 100644 (file)
@@ -81,7 +81,7 @@ module MCollective
         if ddlfile = findddlfile
           instance_eval(File.read(ddlfile), ddlfile, 1)
         else
-          raise_code(:PLMC18, "Can't find DDL for %{type} plugin '%{name}'", :debug, :type => @plugintype, :name => @pluginname)
+          raise_code(:PLMC40, "Can't find DDL for %{type} plugin '%{name}'", :debug, :type => @plugintype, :name => @pluginname)
         end
       end
 
index 2ff5d7a7849dd6cb74ea533246c7359b5169de72..2bfee67bd0ea5ccc25120c66f50827fd374010e4 100644 (file)
@@ -278,6 +278,13 @@ en:
         
         This message indicate that on first start this plugin failed to run, it will show the exception class, line and exception message to assist with debugging
     pattern: "Failed to start registration plugin: %{error}"
+  PLMC40: 
+    example: "Can't find DDL for agent plugin 'puppet'"
+    expanded: |-
+        MCollective plugins come with DDL files that describe their behaviours, versions, capabilities and requirements.
+        
+        This error indicate that a DDL file for the plugin mentioned could not be found - it could be that you have a typing error in your command line or an installation error.
+    pattern: "Can't find DDL for %{type} plugin '%{name}'"
   PLMC5: 
     expanded: |-
         In previous versions of MCollective a application called 'controller' were included that had the ability to request agent reloads and other commands that would control the runner.
index ede2ec4045bca7ea5d211a0c4572fae7f37566c5..3d5d5d39f4becfea40e5331201901a40ee2ea0dc 100644 (file)
@@ -10,8 +10,6 @@ module MCollective
         config = Config.instance.pluginconf
 
         @timeout = 5
-        @timeout = config["discovery.timeout"].to_i if config.include?("discovery.timeout")
-
         @meta = {:license => "Apache License, Version 2",
                  :author => "R.I.Pienaar <rip@devco.net>",
                  :timeout => @timeout,
index c69cfd18b6fa854e6e9330932a02fd31116a8ab2..32d59f97264459ae05c97ef94a53a0deb292fd75 100644 (file)
@@ -84,6 +84,8 @@ class MCollective::Application::Rpc<MCollective::Application
 
     string_to_ddl_type(configuration[:arguments], mc.ddl.action_interface(configuration[:action])) if mc.ddl
 
+    mc.validate_request(configuration[:action], configuration[:arguments])
+
     if mc.reply_to
       configuration[:arguments][:process_results] = true
 
index cb14647ef1b8c09602180f49a443fd772e086934..eadeb17127d5b498142a296d5325007919530c5d 100644 (file)
@@ -32,7 +32,7 @@ module MCollective
     #    plugin.activemq.pool.size = 2
     #
     #    plugin.activemq.pool.1.host = stomp1.your.net
-    #    plugin.activemq.pool.1.port = 6163
+    #    plugin.activemq.pool.1.port = 61613
     #    plugin.activemq.pool.1.user = you
     #    plugin.activemq.pool.1.password = secret
     #    plugin.activemq.pool.1.ssl = true
@@ -42,7 +42,7 @@ module MCollective
     #    plugin.activemq.pool.1.ssl.fallback = true
     #
     #    plugin.activemq.pool.2.host = stomp2.your.net
-    #    plugin.activemq.pool.2.port = 6163
+    #    plugin.activemq.pool.2.port = 61613
     #    plugin.activemq.pool.2.user = you
     #    plugin.activemq.pool.2.password = secret
     #    plugin.activemq.pool.2.ssl = false
@@ -161,7 +161,7 @@ module MCollective
             host = {}
 
             host[:host] = get_option("activemq.pool.#{poolnum}.host")
-            host[:port] = get_option("activemq.pool.#{poolnum}.port", 6163).to_i
+            host[:port] = get_option("activemq.pool.#{poolnum}.port", 61613).to_i
             host[:login] = get_env_or_option("STOMP_USER", "activemq.pool.#{poolnum}.user")
             host[:passcode] = get_env_or_option("STOMP_PASSWORD", "activemq.pool.#{poolnum}.password")
             host[:ssl] = get_bool_option("activemq.pool.#{poolnum}.ssl", false)
index 2bb3b1c95dcfea70a8702d9e23181669ab9d89eb..f3e2dbe94abbcb17d96e144890cb56689f7f7313 100644 (file)
@@ -73,7 +73,7 @@ module MCollective
             host = {}
 
             host[:host] = get_option("rabbitmq.pool.#{poolnum}.host")
-            host[:port] = get_option("rabbitmq.pool.#{poolnum}.port", 6163).to_i
+            host[:port] = get_option("rabbitmq.pool.#{poolnum}.port", 61613).to_i
             host[:login] = get_env_or_option("STOMP_USER", "rabbitmq.pool.#{poolnum}.user")
             host[:passcode] = get_env_or_option("STOMP_PASSWORD", "rabbitmq.pool.#{poolnum}.password")
             host[:ssl] = get_bool_option("rabbitmq.pool.#{poolnum}.ssl", false)
@@ -190,7 +190,7 @@ module MCollective
           target = {:name => msg.request.headers["reply-to"], :headers => {}, :id => ""}
 
         elsif [:request, :direct_request].include?(msg.type)
-          target = make_target(msg.agent, msg.type, msg.collective, node)
+          target = make_target(msg.agent, msg.type, msg.collective, msg.reply_to, node)
 
         else
           raise "Don't now how to create a target for message type #{msg.type}"
@@ -200,7 +200,7 @@ module MCollective
         return target
       end
 
-      def make_target(agent, type, collective, node=nil)
+      def make_target(agent, type, collective, reply_to=nil, node=nil)
         raise("Unknown target type #{type}") unless [:directed, :broadcast, :reply, :request, :direct_request].include?(type)
         raise("Unknown collective '#{collective}' known collectives are '#{@config.collectives.join ', '}'") unless @config.collectives.include?(collective)
 
@@ -213,7 +213,11 @@ module MCollective
 
           when :broadcast, :request # publishing a request to all nodes with an agent
             target[:name] = "/exchange/%s_broadcast/%s" % [collective, agent]
-            target[:headers]["reply-to"] = "/temp-queue/mcollective_reply_%s" % agent
+            if reply_to
+              target[:headers]["reply-to"] = reply_to
+            else
+              target[:headers]["reply-to"] = "/temp-queue/mcollective_reply_%s" % agent
+            end
             target[:id] = "%s_broadcast_%s" % [collective, agent]
 
           when :direct_request # a request to a specific node
index 9b1c434b5930c7fe2527a722f20b261caebe4135..d2e64eb137e82563369535a8cf1d0f7948963950 100755 (executable)
@@ -414,7 +414,7 @@ module MCollective
 
     describe "#halt" do
       before do
-        @stats = {:discoverytime => 0, :discovered => 0, :failcount => 0, :responses => 0}
+        @stats = {:discoverytime => 0, :discovered => 0, :failcount => 0, :responses => 0, :okcount => 0}
       end
 
       it "should exit with code 0 if discovery was done and all responses passed" do
@@ -423,28 +423,25 @@ module MCollective
         @stats[:discoverytime] = 2
         @stats[:discovered] = 2
         @stats[:responses] = 2
+        @stats[:okcount] = 2
 
-        app.expects(:exit).with(0)
-
-        app.halt(@stats)
+        app.halt_code(@stats).should == 0
       end
 
       it "should exit with code 0 if no discovery were done but responses were received" do
         app = Application.new
 
         @stats[:responses] = 1
+        @stats[:okcount] = 1
+        @stats[:discovered] = 1
 
-        app.expects(:exit).with(0)
-
-        app.halt(@stats)
+        app.halt_code(@stats).should == 0
       end
 
-      it "should exit with code 0 if discovery info is missing" do
+      it "should exit with code 1 if discovery info is missing" do
         app = Application.new
 
-        app.expects(:exit).with(0)
-
-        app.halt({})
+        app.halt_code({}).should == 1
       end
 
       it "should exit with code 1 if no nodes were discovered and discovery was done" do
@@ -452,22 +449,29 @@ module MCollective
 
         @stats[:discoverytime] = 2
 
-        app.expects(:exit).with(1)
-
-        app.halt(@stats)
+        app.halt_code(@stats).should == 1
       end
 
       it "should exit with code 2 if a request failed for some nodes" do
         app = Application.new
 
-        @stats[:discovered] = 1
+        @stats[:discovered] = 2
         @stats[:failcount] = 1
         @stats[:discoverytime] = 2
-        @stats[:responses] = 1
+        @stats[:responses] = 2
 
-        app.expects(:exit).with(2)
+        app.halt_code(@stats).should == 2
+      end
+
+      it "should exit with code 2 when no discovery were done and there were failure results" do
+        app = Application.new
 
-        app.halt(@stats)
+        @stats[:discovered] = 1
+        @stats[:failcount] = 1
+        @stats[:discoverytime] = 0
+        @stats[:responses] = 1
+
+        app.halt_code(@stats).should == 2
       end
 
       it "should exit with code 3 if no responses were received after discovery" do
@@ -476,17 +480,13 @@ module MCollective
         @stats[:discovered] = 1
         @stats[:discoverytime] = 2
 
-        app.expects(:exit).with(3)
-
-        app.halt(@stats)
+        app.halt_code(@stats).should == 3
       end
 
       it "should exit with code 4 if no discovery was done and no responses were received" do
         app = Application.new
 
-        app.expects(:exit).with(4)
-
-        app.halt(@stats)
+        app.halt_code(@stats).should == 4
       end
     end
 
index adf71a5c7e330ef4cc167867b5b976be2e3e0584..f166f225214c72aff64d5f52070cd8d96abc68f9 100755 (executable)
@@ -5,6 +5,13 @@ require 'spec_helper'
 module MCollective
   describe Config do
     describe "#loadconfig" do
+      it "should fail when no libdir is set" do
+        File.expects(:exists?).with("/nonexisting").returns(true)
+        File.expects(:readlines).with("/nonexisting").returns([])
+        Config.instance.stubs(:set_config_defaults)
+        expect { Config.instance.loadconfig("/nonexisting") }.to raise_error("The /nonexisting config file does not specify a libdir setting, cannot continue")
+      end
+
       it "should only test that libdirs are absolute paths" do
         Util.expects(:absolute_path?).with("/one").returns(true)
         Util.expects(:absolute_path?).with("/two").returns(true)
@@ -15,14 +22,14 @@ module MCollective
         File.stubs(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true)
 
         ["/one:/two", "/three"].each do |path|
-          File.stubs(:open).with("/nonexisting", "r").returns(StringIO.new("libdir = #{path}"))
+          File.expects(:readlines).with("/nonexisting").returns(["libdir = #{path}"])
 
           Config.instance.loadconfig("/nonexisting")
 
           PluginManager.clear
         end
 
-        File.stubs(:open).with("/nonexisting", "r").returns(StringIO.new("libdir = four"))
+        File.expects(:readlines).with("/nonexisting").returns(["libdir = four"])
 
         expect { Config.instance.loadconfig("/nonexisting") }.to raise_error(/should be absolute paths/)
       end
@@ -38,7 +45,7 @@ module MCollective
           "\\\\?\\c:\\foo", "//?/UNC/bar", "//foo/bar",
           "//?/c:/foo"
         ].each do |input|
-          File.expects(:open).with("/nonexisting", "r").returns(StringIO.new("identity = #{input}"))
+          File.expects(:readlines).with("/nonexisting").returns(["identity = #{input}", "libdir=/nonexistinglib"])
           File.expects(:exists?).with("/nonexisting").returns(true)
           File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true)
 
@@ -50,7 +57,7 @@ module MCollective
 
       it "should allow valid identities" do
         ["foo", "foo_bar", "foo-bar", "foo-bar-123", "foo.bar", "foo_bar_123"].each do |input|
-          File.expects(:open).with("/nonexisting", "r").returns(StringIO.new("identity = #{input}"))
+          File.expects(:readlines).with("/nonexisting").returns(["identity = #{input}", "libdir=/nonexistinglib"])
           File.expects(:exists?).with("/nonexisting").returns(true)
           File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true)
           PluginManager.stubs(:loadclass)
@@ -60,9 +67,31 @@ module MCollective
         end
       end
 
+      it "should set direct_addressing to true by default" do
+        File.expects(:readlines).with("/nonexisting").returns(["libdir=/nonexistinglib"])
+        File.expects(:exists?).with("/nonexisting").returns(true)
+        File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true)
+        PluginManager.stubs(:loadclass)
+        PluginManager.stubs("<<")
+
+        Config.instance.loadconfig("/nonexisting")
+        Config.instance.direct_addressing.should == true
+      end
+
+      it "should allow direct_addressing to be disabled in the config file" do
+        File.expects(:readlines).with("/nonexisting").returns(["libdir=/nonexistinglib", "direct_addressing=n"])
+        File.expects(:exists?).with("/nonexisting").returns(true)
+        File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true)
+        PluginManager.stubs(:loadclass)
+        PluginManager.stubs("<<")
+
+        Config.instance.loadconfig("/nonexisting")
+        Config.instance.direct_addressing.should == false
+      end
+
       it "should not allow the syslog logger type on windows" do
         Util.expects("windows?").returns(true).twice
-        File.expects(:open).with("/nonexisting", "r").returns(StringIO.new("logger_type = syslog"))
+        File.expects(:readlines).with("/nonexisting").returns(["libdir=/nonexistinglib", "logger_type=syslog"])
         File.expects(:exists?).with("/nonexisting").returns(true)
         File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true)
         PluginManager.stubs(:loadclass)
@@ -74,7 +103,7 @@ module MCollective
       it "should default to finding the help template in the same dir as the config file" do
         path = File.join(File.dirname("/nonexisting"), "rpc-help.erb")
 
-        File.expects(:open).with("/nonexisting", "r").returns(StringIO.new(""))
+        File.expects(:readlines).with("/nonexisting").returns(["libdir=/nonexistinglib"])
         File.expects(:exists?).with("/nonexisting").returns(true)
         PluginManager.stubs(:loadclass)
         PluginManager.stubs("<<")
@@ -88,7 +117,7 @@ module MCollective
       it "should fall back to old behavior if the help template file does not exist in the config dir" do
         path = File.join(File.dirname("/nonexisting"), "rpc-help.erb")
 
-        File.expects(:open).with("/nonexisting", "r").returns(StringIO.new(""))
+        File.expects(:readlines).with("/nonexisting").returns(["libdir=/nonexistinglib"])
         File.expects(:exists?).with("/nonexisting").returns(true)
         File.expects(:exists?).with(path).returns(false)
         PluginManager.stubs(:loadclass)
@@ -99,7 +128,7 @@ module MCollective
       end
 
       it "should support multiple default_discovery_options" do
-        File.expects(:open).with("/nonexisting", "r").returns(StringIO.new("default_discovery_options = 1\ndefault_discovery_options = 2"))
+        File.expects(:readlines).with("/nonexisting").returns(["default_discovery_options = 1", "default_discovery_options = 2", "libdir=/nonexistinglib"])
         File.expects(:exists?).with("/nonexisting").returns(true)
         File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true)
         PluginManager.stubs(:loadclass)
@@ -155,7 +184,8 @@ module MCollective
         File.stubs(:exists?).returns(true)
         File.stubs(:directory?).with(@plugindir).returns(true)
         File.stubs(:exists?).with(servercfg).returns(true)
-        File.expects(:open).with(servercfg, "r").returns(["plugin.rspec.key = default"])
+        File.expects(:readlines).with(servercfg).returns(["plugin.rspec.key = default", "libdir=/nonexisting"])
+        File.stubs(:directory?).with("/nonexisting").returns(true)
 
         Dir.expects(:new).with(@plugindir).returns(["rspec.cfg"])
         File.expects(:open).with(File.join(@plugindir, "rspec.cfg"), "r").returns(["key = overridden"])
index 51ffa6ce0d6419f67a6f1f43b3efdacc479063db..80a150438fe8cc7ee68dd68c3dc570e999bbb095 100644 (file)
@@ -7,6 +7,7 @@ module MCollective
     describe Base do
       before do
         @ddl = mock
+        @ddl.stubs(:dataquery_interface).returns({:output => {'rspec' => {}}})
         @ddl.stubs(:meta).returns({:timeout => 1})
       end
 
index 9ea22cdddab826be5954a205ce1b868d1707358e..4f88932529543d8bcb81e3140dc02b1843be02cc 100644 (file)
@@ -6,7 +6,21 @@ module MCollective
   module Data
     describe Result do
       before(:each) do
-        @result = Result.new
+        @result = Result.new({})
+      end
+
+      describe "#initialize" do
+        it "should initialize empty values for all output fields" do
+          result = Result.new({:rspec1 => {}, :rspec2 => {}})
+          result[:rspec1].should == nil
+          result[:rspec2].should == nil
+        end
+
+        it "should set default values for all output fields" do
+          result = Result.new({:rspec1 => {:default => 1}, :rspec2 => {}})
+          result[:rspec1].should == 1
+          result[:rspec2].should == nil
+        end
       end
 
       describe "#[]=" do
index a117ce0bf4db828ea96f5ca49df758d85fc2d3a2..cc7dbf8c2a5fdc0e2880aa3c162a8f30955143f8 100644 (file)
@@ -17,6 +17,8 @@ module MCollective
 
         ddl = mock
         ddl.stubs(:meta).returns({:timeout => 1})
+        ddl.stubs(:dataquery_interface).returns({:rspec => nil})
+        ddl.stubs(:dataquery_interface).returns({:output => {}})
         DDL.stubs(:new).returns(ddl)
         Data::Base.expects(:activate?).returns(false)
         PluginManager.expects("[]").with("rspec_data").returns(Data::Base.new)
@@ -30,6 +32,7 @@ module MCollective
 
         ddl = mock
         ddl.stubs(:meta).returns({:timeout => 1})
+        ddl.stubs(:dataquery_interface).returns({:output => {}})
         DDL.stubs(:new).returns(ddl)
         Data::Base.expects(:activate?).raises("rspec failure")
         Log.expects(:debug).once.with("Disabling data plugin rspec_data due to exception RuntimeError: rspec failure")
index 82b9d94119302ef6d23d2646f8a7b850a0c3b31d..bf097040a9d6fa8ac09f6216c5f8a285266a5230 100644 (file)
@@ -264,6 +264,7 @@ module MCollective
           msg.stubs(:agent).returns("agent")
           msg.stubs(:collective).returns("mcollective")
           msg.stubs(:type).returns(:direct_request)
+          msg.stubs(:reply_to).returns("/topic/mcollective")
           msg.expects(:discovered_hosts).returns(["one", "two"])
 
           @connection.expects(:publish).with('/exchange/mcollective_directed/one', 'msg', {'reply-to' => '/temp-queue/mcollective_reply_agent'})
@@ -345,8 +346,9 @@ module MCollective
           message.expects(:type).returns(:request).times(3)
           message.expects(:agent).returns("rspecagent")
           message.expects(:collective).returns("mcollective")
+          message.expects(:reply_to).returns("/topic/rspec")
 
-          @c.expects(:make_target).with("rspecagent", :request, "mcollective", nil)
+          @c.expects(:make_target).with("rspecagent", :request, "mcollective", "/topic/rspec", nil)
           @c.target_for(message)
         end
 
@@ -355,8 +357,9 @@ module MCollective
           message.expects(:type).returns(:direct_request).times(3)
           message.expects(:agent).returns("rspecagent")
           message.expects(:collective).returns("mcollective")
+          message.expects(:reply_to).returns("/topic/rspec")
 
-          @c.expects(:make_target).with("rspecagent", :direct_request, "mcollective", nil)
+          @c.expects(:make_target).with("rspecagent", :direct_request, "mcollective", "/topic/rspec", nil)
           @c.target_for(message)
         end
 
@@ -383,8 +386,9 @@ module MCollective
           @c.make_target("test", :reply, "mcollective").should == {:name => "/temp-queue/mcollective_reply_test", :headers => {}, :id => "mcollective_test_replies"}
           @c.make_target("test", :broadcast, "mcollective").should == {:name => "/exchange/mcollective_broadcast/test", :headers => {"reply-to"=>"/temp-queue/mcollective_reply_test"}, :id => "mcollective_broadcast_test"}
           @c.make_target("test", :request, "mcollective").should == {:name => "/exchange/mcollective_broadcast/test", :headers => {"reply-to"=>"/temp-queue/mcollective_reply_test"}, :id => "mcollective_broadcast_test"}
-          @c.make_target("test", :direct_request, "mcollective", "rspec").should == {:headers=>{"reply-to"=>"/temp-queue/mcollective_reply_test"}, :name=>"/exchange/mcollective_directed/rspec", :id => nil}
+          @c.make_target("test", :direct_request, "mcollective", nil, "rspec").should == {:headers=>{"reply-to"=>"/temp-queue/mcollective_reply_test"}, :name=>"/exchange/mcollective_directed/rspec", :id => nil}
           @c.make_target("test", :directed, "mcollective").should == {:name => "/exchange/mcollective_directed/rspec", :headers=>{}, :id => "rspec_directed_to_identity"}
+          @c.make_target("test", :request, "mcollective", "/topic/rspec", "rspec").should == {:headers=>{"reply-to"=>"/topic/rspec"}, :name=>"/exchange/mcollective_broadcast/test", :id => "mcollective_broadcast_test"}
         end
 
         it "should raise an error for unknown collectives" do
index 8477a63f89ac71704f060b63563ec9eaeae59af3..6c8670f9094a4f2728c7979eee36026b96f7faa4 100644 (file)
@@ -10,6 +10,7 @@ module MCollective
       describe "#query_data" do
         before do
           @ddl = mock
+          @ddl.stubs(:dataquery_interface).returns({:output => {}})
           @ddl.stubs(:meta).returns({:timeout => 1})
           DDL.stubs(:new).returns(@ddl)
           @plugin = Agent_data.new
index babca399865e11b328c1eb8354e8ef50e65dac95..228c0b1b78a63e6c6ec5fee29e92c5fc3339e845 100644 (file)
@@ -11,6 +11,7 @@ module MCollective
         before do
           @ddl = mock
           @ddl.stubs(:meta).returns({:timeout => 1})
+          @ddl.stubs(:dataquery_interface).returns({:output => {}})
           DDL.stubs(:new).returns(@ddl)
           @plugin = Fstat_data.new
 
index d36264c36c2b6e26d39816564f7d6d44730639b0..9aaacf8fdacbc1a6ab507ede57a9e8a9b62676c9 100755 (executable)
@@ -10,7 +10,6 @@ module MCollective
         @config.stubs(:identity).returns("test")
         @config.stubs(:configured).returns(true)
         @config.stubs(:topicsep).returns(".")
-        @config.stubs(:topicprefix).returns("/topic/")
 
         @stats = mock("stats")
 
index b8e678efcca4017700edba290a70b186529c187d..a7cd14f9b29b0c31631f82782a5cb72cc2b34310 100644 (file)
@@ -8,21 +8,32 @@ toc: false
 
 |Date|Description|Ticket|
 |----|-----------|------|
+|2013/03/22|Remove the topicprefix, queueprefix and topicsep options|19673|
+|2013/03/21|Remove the plugin.discovery.timeout setting as it's not relevant anymore|19694|
+|2013/03/21|Improve error reporting from the rpc application in the light of direct_addressing|19827|
+|2013/03/20|Fail with a friendly error message when no libdir is set|19752|
+|2013/03/14|Change default RabbitMQ and ActiveMQ ports to 61613|19734|
+|2013/03/13|Set correct reply-to headers in the RabbitMQ connector|17034|
+|2013/03/12|Pre-populate the data from data plugins like agent replies|19564|
+|2013/03/12|Explicitly include StringIO|19367|
+|2013/03/12|Enable direct addressing by default|19665|
+|2013/02/20|Fix error code collision on PLMC18|19366|
+|2013/02/15|Validate arguments supplied to the RPC application and raise errors sooner|19181|
 |*2013/02/14*|*Release 2.3.1*|19265|
-|2012/02/14|Initial work towards internationalization and online help|18663|
+|2013/02/14|Initial work towards internationalization and online help|18663|
 |2013/02/14|Update vendored JSON gem for CVE-2013-0269|19265|
-|2012/02/13|Restore the ability to set a discovery timeout on a RPC client|19238|
-|2012/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200|
-|2012/02/12|Fix package building on certain Debian systems|19141|
-|2012/02/12|Remove the stomp connector|19146|
-|2012/02/07|Read the client config before trying to use any configuration options|19105|
-|2012/01/22|When an argument fails to parse in the rpc application fail rather than continue with unintended consequences|18773|
-|2012/01/22|The fix the *--no-response* argument to the rpc application that broke due to 18438|18513|
-|2012/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758|
-|2012/01/21|Improve presentation of the --help output for applications|18447|
-|2012/01/21|When a request failed via *reply.fail*, only show the message and not the half built data|18434|
+|2013/02/13|Restore the ability to set a discovery timeout on a RPC client|19238|
+|2013/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200|
+|2013/02/12|Fix package building on certain Debian systems|19141|
+|2013/02/12|Remove the stomp connector|19146|
+|2013/02/07|Read the client config before trying to use any configuration options|19105|
+|2013/01/22|When an argument fails to parse in the rpc application fail rather than continue with unintended consequences|18773|
+|2013/01/22|The fix the *--no-response* argument to the rpc application that broke due to 18438|18513|
+|2013/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758|
+|2013/01/21|Improve presentation of the --help output for applications|18447|
+|2013/01/21|When a request failed via *reply.fail*, only show the message and not the half built data|18434|
 |*2013/01/10*|*Release 2.3.0*|18259|
-|2012/01/10|Raise the correct exception when trying to access unknown data items in a Data results|18466|
+|2013/01/10|Raise the correct exception when trying to access unknown data items in a Data results|18466|
 |2013/01/10|Fix failing documentation generation for data plugins|18437|
 |2013/01/09|Correctly support negative boolean flags declared as --[no]-foo|18438|
 |2013/01/03|Add the package iteration number as a dependency for the common packages|18273|
@@ -53,12 +64,12 @@ toc: false
 |----|-----------|------|
 |*2013/02/14*|*Release 2.2.3*|19265|
 |2013/02/14|Update vendored JSON gem for CVE-2013-0269|19265|
-|2012/02/13|Restore the ability to set a discovery timeout on a RPC client|19238|
-|2012/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200|
-|2012/02/12|Fix package building on certain Debian systems|19141|
-|2012/02/12|Deprecate the stomp connector|19146|
-|2012/02/07|Read the client config before trying to use any configuration options|19105|
-|2012/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758|
+|2013/02/13|Restore the ability to set a discovery timeout on a RPC client|19238|
+|2013/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200|
+|2013/02/12|Fix package building on certain Debian systems|19141|
+|2013/02/12|Deprecate the stomp connector|19146|
+|2013/02/07|Read the client config before trying to use any configuration options|19105|
+|2013/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758|
 |*2013/01/17*|*Release 2.2.2*|18258|
 |2013/01/03|Add the package iteration number as a dependency for the common packages|18273|
 |2012/12/24|Restore the :any validator|18265|
diff --git a/website/configure/server.md b/website/configure/server.md
new file mode 100644 (file)
index 0000000..b8cba6f
--- /dev/null
@@ -0,0 +1,732 @@
+---
+title: "MCollective » Configure » Servers"
+layout: default
+---
+
+
+<!-- TODO Got to change this middleware link as soon as enough of the deploy docs come up. -->
+[middleware]: /mcollective/deploy/middleware/activemq.html
+[filters]: /mcollective/reference/ui/filters.html
+[plugin_directory]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki
+[facter_plugin]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki/FactsFacter
+[ohai_plugin]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki/FactsOhai
+[chef_classfile]: /mcollective/reference/integration/chef.html#class-filters
+[fact]: #facts-identity-and-classes
+[connector_plugin]: #connector-settings
+[subcollectives]: /mcollective/reference/basic/subcollectives.html
+[registration]: /mcollective/reference/plugins/registration.html
+[puppetdb]: /puppetdb/
+[security_plugin]: #security-plugin-settings
+[auditing]: /mcollective/simplerpc/auditing.html
+[authorization]: /mcollective/simplerpc/authorization.html
+[actionpolicy]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki/AuthorizationActionPolicy
+[security_aes]: /mcollective/reference/plugins/security_aes.html
+[security_overview]: /mcollective/security.html
+[ssl_plugin]: /mcollective/reference/plugins/security_ssl.html
+[activemq_tls_verified]: /mcollective/reference/integration/activemq_ssl.html#ca-verified-tls
+[activemq_connector]: /mcollective/reference/plugins/connector_activemq.html
+[rabbitmq_connector]: /mcollective/reference/plugins/connector_rabbitmq.html
+[stdlib]: http://forge.puppetlabs.com/puppetlabs/stdlib
+
+{% capture badbool %}**Note:** Use these exact values only; do not use "true" or "false."{% endcapture %}
+
+{% capture pluginname %}**Note:** Capitalization of plugin names doesn't matter; MCollective normalizes it before loading the plugin.{% endcapture %}
+
+{% capture path_separator %}system path separator (colon \[`:`\] on \*nix, semicolon \[`;`\] on Windows){% endcapture %}
+
+
+
+This document describes MCollective server configuration in MCollective 2.0.0 and higher. Older versions may lack certain fetaures.
+
+
+Example / Index
+-----
+
+The following is an example MCollective server config file showing all of the major groups of settings. All of the setting names styled as links can be clicked, and will take you down the page to a full description of that setting.
+
+[See below the example for a full description of the config file location and format.](#the-server-config-files)
+
+<pre><code># /etc/mcollective/server.cfg
+
+# <a href="#connector-settings">Connector settings (required):</a>
+# -----------------------------
+
+<a href="#connector">connector</a> = activemq
+<a href="#directaddressing">direct_addressing</a> = 1
+
+# <a href="#activemq-connector-settings">ActiveMQ connector settings:</a>
+plugin.activemq.pool.size = 1
+plugin.activemq.pool.1.host = middleware.example.net
+plugin.activemq.pool.1.port = 61614
+plugin.activemq.pool.1.user = mcollective
+plugin.activemq.pool.1.password = secret
+plugin.activemq.pool.1.ssl = 1
+plugin.activemq.pool.1.ssl.ca = /var/lib/puppet/ssl/certs/ca.pem
+plugin.activemq.pool.1.ssl.cert = /var/lib/puppet/ssl/certs/web01.example.com.pem
+plugin.activemq.pool.1.ssl.key = /var/lib/puppet/ssl/private_keys/web01.example.com.pem
+plugin.activemq.pool.1.ssl.fallback = 0
+
+# <a href="#rabbitmq-connector-settings">RabbitMQ connector settings:</a>
+plugin.rabbitmq.vhost = /mcollective
+plugin.rabbitmq.pool.size = 1
+plugin.rabbitmq.pool.1.host = middleware.example.net
+# ... etc., similar to activemq settings
+
+# <a href="#security-plugin-settings">Security plugin settings (required):</a>
+# -----------------------------------
+
+<a href="#securityprovider">securityprovider</a> = ssl
+
+# <a href="#ssl-plugin-settings">SSL plugin settings:</a>
+plugin.ssl_client_cert_dir = /etc/mcollective.d/clients
+plugin.ssl_server_private = /etc/mcollective.d/server_private.pem
+plugin.ssl_server_public = /etc/mcollective.d/server_public.pem
+
+# <a href="#psk-plugin-settings">PSK plugin settings:</a>
+plugin.psk = j9q8kx7fnuied9e
+
+# <a href="#facts-identity-and-classes">Facts, identity, and classes (recommended):</a>
+# ------------------------------------------
+
+<a href="#factsource">factsource</a> = yaml
+<a href="#pluginyaml">plugin.yaml</a> = /etc/mcollective/facts.yaml
+<a href="#factcachetime">fact_cache_time</a> = 300
+
+<a href="#identity">identity</a> = web01.example.com
+
+<a href="#classesfile">classesfile</a> = /var/lib/puppet/state/classes.txt
+
+# <a href="#subcollectives">Subcollectives (optional):</a>
+# -------------------------
+
+<a href="#collectives">collectives</a> = mcollective,uk_collective
+<a href="#maincollective">main_collective</a> = mcollective
+
+# <a href="#node-registration">Registration (optional):</a>
+# -----------------------
+
+<a href="#registerinterval">registerinterval</a> = 300
+<a href="#registration">registration</a> = agentlist
+<a href="#registrationcollective">registration_collective</a> = mcollective
+
+# <a href="#auditing">Auditing (optional):</a>
+# -------------------
+
+<a href="#rpcaudit">rpcaudit</a> = 1
+<a href="#rpcauditprovider">rpcauditprovider</a> = logfile
+<a href="#pluginrpcauditlogfile">plugin.rpcaudit.logfile</a> = /var/log/mcollective-audit.log
+
+# <a href="#authorization">Authorization (optional):</a>
+# ------------------------
+
+<a href="#rpcauthorization">rpcauthorization</a> = 1
+<a href="#rpcauthprovider">rpcauthprovider</a> = action_policy
+
+# <a href="#logging">Logging:</a>
+# -------
+
+<a href="#loggertype">logger_type</a> = file
+<a href="#loglevel">loglevel</a> = info
+<a href="#keeplogs">keeplogs</a> = 5
+<a href="#maxlogsize">max_log_size</a> = 2097152
+<a href="#logfacility">logfacility</a> = user
+
+# <a href="#platform-defaults">Platform defaults:</a>
+# -----------------
+
+<a href="#daemonize">daemonize</a> = 1
+<a href="#libdir">libdir</a> = /usr/libexec/mcollective
+<a href="#sslcipher">ssl_cipher</a> = aes-256-cbc
+</code>
+</pre>
+
+
+([↑ Back to top](#content))
+
+
+
+
+
+
+The Server Config File(s)
+-----
+
+### Main Config File
+
+MCollective servers are configured with the `/etc/mcollective/server.cfg` file. It contains MCollective's core settings, as well as settings for the various plugins.
+
+> **Warning:** This file contains sensitive credentials, and should only be readable by the root user, or whatever user the MCollective daemon runs as.
+
+### File Format
+
+Each line consists of a setting, an equals sign, and a value:
+
+    # setting = value
+    connector = activemq
+
+The spaces on either side of the equals sign are optional. Lines starting with a `#` are comments.
+
+> **Note on Boolean Values:** MCollective's config code does not have consistent handling of boolean values. Many of the core settings will accept values of `1/0` and `y/n`, but will fail to handle `true/false`; additionally, each plugin can handle boolean values differently, and some of them do not properly handle the `y/n` values accepted by the core settings.
+>
+> Nearly all known plugins and core settings accept `1` and `0`. Until further notice, you should always use these for all boolean settings, as no other values are universally safe.
+
+### Plugin Config Directory (Optional)
+
+Many of MCollective's settings are named with the format `plugin.<NAME>.<SETTING_NAME>`. These settings can optionally be put in separate files, in the `/etc/mcollective/plugin.d/` directory.
+
+To move a plugin setting to an external file, put it in `/etc/mcollective/plugin.d/<NAME>.cfg`, and use only the `<SETTING_NAME>` segment of the setting. So this:
+
+    # /etc/mcollective/server.cfg
+    plugin.puppet.splay = true
+
+...is equivalent to:
+
+    # /etc/mcollective/plugin.d/puppet.cfg
+    splay = true
+
+Note that this doesn't work for settings like `plugin.psk`, since they have no `<SETTING_NAME>` segment; a setting must have at least three segments to go in a plugin.cfg file.
+
+### Best Practices
+
+You should manage your MCollective servers' config files with config management software (such as Puppet). While most settings in a deployment are the same, several should be different for each server, and managing these differences manually is impractical.
+
+If your deployment is fairly simple and there is little division of responsibility (e.g. having one group in charge of MCollective core and another group in charge of several agent plugins), then you can manage the config file with a simple template.
+
+If your deployment is large or complex, or you expect it to become so, you should manage MCollective settings as individual resources, as this is the only practical way to divide responsibilities within a single file.
+
+Below is an example of how to do this using the `file_line` type from the [puppetlabs/stdlib module][stdlib]:
+
+{% highlight ruby %}
+    # /etc/puppet/modules/mcollective/manifests/setting.pp
+    define mcollective::setting ($setting = $title, $target = '/etc/mcollective/server.cfg', $value) {
+      validate_re($target, '\/(plugin\.d\/[a-z]+|server)\.cfg\Z')
+      $regex_escaped_setting = regsubst($setting, '\.', '\\.', 'G') # assume dots are the only regex-unsafe chars in a setting name.
+
+      file_line {"mco_setting_${title}":
+        path  => $target,
+        line  => "${setting} = ${value}",
+        match => "^ *${regex_escaped_setting} *=.*$",
+      }
+    }
+
+    # /etc/puppet/modules/mcollective_core/manifests/server/connector.pp
+    # ...
+    # Connector settings:
+    mcollective::setting {
+      'connector':
+        value => 'activemq';
+      'direct_addressing':
+        value => '1';
+      'plugin.activemq.pool.size':
+        value => '1';
+      'plugin.activemq.pool.1.host':
+        value => $activemq_server;
+      'plugin.activemq.pool.1.port':
+        value => '61614';
+      'plugin.activemq.pool.1.user':
+        value => $activemq_user;
+      'plugin.activemq.pool.1.password':
+        value => $activemq_password;
+      'plugin.activemq.pool.1.ssl':
+        value => '1';
+      'plugin.activemq.pool.1.ssl.fallback':
+        value => '1';
+    }
+    # ...
+{% endhighlight %}
+
+([↑ Back to top](#content))
+
+
+Required Settings
+-----
+
+### Connector Settings
+
+
+<pre><code><a href="#connector">connector</a> = activemq
+<a href="#directaddressing">direct_addressing</a> = 1
+
+# <a href="#activemq-connector-settings">ActiveMQ connector settings:</a>
+plugin.activemq.pool.size = 1
+plugin.activemq.pool.1.host = middleware.example.net
+plugin.activemq.pool.1.port = 61614
+plugin.activemq.pool.1.user = mcollective
+plugin.activemq.pool.1.password = secret
+plugin.activemq.pool.1.ssl = 1
+plugin.activemq.pool.1.ssl.ca = /var/lib/puppet/ssl/certs/ca.pem
+plugin.activemq.pool.1.ssl.cert = /var/lib/puppet/ssl/certs/web01.example.com.pem
+plugin.activemq.pool.1.ssl.key = /var/lib/puppet/ssl/private_keys/web01.example.com.pem
+plugin.activemq.pool.1.ssl.fallback = 0
+
+# <a href="#rabbitmq-connector-settings">RabbitMQ connector settings:</a>
+plugin.rabbitmq.vhost = /mcollective
+plugin.rabbitmq.pool.size = 1
+plugin.rabbitmq.pool.1.host = middleware.example.net
+plugin.rabbitmq.pool.1.port = 61613
+# ... etc., similar to activemq settings
+</code>
+</pre>
+
+
+MCollective always requires a connector plugin. The connector plugin is determined by the [middleware][] you chose for your deployment. Each connector plugin will have additional settings it requires.
+
+> #### Shared Configuration
+>
+> * All servers and clients must use the same connector plugin, and its settings must be configured compatibly.
+> * You must use the right connector plugin for your [choice of middleware][middleware].
+> * The hostname and port must match what the middleware is using. The username and password must be valid login accounts on the middleware. If you are using [CA-verified TLS][activemq_tls_verified], the certificate must be signed by the same CA the middleware is using.
+
+#### `connector`
+
+Which connector plugin to use. This is determined by your [choice of middleware][middleware].
+
+- _Default:_ `activemq`
+- _Allowed values:_ `activemq`, `rabbitmq`, or the name of a third-party connector plugin. {{ pluginname }}
+
+
+#### `direct_addressing`
+
+Whether your middleware supports direct point-to-point messages. **This should usually be turned on,** although it is off by default. The built-in `activemq` and `rabbitmq` connectors both support direct addressing, as does the external `redis` connector. (The older `stomp` connector, however, does not.)
+
+- _Default:_ `0`
+- _Allowed values:_ `1`, `0`, `y`, `n` --- {{ badbool }}
+
+#### ActiveMQ Connector Settings
+
+ActiveMQ is the main middleware we recommend for MCollective. The ActiveMQ connector can use multiple servers as a failover pool; if you have only one server, just use a pool size of `1`.
+
+> **Note:** This is only a summary of the most commonly used ActiveMQ settings; there are about ten more settings that can be used to tune the connector's performance. [See the ActiveMQ connector documentation][activemq_connector] for more complete details.
+
+- **`plugin.activemq.pool.size`** --- How many ActiveMQ servers to attempt to use. _Default:_ (nothing)
+- **`plugin.activemq.pool.1.host`** --- The hostname of the first ActiveMQ server. (Note that additional servers use the same settings as the first, incrementing the number.) _Default:_ (nothing)
+- **`plugin.activemq.pool.1.port`** --- The Stomp port of the first ActiveMQ server. _Default:_ `61613` or `6163`, depending on the MCollective version.
+- **`plugin.activemq.pool.1.user`** --- The ActiveMQ user account to connect as. If the `STOMP_USER` environment variable is set, MCollective will use its value instead of this setting.
+- **`plugin.activemq.pool.1.password`** --- The password for the user account being used. If the `STOMP_PASSWORD` environment variable is set, MCollective will use its value instead of this setting.
+- **`plugin.activemq.pool.1.ssl`** --- Whether to use TLS when connecting to ActiveMQ. _Default:_ `0`; _allowed:_ `1/0`, `true/false`, `yes/no`
+- **`plugin.activemq.pool.1.ssl.fallback`** --- _(When `ssl == 1`)_ Whether to allow unverified TLS if the ca/cert/key settings aren't set. _Default:_ `0`; _allowed:_ `1/0`, `true/false`, `yes/no`
+- **`plugin.activemq.pool.1.ssl.ca`** --- _(When `ssl == 1`)_ The CA certificate to use when verifying ActiveMQ's certificate. Must be the path to a `.pem` file. _Default:_ (nothing)
+- **`plugin.activemq.pool.1.ssl.cert`** --- _(When `ssl == 1`)_ The certificate to present when connecting to ActiveMQ. Must be the path to a `.pem` file. _Default:_ (nothing)
+- **`plugin.activemq.pool.1.ssl.key`** --- _(When `ssl == 1`)_ The private key corresponding to this node's certificate. Must be the path to a `.pem` file. _Default:_ (nothing)
+
+#### RabbitMQ Connector Settings
+
+The RabbitMQ connector uses very similar settings to the ActiveMQ connector, with the same `.pool.1.host` style of setting names.
+
+[See the RabbitMQ connector documentation][rabbitmq_connector] for more complete details.
+
+
+([↑ Back to top](#content))
+
+
+### Security Plugin Settings
+
+<pre><code><a href="#securityprovider">securityprovider</a> = ssl
+
+# <a href="#ssl-plugin-settings">SSL plugin settings:</a>
+plugin.ssl_client_cert_dir = /etc/mcollective.d/clients
+plugin.ssl_server_private = /etc/mcollective.d/server_private.pem
+plugin.ssl_server_public = /etc/mcollective.d/server_public.pem
+
+# <a href="#psk-plugin-settings">PSK plugin settings:</a>
+plugin.psk = j9q8kx7fnuied9e
+</code>
+</pre>
+
+MCollective always requires a security plugin. (Although they're called security plugins, they actually handle more, including message serialization.) Each security plugin will have additional settings it requires.
+
+> #### Shared Configuration
+>
+> All servers and clients must use the same security plugin, and its settings must be configured compatibly.
+
+It's possible to write new security plugins, but most people use one of the three included in MCollective:
+
+- **SSL:** The best choice for most users. Provides very good security when combined with TLS on the connector plugin (see above).
+- **PSK:** Poor security, but easy to configure; fine for proof-of-concept deployments.
+- **AES:** Complex to configure, and carries a noticable performance cost in large networks. Only suitable for certain use cases, like where TLS on the middleware is impossible.
+
+For a full-system look at how security works in MCollective, see [Security Overview][security_overview].
+
+
+#### `securityprovider`
+
+Which security plugin to use.
+
+- _Default:_ `psk`
+- _Allowed values:_ `ssl`, `psk`, `aes_security`, or the name of a third-party security plugin. {{ pluginname }}
+
+#### SSL Plugin Settings
+
+> **Note:** This security plugin requires you to manage and distribute SSL credentials. [See the SSL security plugin page][ssl_plugin] for full details. In summary:
+>
+> * All servers share **one** "server" keypair. They must all have a copy of the public key and private key.
+> * Every admin user must have a copy of the server public key.
+> * Every admin user has their own "client" keypair.
+> * Every server must have a copy of **every** authorized client public key.
+
+All of these settings have **no default,** and must be set for the SSL plugin to work.
+
+- **`plugin.ssl_server_private`** --- The path to the server private key file, which must be in `.pem` format.
+- **`plugin.ssl_server_public`** --- The path to the server public key file, which must be in `.pem` format.
+- **`plugin.ssl_client_cert_dir`** --- A directory containing every authorized client public key.
+
+
+#### PSK Plugin Settings
+
+> **Note:** The only credential used by this plugin is a single shared password, which all servers and admin users have a copy of.
+
+- **`plugin.psk`** --- The shared passphrase. If the `MCOLLECTIVE_PSK` environment variable is set, MCollective will use its value instead of this setting.
+
+
+([↑ Back to top](#content))
+
+
+Facts, Identity, and Classes
+-----
+
+<pre><code><a href="#factsource">factsource</a> = yaml
+<a href="#pluginyaml">plugin.yaml</a> = /etc/mcollective/facts.yaml
+<a href="#factcachetime">fact_cache_time</a> = 300
+
+<a href="#identity">identity</a> = web01.example.com
+
+<a href="#classesfile">classesfile</a> = /var/lib/puppet/state/classes.txt
+</code>
+</pre>
+
+MCollective clients use filters to discover nodes and limit commands. (See [Discovery Filters][filters] for more details.) These filters can use a variety of per-server metadata, including **facts, identity,** and **classes.**
+
+* **Facts:** A collection of key/value data about a server's hardware and software. (E.g. `memorytotal = 8.00 GB`, `kernel = Darwin`, etc.)
+* **Identity:** The name of the node.
+* **Classes:** The Puppet classes (or Chef cookbooks, etc.) applied to this node. Classes are useful as metadata because they describe what _roles_ a server fills at your site.
+
+None of these settings are mandatory, but MCollective is less useful without them.
+
+#### `identity`
+
+The node's name or identity. This **should** be unique for each node, but does not **need** to be.
+
+- _Default:_ The value of Ruby's `Socket.gethostname` method, which is usually the server's FQDN.
+- _Sample value:_ `web01.example.com`
+- _Allowed values:_ Any string containing only alphanumeric characters, hyphens, and dots --- i.e. matching the regular expression `/\A[\w\.\-]+\Z/`
+
+#### `classesfile`
+
+A file with a list of classes applied by your configuration management system. This should be a plain text file containing one class name per line.
+
+Puppet automatically writes a class file, which can be found by running `sudo puppet apply --configprint classfile`. [Chef can be made to write a class file][chef_classfile].
+
+- _Default:_ `/var/lib/puppet/state/classes.txt`
+
+
+#### `factsource`
+
+Which fact plugin to use.
+
+MCollective includes a fact plugin called `yaml`. Most users should use this default, set [the `plugin.yaml` setting (see below)](#pluginyaml), and arrange to fill the file it relies on.
+
+Other fact plugins (including [Facter][facter_plugin] and [Ohai][ohai_plugin] ones) are available in the [plugin directory][plugin_directory]. These may require settings of their own.
+
+- _Default:_ `yaml`
+- _Allowed values:_ The name of any installed fact plugin, with the `_facts` suffix trimmed off. {{ pluginname }}
+
+#### `plugin.yaml`
+
+_When `factsource == yaml`_
+
+The fact file(s) to load for [the default `yaml` fact plugin](#factsource).
+
+- _Default:_ (nothing)
+- _Sample value:_ `/etc/mcollective/facts.yaml`
+- _Valid values:_ A single path, or a list of paths separated by the {{ path_separator }}.
+
+**Notes:**
+
+The default `yaml` fact plugin reads cached facts from a file, which should be a simple YAML hash. If multiple files are specified, they will be merged. (Later files override prior ones if there are conflicting values.)
+
+**The user is responsible for populating the fact file;** by default it is empty, and MCollective has no facts.
+
+If you are using Puppet and Facter, you can populate it by putting something like the following in your puppet master's `/etc/puppet/manifests/site.pp`, outside any node definition:
+
+{% highlight ruby %}
+    # /etc/puppet/manifests/site.pp
+    file{"/etc/mcollective/facts.yaml":
+       owner    => root,
+       group    => root,
+       mode     => 400,
+       loglevel => debug, # reduce noise in Puppet reports
+       content  => inline_template("<%= scope.to_hash.reject { |k,v| k.to_s =~ /(uptime_seconds|timestamp|free)/ }.to_yaml %>"), # exclude rapidly changing facts
+    }
+{% endhighlight %}
+
+#### `fact_cache_time`
+
+How long (in seconds) to cache fact results before refreshing from source. This can be ignored unless you're using a non-default `factsource`.
+
+- _Default:_ `300`
+
+([↑ Back to top](#content))
+
+
+Optional Features
+-----
+
+### Subcollectives
+
+<pre><code><a href="#collectives">collectives</a> = mcollective,uk_collective
+<a href="#maincollective">main_collective</a> = mcollective
+</code>
+</pre>
+
+Subcollectives provide an alternate way of dividing up the servers in a deployment. They are mostly useful because the middleware can be made aware of them, which enables traffic flow and access restrictions. In multi-datacenter deployments, this can save bandwidth costs and give some extra security.
+
+* [See the Subcollectives and Partitioning page][subcollectives] for more details and an example of site partitioning.
+
+Subcollective membership is managed **on the server side,** by each server's config file. A given server can join any number of collectives, and will respond to commands from any of them.
+
+> #### Shared Configuration
+>
+> If you are using any additional collectives (besides the default `mcollective` collective), your middleware must be configured to permit traffic on those collectives. See the middleware deployment guide for your specific middleware to see how to do this:
+>
+> * ActiveMQ: [Subcollective topic/queue names](/mcollective/deploy/middleware/activemq.html#topic-and-queue-names) --- [Multi-subcollective authorization example](/mcollective/deploy/middleware/activemq.html#detailed-restrictions-with-multiple-subcollectives)
+
+
+#### `collectives`
+
+A comma-separated list (spaces OK) of [subcollectives][] this server should join.
+
+- _Default:_ `mcollective`
+- _Sample value:_ `mcollective,uk_collective`
+
+#### `main_collective`
+
+The main collective for this server. Currently, this is only used as the default value for the [`registration_collective`](#registrationcollective) setting.
+
+- _Default:_ (the first value of [the `collectives` setting](#collectives), usually `mcollective`)
+
+
+([↑ Back to top](#content))
+
+
+### Node Registration
+
+<pre><code><a href="#registerinterval">registerinterval</a> = 300
+<a href="#registration">registration</a> = agentlist
+<a href="#registrationcollective">registration_collective</a> = mcollective
+</code>
+</pre>
+
+By default, registration is disabled, due to [`registerinterval`](#registerinterval) being set to 0.
+
+Optionally, MCollective servers can [send periodic heartbeat messages][registration] containing some inventory information. This can provide a central inventory at sites that don't already use something like [PuppetDB][], and can also be used as a simple passive monitoring system.
+
+The default registration plugin, `agentlist`, sends a standard SimpleRPC command over the MCollective middleware, to be processed by some server with an agent called `registration` installed. You would need to ensure that the `registration` agent is extremely performant (due to the volume of message it will receive) and installed on a limited number of servers. If your [middleware][] supports detailed permissions, you must also ensure that it allows servers to send commands to the registration agent ([ActiveMQ instructions](/mcollective/deploy/middleware/activemq.html#detailed-restrictions)).
+
+Some registration plugins (e.g. `redis`) can insert data directly into the inventory instead of sending an RPC message. This is a flexible system, and the user is in charge of deciding what to build with it, if anything. If all you need is a searchable inventory, [PuppetDB][] is probably closer to your needs.
+
+#### `registerinterval`
+
+How long (in seconds) to wait between registration messages. Setting this to 0 disables registration.
+
+- _Default:_ `0`
+
+#### `registration`
+
+The [registration plugin][registration] to use.
+
+This plugin must be installed on the server sending the message, and will dictate what the message contains. The default `agentlist` plugin will only send a list of the installed agents. See [Registration Plugins][registration] for more details.
+
+- _Default:_ `agentlist`
+- _Allowed values:_ The name of any installed registration plugin. {{ pluginname }}
+
+#### `registration_collective`
+
+Which subcollective to send registration messages to, when using a SimpleRPC-based registration plugin.
+
+- _Default:_ (the value of [`main_collective`](#maincollective), usually `mcollective`)
+
+
+([↑ Back to top](#content))
+
+
+### Auditing
+
+<pre><code><a href="#rpcaudit">rpcaudit</a> = 1
+<a href="#rpcauditprovider">rpcauditprovider</a> = logfile
+<a href="#pluginrpcauditlogfile">plugin.rpcaudit.logfile</a> = /var/log/mcollective-audit.log
+</code>
+</pre>
+
+Optionally, MCollective can log the SimpleRPC agent commands it receives from admin users, recording both the command itself and some identifying information about the user who issued it. The caller ID of a command is determined by the [security plugin][security_plugin] being used.
+
+MCollective ships with a local logging audit plugin, called `Logfile`, which saves audit info to a local file (different from the daemon log file). Log lines look like this:
+
+    2010-12-28T17:09:03.889113+0000: reqid=319719cc475f57fda3f734136a31e19b: reqtime=1293556143 caller=cert=nagios@monitor1 agent=nrpe action=runcommand data={:process_results=>true, :command=>"check_mailq"}
+
+Tthere are central loggers available from [the plugin directory][plugin_directory], and you can also write your own audit plugins; see [Writing Auditing Plugins][auditing] for more information.
+
+
+#### `rpcaudit`
+
+Whether to enable [SimpleRPC auditing][Auditing] for all SimpleRPC agent commands.
+
+- _Default:_ `0`
+- _Allowed values:_ `1`, `0`, `y`, `n` --- {{ badbool }}
+
+#### `rpcauditprovider`
+
+The name of the audit plugin to use whenever SimpleRPC commands are received.
+
+- _Default:_ (nothing)
+- _Sample value:_ `logfile`
+- _Allowed values:_ The name of any installed audit plugin. {{ pluginname }}
+
+
+#### `plugin.rpcaudit.logfile`
+
+_When `rpcauditprovider == logfile`_
+
+The file to write to when using the `logfile` audit plugin. **Note:** this file is not automatically rotated.
+
+- _Default:_ `/var/log/mcollective-audit.log`
+
+
+([↑ Back to top](#content))
+
+
+### Authorization
+
+<pre><code><a href="#rpcauthorization">rpcauthorization</a> = 1
+<a href="#rpcauthprovider">rpcauthprovider</a> = action_policy
+</code>
+</pre>
+
+Optionally, MCollective can refuse to execute agent commands unless they meet some requirement. The exact requirement is defined by an [authorization plugin][authorization].
+
+See [SimpleRPC Authorization][authorization] for more details, including how to enable authorization for only certain agents.
+
+The [actionpolicy][] plugin, which is provided in the [plugin directory][plugin_directory], is fairly popular and seems to meet many users' needs, when combined with a [security plugin][security_plugin] that provides a verified caller ID (such as the SSL plugin). [See its documentation][actionpolicy] for details.
+
+#### `rpcauthorization`
+
+Whether to enable [SimpleRPC authorization][Authorization] globally.
+
+- _Default:_ `0`
+- _Allowed values:_ `1`, `0`, `y`, `n` --- {{ badbool }}
+
+#### `rpcauthprovider`
+
+The plugin to use when globally managing authorization. See [SimpleRPC Authorization][authorization] for more details.
+
+- _Default:_ (nothing)
+- _Sample value:_ `action_policy`
+- _Allowed values:_ The name of any installed authorization plugin. This uses different capitalization/formatting rules from the other plugin settings: if the name of the plugin (in the code) has any interior capital letters (e.g. `ActionPolicy`), you should use a lowercase value for the setting but insert an underscore before the place where the interior capital letter(s) would have gone (e.g. `action_policy`). If the name contains no interior capital letters, simply use a lowercase value with no other changes.
+
+
+([↑ Back to top](#content))
+
+
+Advanced Settings
+-----
+
+### Logging
+
+<pre><code><a href="#loggertype">logger_type</a> = file
+<a href="#loglevel">loglevel</a> = info
+<a href="#logfile">logfile</a> = /var/log/mcollective.log
+<a href="#keeplogs">keeplogs</a> = 5
+<a href="#maxlogsize">max_log_size</a> = 2097152
+<a href="#logfacility">logfacility</a> = user
+</code>
+</pre>
+
+The MCollective server daemon can log to its own log file (which it will automatically rotate), or to the syslog. It can also log directly to the console, if you are running it in the foreground instead of daemonized.
+
+Some of the settings below only apply if you are using log files, and some only apply if you are using syslog.
+
+#### `logger_type`
+
+How the MCollective server daemon should log. You generally want to use a file or syslog.
+
+- _Default:_ `file`
+- _Allowed values:_ `file`, `syslog`, `console`
+
+#### `loglevel`
+
+How verbosely to log.
+
+- _Default:_ `info`
+- _Allowed values:_ In increasing order of verbosity: `fatal`, `error` , `warn`, `info`, `debug`
+
+#### `logfile`
+
+_When `logger_type == file`_
+
+Where the log file should be stored.
+
+- _Default:_ (nothing; the package's default config file usually sets a platform-appropriate value)
+- _Sample value:_ `/var/log/mcollective.log`
+
+#### `keeplogs`
+
+_When `logger_type == file`_
+
+The number of log files to keep when rotating.
+
+- _Default:_ `5`
+
+#### `max_log_size`
+
+_When `logger_type == file`_
+
+Max size in bytes for log files before rotation happens.
+
+- _Default:_ `2097152`
+
+#### `logfacility`
+
+_When `logger_type == syslog`_
+
+The syslog facility to use.
+
+- _Default:_ `user`
+
+
+([↑ Back to top](#content))
+
+
+### Platform Defaults
+
+<pre><code><a href="#daemonize">daemonize</a> = 1
+<a href="#libdir">libdir</a> = /usr/libexec/mcollective
+<a href="#sslcipher">ssl_cipher</a> = aes-256-cbc
+</code>
+</pre>
+
+These settings generally shouldn't be changed by the user, but their values may vary by platform. The package you used to install MCollective should have created a config file with platform-appropriate values for these settings.
+
+#### `daemonize`
+
+Whether to fork and run the MCollective server daemon in the background.
+
+This depends on your platform's init system. For example, newer Ubuntu releases require this to be false, while RHEL-derived systems require it to be true.
+
+- _Default:_ `0` <!-- Actually nil but acts like false -->
+- _Allowed values:_ `1`, `0`, `y`, `n` --- {{ badbool }}
+
+#### `libdir`
+
+Where to look for plugins. Should be a single path or a list of paths separated by the {{ path_separator }}.
+
+By default, this setting is blank, but the package you installed MCollective with should supply a default server.cfg file with a platform-appropriate value for this setting. **If server.cfg has no value for this setting, MCollective will not work.**
+
+- _Default:_ (nothing; the package's default config file usually sets a platform-appropriate value)
+- _Sample value:_ `/usr/libexec/mcollective:/opt/mcollective`
+
+#### `ssl_cipher`
+
+The cipher to use for encryption. This is currently only relevant if you are using the [AES security plugin][security_aes].
+
+This setting should be a standard OpenSSL cipher string. See `man enc` for a list.
+
+- _Default:_ `aes-256-cbc`
diff --git a/website/deploy/middleware/activemq.md b/website/deploy/middleware/activemq.md
new file mode 100644 (file)
index 0000000..1396a9a
--- /dev/null
@@ -0,0 +1,694 @@
+---
+title: "MCollective » Deploy » Middleware » ActiveMQ Config"
+subtitle: "ActiveMQ Config Reference for MCollective Users"
+layout: default
+---
+
+[Wildcard]: http://activemq.apache.org/wildcards.html
+[minimal_example]: http://github.com/puppetlabs/marionette-collective/raw/master/ext/activemq/examples/single-broker/activemq.xml
+[maximal_example]: https://github.com/puppetlabs/marionette-collective/tree/master/ext/activemq/examples/multi-broker
+[template_example]: TODO
+[apache_activemq_config_docs]: http://activemq.apache.org/version-5-xml-configuration.html
+
+[subcollectives]: /reference/basic/subcollectives.html
+[activemq_connector]: /reference/plugins/connector_activemq.html
+[mcollective_connector_tls]: /mcollective/reference/integration/activemq_ssl.html
+
+
+Summary
+-----
+
+Apache ActiveMQ is the primary middleware we recommend with MCollective. It's good software, but its XML config file is large and unwieldy, and you may need to edit many sections of it in a complex MCollective deployment. This reference guide attempts to describe every major ActiveMQ setting that matters to MCollective.
+
+### How to Use This Page
+
+* This page **doesn't** describe the complete format of the activemq.xml config file, and will sometimes use incomplete shorthand to describe elements of it.
+* You should definitely refer to an example config file while reading, so you can see each element's full syntax in context.
+* You don't need to read this entire page when setting up a new deployment. We recommend that you:
+    * Start with an example config file (see directly below).
+    * Make heavy use of the table of contents above.
+    * Skim the sections of this page you currently care about, and edit your config as needed.
+    * Refer back to this page later when you need to expand your broker infrastructure.
+* If you are a new user, we recommend that you:
+    * Start with the [single-broker example config][minimal_example].
+    * Change the [user account passwords](#authentication-users-and-groups).
+    * [Set up TLS](#tls-credentials).
+
+### Example Config Files
+
+We have several. 
+
+* [Minimal config example][minimal_example] --- single broker <!-- , minimal authorization. -->
+* [Maximal config example][maximal_example] --- multi-broker <!--  with extensive authorization. -->
+
+<!-- 
+* [Template-based example][template_example] --- reduces configuration down to a handful of variables; shows how those few decisions ramify into many config edits.
+ -->
+
+
+> **Note:** Some config data needs to be set in both MCollective and ActiveMQ; your configuration of one will affect the other. In this page, we call out that information with headers labeled "Shared Configuration."
+
+### Version Limits
+
+This document is about the "new" MCollective/ActiveMQ interface, which means it requires the following:
+
+* MCollective 2.0.0 or newer
+* ActiveMQ 5.5.0 or newer
+* Stomp gem 1.2.2 or newer
+* The [activemq connector][activemq_connector] plugin (included with MCollective 2.0.0 and newer)
+
+([↑ Back to top](#content))
+
+How MCollective Uses ActiveMQ
+-----
+
+MCollective connects to ActiveMQ over the Stomp protocol, and presents certain credentials:
+
+* It provides a username and password, with which ActiveMQ can do what it pleases. 
+* If TLS is in use, it will also present a certificate (and verify the ActiveMQ server's certificate).
+
+Once allowed to connect, MCollective will use the Stomp protocol to create subscriptions. It will then produce and consume a lot of traffic on queues and topics whose names begin with `mcollective`. (See "Topic and Queue Names" directly below.)
+
+### Absolute Minimum Requirements
+
+ActiveMQ defaults to believing that it is routing traffic between processes in a single JVM instance: it doesn't assume it is connected to the network, and it uses a loose-to-nonexistent security model.
+
+This means that if you do nothing but enable Stomp traffic, MCollective will work fine. (Albeit with terrible security and eventual out-of-control memory usage.)
+
+### Topic and Queue Names
+
+MCollective uses the following destination names. This list uses standard [ActiveMQ destination wildcards][wildcard]. "COLLECTIVE" is the name of the collective being used; by default, this is `mcollective`, but if you are using [subcollectives][], each one is implemented as an equal peer of the default collective.
+
+Topics: 
+
+- `ActiveMQ.Advisory.>` (built-in topics that all ActiveMQ producers and consumers need all permissions on)
+- `COLLECTIVE.*.agent` (for each agent plugin, where the `*` is the name of the plugin)
+
+Queues:
+
+- `COLLECTIVE.nodes` (used for direct addressing; this is a single destination that uses JMS selectors, rather than a group of destinations)
+- `COLLECTIVE.reply.>` (where the continued portion is a request ID)
+
+> #### Shared Configuration
+> 
+> Subcollectives must also be configured in the MCollective client and server config files. ActiveMQ must allow traffic on any subcollective that MCollective servers and clients expect to use.
+
+([↑ Back to top](#content))
+
+Config File Location and Format
+-----
+
+ActiveMQ's config is usually called activemq.xml, and is kept in ActiveMQ's configuration directory (`/etc/activemq` with Puppet Labs's Red Hat-like packages, or a subdirectory of `/etc/activemq/instances-enabled` with the standard Debian or Ubuntu packages). Any other files referenced in activemq.xml will be looked for in the same directory.
+
+The config file is in Java's Beans XML format. Note that all of the settings relevant to MCollective are located inside activemq.xml's `<broker>` element. 
+
+This document won't describe the complete format of the activemq.xml config file, and will sometimes use incomplete shorthand to describe elements of it. You should definitely [refer to an example config file](#example-config-files) while reading, so you can see each element's full syntax in context.
+
+You can also read external documentation for a more complete understanding.
+
+> **Bug Warning:** In ActiveMQ 5.5, the first-level children of the `<broker>` element must be arranged in alphabetical order. There is no good reason for this behavior, and it was fixed in ActiveMQ 5.6.
+
+### External ActiveMQ Documentation
+
+The Apache ActiveMQ documentation contains important information, but it is often incomplete, badly organized, and confusing. The Fuse documentation (a commercially supported release of ActiveMQ) is significantly better written and better organized, although it requires signing up for an email newsletter, but it may be out of sync with the most recent ActiveMQ releases.
+
+* [Apache ActiveMQ Documentation][apache_activemq_config_docs]
+* [Fuse Documentation](http://fusesource.com/documentation/fuse-message-broker-documentation/)
+
+### Wildcards
+
+You'll see a lot of [ActiveMQ destination wildcards][wildcard] below. In short:
+
+* Segments in a destination name are separated with dots (`.`)
+* A `*` represents _one segment_ (i.e. any sequence of non-dot characters)
+* A `>` represents _the whole rest of the name_ after a prefix
+
+
+([↑ Back to top](#content))
+
+Required Settings
+-----
+
+One way or another, you must set all of the following.
+
+### Transport Connector(s)
+
+It's generally best to only enable the transport connectors you need. For example, if you're using Stomp over TLS, don't leave a bare Stomp transport open. If you're not using a network of brokers, close the OpenWire transport.
+
+The `name` attribute of a transport connector doesn't seem to matter as long as it's locally unique.
+
+#### Stomp
+
+ActiveMQ must listen over the network for Stomp connections; otherwise, MCollective can't reach it. Enable this with a `<transportConnector>` element inside the `<transportConnectors>` element. We generally recommend using TLS.
+
+{% highlight xml %}
+    <transportConnectors>
+      <transportConnector name="stomp+nio" uri="stomp+nio://0.0.0.0:61613"/>
+    </transportConnectors>
+{% endhighlight %}
+
+* Note that the protocol/port/arguments for Stomp URIs can differ:
+    * Unencrypted: `stomp+nio://0.0.0.0:61613`
+    * CA-verified TLS: `stomp+ssl://0.0.0.0:61614?needClientAuth=true`
+    * Anonymous TLS: `stomp+ssl://0.0.0.0:61614`
+* You can choose to restrict the interface/hostname to use instead of listening on `0.0.0.0`.
+
+> **If you are using TLS,** note that you must also:
+> 
+> * [Configure ActiveMQ's TLS credentials](#tls-credentials) (see below)
+> * [Configure MCollective to use TLS credentials][mcollective_connector_tls]
+
+#### OpenWire
+
+If you are using a network of brokers instead of just one ActiveMQ server, they talk to each other over OpenWire, and will all need a transport connector for that protocol too:
+
+{% highlight xml %}
+    <transportConnector name="openwire+ssl" uri="ssl://0.0.0.0:61617?needClientAuth=true"/>
+{% endhighlight %}
+
+* Note that the protocol/port/arguments for OpenWire URIs can differ:
+    * Unencrypted: `tcp://0.0.0.0:61616`
+    * CA-verified TLS: `ssl://0.0.0.0:61617?needClientAuth=true`
+    * Anonymous TLS: `ssl://0.0.0.0:61617`
+* You can choose to restrict the interface/hostname to use instead of listening on `0.0.0.0`.
+
+
+
+#### Standard Ports for Stomp and OpenWire
+
+Alas, there aren't any; just a rough consensus.
+
+* 61613 for unencrypted Stomp
+* 61614 for Stomp with TLS
+* 61616 for unencrypted OpenWire
+* 61617 for OpenWire with TLS
+
+All of our documentation assumes these ports.
+
+> #### Shared Configuration
+> 
+> MCollective needs to know the following:
+> 
+> * The port to use for Stomp traffic
+> * The hostname or IP address to reach ActiveMQ at
+> * Whether to use TLS
+> 
+> In a network of brokers, the other ActiveMQ servers need to know the following:
+> 
+> * The port to use for OpenWire traffic
+> * The hostname or IP address to reach peer ActiveMQ servers at
+> * Whether to use TLS
+
+
+### Reply Queue Pruning
+
+MCollective sends replies on uniquely-named, single-use queues with names like `mcollective.reply.<UNIQUE ID>`. These have to be deleted after about five minutes, lest they clog up ActiveMQ's available memory. By default, queues live forever, so you have to configure this.
+
+Use a `<policyEntry>` element for `*.reply.>` queues, with `gcInactiveDestinations` set to true and `inactiveTimoutBeforeGC` set to 300000 ms (five minutes). 
+
+{% highlight xml %}
+    <destinationPolicy>
+      <policyMap>
+        <policyEntries>
+          <policyEntry queue="*.reply.>" gcInactiveDestinations="true" inactiveTimoutBeforeGC="300000" />
+          <policyEntry topic=">" producerFlowControl="false"/>
+        </policyEntries>
+      </policyMap>
+    </destinationPolicy>
+{% endhighlight %}
+
+### Disable Producer Flow Control on Topics
+
+In the example above, you can also see that `producerFlowControl` is set to false for all topics. This is highly recommended; setting it to true can cause MCollective servers to appear blocked when there's heavy traffic.
+
+
+([↑ Back to top](#content))
+
+Recommended Settings
+-----
+
+### TLS Credentials
+
+If you are using TLS in either your Stomp or OpenWire [transport connectors](#transport-connectors), ActiveMQ needs a keystore file, a truststore file, and a password for each:
+
+{% highlight xml %}
+    <sslContext>
+      <sslContext
+         keyStore="keystore.jks" keyStorePassword="secret"
+         trustStore="truststore.jks" trustStorePassword="secret"
+      />
+    </sslContext>
+{% endhighlight %}
+
+**Note:** This example is for CA-verified TLS. If you are using anonymous TLS, you may optionally skip the truststore attributes.
+
+The redundant nested `<sslContext>` elements are not a typo; for some reason ActiveMQ actually needs this.
+
+ActiveMQ will expect to find these files in the same directory as activemq.xml.
+
+> #### Creating a Keystore and Truststore
+> 
+> There is a [separate guide that covers how to create keystores.][activemq_keystores]
+
+[activemq_keystores]: ./activemq_keystores.html
+
+
+### Authentication (Users and Groups)
+
+When they connect, MCollective clients and servers provide a username, password, and optionally an SSL certificate. ActiveMQ can use any of these to authenticate them. 
+
+By default, ActiveMQ ignores all of these and has no particular concept of "users." Enabling authentication means ActiveMQ will only allow users with proper credentials to connect. It also gives you the option of setting up per-destination authorization (see below). 
+
+You set up authentication by adding the appropriate element to the `<plugins>` element. [The Fuse documentation has a more complete description of ActiveMQ's authentication capabilities;][fuse_security] the [ActiveMQ docs version][activemq_security] is less organized and less complete. In summary:
+
+- `simpleAuthenticationPlugin` defines users directly in activemq.xml. It's well-tested and easy. It also requires you to edit activemq.xml and restart the broker every time you add a new user. The activemq.xml file will contain sensitive passwords and must be protected.
+- `jaasAuthenticationPlugin` lets you use external text files (or even an LDAP database) to define users and groups. You need to make a `login.config` file in the ActiveMQ config directory, and possibly two more files. You can add users and groups without restarting the broker. The external users file will contain sensitive passwords and must be protected.
+- `jaasCertificateAuthenticationPlugin` ignores the username and password that MCollective presents; instead, it reads the distinguished name of the certificate and maps that to a username. It requires TLS, a `login.config` file, and two other external files. It is also impractical unless your servers are all using the same SSL certificate to connect to ActiveMQ; the currently recommended approach of re-using Puppet certificates makes this problematic, but you can probably ship credentials around and figure out a way to make it work. This is not currently well-tested with MCollective.
+
+[fuse_security]: http://fusesource.com/docs/broker/5.5/security/front.html
+[activemq_security]: http://activemq.apache.org/security.html
+
+The example below uses `simpleAuthenticationPlugin`.
+
+{% highlight xml %}
+    <plugins>
+      <simpleAuthenticationPlugin>
+        <users>
+          <authenticationUser username="mcollective" password="marionette" groups="mcollective,everyone"/>
+          <authenticationUser username="admin" password="secret" groups="mcollective,admins,everyone"/>
+        </users>
+      </simpleAuthenticationPlugin>
+      <!-- ... authorization goes below... -->
+    </plugins>
+{% endhighlight %}
+
+This creates two users, with the expectation that MCollective servers will log in as `mcollective` and admin users issuing commands will log in as `admin`. 
+
+Note that unless you set up authorization (see below), these users have the exact same capabilities. 
+
+> #### Shared Configuration
+> 
+> MCollective servers and clients both need a username and password to use when connecting. That user **must** have appropriate permissions (see "Authorization," directly below) for that server or client's role. 
+
+
+
+### Authorization (Group Permissions)
+
+By default, ActiveMQ allows everyone to **read** from any topic or queue, **write** to any topic or queue, and create (**admin**) any topic or queue. 
+
+By setting rules in an `<authorizationPlugin>` element, you can regulate things a bit. Some notes:
+
+* Authorization is done **by group.**
+* The exact behavior of authorization doesn't seem to be documented anywhere. Going by observation, it appears that ActiveMQ first tries the most specific rule available, then retreats to less specific rules. This means if a given group isn't allowed an action by a more specific rule but is allowed it by a more general rule, it still gets authorized to take that action. If you have any solid information about how this works, please email us at <faq@puppetlabs.com>.
+* MCollective creates subscriptions before it knows whether there will be any content coming. That means any role able to **read** from or **write** to a destination must also be able to **admin** that destination. Think of "admin" as a superset of both read and write.
+
+#### Simple Restrictions
+
+The following example grants all permissions on destinations beginning with `mcollective` to everyone in group `mcollective`:
+
+{% highlight xml %}
+    <plugins>
+      <!-- ...authentication stuff... -->
+      <authorizationPlugin>
+        <map>
+          <authorizationMap>
+            <authorizationEntries>
+              <authorizationEntry queue=">" write="admins" read="admins" admin="admins" />
+              <authorizationEntry topic=">" write="admins" read="admins" admin="admins" />
+              <authorizationEntry topic="mcollective.>" write="mcollective" read="mcollective" admin="mcollective" />
+              <authorizationEntry queue="mcollective.>" write="mcollective" read="mcollective" admin="mcollective" />
+              <authorizationEntry topic="ActiveMQ.Advisory.>" read="everyone" write="everyone" admin="everyone"/>
+            </authorizationEntries>
+          </authorizationMap>
+        </map>
+      </authorizationPlugin>
+    </plugins>
+{% endhighlight %}
+
+This means admins can issue commands and MCollective servers can read those commands and reply. However, it also means that servers can issue commands, which you probably don't want.
+
+Note that the `everyone` group (as seen in the `ActiveMQ.Advisory.>` topics) **isn't special.** You need to manually make sure all users are members of it. ActiveMQ does not appear to have any kind of real wildcard "everyone" group, unfortunately.
+
+#### Detailed Restrictions
+
+The following example splits permissions along a simple user/server model:
+
+{% highlight xml %}
+    <plugins>
+      <!-- ...authentication stuff... -->
+      <authorizationPlugin>
+        <map>
+          <authorizationMap>
+            <authorizationEntries>
+              <authorizationEntry queue=">" write="admins" read="admins" admin="admins" />
+              <authorizationEntry topic=">" write="admins" read="admins" admin="admins" />
+              <authorizationEntry queue="mcollective.>" write="admins" read="admins" admin="admins" />
+              <authorizationEntry topic="mcollective.>" write="admins" read="admins" admin="admins" />
+              <authorizationEntry queue="mcollective.nodes" read="mcollective" admin="mcollective" />
+              <authorizationEntry queue="mcollective.reply.>" write="mcollective" admin="mcollective" />
+              <authorizationEntry topic="mcollective.*.agent" read="mcollective" admin="mcollective" />
+              <authorizationEntry topic="mcollective.registration.agent" write="mcollective" read="mcollective" admin="mcollective" />
+              <authorizationEntry topic="ActiveMQ.Advisory.>" read="everyone" write="everyone" admin="everyone"/>
+            </authorizationEntries>
+          </authorizationMap>
+        </map>
+      </authorizationPlugin>
+    </plugins>
+{% endhighlight %}
+
+This means admins can issue commands and MCollective servers can read those commands and reply. This time, though, servers can't issue commands. The exception is the `mcollective.registration.agent` destination, which servers DO need the ability to write to if you've turned on registration. 
+
+Admins, of course, can also read commands and reply, since they have power over the entire `mcollective.>` destination set. This isn't considered much of an additional security risk, considering that admins can already control your entire infrastructure.
+
+#### Detailed Restrictions with Multiple Subcollectives
+
+Both of the above examples assume only a single `mcollective` collective. If you are using additional [subcollectives][] (e.g. `uk_collective`, `us_collective`, etc.), their destinations will start with their name instead of `mcollective`. If you need to separately control authorization for each collective, it's best to use a template to do so, so you can avoid repeating yourself. 
+
+{% highlight xml %}
+    <plugins>
+      <!-- ...authentication stuff... -->
+      <authorizationPlugin>
+        <map>
+          <authorizationMap>
+            <authorizationEntries>
+              <!-- "admins" group can do anything. -->
+              <authorizationEntry queue=">" write="admins" read="admins" admin="admins" />
+              <authorizationEntry topic=">" write="admins" read="admins" admin="admins" />
+
+              <%- @collectives.each do |collective| -%>
+              <authorizationEntry queue="<%= collective %>.>" write="admins,<%= collective %>-admins" read="admins,<%= collective %>-admins" admin="admins,<%= collective %>-admins" />
+              <authorizationEntry topic="<%= collective %>.>" write="admins,<%= collective %>-admins" read="admins,<%= collective %>-admins" admin="admins,<%= collective %>-admins" />
+              <authorizationEntry queue="<%= collective %>.nodes" read="servers,<%= collective %>-servers" admin="servers,<%= collective %>-servers" />
+              <authorizationEntry queue="<%= collective %>.reply.>" write="servers,<%= collective %>-servers" admin="servers,<%= collective %>-servers" />
+              <authorizationEntry topic="<%= collective %>.*.agent" read="servers,<%= collective %>-servers" admin="servers,<%= collective %>-servers" />
+              <authorizationEntry topic="<%= collective %>.registration.agent" write="servers,<%= collective %>-servers" read="servers,<%= collective %>-servers" admin="servers,<%= collective %>-servers" />
+              <%- end -%>
+
+              <authorizationEntry topic="ActiveMQ.Advisory.>" read="everyone" write="everyone" admin="everyone"/>
+            </authorizationEntries>
+          </authorizationMap>
+        </map>
+      </authorizationPlugin>
+    </plugins>
+{% endhighlight %}
+
+This example divides your users into several groups:
+
+* `admins` is the "super-admins" group, who can command all servers.
+* `servers` is the "super-servers" group, who can receive and respond to commands on any collective they believe themselves to be members of.
+* `COLLECTIVE-admins` can only command servers on their specific collective. (Since all servers are probably members of the default `mcollective` collective, the `mcollective-admins` group are sort of the "almost-super-admins.")
+* `COLLECTIVE-servers` can only receive and respond to commands on their specific collective.
+
+Thus, when you define your users in the [authentication setup](#authentication-users-and-groups), you could allow a certain user to command both the EU and UK collectives (but not the US collective) with `groups="eu_collective-admins,uk_collective-admins"`. You would probably want most servers to be "super-servers," since each server already gets to choose which collectives to ignore.
+
+#### MCollective's Exact Authorization Requirements
+
+As described above, any user able to read OR write on a destination must also be able to admin that destination. 
+
+Topics: 
+
+- `ActiveMQ.Advisory.>` --- Everyone must be able to read and write. 
+- `COLLECTIVE.*.agent` --- Admin users must be able to write. Servers must be able to read. 
+- `COLLECTIVE.registration.agent` --- If you're using registration, servers must be able to read and write. Otherwise, it can be ignored.
+
+Queues:
+
+- `COLLECTIVE.nodes` --- Admin users must be able to write. Servers must be able to read.
+- `COLLECTIVE.reply.>` --- Servers must be able to write. Admin users must be able to read.
+
+
+> #### Shared Configuration
+> 
+> Subcollectives must also be configured in the MCollective client and server config files. If you're setting up authorization per-subcollective, ActiveMQ must allow traffic on any subcollective that MCollective servers and clients expect to use.
+
+
+([↑ Back to top](#content))
+
+Settings for Networks of Brokers
+-----
+
+You can group multiple ActiveMQ servers into networks of brokers, and they can route local MCollective traffic amongst themselves. There are a lot of reasons to do this:
+
+* Scale --- we recommend a maximum of about 800 MCollective servers per ActiveMQ broker, and multiple brokers let you expand past this.
+* High availability --- MCollective servers and clients can attempt to connect to mupltiple brokers in a failover pool.
+* Partition resilience --- if an inter-datacenter link goes down, each half's local MCollective system will still work fine.
+* Network isolation and traffic limiting --- if your clients default to only sending messages to local machines, you can get better performance in the most common case while still being able to command a global collective when you need to. 
+* Security --- destination filtering can prevent certain users from sending requests to certain datacenters.
+
+This is naturally more complicated than configuring a single broker.
+
+Designing your broker network's topology is beyond the scope of this reference. The [ActiveMQ Clusters guide](/mcollective/reference/integration/activemq_clusters.html) has a brief description of an example network; see [the ActiveMQ docs][NetworksOfBrokers] or [the Fuse docs][fuse_cluster] for more detailed info. For our purposes, we assume you have already decided:
+
+* Which ActiveMQ brokers can communicate with each other.
+* What kinds of traffic should be excluded from other brokers.
+
+[NetworksOfBrokers]: http://activemq.apache.org/networks-of-brokers.html
+[fuse_cluster]: http://fusesource.com/docs/broker/5.5/clustering/index.html
+
+
+### Broker Name
+
+_Required._
+
+The main `<broker>` element has a `brokerName` attribute. In single-broker deployments, this can be anything and defaults to `localhost`. In a network of brokers, each broker's name must be globally unique across the deployment; duplicates can cause message loops.
+
+{% highlight xml %}
+    <broker xmlns="http://activemq.apache.org/schema/core" brokerName="uk-datacenter-broker" dataDirectory="${activemq.base}/data" destroyApplicationContextOnStop="true">
+{% endhighlight %}
+
+### OpenWire Transports
+
+_Required._
+
+All participants in a network of brokers need OpenWire network transports enabled. [See "Transport Connectors" above](#transport-connectors) for details.
+
+### Network Connectors
+
+_Required._
+
+If you are using a network of brokers, you need to configure which brokers can talk to each other. 
+
+On **one** broker in each linked pair, set up **two** bi-directional network connectors: one for topics, and one for queues. (The only difference between them is the `conduitSubscriptions` attribute, which must be false for the queue connector.)  
+
+This is done with a pair of `<networkConnector>` elements inside the `<networkConnectors>` element. Note that the queues connector excludes topics and vice-versa.
+
+{% highlight xml %}
+    <networkConnectors>
+      <networkConnector
+        name="stomp1-stomp2-topics"
+        uri="static:(tcp://stomp2.example.com:61616)"
+        userName="amq"
+        password="secret"
+        duplex="true"
+        decreaseNetworkConsumerPriority="true"
+        networkTTL="2"
+        dynamicOnly="true">
+        <excludedDestinations>
+          <queue physicalName=">" />
+        </excludedDestinations>
+      </networkConnector>
+      <networkConnector
+        name="stomp1-stomp2-queues"
+        uri="static:(tcp://stomp2.example.com:61616)"
+        userName="amq"
+        password="secret"
+        duplex="true"
+        decreaseNetworkConsumerPriority="true"
+        networkTTL="2"
+        dynamicOnly="true"
+        conduitSubscriptions="false">
+        <excludedDestinations>
+          <topic physicalName=">" />
+        </excludedDestinations>
+      </networkConnector>
+    </networkConnectors>
+{% endhighlight %}
+
+Notes: 
+
+* If you're using TLS for OpenWire, you'll need to change the URIs to something like `static:(ssl://stomp2.example.com:61617)` --- note the change of both protocol and port. 
+* You will need to adjust the TTL for your network's conditions.
+* A username and password are required. The broker with the `<networkConnector>` connects to the other broker as this user. This user should have **full rights** on **all** queues and topics, unless you really know what you're doing. (See [authentication](#authentication-users-and-groups) and [authorization](#authorization-group-permissions) above.)
+* The `name` attribute on each connector must be globally unique. Easiest way to do that is to combine the pair of hostnames involved with the word "queues" or "topics."
+* Alternately, you can set up two uni-directional connectors on both brokers; see the Fuse or ActiveMQ documentation linked above for more details. 
+
+
+### Destination Filtering
+
+[fuse_filtering]: http://fusesource.com/docs/broker/5.5/clustering/Networks-Filtering.html
+
+_Optional._
+
+Relevant external docs:
+
+* [Fuse filtering guide][fuse_filtering]
+
+If you want to prevent certain traffic from leaving a given datacenter, you can do so with `<excludedDestinations>` or `<dynamicallyIncludedDestinations>` elements **inside each `<networkConnector>` element.** This is mostly useful for noise reduction, by blocking traffic that other datacenters don't care about, but it can also serve security purposes. Generally, you'll be filtering on [subcollectives][], which, as described above, begin their destination names with the name of the collective.
+
+Both types of filter element can contain `<queue>` and `<topic>` elements, with their `physicalName` attributes defining a destination name with the normal wildcards.
+
+**Remember to retain the all-queues/all-topics exclusions as [shown above](#network-connectors).**
+
+#### Examples
+
+Assume a star network topology. 
+
+This topology can be achieved by either having each edge broker connect to the central broker, or having the central broker connect to each edge broker. You can achieve the same filtering in both situations, but with slightly different configuration. The two examples below have similar but not identical effects; the ramifications are subtle, and we _really_ recommend reading the external ActiveMQ and Fuse documentation if you've come this far in your deployment scale.
+
+If your central broker is connecting to the UK broker, and you want it to only pass on traffic for the global `mcollective` collective and the UK-specific `uk_collective` collective:
+
+{% highlight xml %}
+    <dynamicallyIncludedDestinations>
+      <topic physicalName="mcollective.>" />
+      <queue physicalName="mcollective.>" />
+      <topic physicalName="uk_collective.>" />
+      <queue physicalName="uk_collective.>" />
+    </dynamicallyIncludedDestinations>
+{% endhighlight %}
+
+In this case, admin users connected to the central broker can command nodes on the `uk_collective`, but admin users connected to the UK broker can't command nodes on the `us_collective`, etc. 
+
+Alternately, if your UK broker is connecting to your central broker and you want it to refrain from passing on UK-specific traffic that no one outside that datacenter cares about:
+
+{% highlight xml %}
+    <excludedDestinations>
+       <topic physicalName="uk_collective.>" />
+       <queue physicalName="uk_collective.>" />
+    </excludedDestinations>
+{% endhighlight %}
+
+In this case, admin users connected to the central broker **cannot** command nodes on the `uk_collective`; it's expected that they'll be issuing commands to the main `mcollective` collective if they need to (and are authorized to) cross outside their borders. 
+
+([↑ Back to top](#content))
+
+Tuning
+-----
+
+The minor adjustments listed below (turn off dedicated task runner, increase heap, and increase memory and temp usage in activemq.xml) will generally let you reach about 800 MCollective nodes connected to a single ActiveMQ server, depending on traffic and usage patterns, number of topics and queues, etc. Any more detailed tuning is beyond the scope of this reference, and is likely to be unnecessary for your deployment. 
+
+### Don't Use Dedicated Task Runner
+
+Set `-Dorg.apache.activemq.UseDedicatedTaskRunner=false` when starting ActiveMQ. MCollective creates a lot of queues and topics, so _not_ using a thread per destination will save you a lot of memory usage.
+
+This setting is **not** configured in activemq.xml; it's an extra argument to the JVM, which should be provided when ActiveMQ starts up. The place to put this varies, depending on the package you installed ActiveMQ with; it usually goes in the wrapper config file. Check your init script for clues about this file's location. With the common TanukiWrapper scripts, it would look something like this:
+
+    wrapper.java.additional.4=-Dorg.apache.activemq.UseDedicatedTaskRunner=false
+
+### Increase JVM Heap if Necessary
+
+Likewise, the max heap is usually configured in the wrapper config file (`wrapper.java.maxmemory=512`) or on the command line (`-Xmx512m`).
+
+### Memory and Temp Usage for Messages (`systemUsage`)
+
+Since ActiveMQ expects to be embedded in another JVM application, it won't automatically fill up the heap with messages; it has extra limitations on how much space to take up with message contents. 
+
+As your deployment gets bigger, you may need to increase the `<memaryUsage>` and `<tempUsage>` elements in the `<systemUsage>` element. Unfortunately, we lack a lot of solid data for what to actually set these to. Most users leave the defaults for memory and temp until they have problems, then double the defaults and see whether their problems go away. This isn't perfectly effecient, but anecdotally it appears to work.
+
+The many redundant nested elements are not a typo; for some reason, ActiveMQ seems to require this.
+
+{% highlight xml %}
+    <!--
+      The systemUsage controls the maximum amount of space the broker will 
+      use for messages.
+
+      - memoryUsage is the amount of memory ActiveMQ will take up with
+        *actual messages;* it doesn't include things like thread management.
+      - tempUsage is the amount of disk space it will use for stashing
+        non-persisted messages if the memoryUsage is exceeded (e.g. in the
+        event of a sudden flood of messages).
+      - storeUsage is the amount of disk space dedicated to persistent
+        messages (which MCollective doesn't use directly, but which may be
+        used in networks of brokers to avoid duplicates).           
+
+      If producer flow control is on, ActiveMQ will slow down producers
+      when any limits are reached; otherwise, it will use up the
+      memoryUsage, overflow into tempUsage (assuming the default cursor
+      settings aren't changed), and start failing message deliveries after
+      tempUsage is spent. In MCollective, the latter behavior is generally
+      preferable. For more information, see:
+
+      http://activemq.apache.org/producer-flow-control.html
+      http://activemq.apache.org/javalangoutofmemory.html
+    -->
+    <systemUsage>
+        <systemUsage>
+            <memoryUsage>
+                <memoryUsage limit="20 mb"/>
+            </memoryUsage>
+            <storeUsage>
+                <storeUsage limit="1 gb"/>
+            </storeUsage>
+            <tempUsage>
+                <tempUsage limit="100 mb"/>
+            </tempUsage>
+        </systemUsage>
+    </systemUsage>
+{% endhighlight %}
+
+
+([↑ Back to top](#content))
+
+Boilerplate
+-----
+
+There's little reason to care about these settings in most conditions, but they're in the example config files anyway.
+
+### Persistence
+
+MCollective rarely uses this. It's only necessary in networks of brokers, where it is used to prevent routing loops. Leave it enabled; it has no notable performance penalty and its disk usage is limited by the `<storeUsage>` element described above.
+
+{% highlight xml %}
+    <persistenceAdapter>
+      <kahaDB directory="${activemq.base}/data/kahadb"/>
+    </persistenceAdapter>
+{% endhighlight %}
+### Management Context
+
+This is for monitoring. MCollective doesn't use this and the examples have it turned off, but you may want it for your own purposes.
+
+{% highlight xml %}
+    <!-- 
+      The managementContext is used to configure how ActiveMQ is exposed in 
+      JMX. By default, ActiveMQ uses the MBean server that is started by 
+      the JVM. For more information, see: 
+    
+      http://activemq.apache.org/jmx.html 
+    -->
+
+    <managementContext>
+      <managementContext createConnector="false"/>
+    </managementContext>
+{% endhighlight %}
+
+### Statistics Broker
+
+MCollective doesn't use this.
+
+{% highlight xml %}
+    <plugins>
+      <!--
+        Enable the statisticsBrokerPlugin to allow ActiveMQ to collect
+        statistics.
+      -->
+      <statisticsBrokerPlugin/>
+      <!-- ...auth, etc... -->
+    </plugins>
+{% endhighlight %}
+
+
+### Jetty (Web Consoles, APIs, etc.)
+
+The activemq.xml file will often either contain Jetty settings or import them from another file. MCollective doesn't use this. If you're not using it to manage ActiveMQ, leaving it enabled may be a security risk. Note that this configuration is **outside** the `<broker>` element. 
+
+{% highlight xml %}
+    <!-- 
+      Enable web consoles, REST and Ajax APIs and demos
+      It also includes Camel (with its web console), see ${ACTIVEMQ_HOME}/conf/camel.xml for more info
+        
+      Take a look at ${ACTIVEMQ_HOME}/conf/jetty.xml for more details 
+    -->
+    <import resource="jetty.xml"/>
+{% endhighlight %}
+
+([↑ Back to top](#content))
diff --git a/website/deploy/middleware/activemq_keystores.md b/website/deploy/middleware/activemq_keystores.md
new file mode 100644 (file)
index 0000000..0d7ad05
--- /dev/null
@@ -0,0 +1,273 @@
+---
+title: "MCollective » Deploy » Middleware » ActiveMQ Keystores"
+subtitle: "Setting Up Keystores For ActiveMQ"
+layout: default
+---
+
+[tls]: ./activemq.html#tls-credentials
+
+Since ActiveMQ runs on the JVM, [configuring it to use TLS encryption/authentication][tls] requires a pair of Java keystores; it can't just use the normal PEM format certificates and keys used by Puppet and MCollective. 
+
+Java keystores require some non-obvious steps to set up, so this guide provides full instructions, including both a [manual method](#manually-creating-keystores) and a [Puppet method](#creating-keystores-with-puppet).
+
+
+## Step 0: Obtain Certificates and Keys
+
+ActiveMQ needs the following credentials:
+
+* A copy of the site's CA certificate
+* A certificate signed by the site's CA
+* A private key to match its certificate
+
+These can come from anywhere, but the CA has to match the one used by MCollective. 
+
+The easiest approach is to re-use your site's Puppet cert infrastructure, since it's already everywhere and has tools for issuing and signing arbitrary certificates.
+
+As ever, remember to **protect the private key.**
+
+### Option A: Re-Use the Node's Puppet Agent Certificate
+
+On your ActiveMQ server:
+
+* Locate the ssldir by running `sudo puppet agent --configprint ssldir`.
+* Copy the following files to your working directory, making sure to give unique names to the cert and private key:
+    * `<ssldir>/certs/ca.pem`
+    * `<ssldir>/certs/<node name>.pem`
+    * `<ssldir>/private_keys/<node name>.pem`
+
+### Option B: Get a New Certificate from the Puppet CA
+
+On your CA puppet master:
+
+* Run `sudo puppet cert generate activemq.example.com`, substituting some name for your ActiveMQ server. Unlike with a puppet master, the cert's common name can be anything; it doesn't have to be the node's hostname or FQDN.
+* Locate the ssldir by running `sudo puppet master --configprint ssldir`.
+* Retrieve the following files and copy them to a working directory on your ActiveMQ server, making sure to give unique names to the cert and private key:
+    * `<ssldir>/certs/ca.pem`
+    * `<ssldir>/certs/activemq.example.com.pem`
+    * `<ssldir>/private_keys/activemq.example.com.pem`
+
+### Option C: Do Whatever You Want
+
+If you have some other CA infrastructure, you can use that instead.
+
+You can now:
+
+* [Manually create the keystores](#manually-creating-keystores)
+* [Use Puppet to create the keystores](#creating-keystores-with-puppet)
+
+## Manually Creating Keystores
+
+We need a **"truststore"** and a **"keystore."** We also need a **password** for each. (You can use the same password for both stores.)
+
+Remember the password(s) for later, because it needs to [go in the activemq.xml file][tls]. 
+
+### Step 1: Truststore
+
+> **Note:** The truststore is only required for CA-verified TLS. If you are using anonymous TLS, you may skip it.
+
+The truststore determines which certificates are allowed to connect to ActiveMQ. If you import a CA cert into it, ActiveMQ will trust any certificate signed by that CA.
+
+> You could also _not_ import a CA, and instead import every individual certificate you want to allow. If you do that, you're on your own, but the commands should be similar.
+
+In the working directory with your PEM-format credentials, run the following command. Replace `ca.pem` with whatever you named your copy of the CA cert, and use the password when requested.
+
+{% highlight console %}
+$ sudo keytool -import -alias "My CA" -file ca.pem -keystore truststore.jks
+Enter keystore password:
+Re-enter new password:
+.
+.
+.
+Trust this certificate? [no]:  y
+Certificate was added to keystore
+{% endhighlight %}
+
+The truststore is now done.
+
+If you want, you can compare fingerprints:
+
+{% highlight console %}
+$ sudo keytool -list -keystore truststore.jks
+Enter keystore password:
+
+Keystore type: JKS
+Keystore provider: SUN
+
+Your keystore contains 1 entry
+
+my ca, Mar 30, 2012, trustedCertEntry,
+Certificate fingerprint (MD5): 99:D3:28:6B:37:13:7A:A2:B8:73:75:4A:31:78:0B:68
+
+$ sudo openssl x509 -in ca.pem -fingerprint -md5
+MD5 Fingerprint=99:D3:28:6B:37:13:7A:A2:B8:73:75:4A:31:78:0B:68
+{% endhighlight %}
+
+
+### Step 2: Keystore
+
+The keystore contains the ActiveMQ broker's certificate and private key, which it uses to identify itself to the applications that connect to it.
+
+In the working directory with your PEM-format credentials, run the following commands. Substitute the names of your key and certificate files where necessary, and the common name of your ActiveMQ server's certificate for `activemq.example.com`.
+
+These commands use both an "export/source" password and a "destination" password. The export/source password is never used again after this series of commands.
+
+{% highlight console %}
+$ sudo cat activemq_private.pem activemq_cert.pem > temp.pem
+$ sudo openssl pkcs12 -export -in temp.pem -out activemq.p12 -name activemq.example.com
+Enter Export Password:
+Verifying - Enter Export Password:
+$sudo keytool -importkeystore  -destkeystore keystore.jks -srckeystore activemq.p12 -srcstoretype PKCS12 -alias activemq.example.com
+Enter destination keystore password:
+Re-enter new password:
+Enter source keystore password:
+{% endhighlight %}
+
+The keystore is now done.
+
+If you want, you can compare fingerprints:
+
+{% highlight console %}
+$ sudo keytool -list -keystore keystore.jks
+Enter keystore password:
+
+Keystore type: JKS
+Keystore provider: SUN
+
+Your keystore contains 1 entry
+
+activemq.example.com, Mar 30, 2012, PrivateKeyEntry,
+Certificate fingerprint (MD5): 7E:2A:B4:4D:1E:6D:D1:70:A9:E7:20:0D:9D:41:F3:B9
+
+$ sudo openssl x509 -in activemq_cert.pem -fingerprint -md5
+MD5 Fingerprint=7E:2A:B4:4D:1E:6D:D1:70:A9:E7:20:0D:9D:41:F3:B9
+{% endhighlight %}
+
+### Step 3: Finish
+
+Move the keystore and truststore to ActiveMQ's config directory. Make sure they are owned by the ActiveMQ user and unreadable to any other users. [Configure ActiveMQ to use them in its `sslContext`.][tls] **Double-check** that you've made activemq.xml world-unreadable, since it now contains sensitive credentials.
+
+## Creating Keystores with Puppet
+
+If you're managing your ActiveMQ server with Puppet anyway, you can use the [puppetlabs/java_ks module](http://forge.puppetlabs.com/puppetlabs/java_ks) to handle the format conversion.
+
+This approach is more work for a single permanent ActiveMQ server, but less work if you intend to deploy multiple ActiveMQ servers or eventually change the credentials.
+
+### Step 1: Install the `java_ks` Module
+
+On your puppet master, run `sudo puppet module install puppetlabs/java_ks`.
+
+### Step 2: Create a Puppet Class
+
+The class to manage the keystores should do the following:
+
+* Make sure the PEM cert and key files are present and protected.
+* Declare a pair of `java_ks` resources.
+* Manage the mode and ownership of the keystore files.
+
+The code below is an example, but it will work fine if you put it in a module (example file location in the first comment) and set its parameters when you declare it. The name of the class (and its home module) can be changed as needed.
+
+
+{% highlight ruby %}
+    # /etc/puppet/modules/activemq/manifests/keystores.pp
+    class activemq::keystores (
+      $keystore_password, # required
+
+      # User must put these files in the module, or provide other URLs
+      $ca = 'puppet:///modules/activemq/ca.pem',
+      $cert = 'puppet:///modules/activemq/cert.pem',
+      $private_key = 'puppet:///modules/activemq/private_key.pem',
+
+      $activemq_confdir = '/etc/activemq',
+      $activemq_user = 'activemq',
+    ) {
+
+      # ----- Restart ActiveMQ if the SSL credentials ever change       -----
+      # ----- Uncomment if you are fully managing ActiveMQ with Puppet. -----
+
+      # Package['activemq'] -> Class[$title]
+      # Java_ks['activemq_cert:keystore'] ~> Service['activemq']
+      # Java_ks['activemq_ca:truststore'] ~> Service['activemq']
+
+
+      # ----- Manage PEM files -----
+
+      File {
+        owner => root,
+        group => root,
+        mode  => 0600,
+      }
+      file {"${activemq_confdir}/ssl_credentials":
+        ensure => directory,
+        mode   => 0700,
+      }
+      file {"${activemq_confdir}/ssl_credentials/activemq_certificate.pem":
+        ensure => file,
+        source => $cert,
+      }
+      file {"${activemq_confdir}/ssl_credentials/activemq_private.pem":
+        ensure => file,
+        source => $private_key,
+      }
+      file {"${activemq_confdir}/ssl_credentials/ca.pem":
+        ensure => file,
+        source => $ca,
+      }
+
+
+      # ----- Manage Keystore Contents -----
+
+      # Each keystore should have a dependency on the PEM files it relies on.
+
+      # Truststore with copy of CA cert
+      java_ks { 'activemq_ca:truststore':
+        ensure       => latest,
+        certificate  => "${activemq_confdir}/ssl_credentials/ca.pem",
+        target       => "${activemq_confdir}/truststore.jks",
+        password     => $keystore_password,
+        trustcacerts => true,
+        require      => File["${activemq_confdir}/ssl_credentials/ca.pem"],
+      }
+
+      # Keystore with ActiveMQ cert and private key
+      java_ks { 'activemq_cert:keystore':
+        ensure       => latest,
+        certificate  => "${activemq_confdir}/ssl_credentials/activemq_certificate.pem",
+        private_key  => "${activemq_confdir}/ssl_credentials/activemq_private.pem",
+        target       => "${activemq_confdir}/keystore.jks",
+        password     => $keystore_password,
+        require      => [
+          File["${activemq_confdir}/ssl_credentials/activemq_private.pem"],
+          File["${activemq_confdir}/ssl_credentials/activemq_certificate.pem"]
+        ],
+      }
+
+
+      # ----- Manage Keystore Files -----
+
+      # Permissions only.
+      # No ensure, source, or content.
+
+      file {"${activemq_confdir}/keystore.jks":
+        owner   => $activemq_user,
+        group   => $activemq_user,
+        mode    => 0600,
+        require => Java_ks['activemq_cert:keystore'],
+      }
+      file {"${activemq_confdir}/truststore.jks":
+        owner   => $activemq_user,
+        group   => $activemq_user,
+        mode    => 0600,
+        require => Java_ks['activemq_ca:truststore'],
+      }
+    
+    }
+{% endhighlight %}
+
+
+### Step 3: Assign the Class to the ActiveMQ Server
+
+...using your standard Puppet site tools.
+
+### Step 4: Finish
+
+[Configure ActiveMQ to use the keystores in its `sslContext`][tls], probably with the Puppet template you're using to manage activemq.xml.  **Double-check** that you've made activemq.xml world-unreadable, since it now contains sensitive credentials.
index 5b83ee9161b8a6d533049587165a60db8cd5f8f9..a5c747d24b27d171a104371d1f184c0655169b73 100644 (file)
@@ -36,6 +36,7 @@ toc: false
 [ActiveMQ]: /mcollective/reference/integration/activemq_security.html
 [MessageFormat]: /mcollective/reference/basic/messageformat.html
 [ChangeLog]: /mcollective/changelog.html
+[server_config]: /mcollective/configure/server.html
 
 The Marionette Collective AKA mcollective is a framework to build server
 orchestration or parallel job execution systems.
@@ -93,7 +94,7 @@ MCollective is licensed under the Apache 2 license.
 
 ### Introductory and Tutorial Pages
  * See it in action in our [Screencasts]
- * Read the [GettingStarted] and [Configuration] guides for installation instructions
+ * Read the [GettingStarted], [Server Configuration Reference][server_config], and [Configuration] guides for installation instructions
  * Read the [Terminology] page if you see any words where the meaning in the context of MCollective is not clear
  * Read the [ChangeLog] page to see how MCollective has developed
  * Learn how to write basic reports for your servers - [NodeReports]
index 4fbd2456783e7a62140ae4d946e321b9f4d94908..92bf9a6fd49b9e8219cf80855521464dcd377afa 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC1
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC1
-===========================================
-
 Example Message
 ---------------
 
index cd818dc459c803054216537a4f897af791aa5cb5..a0fd7b5b7049a8c20d02f564dd1ad17c9564140f 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC10
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC10
-===========================================
-
 Example Message
 ---------------
 
index 8ff9a60bf90629fe86f8b96bcd46d31e2bf7c940..e07cd16cbfa4854cec72d5de4d63312c7a137a95 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC11
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC11
-===========================================
-
 Example Message
 ---------------
 
index be7cb5a93a985412596c979732bf4fd961b40281..c995c7f961c4511c11f09e89d77481b914aa8083 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC12
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC12
-===========================================
-
 Example Message
 ---------------
 
index 550c8c5fadd42712dc5bdad148064536cbefdae6..5efd236cd027b7019eac8bfce3a0d1606816a2ea 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC13
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC13
-===========================================
-
 Example Message
 ---------------
 
index 149ec8f4275385ca58ff34768403d912215743ec..8287488a58bb04eb096abba3ccf44df405e1edd1 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC14
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC14
-===========================================
-
 Example Message
 ---------------
 
index c269575e28a6d6181ee227d4f387a98b12cc815a..74afc2dda79f8aa5bfe39510a44179d0467b7b21 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC15
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC15
-===========================================
-
 Example Message
 ---------------
 
index 56efeca08c1bc3b719be637e6b36fed667b2b08c..b169953d8a5b1f5015a696b9bf5796df2a0fbf39 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC16
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC16
-===========================================
-
 Example Message
 ---------------
 
index f4d938d0c367a910b2b725b9ceaaade3830c2dd4..bf3ededb3067e74beb9b26e77e9e61a388b16a6b 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC17
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC17
-===========================================
-
 Example Message
 ---------------
 
index d463e4dacfec7f4421b8541f372ef68d926242bd..f715267078d0a5b040c230390993ab78bc06349c 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC18
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC18
-===========================================
-
 Example Message
 ---------------
 
index bbcf8875b8a60f921b7db4ed6e27735da775585d..f449db57b75a89b552e9405619196f63557763d7 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC19
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC19
-===========================================
-
 Example Message
 ---------------
 
index 675ae91dce980e01f205938b232ca1a7ddf1594d..39fb4763705a65ab45203c415ba4fe60d7bfb824 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC2
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC2
-===========================================
-
 Example Message
 ---------------
 
index 237737698326237a0939d98dd3ab658b1af516a9..d9e01916ee3bcc69dc99caf4d8de75ba5d12953f 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC20
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC20
-===========================================
-
 Example Message
 ---------------
 
index 5531687518ab22c831d59725cef330c03ed297f5..242e7f080aa4aa5e726c5fb5f3b7cca0c539bc1d 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC21
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC21
-===========================================
-
 Example Message
 ---------------
 
index d786a523d6bae7e32f2c3ba8af6e8cad1d63ab82..7d7dc622fe2882b30572a6b590691a79ba0d5988 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC22
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC22
-===========================================
-
 Example Message
 ---------------
 
index 0085f0e8ac4d9405bed8fa596c54b27a4b2b5427..b782478ca04e2b0b7fce271ab0218662dfa97830 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC23
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC23
-===========================================
-
 Example Message
 ---------------
 
index 0bfb4345c9a04f1f88a0b2025d2950975b6f80af..423d4e91fadc09284a98bf9da52b3e0d39895db4 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC24
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC24
-===========================================
-
 Example Message
 ---------------
 
index 7c178af588fdeb5be3240ff1328aa03d9248ed0b..14fb3215dc5e12f1431f87a8278df2d323631512 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC25
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC25
-===========================================
-
 Example Message
 ---------------
 
index d91ed428e6920e6c00747d32e40abe4ca1ba68f4..15f8335f2a64100033318edafe2f7db4428c8cce 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC26
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC26
-===========================================
-
 Example Message
 ---------------
 
index d5c2225fed5fc25c52be1beff1a79b27ead4907e..77f955f76dc44c478b9fecf4a8f4536fa52423d5 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC27
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC27
-===========================================
-
 Example Message
 ---------------
 
index 49a317d4308f65326de6b52bc6cf0494631d8199..160bbe66c4b4d01db12f9df8d11c09a5302d93e0 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC28
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC28
-===========================================
-
 Example Message
 ---------------
 
index dda52e647925592ab6f2055f06c4bd86a61a2a2c..17abe8943ad4c709706f25421584585b23ad4689 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC29
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC29
-===========================================
-
 Example Message
 ---------------
 
index 913679596d9837d63ef2c454299c4e7eea5a61ee..8e1c90aff7e3ae9be82a102f8ef47ffd42060b9a 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC3
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC3
-===========================================
-
 Example Message
 ---------------
 
index cc9dfc4726682441e5cc2e6dbc7ae694e118739f..95a947f97b0af4b2f08f0babd9577ebdcfb91f92 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC30
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC30
-===========================================
-
 Example Message
 ---------------
 
index 97846cdd238931b2b6b60c129172ddac080a12da..9ac14bd2b8dba42ffe6e1da0d83f0dd0e6d59c5e 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC31
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC31
-===========================================
-
 Example Message
 ---------------
 
index e79f614fd62d8d6645562f542a01b470d4f5bb7d..c432da928e7b609336393f29ead36e1e8928df39 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC32
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC32
-===========================================
-
 Example Message
 ---------------
 
index f56c04cff67baff77e81736e459c709a7b4970a7..2bf994d405d36be808deed2e6629b6d64bc94423 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC33
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC33
-===========================================
-
 Example Message
 ---------------
 
index 71bac1a7544dd8e17fc96a1319ddf6712ccced9a..a14ffbe210bf8f2a4c78f101a52523603e16c457 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC34
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC34
-===========================================
-
 Example Message
 ---------------
 
index 2340786bea765c8d547d8abef313b542a4a29972..083d47804fc53bc0c8919a978cc34d95ecc5a208 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC35
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC35
-===========================================
-
 Example Message
 ---------------
 
index 494b2a5a95e4ac2e12522f949feee1a2bd9d010b..ebfa38bda547c500cf25ef58ef135992ad22994a 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC36
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC36
-===========================================
-
 Example Message
 ---------------
 
index 638430b655c0d6dc731cab8b296b35253dbdd628..a047b506a925c46d5685948ecd239cfa1b2aae77 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC37
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC37
-===========================================
-
 Example Message
 ---------------
 
index 0f6800a05a2e260a9393c1a96d58f45e8aaa2147..1c984759634a4e71edd1d437f3f068fe19595a39 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC38
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC38
-===========================================
-
 Example Message
 ---------------
 
index a34cbc874c57688dcd31c9149d6ae512b885cc25..728abf9084b93fcf46a3e2cf0f2ec121adf5b99c 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC39
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC39
-===========================================
-
 Example Message
 ---------------
 
index 3323b86f91e1cc9863486da22a4cd921abb18b6a..57e586c0e5d685795e8de67ba144238d5374188a 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC4
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC4
-===========================================
-
 Example Message
 ---------------
 
index 9fafa06c2fa62ccb64caf12b660e5a118c100994..38f22feb0be2aa739461675218724ebc5db3ea67 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC5
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC5
-===========================================
-
 Example Message
 ---------------
 
index 8b4bf59719f608cfd74ded316f6a68550aa99cce..42e7e983ed734b8f17a4075fd7937273b362421c 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC6
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC6
-===========================================
-
 Example Message
 ---------------
 
index b6956131dc36cb4e124796c8c57939a615acad24..1a5a0649140e4eb37e2f2d00c9fd5401b4dc1710 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC7
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC7
-===========================================
-
 Example Message
 ---------------
 
index 244b470099864c072d63f65e8c1b5365b11315c6..53546a5b6f51560ca1f2e6e950943345fbe0df11 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC8
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC8
-===========================================
-
 Example Message
 ---------------
 
index f0183b8af7b56af98c9d156e5e56571d97b2e73d..fe8818b5f32c63606db5ed6410ae963fa195c95c 100644 (file)
@@ -4,9 +4,6 @@ title: Message detail for PLMC9
 toc: false
 ---
 
-Detail for Marionette Collective message PLMC9
-===========================================
-
 Example Message
 ---------------
 
index 7d79b1ae37f64f569c8ba16da174a48293bc7cca..54a9a9bc0cf8c6dcf2a2b6769e9e4833fa7084f9 100644 (file)
@@ -9,6 +9,9 @@ title: Configuration Guide
 [Auditing]: /mcollective/simplerpc/auditing.html
 [Authorization]: /mcollective/simplerpc/authorization.html
 [Subcollectives]: /mcollective/reference/basic/subcollectives.html
+[server_config]: /mcollective/configure/server.html
+
+> **Note:** There is a new [Server Configuration Reference][server_config] page with a more complete overview of MCollective's server daemon settings. A similar client configuration page is forthcoming.
 
 This guide tells you about the major configuration options in the daemon and client config files.  There are options not mentioned
 here typically ones specific to a certain plugin.
@@ -22,9 +25,6 @@ Configuration is a simple *key = val* style configuration file.
 
 |Key|Sample|Description|
 |---|------|-----------|
-|topicprefix|/topic/|Prefix that gets used for all messages.|
-|queueprefix|/queue/|Prefix that gets used for all queued messages.|
-|topicsep|.|The seperator to use between parts of the topic path|
 |collectives|mcollective,subcollective|A list of [Subcollectives] to join - 1.1.3 and newer only|
 |main_collective|mcollective|The main collective to target - 1.1.3 and newer only|
 |logfile|/var/log/mcollective.log|Where to log|
@@ -33,7 +33,7 @@ Configuration is a simple *key = val* style configuration file.
 |keeplogs|5|The amount of logs to keep|
 |max_log_size|2097152|Max size in bytes for log files before rotation happens|
 |libdir|/usr/libexec/mcollective:/site/mcollective|Where to look for plugins|
-|connector|Stomp|Which _connector_ plugin to use for communication|
+|connector|activemq|Which _connector_ plugin to use for communication|
 |securityprovider|Psk|Which security model to use, see [SSL Security Plugin][SSLSecurity] and [AES Security Plugin][AESSecurity] for details on others|
 |rpchelptemplate|/etc/mcollective/rpc-help.erb|The path to the erb template used for generating help|
 |helptemplatedir|/etc/mcollective|The path that contains all the erb templates for generating help|
@@ -63,7 +63,6 @@ The server configuration file should be root only readable
 |rpcauthprovider|action_policy|Use the _MCollective::Util::ActionPolicy_ plugin to manage authorization|
 |rpclimitmethod|The method used for --limit-results.  Can be either _first_ or _random_|
 |fact_cache_time|300|How long to cache fact results for before refreshing from source|
-|plugin.discovery.timeout|10|Sets the timeout for the discovery agent, useful if facts are very slow|
 
 The last example sets a option for the _discovery_ plugin, you can also set this in _/etc/mcollective/plugin.d/discovery.cfg_, in that case
 you'd just set _timeout=10_ in the file.
@@ -88,10 +87,6 @@ Common plugin options are:
 
 |Key|Sample|Description|
 |---|------|-----------|
-|plugin.stomp.host|stomp.your.com|Host to connect too|
-|plugin.stomp.port|6163|Port to connecto too|
-|plugin.stomp.user|mcollective|User to connect as|
-|plugin.stomp.password|password|Password to use|
 |plugin.yaml|/etc/mcollective/facts.yaml:/other/facts.yaml|Where the yaml fact source finds facts from, multiples get merged|
 |plugin.psk|123456789|The pre-shared key to use for the Psk security provider|
 |plugin.psk.callertype|group|What to base the callerid on for the PSK plugin, uid, gid, user, group or identity|
@@ -106,7 +101,6 @@ You can set various Environment variables per user to supply these values:
 {% highlight bash %}
 export STOMP_USER=user
 export STOMP_PASSWORD=password
-export STOMP_SERVER=stomp.your.com
 export MCOLLECTIVE_PSK=123456789
 {% endhighlight %}
 
index 6a36e6cb0f05179fe3f5278f08940087135c24c5..bd1755de8a127f6f0796a92f15da68d93280d9cc 100644 (file)
@@ -4,6 +4,7 @@ title: Getting Started
 ---
 [Screencasts]: /mcollective/screencasts.html
 [ActiveMQ]: http://activemq.apache.org/
+[RabbitMQ]: http://www.rabbitmq.com/
 [EC2Demo]: /mcollective/ec2demo.html
 [Stomp]: http://stomp.codehaus.org/Ruby+Client
 [DepRPMs]: http://www.marionette-collective.org/activemq/
@@ -17,24 +18,24 @@ title: Getting Started
 [ControllingTheDaemon]: /mcollective/reference/basic/daemon.html
 [SSLSecurityPlugin]: /mcollective/reference/plugins/security_ssl.html
 [AESSecurityPlugin]: /mcollective/reference/plugins/security_aes.html
-[ConnectorStomp]: /mcollective/reference/plugins/connector_stomp.html
+[ConnectorActiveMQ]: /mcollective/reference/plugins/connector_activemq.html
+[ConnectorRabbitMQ]: /mcollective/reference/plugins/connector_rabbitmq.html
 [MessageFlowCast]: /mcollective/screencasts.html#message_flow
 [Plugins]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki
 [RedHatGuide]: gettingstarted_redhat.html
 [DebianGuide]: gettingstarted_debian.html
+[server_config]: /mcollective/configure/server.html
 
-*NOTE:* We are currently improving the Getting Started documentation.  Red Hat and CentOS users can refer to [our Redhat guide][RedHatGuide]. Debian users can refer to [our Debian guide][DebianGuide].
+*NOTE:* This is an older, deprecated version of the Getting Started documentation.  Red Hat and CentOS users can refer to [our Redhat guide][RedHatGuide]. Debian users can refer to [our Debian guide][DebianGuide]. Users on less common platforms should adapt one of those two instead of continuing to read this page.
 
 Below find a rough guide to get you going, this assumes the client and server is on the same node, but servers don't need the client code installed.
 
-For an even quicker intro to how it all works you can try our [EC2 based demo][EC2Demo]
-
 Look at the [Screencasts] page, there are [some screencasts dealing with basic architecture, terminology and so forth][MessageFlowCast] that you might find helpful before getting started.
 
 ## Requirements
 We try to keep the requirements on external Gems to a minimum, you only need:
 
- * A Stomp server, tested against [ActiveMQ]
+ * A Stomp server, tested against [ActiveMQ] and [RabbitMQ]
  * Ruby
  * Rubygems
  * [Ruby Stomp Client][Stomp]
@@ -42,9 +43,9 @@ We try to keep the requirements on external Gems to a minimum, you only need:
 RPMs for these are available [here][DepRPMs].
 
 ## ActiveMQ
-I've developed this against ActiveMQ.  It should work against other Stomp servers but I suspect if you choose
-one without username and password support you might have problems, please let me know if that's the case
-and I'll refactor the code around that.
+ActiveMQ is currently the most used middleware for MCollective, it would be our recommended choice and one
+that the community has most experience supporting.  There is a specific connector for RabbitMQ if you wish
+to go that route though - see [ConnectorRabbitMQ] for details.  This guide will focus on ActiveMQ.
 
 Full details on setting up and configuring ActiveMQ is out of scope for this, but you can follow these simple
 setup instructions for initial testing (make sure JDK is installed, see below for Debian specific issue regarding JDK):
@@ -129,8 +130,8 @@ And then you should add a user or two, to keep it simple we'll just add one user
         </systemUsage>
 
         <transportConnectors>
-            <transportConnector name="openwire" uri="tcp://0.0.0.0:6166"/>
-            <transportConnector name="stomp" uri="stomp://0.0.0.0:6163"/>
+            <transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/>
+            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613"/>
         </transportConnectors>
     </broker>
 </beans>
@@ -143,7 +144,7 @@ Save the above code as activemq.xml and run activemq as - if installing from a p
 Else your package would have a RC script:
 
 {% highlight console %}
-  # /etc/init.d/activemq start
+# /etc/init.d/activemq start
 {% endhighlight %}
 
 For further info about ActiveMQ settings you might need see [SecurityWithActiveMQ] and [ActiveMQClustering].
@@ -161,7 +162,7 @@ locations.  If you use the tarball you'll need to double check all the paths in
 You'll need to tweak some configs in */etc/mcollective/client.cfg*, a full reference of config settings can be
 found [here][ConfigurationReference]:
 
-Mostly what you'll need to change is the *identity*, *plugin.stomp.`*`* and the *plugin.psk*:
+Mostly what you'll need to change is the *identity*, *plugin.activemq.1.`*`* and the *plugin.psk*:
 
 {% highlight ini %}
   # main config
@@ -171,18 +172,19 @@ Mostly what you'll need to change is the *identity*, *plugin.stomp.`*`* and the
   identity = fqdn
 
   # connector plugin config
-  connector = stomp
-  plugin.stomp.host = stomp.your.net
-  plugin.stomp.port = 6163
-  plugin.stomp.user = unset
-  plugin.stomp.password = unset
+  connector = activemq
+  plugin.activemq.pool.size = 1
+  plugin.activemq.pool.1.host = stomp.your.net
+  plugin.activemq.pool.1.port = 61613
+  plugin.activemq.pool.1.user = unset
+  plugin.activemq.pool.1.password = unset
 
   # security plugin config
   securityprovider = psk
   plugin.psk = abcdefghj
 {% endhighlight %}
 
-You should also create _/etc/mcollective/server.cfg_ here's a sample, , a full reference of config settings can be found here [ConfigurationReference]:
+You should also create _/etc/mcollective/server.cfg_ here's a sample, a full reference of config settings can be found on the [Server Configuration Reference][server_config]:
 
 {% highlight ini %}
   # main config
@@ -196,11 +198,12 @@ You should also create _/etc/mcollective/server.cfg_ here's a sample, , a full r
   registerinterval = 300
 
   # connector plugin config
-  connector = stomp
-  plugin.stomp.host = stomp.your.net
-  plugin.stomp.port = 6163
-  plugin.stomp.user = mcollective
-  plugin.stomp.password = password
+  connector = activemq
+  plugin.activemq.pool.size = 1
+  plugin.activemq.pool.1.host = stomp.your.net
+  plugin.activemq.pool.1.port = 61613
+  plugin.activemq.pool.1.user = mcollective
+  plugin.activemq.pool.1.password = password
 
   # facts
   factsource = yaml
@@ -211,12 +214,12 @@ You should also create _/etc/mcollective/server.cfg_ here's a sample, , a full r
   plugin.psk = abcdefghj
 {% endhighlight %}
 
-Replace the *plugin.stomp.host* with your server running ActiveMQ and replace the *plugin.psk* with a Pre-Shared Key of your own.
+Replace the *plugin.activemq.pool.1.host* with your server running ActiveMQ and replace the *plugin.psk* with a Pre-Shared Key of your own.
 
-The STOMP connector supports other options like failover pools, see [ConnectorStomp] for full details.
+The ActiveMQ connector supports other options like failover pools, see [ConnectorActiveMQ] for full details.
 
 ### Create Facts
-By default - and for this setup - we'll use a simple YAML file for a fact source, later on you can use Reductive Labs Facter or something else.
+By default - and for this setup - we'll use a simple YAML file for a fact source, later on you can use Puppet Labs Facter or something else.
 
 Create */etc/mcollective/facts.yaml* along these lines:
 
@@ -252,7 +255,7 @@ your.domain.com
 
 This searches all systems currently active for ones with a fact *country=uk*, it got the data from the yaml file you made earlier.
 
-If you use confiuration management tools like puppet and the nodes are setup with classes with *classes.txt* in */var/lib/puppet* then you
+If you use configuration management tools like puppet and the nodes are setup with classes with *classes.txt* in */var/lib/puppet* then you
 can search for nodes with a specific class on them - the locations will configurable soon:
 
 {% highlight console %}
@@ -280,4 +283,3 @@ From here you should look at the rest of the wiki pages some key pages are:
  * [ControllingTheDaemon] - Controlling a running daemon
  * [AESSecurityPlugin] - Using AES+RSA for secure message encryption and authentication of clients
  * [SSLSecurityPlugin] - Using SSL for secure message signing and authentication of clients
- * [ConnectorStomp] - Full details on the Stomp adapter including failover pools
index ecab62566bc3ebb27b4c5705285ace5e3e92afbe..3539663a0a2a32d8c56cda6a36a4b66777381b53 100644 (file)
@@ -19,16 +19,16 @@ title: Getting Started
 [ControllingTheDaemon]: /mcollective/reference/basic/daemon.html
 [SSLSecurityPlugin]: /mcollective/reference/plugins/security_ssl.html
 [AESSecurityPlugin]: /mcollective/reference/plugins/security_aes.html
-[ConnectorStomp]: /mcollective/reference/plugins/connector_stomp.html
+[ConnectorActiveMQ]: /mcollective/reference/plugins/connector_activemq.html
+[ConnectorRabbitMQ]: /mcollective/reference/plugins/connector_rabbitmq.html
 [MessageFlowCast]: /mcollective/screencasts.html#message_flow
 [Plugins]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki
 [MCDownloads]: http://www.puppetlabs.com/downloads/mcollective/
 [RubyGems]: http://packages.debian.org/search?suite=default&section=all&arch=any&searchon=names&keywords=rubygems
+[server_config]: /mcollective/configure/server.html
 
 Getting started using Debian based distribution like Debian squeeze and Ubuntu is easy as DEBs are available for most the required components.  This guide walks you through the process.
 
-If you just want to experiment with the system please try our [EC2 based demo][EC2Demo].  You should be familiar with the architecture and terminology of Marionette Collective, please review the [basic architecture, terminology and message flow][MessageFlowCast] screencast first.
-
 ## Requirements
 We try to keep the requirements on external Gems to a minimum, you only need:
 
@@ -46,15 +46,16 @@ We strongly recommend you set up a local Apt repository that will host all the p
  * Ruby - included with your distribution
  * [RubyGems]
  * Stomp Ruby Gem
- * [MCollective][MCDownloads] - mcollective-1.x.x-1_all.deb, mcollective-common-1.x.x-1_all.deb, mcollective-client-1.x.x-1_all.deb
+ * [MCollective][MCDownloads] - mcollective-2.2.x-1_all.deb, mcollective-common-2.2.x-1_all.deb, mcollective-client-2.2.x-1_all.deb
 
 The rest of this guide will assume you set up a Apt repository.  Puppet Labs hosts a Apt repository with all these dependencies at _apt.puppetlabs.com_.
 
 ## ActiveMQ
+
 ActiveMQ is currently the most used and tested middleware for use with MCollective.
 
 You need at least one ActiveMQ server on your network, all the nodes you wish to manage will connect to the central ActiveMQ server.
-Later on your can [cluster the ActiveMQ servers for availability and scale][ActiveMQClustering].
+Later on you can [cluster the ActiveMQ servers for availability and scale][ActiveMQClustering].
 
 ### Install
 
@@ -68,82 +69,17 @@ ActiveMQ installation instructions can be found [here][ActiveMQ Getting Started]
 
 ### Configuring
 
-Initially you'll just keep it simple with a single ActiveMQ broker and a basic user setup, further security information for ActiveMQ
-can be found [here][SecurityWithActiveMQ]
-
-Place the following in your ActiveMQ configuration path as *activemq.xml*. You can download this file from [GitHub][ActiveMQSingleBrokerSample]
-
-Other examples are also available from [GitHub][ActiveMQSamples]
-
-{% highlight xml %}
-<beans
-  xmlns="http://www.springframework.org/schema/beans"
-  xmlns:amq="http://activemq.apache.org/schema/core"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
-  http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
-  http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd">
-
-    <broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" useJmx="true">
-        <destinationPolicy>
-          <policyMap>
-            <policyEntries>
-              <policyEntry topic=">" producerFlowControl="false"/>
-              <policyEntry queue="*.reply.>" gcInactiveDestinations="true" inactiveTimoutBeforeGC="300000" />
-            </policyEntries>
-          </policyMap>
-        </destinationPolicy>
-
-        <managementContext>
-            <managementContext createConnector="false"/>
-        </managementContext>
-
-        <plugins>
-          <statisticsBrokerPlugin/>
-          <simpleAuthenticationPlugin>
-            <users>
-              <authenticationUser username="mcollective" password="marionette" groups="mcollective,everyone"/>
-              <authenticationUser username="admin" password="secret" groups="mcollective,admin,everyone"/>
-            </users>
-          </simpleAuthenticationPlugin>
-          <authorizationPlugin>
-            <map>
-              <authorizationMap>
-                <authorizationEntries>
-                  <authorizationEntry queue=">" write="admins" read="admins" admin="admins" />
-                  <authorizationEntry topic=">" write="admins" read="admins" admin="admins" />
-                  <authorizationEntry topic="mcollective.>" write="mcollective" read="mcollective" admin="mcollective" />
-                  <authorizationEntry queue="mcollective.>" write="mcollective" read="mcollective" admin="mcollective" />
-                  <authorizationEntry topic="ActiveMQ.Advisory.>" read="everyone" write="everyone" admin="everyone"/>
-                </authorizationEntries>
-              </authorizationMap>
-            </map>
-          </authorizationPlugin>
-        </plugins>
-
-        <systemUsage>
-            <systemUsage>
-                <memoryUsage>
-                    <memoryUsage limit="20 mb"/>
-                </memoryUsage>
-                <storeUsage>
-                    <storeUsage limit="1 gb" name="foo"/>
-                </storeUsage>
-                <tempUsage>
-                    <tempUsage limit="100 mb"/>
-                </tempUsage>
-            </systemUsage>
-        </systemUsage>
-
-        <transportConnectors>
-            <transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/>
-            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613"/>
-        </transportConnectors>
-    </broker>
-</beans>
-{% endhighlight %}
+[The ActiveMQ config reference][activemq_config] describes all of the ActiveMQ settings that MCollective cares about. For best use, skim the sections you care about while comparing it to an example activemq.xml file.
+
+[activemq_config]: /mcollective/deploy/middleware/activemq.html
 
-This creates a user *mcollective* with the password *marionette* and give it access to read/write/admin */topic/mcollective.`*`*.  You should change this passsword.
+We recommend that new users:
+
+* Start with the [single-broker example config][ActiveMQSingleBrokerSample].
+* Change the [user account passwords](/mcollective/deploy/middleware/activemq.html#authentication-users-and-groups).
+* [Set up TLS](/mcollective/deploy/middleware/activemq.html#tls-credentials) and [use a TLS Stomp transport connector](/mcollective/deploy/middleware/activemq.html#transport-connectors).
+
+Other example config files are also available from [GitHub][ActiveMQSamples].
 
 ### Starting
 
@@ -156,13 +92,13 @@ Start the ActiveMQ service:
 You should see it running in the process list:
 
 {% highlight console %}
- # ps -auxw|grep java
+ # ps auxw|grep java
  activemq  3012  0.1 14.5 1155112 152180 ?      Sl   Dec28   2:02 java -Dactivemq.home=/usr/share/activemq -Dactivemq.base=/usr/share/activemq -Dcom.sun.management.jmxremote -Dorg.apache.activemq.UseDedicatedTaskRunner=true -Xmx512m -Djava.library.path=/usr/lib:/usr/lib64 -classpath /usr/share/java/tanukiwrapper.jar:/usr/share/activemq/bin/run.jar -Dwrapper.key=eg4_VvENzCmvtAKg -Dwrapper.port=32000 -Dwrapper.jvm.port.min=31000 -Dwrapper.jvm.port.max=31999 -Dwrapper.pid=3000 -Dwrapper.version=3.2.3 -Dwrapper.native_library=wrapper -Dwrapper.service=TRUE -Dwrapper.cpu.timeout=10 -Dwrapper.jvmid=1 org.tanukisoftware.wrapper.WrapperSimpleApp org.apache.activemq.console.Main start
 {% endhighlight %}
 
-You should also see it listening on port 61613 in your network stack
+You should also see it listening on port 61613 or 61614 in your network stack, depending on whether you turned on TLS.
 
-You should open port 61613 for all your nodes to connect to.
+You should open port 61613 or 61614 for all your nodes to connect to.
 
 ## Marionette Collective
 
@@ -185,7 +121,7 @@ A machine can be both at once, in which case you need to install all 3 packages.
 You'll need to tweak some configs in */etc/mcollective/client.cfg*, a full reference of config settings can be
 found [here][ConfigurationReference]:
 
-We're assuming you called the machine running ActiveMQ *stomp.example.net* please change as appropriate
+We're assuming you called the machine running ActiveMQ *stomp.example.net*; please change as appropriate. Also note that the port should be 61614 if you turned on TLS.
 
 {% highlight ini %}
   # main config
@@ -194,18 +130,19 @@ We're assuming you called the machine running ActiveMQ *stomp.example.net* pleas
   loglevel = error
 
   # connector plugin config
-  connector = stomp
-  plugin.stomp.host = stomp.example.net
-  plugin.stomp.port = 61613
-  plugin.stomp.user = mcollective
-  plugin.stomp.password = marionette
+  connector = activemq
+  plugin.activemq.pool.size = 1
+  plugin.activemq.pool.1.host = stomp.example.net
+  plugin.activemq.pool.1.port = 61613
+  plugin.activemq.pool.1.user = mcollective
+  plugin.activemq.pool.1.password = marionette
 
   # security plugin config
   securityprovider = psk
   plugin.psk = abcdefghj
 {% endhighlight %}
 
-You should also create _/etc/mcollective/server.cfg_ here's a sample, , a full reference of config settings can be found here [ConfigurationReference]:
+You should also create _/etc/mcollective/server.cfg_ here's a sample, a full reference of config settings can be found on the [Server Configuration Reference][server_config]:
 
 {% highlight ini %}
   # main config
@@ -215,11 +152,13 @@ You should also create _/etc/mcollective/server.cfg_ here's a sample, , a full r
   loglevel = info
 
   # connector plugin config
-  connector = stomp
-  plugin.stomp.host = stomp.example.net
-  plugin.stomp.port = 61613
-  plugin.stomp.user = mcollective
-  plugin.stomp.password = marionette
+  connector = activemq
+  plugin.activemq.pool.size = 1
+  plugin.activemq.pool.1.host = stomp.example.net
+  plugin.activemq.pool.1.port = 61613
+  plugin.activemq.pool.1.user = mcollective
+  plugin.activemq.pool.1.password = marionette
+
 
   # facts
   factsource = yaml
@@ -309,4 +248,3 @@ From here you should look at the rest of the wiki pages some key pages are:
  * [ControllingTheDaemon] - Controlling a running daemon
  * [AESSecurityPlugin] - Using AES+RSA for secure message encryption and authentication of clients
  * [SSLSecurityPlugin] - Using SSL for secure message signing and authentication of clients
- * [ConnectorStomp] - Full details on the Stomp adapter including failover pools
index 852e4be0a46ba5625dc669533e723c30adf2d2b1..59ff23cdcd692e51d5e5733263f1cd61b02fe6dd 100644 (file)
@@ -18,16 +18,16 @@ title: Getting Started
 [ControllingTheDaemon]: /mcollective/reference/basic/daemon.html
 [SSLSecurityPlugin]: /mcollective/reference/plugins/security_ssl.html
 [AESSecurityPlugin]: /mcollective/reference/plugins/security_aes.html
-[ConnectorStomp]: /mcollective/reference/plugins/connector_stomp.html
+[ConnectorActiveMQ]: /mcollective/reference/plugins/connector_activemq.html
+[ConnectorRabbitMQ]: /mcollective/reference/plugins/connector_rabbitmq.html
 [MessageFlowCast]: /mcollective/screencasts.html#message_flow
 [Plugins]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki
 [MCDownloads]: http://www.puppetlabs.com/downloads/mcollective/
 [EPEL]: http://fedoraproject.org/wiki/EPEL
+[server_config]: /mcollective/configure/server.html
 
 Getting started using Red Hat based distribution like Red Hat Enterprise Linux and CentOS is easy as RPMs are available for all the required components.  This guide walks you through the process.
 
-If you just want to experiment with the system please try our [EC2 based demo][EC2Demo].  You should be familiar with the architecture and terminology of Marionette Collective, please review the [basic architecture, terminology and message flow][MessageFlowCast] screencast first.
-
 ## Requirements
 We try to keep the requirements on external Gems to a minimum, you only need:
 
@@ -45,7 +45,7 @@ We strongly recommend you set up a local Yum repository that will host all the p
  * Ruby - included with your distribution
  * RubyGems - [EPEL]
  * Stomp Ruby Gem - [EPEL]
- * [MCollective][MCDownloads] - mcollective-1.x.x-1.el5.noarch.rpm, mcollective-common-1.x.x-1.el5.noarch.rpm, mcollective-client-1.x.x-1.el5.noarch.rpm
+ * [MCollective][MCDownloads] - mcollective-2.2.x-1.el5.noarch.rpm, mcollective-common-2.2.x-1.el5.noarch.rpm, mcollective-client-2.2.x-1.el5.noarch.rpm
 
 The rest of this guide will assume you set up a Yum repository.  Puppet Labs hosts a Yum repository with all these dependencies at _yum.puppetlabs.com_.
 
@@ -65,82 +65,18 @@ On the server that you chose to configure as the ActiveMQ server:
 
 ### Configuring
 
-Initially you'll just keep it simple with a single ActiveMQ broker and a basic user setup, further security information for ActiveMQ
-can be found [here][SecurityWithActiveMQ]
-
-Place the following in _/etc/activemq/activemq.xml_ you can download this file from [GitHub][ActiveMQSingleBrokerSample]
-
-Other examples are also available from [GitHub][ActiveMQSamples]
-
-{% highlight xml %}
-<beans
-  xmlns="http://www.springframework.org/schema/beans"
-  xmlns:amq="http://activemq.apache.org/schema/core"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
-  http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
-  http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd">
-
-    <broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" useJmx="true">
-        <destinationPolicy>
-          <policyMap>
-            <policyEntries>
-              <policyEntry topic=">" producerFlowControl="false"/>
-              <policyEntry queue="*.reply.>" gcInactiveDestinations="true" inactiveTimoutBeforeGC="300000" />
-            </policyEntries>
-          </policyMap>
-        </destinationPolicy>
-
-        <managementContext>
-            <managementContext createConnector="false"/>
-        </managementContext>
-
-        <plugins>
-          <statisticsBrokerPlugin/>
-          <simpleAuthenticationPlugin>
-            <users>
-              <authenticationUser username="mcollective" password="marionette" groups="mcollective,everyone"/>
-              <authenticationUser username="admin" password="secret" groups="mcollective,admin,everyone"/>
-            </users>
-          </simpleAuthenticationPlugin>
-          <authorizationPlugin>
-            <map>
-              <authorizationMap>
-                <authorizationEntries>
-                  <authorizationEntry queue=">" write="admins" read="admins" admin="admins" />
-                  <authorizationEntry topic=">" write="admins" read="admins" admin="admins" />
-                  <authorizationEntry topic="mcollective.>" write="mcollective" read="mcollective" admin="mcollective" />
-                  <authorizationEntry queue="mcollective.>" write="mcollective" read="mcollective" admin="mcollective" />
-                  <authorizationEntry topic="ActiveMQ.Advisory.>" read="everyone" write="everyone" admin="everyone"/>
-                </authorizationEntries>
-              </authorizationMap>
-            </map>
-          </authorizationPlugin>
-        </plugins>
-
-        <systemUsage>
-            <systemUsage>
-                <memoryUsage>
-                    <memoryUsage limit="20 mb"/>
-                </memoryUsage>
-                <storeUsage>
-                    <storeUsage limit="1 gb" name="foo"/>
-                </storeUsage>
-                <tempUsage>
-                    <tempUsage limit="100 mb"/>
-                </tempUsage>
-            </systemUsage>
-        </systemUsage>
-
-        <transportConnectors>
-            <transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/>
-            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613"/>
-        </transportConnectors>
-    </broker>
-</beans>
-{% endhighlight %}
+[The ActiveMQ config reference][activemq_config] describes all of the ActiveMQ settings that MCollective cares about. For best use, skim the sections you care about while comparing it to an example activemq.xml file.
+
+[activemq_config]: /mcollective/deploy/middleware/activemq.html
+
+We recommend that new users:
+
+* Start with the [single-broker example config][ActiveMQSingleBrokerSample].
+* Change the [user account passwords](/mcollective/deploy/middleware/activemq.html#authentication-users-and-groups).
+* [Set up TLS](/mcollective/deploy/middleware/activemq.html#tls-credentials) and [use a TLS Stomp transport connector](/mcollective/deploy/middleware/activemq.html#transport-connectors).
+
+Other example config files are also available from [GitHub][ActiveMQSamples].
 
-This creates a user *mcollective* with the password *marionette* and give it access to read/write/admin */topic/mcollective.`*`*.  You should change this passsword.
 
 ### Starting
 
@@ -153,7 +89,7 @@ Start the ActiveMQ service:
 You should see it running in the process list:
 
 {% highlight console %}
- # ps -auxw|grep java
+ # ps auxw|grep java
  activemq  3012  0.1 14.5 1155112 152180 ?      Sl   Dec28   2:02 java -Dactivemq.home=/usr/share/activemq -Dactivemq.base=/usr/share/activemq -Dcom.sun.management.jmxremote -Dorg.apache.activemq.UseDedicatedTaskRunner=true -Xmx512m -Djava.library.path=/usr/lib:/usr/lib64 -classpath /usr/share/java/tanukiwrapper.jar:/usr/share/activemq/bin/run.jar -Dwrapper.key=eg4_VvENzCmvtAKg -Dwrapper.port=32000 -Dwrapper.jvm.port.min=31000 -Dwrapper.jvm.port.max=31999 -Dwrapper.pid=3000 -Dwrapper.version=3.2.3 -Dwrapper.native_library=wrapper -Dwrapper.service=TRUE -Dwrapper.cpu.timeout=10 -Dwrapper.jvmid=1 org.tanukisoftware.wrapper.WrapperSimpleApp org.apache.activemq.console.Main start
 {% endhighlight %}
 
@@ -190,18 +126,19 @@ We're assuming you called the machine running ActiveMQ *stomp.example.net* pleas
   loglevel = error
 
   # connector plugin config
-  connector = stomp
-  plugin.stomp.host = stomp.example.net
-  plugin.stomp.port = 61613
-  plugin.stomp.user = mcollective
-  plugin.stomp.password = marionette
+  connector = activemq
+  plugin.activemq.pool.size = 1
+  plugin.activemq.pool.1.host = stomp.example.net
+  plugin.activemq.pool.1.port = 61613
+  plugin.activemq.pool.1.user = mcollective
+  plugin.activemq.pool.1.password = marionette
 
   # security plugin config
   securityprovider = psk
   plugin.psk = abcdefghj
 {% endhighlight %}
 
-You should also create _/etc/mcollective/server.cfg_ here's a sample, , a full reference of config settings can be found here [ConfigurationReference]:
+You should also create _/etc/mcollective/server.cfg_ here's a sample, a full reference of config settings can be found on the [Server Configuration Reference][server_config]:
 
 {% highlight ini %}
   # main config
@@ -211,11 +148,12 @@ You should also create _/etc/mcollective/server.cfg_ here's a sample, , a full r
   loglevel = info
 
   # connector plugin config
-  connector = stomp
-  plugin.stomp.host = stomp.example.net
-  plugin.stomp.port = 61613
-  plugin.stomp.user = mcollective
-  plugin.stomp.password = marionette
+  connector = activemq
+  plugin.activemq.pool.size = 1
+  plugin.activemq.pool.1.host = stomp.example.net
+  plugin.activemq.pool.1.port = 61613
+  plugin.activemq.pool.1.user = mcollective
+  plugin.activemq.pool.1.password = marionette
 
   # facts
   factsource = yaml
@@ -305,4 +243,3 @@ From here you should look at the rest of the wiki pages some key pages are:
  * [ControllingTheDaemon] - Controlling a running daemon
  * [AESSecurityPlugin] - Using AES+RSA for secure message encryption and authentication of clients
  * [SSLSecurityPlugin] - Using SSL for secure message signing and authentication of clients
- * [ConnectorStomp] - Full details on the Stomp adapter including failover pools
index 424020712b0552429a02f65908eba0498ede3a85..60e6d64a649b2c577aeb4b1e9042dd72593f2cab 100644 (file)
@@ -2,10 +2,15 @@
 layout: default
 title: Subcollectives
 ---
+
 [ActiveMQClustering]: /mcollective/reference/integration/activemq_clusters.html
-[MessageFlow]: messageflow.html
+[activemq_authorization]: /mcollective/deploy/middleware/activemq.html#authorization-group-permissions
+[activemq_detailed]: /mcollective/deploy/middleware/activemq.html#detailed-restrictions
+[activemq_subcollectives]: /mcollective/deploy/middleware/activemq.html#detailed-restrictions-with-multiple-subcollectives
+[activemq_filtering]: /mcollective/deploy/middleware/activemq.html#destination-filtering
+[activemq_authentication]: /mcollective/deploy/middleware/activemq.html#authentication-users-and-groups
 
-# Overview
+## Overview
 
 By default all servers are part of a single broadcast domain, if you have an
 agent on all machines in your network and you send a message directed to
@@ -30,7 +35,7 @@ following scenarios:
 We've introduced the concept of sub collectives that lets you define broadcast
 domains and configure a mcollective server to belong to one or many of these domains.
 
-# Partitionion Approaches
+## Partitioning Approaches
 
 Determining how to partition your nework can be a very complex subject and
 requires an understanding of your message flow, where requestors sit and also
@@ -90,7 +95,7 @@ network this can have a big impact.
 
 ![Subcollectives](../../images/subcollectives-impact.png)
 
-# Configuring MCollective
+## Configuring MCollective
 
 Configuring the partitioned collective above is fairly simple.  We'll look at
 one of the DE nodes for reference:
@@ -104,19 +109,7 @@ The _collectives_ directive tells the node all the collectives it should belong
 to and the _main`_`collective_ instructs Registration where to direct messages
 to.
 
-# Partitioning for Security
-
-Another possible advantage from subcollectives is security.  While the SimpleRPC
-framework has a security model that is aware of the topology the core network
-layer does not.  Even if you only give someone access to run SimpleRPC requests
-against some machines they can still use _mc ping_ to discover other nodes on
-your network.
-
-By creating a subcollective of just their nodes and restricting them on the
-middleware level to just that collective you can effectively and completely
-create a secure isolated zone that overlays your exiting network.
-
-# Testing
+## Testing
 
 Testing that it works is pretty simple, first we need a _client.cfg_ that
 configures your client to talk to all the sub collectives:
@@ -126,10 +119,10 @@ collectives = mcollective,uk_collective,us_collective,de_collective,eu_collectiv
 main_collective = mcollective
 {% endhighlight %}
 
-You can now test with _mc ping_:
+You can now test with _mco ping_:
 
 {% highlight console %}
-$ mc ping -T us_collective
+$ mco ping -T us_collective
 host1.us.my.net         time=200.67 ms
 host2.us.my.net         time=241.30 ms
 host3.us.my.net         time=245.24 ms
@@ -153,7 +146,7 @@ You can discover the list of known collectives and how many nodes are in each
 using the _inventory_ application:
 
 {% highlight console %}
-$ mc inventory --list-collectives
+$ mco inventory --list-collectives
 
  * [ ==================================== ] 52 / 52
 
@@ -170,43 +163,39 @@ $ mc inventory --list-collectives
 
 {% endhighlight %}
 
-# ActiveMQ Filters
+## Partitioning for Security
 
-The above setup should just work in most cases but you might want to go one step
-further and actively prevent propagation across the network of sub collective
-traffic.
+Another possible advantage from subcollectives is security.  While the SimpleRPC
+framework has a security model that is aware of the topology the core network
+layer does not.  Even if you only give someone access to run SimpleRPC requests
+against some machines they can still use _mco ping_ to discover other nodes on
+your network.
 
-In your ActiveMQ broker setup you will already have a section defining your
-network connections, something like:
+By creating a subcollective of just their nodes and restricting them on the
+middleware level to just that collective you can effectively and completely
+create a secure isolated zone that overlays your exiting network.
 
-{% highlight xml %}
-<networkConnectors>
-  <networkConnector
-     name="us-uk"
-     uri="static:(tcp://stomp1.uk.my.net:6166)"
-     userName="amq"
-     password="secret"
-     duplex="true" />
-</networkConnectors>
-{% endhighlight %}
+These restrictions have to be configured on the middleware server, outside of MCollective itself. The method will vary based on the middleware you use; the suggestions below are for ActiveMQ, the main recommended middleware.
 
-You can add filters here restricting traffic in this case the US<->UK connection
-should never transmit _us`_`collective_ traffic, so lets restrict that:
-
-{% highlight xml %}
-<networkConnectors>
-  <networkConnector
-     <excludedDestinations>
-       <topic physicalName="us_collective.>" />
-       <topic physicalName="uk_collective.>" />
-       <topic physicalName="de_collective.>" />
-       <topic physicalName="za_collective.>" />
-       <topic physicalName="eu_collective.>" />
-     </excludedDestinations>
-     name="us-uk"
-     uri="static:(tcp://stomp1.uk.my.net:6166)"
-     userName="amq"
-     password="secret"
-     duplex="true" />
-</networkConnectors>
-{% endhighlight %}
+### Identifying Subcollectives on ActiveMQ
+
+The ActiveMQ connector plugin identifies subcollectives with the **first segment** of every destination (topic or queue) name.
+
+So for direct node addressing, for example, the default `mcollective` collective would use the `mcollective.nodes` queue, and `uk_collective` would use the `uk_collective.nodes` queue. For the package agent, they would use the `mcollective.package.agent` and `uk_collective.package.agent` topics, respectively.
+
+This makes it easy to use ActiveMQ destination wildcards to control access to a given collective. 
+
+### Per-Subcollective Authorization
+
+To control subcollective access, identify the set of topics and queues that collective will use, then use ActiveMQ's authorization rules to secure them.
+
+* [See the "Authorization" section of the ActiveMQ config reference][activemq_authorization] for details.
+* The ["Detailed Restrictions"][activemq_detailed] example shows all of the topics and queues used by the default collective; you can copy/paste/modify these for a small number of collectives.
+* The ["Detailed Restrictions with Multiple Subcollectives"][activemq_subcollectives] example uses a snippet of ERB template to manage any number of collectives. 
+
+You must then [configure multiple ActiveMQ user accounts][activemq_authentication] for your site's admins. Give each user membership in the groups they'll need to manage their collectives.
+
+### Destination Filters in a Network of Brokers
+
+In a [network of brokers][ActiveMQClustering], you can also prevent propagation across the network of sub collective
+traffic. See the ["Destination Filtering"][activemq_filtering] section of the ActiveMQ config reference for details.
index 79be05d0cd22983245a013d0116393a38869c3a1..a4f200325f22621f2f0dd634af6bc8201b823a80 100644 (file)
@@ -3,18 +3,17 @@ layout: default
 title: ActiveMQ Clustering
 toc: false
 ---
-[MessageFormat]: /mcollective/reference/basic/messageformat.html
 [MessageFlow]: /mcollective/reference/basic/messageflow.html
 [NetworksOfBrokers]: http://activemq.apache.org/networks-of-brokers.html
-[UsingSSL]: http://activemq.apache.org/how-do-i-use-ssl.html
-[SecurityWithActiveMQ]: /mcollective/reference/integration/activemq_security.html
 [SampleConfig]: http://github.com/puppetlabs/marionette-collective/tree/master/ext/activemq/
+[fuse_cluster]: http://fusesource.com/docs/broker/5.5/clustering/index.html
+[activemq_network]: /mcollective/deploy/middleware/activemq.html#settings-for-networks-of-brokers
 
 Relying on existing middleware tools and not re-inventing the transport wheel ourselves means we can take advantage of a lot of the built in features they provide.  One such feature is clustering in ActiveMQ that allows for highly scalable and flexible network layouts.
 
 We'll cover here how to build a multi data center network of ActiveMQ servers with a NOC, the NOC computers would not need to send any packets direct to the nodes they manage and thanks to our meta data based approach to addressing machines they do not even need to know IPs or hostnames.
 
-There is an example of a 3 node cluster in the [ext/activemq directory][SampleConfig].
+There is an example of a 3 node cluster in the [ext/activemq directory of the MCollective source][SampleConfig].
 
 ## Network Design
 
@@ -24,12 +23,12 @@ There is an example of a 3 node cluster in the [ext/activemq directory][SampleCo
 
 The diagram above shows our sample network, I am using the same techniques to put an ActiveMQ in each of 4 countries and then having local nodes communicate to in-country ActiveMQ nodes.
 
- * These are the terminals of your NOC staff, they run the client code, these could also be isolated web servers for running admin tools etc.
- * Each location has its own instance of ActiveMQ and nodes would only need to communicate to their local ActiveMQ.  This greatly enhances security in a setup like this.
- * The ActiveMQ instances speak to each other using a protocol called OpenWire, you can run this over IPSec or you could use the native support for SSL.
- * These are the servers being managed, they run the server code.  No direct communications needs to be in place between NOC and managed servers.
+* These are the terminals of your NOC staff, they run the client code, these could also be isolated web servers for running admin tools etc.
+* Each location has its own instance of ActiveMQ and nodes would only need to communicate to their local ActiveMQ.  This greatly enhances security in a setup like this.
+* The ActiveMQ instances speak to each other using a protocol called OpenWire, you can run this over IPSec or you could use the native support for SSL.
+* These are the servers being managed, they run the server code.  No direct communications needs to be in place between NOC and managed servers.
 
-Refer to the [MessageFlow] document to see how messages would traverse the middleware in a setup like this.
+Refer to the [MessageFlow][] document to see how messages would traverse the middleware in a setup like this.
 
 ### General Observations
 The main design goal here is to promote network isolation, the staff in your NOC are often high churn people, you'll get replacement staff relatively often and it's a struggle to secure what information they carry and how and when you can trust them.
@@ -38,80 +37,21 @@ Our model of using middleware and off-loading authentication and authorization o
 
 Our usage of meta data to address machines rather than hostnames or ip address means you do not need to divulge this information to NOC staff, from their point of view they access machines like this:
 
- * All machines in _datacenter=a_
- * AND all machines with puppet class _/webserver/_
- * AND all machines with Facter fact _customer=acmeinc_
+* All machines in _datacenter=a_
+* AND all machines with puppet class _/webserver/_
+* AND all machines with Facter fact _customer=acmeinc_
 
 In the end they can target the machines they need to target for maintenance commands as above without the need for any info about hostnames, ips, or even what/where data center A is.
 
 This model works particularly well in a Cloud environment where hostnames are dynamic and not under your control, in a cloud like Amazon S3 machines are better identified by what AMI they have booted and in what availability zones they are rather than what their hostnames are.
 
 ## ActiveMQ Configuration
-ActiveMQ supports many types of cluster, I think their Network of Brokers model works best for us so I'll show a sample setup of that.
 
-There are some relevant docs on the ActiveMQ Wiki:
+ActiveMQ supports many types of cluster; we think their Network of Brokers model works best for MCollective.
 
- * [Network of Brokers][NetworksOfBrokers]
- * [Using SSL for transport security][UsingSSL]
+You will need to configure your ActiveMQ servers with everything from the ["Settings for Networks of Brokers" section of the ActiveMQ config reference][activemq_network]. Note the comments about the bi-directional connections: In the example network described above, you could either configure a pair of connectors on each datacenter broker to connect them to the NOC, or configure several pairs of connectors on the NOC broker to connect it to every datacenter. Do whichever makes sense for your own convenience and security needs.
 
-## Configuring Transports
+There is also a set of example config files in the [ext/activemq directory of the MCollective source][SampleConfig]; refer to these while reading the config reference. 
 
-First you should configure transport for that each ActiveMQ will listen on, this is the configuration for the NOC node, you'd just mirror this setup on each ActiveMQ node.
+See [the ActiveMQ docs][NetworksOfBrokers] or [the Fuse docs][fuse_cluster] for more detailed info about networks of brokers.
 
-{%highlight xml linenos %}
- <broker xmlns="http://activemq.org/config/1.0" brokerName="noc1-broker" useJmx="true"
-      dataDirectory="${activemq.base}/data">
-
-      <transportConnectors>
-         <transportConnector name="openwire" uri="tcp://0.0.0.0:6166"/>
-         <transportConnector name="stomp"   uri="stomp://0.0.0.0:6163"/>
-      </transportConnectors>
-{% endhighlight %}
-
- * *The _brokerName_ attribute is important and should be unique.* (Leaving it set to localhost will cause message loops to occur)
- * The _openwire_ transport is the important one here, you can make it listen on specific hosts and ports as shown.
-
-## Connecting to other ActiveMQs
-
-Next up you should configure the _networkConnectors_:
-
-{%highlight xml linenos %}
-    <networkConnectors>
-       <networkConnector name="noc1-dc1amq1" uri="static:(tcp://192.168.1.10:6166)" userName="amq" password="Afuphohxoh" duplex="true"/>
-    </networkConnectors>
-{% endhighlight %}
-
-Here we're connecting the NOC to Data Center 1.
-
- * The _name_ on each connector should be unique, I just list the pair of hostnames involved which should be unique.
- * This is a bi-directional connection it can send and receive traffic, you can make uni directional connections too if you wanted
- * We're authenticating with a username and password
-
-There are many more options you can set on these connectors and it varies on your topology, you can make a ring of brokers or redundant meshes etc.
-
-### Setting up Authentication
-
-We have an [entire page dedicated][SecurityWithActiveMQ] to the subject of users and authentication, you should check that page out for full details but here's a simple bit of config for the authentication above.
-
-{%highlight xml linenos %}
-    <plugins>
-      <simpleAuthenticationPlugin>
-        <users>
-          <authenticationUser username="amq" password="Afuphohxoh" groups="admins,everyone"/>
-        </users>
-      </simpleAuthenticationPlugin>
-      <authorizationPlugin>
-        <map>
-          <authorizationMap>
-            <authorizationEntries>
-              <authorizationEntry queue=">" write="admins" read="admins" admin="admins" />
-              <authorizationEntry topic=">" write="admins" read="admins" admin="admins" />
-            </authorizationEntries>
-          </authorizationMap>
-        </map>
-      </authorizationPlugin>
-    </plugins>
-  </broker>
-{% endhighlight %}
-
-You can now duplicate this on your other nodes, the NOC will have users and NetworkConnectors for the Data Center 2 as well, you can also flip it around so the DCs connect to the NOC which might be more secure.
index 2b5fbb3b7c547452e01ea0acb6f06521402a47ea..e3ca4ed527ef15b2443803b2e4ab3c0d95b652a7 100644 (file)
@@ -3,90 +3,36 @@ layout: default
 title: ActiveMQ Security
 toc: false
 ---
+
 [Security]: http://activemq.apache.org/security.html
-[Registration]: /mcollective/reference/plugins/registration.html
 [Wildcard]: http://activemq.apache.org/wildcards.html
-[ActiveMQ TLS]: activemq_ssl.html
+[activemq_config]: /mcollective/deploy/middleware/activemq.html
+[mcollective_username]: /mcollective/reference/plugins/connector_activemq.html#configuring-mcollective
+[mcollective_tls]: ./activemq_ssl.html#configuring-mcollective-servers
 
-As part of rolling out mcollective you need to think about security. The various examples in the quick start guide and on this blog has allowed all agents to talk to all nodes all agents. The problem with this approach is that should you have untrusted users on a node they can install the client applications and read the username/password from the server config file and thus control your entire architecture.
+As part of rolling out MCollective you need to think about security. The various examples in the quick start guide and on this blog has allowed all agents to talk to all nodes all agents. The problem with this approach is that should you have untrusted users on a node they can install the client applications and read the username/password from the server config file and thus control your entire architecture.
 
 The default format for message topics is compatible with [ActiveMQ wildcard patterns][Wildcard] and so we can now do fine grained controls over who can speak to what.
 
 General information about [ActiveMQ Security can be found on their wiki][Security].
 
-The default message targets looks like this:
-
-{% highlight console %}
-    /topic/mcollective.agentname.command
-    /topic/mcollective.agentname.reply
-{% endhighlight %}
-
-If you are using Subcollectives each subcollective will have topics like:
-
-{% highlight console %}
-    /topic/subcollective.agentname.command
-    /topic/subcollective.agentname.reply
-{% endhighlight %}
-
-For a node to belong to a sub collective he also need rights to these topics.
-
-The nodes only need read access to the command topics and only need write access to the reply topics. The examples below also give them admin access so these topics can be created dynamically. For simplicity we'll wildcard the agent names, you could go further and limit certain nodes to only run certain agents. Adding these controls effectively means anyone who gets onto your node will not be able to write to the command topics and so will not be able to send commands to the rest of the collective.
-
-There's one special case and that's the registration topic, if you want to enable the [registration feature][Registration] you should give the nodes access to write on the command channel for the registration agent. Nothing should reply on the registration topic so you can limit that in the ActiveMQ config.
-
-We'll let mcollective log in as the mcollective user, create a group called mcollectiveusers, we'll then give the mcollectiveusers group access to run as a typical registration enabled mcollective node.
-
-The rip user is a mcollective admin and can create commands and receive replies.
-
-First we'll create users and the groups.
-
-{% highlight xml %}
-    <simpleAuthenticationPlugin>
-     <users>
-      <authenticationUser username="mcollective" password="pI1SkjRi" groups="mcollectiveusers,everyone"/>
-      <authenticationUser username="rip" password="foobarbaz" groups="admins,everyone"/>
-     </users>
-    </simpleAuthenticationPlugin>
-{% endhighlight %}
-
-Now we'll create the access rights:
+## Configuring Security in activemq.xml
 
-{% highlight xml %}
-    <authorizationPlugin>
-      <map>
-        <authorizationMap>
-          <authorizationEntries>
-            <authorizationEntry queue="mcollective.>" write="admins" read="admins" admin="admins" />
-            <authorizationEntry topic="mcollective.>" write="admins" read="admins" admin="admins" />
-            <authorizationEntry topic="mcollective.*.reply" write="mcollectiveusers" admin="mcollectiveusers" />
-            <authorizationEntry topic="mcollective.registration.command" write="mcollectiveusers" read="mcollectiveusers" admin="mcollectiveusers" />
-            <authorizationEntry topic="mcollective.*.command" read="mcollectiveusers" admin="mcollectiveusers" />
-            <authorizationEntry topic="ActiveMQ.Advisory.>" read="everyone,all" write="everyone,all" admin="everyone,all"/>
-          </authorizationEntries>
-        </authorizationMap>
-      </map>
-    </authorizationPlugin>
-{% endhighlight %}
+[The ActiveMQ config reference][activemq_config] contains all relevant info for configuring security is activemq.xml. The most relevant sections are: 
 
-You could give just the specific node that runs the registration agent access to mcollective.registration.command to ensure the secrecy of your node registration.
+* [Topic and Queue Names](/mcollective/deploy/middleware/activemq.html#topic-and-queue-names) --- Info about the destinations that MCollective uses.
+* [Transport Connectors](/mcollective/deploy/middleware/activemq.html#transport-connectors) --- URL structure for insecure and TLS transports.
+* [TLS Credentials](/mcollective/deploy/middleware/activemq.html#tls-credentials) --- For use with TLS transports.
+* [Authentication](/mcollective/deploy/middleware/activemq.html#authentication-users-and-groups) --- Establishing user accounts and groups.
+* [Authorization](/mcollective/deploy/middleware/activemq.html#authorization-group-permissions) --- Limiting access to destinations based on group membership.
+* [Destination Filtering](/mcollective/deploy/middleware/activemq.html#destination-filtering) --- Preventing certain messages from crossing between datacenters.
 
-Finally the nodes need to be configured, the server.cfg should have the following at least:
 
-{% highlight ini %}
-    plugin.stomp.user = mcollective
-    plugin.stomp.password = pI1SkjRi
-    plugin.psk = aBieveenshedeineeceezaeheer
-{% endhighlight %}
 
-For my clients I can use the ability to configure the user details in my shell environment:
+## Configuring Security in MCollective
 
-{% highlight bash %}
-    export STOMP_USER=rip
-    export STOMP_PASSWORD=foobarbaz
-    export STOMP_SERVER=stomp1
-    export MCOLLECTIVE_PSK=aBieveenshedeineeceezaeheer
-{% endhighlight %}
+MCollective clients and servers need security credentials that line up with ActiveMQ's expectations. Specifically:
 
-And finally the rip user when logged into a shell with these variables have full access to the various commands. You can now give different users access to the entire collective or go further and give a certain admin user access to only run certain agents by limiting the command topics they have access to. Doing the user and password settings in shell environments means it's not kept in any config file in /etc/ for example.
+* [An ActiveMQ username and password][mcollective_username]
+* [TLS credentials, if necessary][mcollective_tls]
 
-Your next step should be to setup TLS between your nodes and your middleware, to set this up follow our [ActiveMQ TLS] quide.
index 4e21b72fc7e84285f8178a5f751c53035c77c024..ea9a90d00f45f9dbcd3d058b4955ab38a9693899 100644 (file)
@@ -3,159 +3,81 @@ layout: default
 title: ActiveMQ TLS
 toc: false
 ---
-[Security]: http://activemq.apache.org/security.html
-[Registration]: /mcollective/reference/plugins/registration.html
-[Wildcard]: http://activemq.apache.org/wildcards.html
 
-In order to achieve end to end encryption we use TLS encryption between
-ActiveMQ, the nodes and the client.
+[keystores]: /mcollective/deploy/middleware/activemq_keystores.html
+[sslcontext]: /mcollective/deploy/middleware/activemq.html#tls-credentials
+[transport]: /mcollective/deploy/middleware/activemq.html#transport-connectors
 
-To set this up you need to Java Keystore, the instructions here work for Java
-1.6 either Sun or OpenJDK based.
+[activemq_connector]: /mcollective/reference/plugins/connector_activemq.html
+[ssl_security]: /mcollective/reference/plugins/security_ssl.html
+[aes_security]: /mcollective/reference/plugins/security_aes.html
 
-## Full CA verified TLS between Stomp >= 1.2.2 and ActiveMQ
-As of MCollective 2.0.0 and Stomp 1.2.2 it's possible to setup a TLS setup
-that will only accept clients with certificates signed by a CA shared with
-your clients and your ActiveMQ server like the one provided by Puppet.
+You can configure MCollective and ActiveMQ to do end-to-end encryption over TLS. This allows you to use MCollective's fast and efficient [SSL security plugin][ssl_security] instead of the slow and hard to configure [AES security plugin][aes_security]. 
 
-You can only use this setup using the ActiveMQ specific connector plugin, not using
-the generic Stomp one.
+There are two main approaches:
 
-These examples will use the Puppet CA to generate the certificates but you can
-use any CA as long as you have PEM format keys and certificates.
+* [CA-verified TLS](#ca-verified-tls) encrypts traffic, and also lets you restrict middleware connections --- only nodes with valid certificates from the site's CA can connect.
+* [Anonymous TLS](#anonymous-tls) encrypts messages to prevent casual traffic sniffing, and will prevent the passwords MCollective uses to connect to ActiveMQ from being stolen. However, it doesn't check whether nodes are allowed to connect, so you have to trust your username and password security.
 
-### Create ActiveMQ certificates and keystores
-With this setup we need the following:
+This feature requires:
 
- * A certificate and keys for the ActiveMQ - we will call the ActiveMQ instance stomp.my.net
- * A Certificate Authority certificate
- * A key store for the ActiveMQ certificates
- * A trust store instructing ActiveMQ what connections to trust
+* MCollective 2.0.0 or newer
+* ActiveMQ 5.5.0 or newer
+* Stomp gem 1.2.2 or newer
+* The [activemq connector][activemq_connector] plugin (included with MCollective 2.0.0 and newer)
 
-First we create the trust store, we load in our CA file which will instruct ActiveMQ
-to trust any certificate signed by the Puppet CA. You could also load in each individual
-certificate for every client if you wanted to be really strict about it.
+## CA-Verified TLS
 
-{% highlight bash %}
-# keytool -import -alias "My CA" -file /var/lib/puppet/ssl/ca/ca_crt.pem -keystore truststore.jks
-Enter keystore password:
-Re-enter new password:
-.
-.
-.
-Trust this certificate? [no]:  y
-Certificate was added to keystore
-{% endhighlight %}
-
-You can view your certificate:
-
-{% highlight bash %}
-# keytool -list -keystore truststore.jks
-Enter keystore password:
-
-Keystore type: JKS
-Keystore provider: SUN
-
-Your keystore contains 1 entry
-
-my ca, Mar 30, 2012, trustedCertEntry,
-Certificate fingerprint (MD5): 99:D3:28:6B:37:13:7A:A2:B8:73:75:4A:31:78:0B:68
-{% endhighlight %}
-
-Note the MD5 fingerprint, you can verify this is the one from your CA:
-
-{% highlight bash %}
-# openssl x509 -in /var/lib/puppet/ssl/ca/ca_crt.pem -fingerprint -md5
-MD5 Fingerprint=99:D3:28:6B:37:13:7A:A2:B8:73:75:4A:31:78:0B:68
-{% endhighlight %}
+**(Recommended For Most Users)**
 
-Now we create the certificate for our ActiveMQ machine and store that in the key store
+### Summary
 
-{% highlight bash %}
-# puppet cert generate stomp.my.net
-notice: stomp.my.net has a waiting certificate request
-notice: Signed certificate request for stomp.my.net
-notice: Removing file Puppet::SSL::CertificateRequest stomp.my.net at '/var/lib/puppet/ssl/ca/requests/stomp.my.net.pem'
-notice: Removing file Puppet::SSL::CertificateRequest stomp.my.net at '/var/lib/puppet/ssl/certificate_requests/stomp.my.net.pem'
-{% endhighlight %}
+This approach configures MCollective and ActiveMQ to only accept connections when the peer has a certificate signed by the site's CA. 
 
-And then we convert it into a format keytool can understand and import it:
+**Benefits:**
 
-{% highlight bash %}
-# cat /var/lib/puppet/ssl/private_keys/stomp.my.net.pem /var/lib/puppet/ssl/certs/stomp.my.net.pem > temp.pem
-# openssl pkcs12 -export -in temp.pem -out activemq.p12 -name stomp.my.net
-Enter Export Password:
-Verifying - Enter Export Password:
-# keytool -importkeystore  -destkeystore keystore.jks -srckeystore activemq.p12 -srcstoretype PKCS12 -alias stomp.my.net
-Enter destination keystore password:
-Re-enter new password:
-Enter source keystore password:
-{% endhighlight %}
+This approach gives extra security, and your MCollective servers will generally already have the credentials they need since you can re-use Puppet certificates.
 
-You can validate this was correct:
+**Drawbacks:**
 
-{% highlight bash %}
-# keytool -list -keystore keystore.jks
-Enter keystore password:
+You will need to go out of your way to issue keys and certificates to your admin users, which is an extra step when onboarding a new admin.
 
-Keystore type: JKS
-Keystore provider: SUN
 
-Your keystore contains 1 entry
+### Step 1: Configure ActiveMQ to Use TLS
 
-stomp.my.net, Mar 30, 2012, PrivateKeyEntry,
-Certificate fingerprint (MD5): 7E:2A:B4:4D:1E:6D:D1:70:A9:E7:20:0D:9D:41:F3:B9
+Do the following steps to get ActiveMQ configured:
 
-# puppet cert fingerprint stomp.my.net --digest=md5
-MD5 Fingerprint=7E:2A:B4:4D:1E:6D:D1:70:A9:E7:20:0D:9D:41:F3:B9
-{% endhighlight %}
+* Follow [the ActiveMQ keystores guide][keystores] to create Java keystores for ActiveMQ.
+* [Configure activemq.xml's `<sslContext>` element to point at the keystores.][sslcontext]
+* [Configure the proper URIs in the broker's transport connectors.][transport]
+* Restart ActiveMQ.
 
-### Configure ActiveMQ
-We need to tell ActiveMQ to read the stores we made:
+At this point, MCollective servers and clients should be unable to connect to ActiveMQ, since they do not yet have credentials configured.
 
-{% highlight xml %}
-<sslContext>
-   <sslContext
-       keyStore="keystore.jks" keyStorePassword="secret"
-       trustStore="truststore.jks" trustStorePassword="secret"
-   />
-</sslContext>
-{% endhighlight %}
+### Step 2: Configure MCollective Servers
 
-And we need to tell ActiveMQ to only accept fully verified connections:
-
-{% highlight xml %}
-<transportConnectors>
-    <transportConnector name="openwire" uri="tcp://0.0.0.0:6166"/>
-    <transportConnector name="stompssl" uri="stomp+ssl://0.0.0.0:6164?needClientAuth=true"/>
-</transportConnectors>
-{% endhighlight %}
-
-If you were to attempt to connect a mcollectived or client using the anonymous setup
-detailed above that should fail as we have not yet setup credentials for the mcollectived
-or mcollective client to use.
-
-### Setting up mcollectived
-
-For the MCollective daemon you can use your existing Puppet certificates by editing the _server.cfg_
+For the MCollective daemon you can use your existing Puppet certificates by editing the _server.cfg_ file:
 
 {% highlight ini %}
 connector = activemq
-plugin.activemq.base64 = yes
-plugin.activemq.pool.size = 2
-plugin.activemq.pool.1.host = stomp.my.net
-plugin.activemq.pool.1.port = 6164
+# Optional:
+# plugin.activemq.base64 = yes
+plugin.activemq.pool.size = 1
+plugin.activemq.pool.1.host = stomp.example.com
+plugin.activemq.pool.1.port = 61614
 plugin.activemq.pool.1.user = mcollective
 plugin.activemq.pool.1.password = secret
-plugin.activemq.pool.1.ssl = 1
+plugin.activemq.pool.1.ssl = true
 plugin.activemq.pool.1.ssl.ca = /var/lib/puppet/ssl/ca/ca_crt.pem
-plugin.activemq.pool.1.ssl.key = /var/lib/puppet/ssl/private_keys/fqdn.pem
-plugin.activemq.pool.1.ssl.cert = /var/lib/puppet/ssl/certs/fqdn.pem
+plugin.activemq.pool.1.ssl.key = /var/lib/puppet/ssl/private_keys/<NAME>.pem
+plugin.activemq.pool.1.ssl.cert = /var/lib/puppet/ssl/certs/<NAME>.pem
 {% endhighlight %}
 
-Fix the paths to the private key and certificate, they will be named after your machines FQDN.
+* Set the correct paths to each node's private key and certificate; they will be named after the node's Puppet certname and located in the ssldir.
+    * You can locate a node's private key by running `sudo puppet agent --configprint hostprivkey`, the certificate with `sudo puppet agent --configprint hostcert`, and the CA certificate with `sudo puppet agent --configprint localcacert`.
+* Set the correct username and password.
 
-### Setting up mcollective clients
+### Step 3: Configure MCollective Clients
 
 Each client will now need a TLS certificate issued by the Puppet CA in order to be able to
 connect to the ActiveMQ:
@@ -183,29 +105,35 @@ You can now configure the mcollective client config in _/home/rip/.mcollective_
 
 {% highlight ini %}
 connector = activemq
-plugin.activemq.base64 = yes
-plugin.activemq.pool.size = 2
-plugin.activemq.pool.1.host = stomp.my.net
-plugin.activemq.pool.1.port = 6164
+# Optional:
+# plugin.activemq.base64 = yes
+plugin.activemq.pool.size = 1
+plugin.activemq.pool.1.host = stomp.example.com
+plugin.activemq.pool.1.port = 61614
 plugin.activemq.pool.1.user = ripienaar
 plugin.activemq.pool.1.password = secret
-plugin.activemq.pool.1.ssl = 1
+plugin.activemq.pool.1.ssl = true
 plugin.activemq.pool.1.ssl.ca = /home/rip/.mcollective.d/ca_crt.pem
 plugin.activemq.pool.1.ssl.key = /home/rip/.mcollective.d/ripienaar-private.pem
 plugin.activemq.pool.1.ssl.cert = /home/rip/.mcollective.d/ripienaar-cert.pem
 {% endhighlight %}
 
-If you are using the SSL or AES security plugins you can use these same files using the _/home/rip/.mcollective.d/ripienaar.pem_
-as the public key for those plugins.
+If you are using the SSL security plugin, you can use these same files by setting `/home/rip/.mcollective.d/ripienaar.pem` as the public key.
 
-### Common Errors
+### Finish: Verify Encryption
 
-You will get some obvious errors from this code if any files are missing, but the errors fro SSL validation will be pretty
+If you want to be sure of this, you should now verify with tcpdump or wireshark that the connection and traffic
+really is all encrypted.
+
+### Troubleshooting Common Errors
+
+You will get some obvious errors from this code if any files are missing, but the errors from SSL validation will be pretty
 hard to understand.
 
-There are only 2 scenarios here:
+There are two main scenarios where ActiveMQ will reject an MCollective conneciton:
+
+#### MCollective Uses Wrong CA to Verify ActiveMQ Cert
 
-#### ActiveMQ rejects the client
 When the client connects using a CA set in _plugin.activemq.pool.1.ssl.ca_ that does not match the one
 in the ActiveMQ _truststore.jks_:
 
@@ -219,6 +147,8 @@ And in the ActiveMQ log:
 Transport failed: javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca
 {% endhighlight %}
 
+#### MCollective Certs Aren't Signed by the Right CA
+
 When your client has the correct CA but his certificates are not signed by that CA:
 
 {% highlight console %}
@@ -231,57 +161,64 @@ And in the ActiveMQ log:
 sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
 {% endhighlight %}
 
-## Basic anonymous TLS between Stomp and ActiveMQ
-### Create a keystore with existing certs
-If you have an exiting PKI deployment, you can probably reuse Puppet ones too the main
-point is that you already have a key and signed cert signed by some CA and you
-now want to create a Java Keystore follow these steps:
 
-{% highlight bash %}
-# cat /etc/pki/host.key /etc/pki/ca.pem /etc/pki/host.cert >cert.pem
-# openssl pkcs12 -export -in cert.pem -out activemq.p12 -name `hostname`
-# keytool -importkeystore -deststorepass secret -destkeypass secret -destkeystore keystore.jks -srckeystore activemq.p12 -srcstoretype PKCS12 -alias `hostname`
-{% endhighlight %}
 
-The above steps will create a standard Java keystore in _keystore.jks_ which you
-should store in your ActiveMQ config directory.  It will have a password
-_secret_ you should change this.
 
-### Configure ActiveMQ
 
-To let ActiveMQ load your keystore you should add the following to the
-_activemq.xml_ file:
+## Anonymous TLS
 
-{% highlight xml %}
-<sslContext>
-   <sslContext keyStore="keystore.jks" keyStorePassword="secret" />
-</sslContext>
-{% endhighlight %}
+**(Less Recommended)**
 
-And you should add a SSL stomp listener, you should get port 6164 opened:
+### Summary
 
-{% highlight xml %}
-<transportConnectors>
-    <transportConnector name="openwire" uri="tcp://0.0.0.0:6166"/>
-    <transportConnector name="stomp" uri="stomp://0.0.0.0:6163"/>
-    <transportConnector name="stompssl" uri="stomp+ssl://0.0.0.0:6164"/>
-</transportConnectors>
-{% endhighlight %}
+This approach configures MCollective and ActiveMQ to encrypt traffic via TLS, but accept connections from anyone.
+
+**Benefits:**
+
+This approach requires less configuration, especially when adding new admin users.
+
+**Drawbacks:**
+
+This approach has some relative security drawbacks. Depending on your site's security needs, these may not concern you --- since MCollective's application-level security plugins will prevent an attacker from issuing agent commands and owning your servers, attacks like those below would only result in denial of service plus some leakage of inventory data via lower-level discovery protocols.
+
+* Although attackers can't sniff MCollective's ActiveMQ passwords, there's nothing to prevent them from logging in if they steal a password through some other means. (With CA-verified TLS, on the other hand, they would also require a private key and certificate, which provides some additional security depth.)
+* An attacker able to run a man-in-the-middle attack at your site could fool your MCollective servers into trusting a malicious ActiveMQ server. 
 
-### Configure MCollective
 
-The last step is to tell MCollective to use the SSL connection, to do this you
-need to use the new pool based configuration, even if you just have 1 ActiveMQ
-in your pool:
+### Step 1: Configure ActiveMQ to Use Anonymous TLS
+
+* Follow [the ActiveMQ keystores guide][keystores] to create a Java keystore for ActiveMQ. _You can skip the truststore._ 
+* [Configure activemq.xml's `<sslContext>` element to point at the keystore.][sslcontext] _You can skip the `trustStore` and `trustStorePassword` attributes._
+* [Configure the proper URIs in the broker's transport connectors][transport], but _leave off the `?needClientAuth=true` portion._
+* Restart ActiveMQ.
+
+
+### Step 2: Configure MCollective Servers and Clients
+
+Set the following settings in the `server.cfg` and `client.cfg` (or `~/.mcollective`) files:
 
 {% highlight ini %}
-plugin.stomp.pool.size = 1
-plugin.stomp.pool.host1 = stomp.your.com
-plugin.stomp.pool.port1 = 6164
-plugin.stomp.pool.user1 = mcollective
-plugin.stomp.pool.password1 = secret
-plugin.stomp.pool.ssl1 = true
+connector = activemq
+# Optional:
+# plugin.activemq.base64 = yes
+plugin.activemq.pool.size = 1
+plugin.activemq.pool.1.host = stomp.example.com
+plugin.activemq.pool.1.port = 61614
+plugin.activemq.pool.1.user = mcollective
+plugin.activemq.pool.1.password = secret
+plugin.activemq.pool.1.ssl = true
+plugin.activemq.pool.1.ssl.fallback = true
 {% endhighlight %}
 
-You should now verify with tcpdump or wireshark that the connection and traffic
+The `plugin.activemq.pool.1.ssl.fallback` setting tells the plugin that it is allowed to:
+
+* Connect to an unverified server
+* Connect without presenting its own SSL credentials
+
+...if it is missing any of the `.ca` `.cert` or `.key` settings or cannot find the files they reference. If the settings _are_ present (and point to correct files), MCollective will try to do a verified connection.
+
+
+### Finish: Verify Encryption
+
+If you want to be sure of this, you should now verify with tcpdump or wireshark that the connection and traffic
 really is all encrypted.
index f38bade522e33ccb1561f455d44465ffd7817673..1456d18fb792070f5bbec14251d2a0ff9c701186 100644 (file)
@@ -3,118 +3,78 @@ layout: default
 title: ActiveMQ Connector
 toc: false
 ---
+
 [STOMP]: http://stomp.codehaus.org/
+[wildcard]: http://activemq.apache.org/wildcards.html
+[subcollectives]: /reference/basic/subcollectives.html
+[activemq_config]: /mcollective/deploy/middleware/activemq.html
+
 
-The ActiveMQ connector uses the [STOMP] rubygem to connect to ActiveMQ servers.  It is specifically optimiszed for ActiveMQ
+The ActiveMQ connector uses the [STOMP][] rubygem to connect to ActiveMQ servers.  It is specifically optimized for ActiveMQ
 and uses features in ActiveMQ 5.5.0 and later.
 
-This code will only work with version _1.1.8_ or newer of the Stomp gem.
+This plugin requires version _1.2.2_ or newer of the Stomp gem.
 
 ## Differences between ActiveMQ connector and Stomp Connector
 
-The ActiveMQ connector requires MCollective 2.0.0 or newer and introduce a new structure to the middleware messsages.
+### Topic and Queue Names
 
- * Replies goes direct to clients using short lived queues
- * Agent topics are called */topic/&lt;collective&gt;.&lt;agent_name&gt;.agent*
- * Support for point to point messages are added by using _/queue/&lt;collective&gt;.nodes_ and using JMS selectors.
+The new connector uses different destination names from the old stomp connector. 
 
-The use of short lived queues mean that replies are now going to go back only to the person who sent the request.
-This has big impact on overall CPU usage by clients on busy networks but also optimize the traffic flow on
-networks with many brokers.
+MCollective uses the following destination names. This list uses standard [ActiveMQ destination wildcards][wildcard]. "COLLECTIVE" is the name of the collective being used; by default, this is `mcollective`, but if you are using [subcollectives][], each one is implemented as an equal peer of the default collective.
+
+Topics: 
+
+- `ActiveMQ.Advisory.>` (built-in topics that all ActiveMQ producers and consumers need all permissions on)
+- `COLLECTIVE.*.agent` (for each agent plugin, where the `*` is the name of the plugin)
+
+Queues:
+
+- `COLLECTIVE.nodes` (used for direct addressing; this is a single destination that uses JMS selectors, rather than a group of destinations)
+- `COLLECTIVE.reply.>` (where the continued portion is a request ID)
 
-Point to Point messages means each node has a unique subscription, the approach using JMS Selectors means
-internally to ActiveMQ only a single thread will be dedicated to this rather than 1 per connected node.
+Note especially that:
+
+* We can now do direct addressing to specific nodes.
+* Replies now go directly to the instigating client instead of being brodcast on a topic. 
+
+This has big impact on overall CPU usage by clients on busy networks, and also optimizes the traffic flow on
+networks with many brokers.
 
-Before using this plugin you will need to make appropriate adjustments to your ActiveMQ Access Control Lists.
 
 ## Configuring ActiveMQ
-For best behavior there are a few settings you need in your _activemq.xml_
-
-### Remove unused queues
-We use uniquely named queues for replies.  As queues will live forever we need to get ActiveMQ to remove
-queues we are done with else they will just add up and grow forever.
-
-{% highlight xml %}
-<destinationPolicy>
-  <policyMap>
-    <policyEntries>
-      <policyEntry queue="*.reply.>" gcInactiveDestinations="true" inactiveTimoutBeforeGC="300000" />
-    </policyEntries>
-  </policyMap>
-</destinationPolicy>
-{% endhighlight %}
 
-The above policy will instruct ActiveMQ to remove dead queues after 5 minutes.
-
-### Optimize network usage for direct requests in a network of brokers
-If you are using a network of brokers you will need to make a big change to how that works.
-At present we tend to have 1 bi-directional connection for everything, with direct requests
-we dedicate a bi-directional connection for these queues leaving the other just for topics.
-
-{% highlight xml %}
-<networkConnectors>
-  <networkConnector
-        name="stomp1-stomp2-topics"
-        uri="static:(tcp://stomp2.xx.net:6166)"
-        userName="amq"
-        password="secret"
-        duplex="true"
-        decreaseNetworkConsumerPriority="true"
-        networkTTL="2"
-        dynamicOnly="true">
-        <excludedDestinations>
-                <queue physicalName=">" />
-        </excludedDestinations>
-  </networkConnector>
-  <networkConnector
-        name="stomp1-stomp2-queues"
-        uri="static:(tcp://stomp2.xx.net:6166)"
-        userName="amq"
-        password="secret"
-        duplex="true"
-        decreaseNetworkConsumerPriority="true"
-        networkTTL="2"
-        dynamicOnly="true"
-        conduitSubscriptions="false">
-        <excludedDestinations>
-                <topic physicalName=">" />
-        </excludedDestinations>
-  </networkConnector>
-</networkConnectors>
-{% endhighlight %}
+See [the ActiveMQ config reference][activemq_config] for details on configuring ActiveMQ for this connector. As recommended at the top of the reference, you should skim the sections you care about and edit an example config file while reading. 
 
-You will need to adjust the TTL for your network.  Note the queue connection has a different
-_conduitSubscriptions_ policy than the topic one, you have to create these different connections
-and set this policy for everything to work correctly.
 
 ## Configuring MCollective
 
-### Common Options
-The most basic configuration method is supported in all versions of the gem:
+MCollective clients and servers use the same connector settings, although the value of settings involving credentials will vary.
 
 ### Failover Pools
+
 A sample configuration can be seen below.  Note this plugin does not support the old style config of the Stomp connector.
 
 {% highlight ini %}
 connector = activemq
 plugin.activemq.pool.size = 2
 plugin.activemq.pool.1.host = stomp1
-plugin.activemq.pool.1.port = 6163
+plugin.activemq.pool.1.port = 61613
 plugin.activemq.pool.1.user = me
 plugin.activemq.pool.1.password = secret
 
 plugin.activemq.pool.2.host = stomp2
-plugin.activemq.pool.2.port = 6163
+plugin.activemq.pool.2.port = 61613
 plugin.activemq.pool.2.user = me
 plugin.activemq.pool.2.password = secret
 {% endhighlight %}
 
 This gives it 2 servers to attempt to connect to, if the first one fails it will use the second.  Usernames and passwords can be set
-with the environment variables STOMP_USER, STOMP_PASSWORD.
+with the environment variables `STOMP_USER`, `STOMP_PASSWORD`.
 
 If you do not specify a port it will default to _61613_
 
-You can also specify the following options for the Stomp gem, these are the defaults in the Stomp 1.1.6 gem:
+You can also specify the following options for the Stomp gem, these are the defaults in the Stomp gem: <!-- last checked: v. 1.1.6 of the gem -->
 
 {% highlight ini %}
 plugin.activemq.initial_reconnect_delay = 0.01
index 2c39169dc7f2b5d889403cce509f894c33141f3a..fba83ab8b4f046ae24c778ec02ece056c2a096ec 100644 (file)
@@ -56,12 +56,12 @@ connector = rabbitmq
 plugin.rabbitmq.vhost = /mcollective
 plugin.rabbitmq.pool.size = 2
 plugin.rabbitmq.pool.1.host = rabbit1
-plugin.rabbitmq.pool.1.port = 6163
+plugin.rabbitmq.pool.1.port = 61613
 plugin.rabbitmq.pool.1.user = mcollective
 plugin.rabbitmq.pool.1.password = changeme
 
 plugin.rabbitmq.pool.2.host = rabbit2
-plugin.rabbitmq.pool.2.port = 6163
+plugin.rabbitmq.pool.2.port = 61613
 plugin.rabbitmq.pool.2.user = mcollective
 plugin.rabbitmq.pool.2.password = changeme
 {% endhighlight %}
index b3ec9f792ce3b8c2b359f97cc705696ac254471b..98eaa7a9c4fb654f48a4815006c953bcaa391aac 100644 (file)
@@ -4,6 +4,10 @@ title: STOMP Connector
 toc: false
 ---
 [STOMP]: http://stomp.codehaus.org/
+[ConnectorActiveMQ]: /mcollective/reference/plugins/connector_activemq.html
+[ConnectorRabbitMQ]: /mcollective/reference/plugins/connector_rabbitmq.html
+
+*NOTE:* This connector is being deprecated and will not be supported in versions newer than 2.2.x.  Please move to one of the [ConnectorActiveMQ] or [ConnectorRabbitMQ].
 
 The stomp connector uses the [STOMP] rubygem to connect to compatible servers.  This is known to work with ActiveMQ and Stompserver.  Anecdotal evidence suggests it works with RabbitMQ's Stomp plugin.
 
@@ -30,7 +34,7 @@ The most basic configuration method is supported in all versions of the gem:
 connector = stomp
 plugin.stomp.base64 = false
 plugin.stomp.host = stomp.my.net
-plugin.stomp.port = 6163
+plugin.stomp.port = 61613
 plugin.stomp.user = me
 plugin.stomp.password = secret
 {% endhighlight %}
@@ -49,12 +53,12 @@ logging about connections, failures and other significant events.
 connector = stomp
 plugin.stomp.pool.size = 2
 plugin.stomp.pool.host1 = stomp1
-plugin.stomp.pool.port1 = 6163
+plugin.stomp.pool.port1 = 61613
 plugin.stomp.pool.user1 = me
 plugin.stomp.pool.password1 = secret
 
 plugin.stomp.pool.host2 = stomp2
-plugin.stomp.pool.port2 = 6163
+plugin.stomp.pool.port2 = 61613
 plugin.stomp.pool.user2 = me
 plugin.stomp.pool.password2 = secret
 {% endhighlight %}
index e0e6f096373d11a77592b0b7f64bb61cf0ea2efb..e5768e3f6a5eee7ec8a438cdc99e9ba248b8d180 100644 (file)
@@ -3,6 +3,7 @@ layout: default
 title: Data Plugins
 ---
 [DDL]: /mcollective/reference/plugins/ddl.html
+[DiscoveryPlugins]: /mcollective/reference/plugins/discovery.html
 
 ## Overview
 Up to MCollective 2.0 the discovery system could only discover against
@@ -36,6 +37,11 @@ action "query" do
 end
 {% endhighlight %}
 
+*NOTE:* As opposed to the [DiscoveryPlugins] which are used by the client   
+to communicate to the nodes using direct addressing, data plugins on the other   
+hand refer to data that the nodes can provide, and hence this uses the normal  
+broadcast discovery paradigm.   
+
 These new data sources are plugins so you can provide via the plugin
 system and they require DDL documents.  The DDL will be used on both the
 client and the server to provide strict validation and configuration.
index 39adb0d478592cd609336681ef86eaebf6db4dca..5458cda198c66c9a936ee7e79f7a553475c96863 100644 (file)
@@ -6,7 +6,7 @@ title: Node Reports
 
 As we have all facts, classes and agents for nodes we can do some custom reporting on all of these.
 
-The _mc inventory_ tool is a generic node and network reporting tool, it has basic scripting abilities.
+The _mco inventory_ tool is a generic node and network reporting tool, it has basic scripting abilities.
 
 **Note: This is an emerging feature, the scripting language is likely to change**
 
@@ -55,7 +55,7 @@ We have a concept of [Subcollectives] and you can use the inventory application
 report on all known collectives:
 
 {% highlight console %}
-$ mc inventory --list-collectives
+$ mco inventory --list-collectives
 
  * [ ===================================== ] 52 / 52
 
@@ -77,7 +77,7 @@ $ mc inventory --list-collectives
 You can also create a DOT format graph of your collective:
 
 {% highlight console %}
-$ mc inventory --collective-graph collective.dot
+$ mco inventory --collective-graph collective.dot
 
 Retrieving collective info....
 Graph of 52 nodes has been written to collective.dot
index a5cd15f5b3b71fd5dc2f3d4cb2df608cede7d916..cc9f31ce5697cf64a8e2ca039c01e5442e579e9e 100644 (file)
@@ -10,7 +10,7 @@ will be highlighted here.
 
 <a name="2_3_1">&nbsp;</a>
 
-## 2.3.1 - 2012/02/14
+## 2.3.1 - 2013/02/14
 
 This is the second release in the new development series of MCollective.  This
 release features enhancements and bug fixes.
@@ -79,22 +79,22 @@ package upgrading from failing
 |Date|Description|Ticket|
 |----|-----------|------|
 |*2013/02/14*|*Release 2.3.1*|19265|
-|2012/02/14|Initial work towards internationalization and online help|18663|
+|2013/02/14|Initial work towards internationalization and online help|18663|
 |2013/02/14|Update vendored JSON gem for CVE-2013-0269|19265|
-|2012/02/13|Restore the ability to set a discovery timeout on a RPC client|19238|
-|2012/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200|
-|2012/02/12|Fix package building on certain Debian systems|19141|
-|2012/02/12|Remove the stomp connector|19146|
-|2012/02/07|Read the client config before trying to use any configuration options|19105|
-|2012/01/22|When an argument fails to parse in the rpc application fail rather than continue with unintended consequences|18773|
-|2012/01/22|The fix the *--no-response* argument to the rpc application that broke due to 18438|18513|
-|2012/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758|
-|2012/01/21|Improve presentation of the --help output for applications|18447|
-|2012/01/21|When a request failed via *reply.fail*, only show the message and not the half built data|18434|
+|2013/02/13|Restore the ability to set a discovery timeout on a RPC client|19238|
+|2013/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200|
+|2013/02/12|Fix package building on certain Debian systems|19141|
+|2013/02/12|Remove the stomp connector|19146|
+|2013/02/07|Read the client config before trying to use any configuration options|19105|
+|2013/01/22|When an argument fails to parse in the rpc application fail rather than continue with unintended consequences|18773|
+|2013/01/22|The fix the *--no-response* argument to the rpc application that broke due to 18438|18513|
+|2013/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758|
+|2013/01/21|Improve presentation of the --help output for applications|18447|
+|2013/01/21|When a request failed via *reply.fail*, only show the message and not the half built data|18434|
 
 <a name="2_2_3">&nbsp;</a>
 
-## 2.2.3 - 2012/02/14
+## 2.2.3 - 2013/02/14
 
 This is a maintenance release to the current production version of MCollective.
 This release is a bug fix only release.
@@ -125,16 +125,16 @@ ActiveMQ or RabbitMQ specific ones.
 |----|-----------|------|
 |*2013/02/14*|*Release 2.2.3*|19265|
 |2013/02/14|Update vendored JSON gem for CVE-2013-0269|19265|
-|2012/02/13|Restore the ability to set a discovery timeout on a RPC client|19238|
-|2012/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200|
-|2012/02/12|Fix package building on certain Debian systems|19141|
-|2012/02/12|Deprecate the stomp connector|19146|
-|2012/02/07|Read the client config before trying to use any configuration options|19105|
-|2012/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758|
+|2013/02/13|Restore the ability to set a discovery timeout on a RPC client|19238|
+|2013/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200|
+|2013/02/12|Fix package building on certain Debian systems|19141|
+|2013/02/12|Deprecate the stomp connector|19146|
+|2013/02/07|Read the client config before trying to use any configuration options|19105|
+|2013/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758|
 
 <a name="2_0_1">&nbsp;</a>
 
-## 2.0.1 - 2012/02/14
+## 2.0.1 - 2013/02/14
 
 This is a maintenance release against our unsupported past production release, it brings no
 visible changes or bug fixes we only updated the vendored JSON gem to version 1.5.5 due to
index b2521ed2720cf8a3fa124172bb4022bdcca21eb1..ad1ea18a2ad8d4814c58f5b7dae290acd5b74631 100644 (file)
@@ -50,7 +50,7 @@ end
 
 The call extra _authorized`_`by :authorize`_`it_ line tells your agent to use the _MCollective::Util::AuthorizeIt_ class for authorization.
 
-## Enabling RPC auditing globally
+## Enabling RPC authorization globally
 You can enable a specific plugin on all RPC agents in the server config file.  If you do this and an agent also specify it's own authorization the agent will take priority.
 
 {% highlight ini %}