You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2012/03/08 22:47:05 UTC

svn commit: r1298602 - in /qpid/trunk/qpid: cpp/etc/Makefile.am cpp/etc/cluster.conf-example.xml cpp/etc/qpidd-primary cpp/src/tests/cluster_failover tools/src/py/qpid-ha

Author: aconway
Date: Thu Mar  8 21:47:04 2012
New Revision: 1298602

URL: http://svn.apache.org/viewvc?rev=1298602&view=rev
Log:
QPID-3603: rgmanager integration for new HA cluster

- service start script qpid-primary, called by rgmanager to promote a broker.
- example cluster.conf
- minor changes to qpid-ha

Added:
    qpid/trunk/qpid/cpp/etc/cluster.conf-example.xml   (with props)
    qpid/trunk/qpid/cpp/etc/qpidd-primary   (with props)
    qpid/trunk/qpid/cpp/src/tests/cluster_failover   (with props)
Modified:
    qpid/trunk/qpid/cpp/etc/Makefile.am
    qpid/trunk/qpid/tools/src/py/qpid-ha

Modified: qpid/trunk/qpid/cpp/etc/Makefile.am
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/etc/Makefile.am?rev=1298602&r1=1298601&r2=1298602&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/etc/Makefile.am (original)
+++ qpid/trunk/qpid/cpp/etc/Makefile.am Thu Mar  8 21:47:04 2012
@@ -20,7 +20,7 @@ SASL_CONF = sasl2/qpidd.conf
 
 EXTRA_DIST = \
 	$(SASL_CONF) \
-	qpidd qpidd.conf qpidc.conf CMakeLists.txt
+	qpidd qpidd-primary qpidd.conf qpidc.conf CMakeLists.txt
 
 confdir=$(sysconfdir)/qpid
 nobase_conf_DATA=\

Added: qpid/trunk/qpid/cpp/etc/cluster.conf-example.xml
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/etc/cluster.conf-example.xml?rev=1298602&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/etc/cluster.conf-example.xml (added)
+++ qpid/trunk/qpid/cpp/etc/cluster.conf-example.xml Thu Mar  8 21:47:04 2012
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+<!--
+This is an example of a cluster.conf file to run qpidd under rgmanager.
+This example assumes a 3 node cluster, with nodes named mrg32, mrg34 and mrg35.
+There is no fencing in this configuration.
+-->
+
+<cluster alias="qpid-hot-standby" config_version="4" name="qpid-hot-standby">
+  <!-- The cluster has 3 nodes. Each has a unique nodid and one vote for quorum. -->
+  <clusternodes>
+    <clusternode name="mrg32" nodeid="1">
+      <fence/>
+    </clusternode>
+    <clusternode name="mrg34" nodeid="2">
+      <fence/>
+    </clusternode>
+    <clusternode name="mrg35" nodeid="3">
+      <fence/>
+    </clusternode>
+  </clusternodes>
+  <cman/>
+  <!-- Optionally you can specify logging, this is the most verbose -->
+  <rm log_level="7" log_facility="daemon">
+
+    <!--
+	There is a failoverdomain for each node containing just that node.
+	This lets us stipulate that the qpidd service should always run on all nodes.
+    -->
+    <failoverdomains>
+      <failoverdomain name="mrg32-domain" restricted="1">
+	<failoverdomainnode name="mrg32"/>
+      </failoverdomain>
+      <failoverdomain name="mrg34-domain" restricted="1">
+	<failoverdomainnode name="mrg34"/>
+      </failoverdomain>
+      <failoverdomain name="mrg35-domain" restricted="1">
+	<failoverdomainnode name="mrg35"/>
+      </failoverdomain>
+    </failoverdomains>
+
+    <resources>
+      <!-- This script starts a qpidd broker acting as a backup. -->
+      <script file="/etc/init.d/qpidd" name="qpidd"/>
+
+      <!-- This script promotes the qpidd broker on this node to primary. -->
+      <script file="/etc/init.d/qpidd-primary" name="qpidd-primary"/>
+
+      <!-- This is a virtual IP address for broker replication traffic. -->
+      <ip address="20.0.10.200" monitor_link="1"/>
+
+      <!-- This is a virtual IP address on a seprate network for client traffic. -->
+      <ip address="20.0.20.200" monitor_link="1"/>
+    </resources>
+
+    <!-- There is a qpidd service on each node, it should be restarted if it fails. -->
+    <service name="mrg32-qpidd-service" domain="mrg32-domain" recovery="restart">
+      <script ref="qpidd"/>
+    </service>
+    <service name="mrg34-qpidd-service" domain="mrg34-domain" recovery="restart">
+      <script ref="qpidd"/>
+    </service>
+    <service name="mrg35-qpidd-service" domain="mrg35-domain"  recovery="restart">
+      <script ref="qpidd"/>
+    </service>
+
+    <!-- There should always be a single qpidd-primary service, it can run on any node. -->
+    <service name="qpidd-primary-service" autostart="1" exclusive="0" recovery="relocate">
+      <script ref="qpidd-primary"/>
+      <!-- The primary has the IP addresses for brokers and clients. -->
+      <ip ref="20.0.10.200"/>
+      <ip ref="20.0.20.200"/>
+    </service>
+  </rm>
+  <fencedevices/>
+  <fence_daemon clean_start="0" post_fail_delay="0" post_join_delay="3"/>
+</cluster>
+

Propchange: qpid/trunk/qpid/cpp/etc/cluster.conf-example.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: qpid/trunk/qpid/cpp/etc/cluster.conf-example.xml
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Propchange: qpid/trunk/qpid/cpp/etc/cluster.conf-example.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: qpid/trunk/qpid/cpp/etc/qpidd-primary
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/etc/qpidd-primary?rev=1298602&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/etc/qpidd-primary (added)
+++ qpid/trunk/qpid/cpp/etc/qpidd-primary Thu Mar  8 21:47:04 2012
@@ -0,0 +1,102 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+#
+# qpidd        Startup script for the Qpid messaging daemon.
+#
+
+### BEGIN INIT INFO
+# Provides: qpidd-primary
+# Required-Start: $qpidd
+# Required-Stop: $qpidd
+# Default-Start:
+# Default-Stop: 0 1 2 3 4 5 6
+# Short-Description: promote qpidd to cluster primary
+# Description: Qpidd can be run in an active/passive cluster. Promote a running qpidd to primary.
+### END INIT INFO
+
+# chkconfig: - 85 15
+# description: Qpidd can be run in an active/passive cluster. Promote a running qpidd to primary.
+# processname: qpidd
+
+prog=qpidd
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+if [ -f /etc/sysconfig/$prog ] ; then
+    . /etc/sysconfig/$prog
+fi
+
+# The following variables can be overridden in /etc/sysconfig/$prog
+[[ $QPID_PORT ]] || QPID_PORT=5672
+[[ $QPID_HA ]]   || QPID_HA=/usr/bin/qpid-ha
+export QPID_PORT
+
+RETVAL=0
+
+#ensure binary is present and executable
+if [[ !(-x $QPID_HA) ]]; then
+    echo "qpid-ha executable not found or not executable"
+fi
+
+status() {
+    if $QPID_HA -b localhost:$QPID_PORT status --expect=primary ; then
+	echo "qpidd is primary"
+    else
+	echo "qpidd is not primary"
+	return 1
+    fi
+}
+
+start() {
+    service qpidd start
+    echo -n $"Promoting qpid daemon to cluster primary: "
+    $QPID_HA -b localhost:$QPID_PORT promote
+    [ "$?" -eq 0 ] && success || failure
+}
+
+stop() {
+    service qpidd stop
+}
+
+reload() {
+    echo 1>&2 $"$0: reload not supported"
+    exit 3
+}
+
+restart() {
+    service qpidd restart && start
+}
+
+# See how we were called.
+case "$1" in
+    start|stop|status|restart|reload)
+	$1
+	RETVAL=$?
+	;;
+    force-reload)
+	restart
+	;;
+    *)
+	echo 1>&2 $"Usage: $0 {start|stop|status|restart|force-reload}"
+	exit 2
+esac
+
+exit $RETVAL

Propchange: qpid/trunk/qpid/cpp/etc/qpidd-primary
------------------------------------------------------------------------------
    svn:executable = *

Added: qpid/trunk/qpid/cpp/src/tests/cluster_failover
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/cluster_failover?rev=1298602&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/cluster_failover (added)
+++ qpid/trunk/qpid/cpp/src/tests/cluster_failover Thu Mar  8 21:47:04 2012
@@ -0,0 +1,18 @@
+#!/bin/sh
+# A simple manual failover test, sends a stream of numbered messages.
+# You can kill the connected broker and verify that the client reconnects 
+# and no messages are lost.
+
+URL=$1
+test -n "$URL" || { echo Usage: $0 URL ; exit 1; }
+SEND=$(mktemp /tmp/send.XXXXXXXXXX)
+RECV=$(mktemp /tmp/recv.XXXXXXXXXX)
+echo $SEND $RECV
+
+seq 1000000 > $SEND
+
+qpid-receive -f -a 'q;{create:always}' -b $URL --connection-options "{reconnect:true}"  | tee $RECV &
+
+qpid-send -a 'q;{create:always}' -b $URL --connection-options "{reconnect:true}" --send-rate 10 --content-stdin < $SEND &
+
+wait

Propchange: qpid/trunk/qpid/cpp/src/tests/cluster_failover
------------------------------------------------------------------------------
    svn:executable = *

Modified: qpid/trunk/qpid/tools/src/py/qpid-ha
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/tools/src/py/qpid-ha?rev=1298602&r1=1298601&r2=1298602&view=diff
==============================================================================
--- qpid/trunk/qpid/tools/src/py/qpid-ha (original)
+++ qpid/trunk/qpid/tools/src/py/qpid-ha Thu Mar  8 21:47:04 2012
@@ -67,26 +67,19 @@ class PromoteCmd(Command):
         qmf_broker._method("promote", {}, HA_BROKER)
 PromoteCmd()
 
-class ReadyCmd(Command):
+class StatusCmd(Command):
     def __init__(self):
-        Command.__init__(self, "ready", "Test if a backup broker is ready.\nReturn 0 if broker is a ready backup, non-0 otherwise.")
+        Command.__init__(self, "status", "Print HA status")
         self.op.add_option(
-            "--wait", type="int", metavar="<seconds>", default=None,
-            help="Wait up to <seconds> for broker to be ready. 0 means wait forever.")
+            "--expect", type="string", metavar="<status>",
+            help="Don't print status but return 0 if it matches <status>, 1 otherwise")
     def do_execute(self, qmf_broker, ha_broker, opts, args):
-        if (ha_broker.status == "backup"): return
-        if (ha_broker.status != "catch-up"):
-            raise Exception("Broker is not a backup, status is '%s'"%ha_broker.status)
-        if (opts.wait is None): return 1
-        delay = 0.1
-        timeout = time.time() + opts.wait
-        while opts.wait == 0 or time.time() < timeout:
-            time.sleep(delay)
-            delay = min(2*delay, 1)
-            ha_broker = qmf_broker.getHaBroker()
-            if (ha_broker.status == "backup"): return
-        return 1
-ReadyCmd()
+        if opts.expect:
+            if opts.expect != ha_broker.status: return 1
+        else:
+            print ha_broker.status
+        return 0
+StatusCmd()
 
 class ReplicateCmd(Command):
     def __init__(self):



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org