[Openais] [PATCH 1/7] CTS: add a test for sync events
Angus Salkeld
asalkeld at redhat.com
Mon Mar 29 19:28:49 PDT 2010
Add a test service to CTS.
This enables us to test sync behaviour better.
-Angus
Signed-off-by: Angus Salkeld <asalkeld at redhat.com>
---
conf/lenses/corosync.aug | 8 +-
cts/agents/Makefile.am | 47 +++++++
cts/agents/syncv2.c | 309 +++++++++++++++++++++++++++++++++++++++++++
cts/corosync.py | 2 +
cts/corotests.py | 81 +++++++++++-
exec/main.c | 4 +-
include/corosync/corodefs.h | 4 +-
7 files changed, 450 insertions(+), 5 deletions(-)
create mode 100644 cts/agents/syncv2.c
diff --git a/conf/lenses/corosync.aug b/conf/lenses/corosync.aug
index 52c613b..e9eff2b 100644
--- a/conf/lenses/corosync.aug
+++ b/conf/lenses/corosync.aug
@@ -122,6 +122,12 @@ let quorum =
qstr /provider/ in
section "quorum" setting
-let lns = (comment|empty|compatibility|totem|quorum|logging|amf)*
+(* The quorum section *)
+let service =
+ let setting =
+ qstr /name|ver/ in
+ section "service" setting
+
+let lns = (comment|empty|compatibility|totem|quorum|logging|amf|service)*
let xfm = transform lns (incl "/etc/corosync/corosync.conf")
diff --git a/cts/agents/Makefile.am b/cts/agents/Makefile.am
index 5c5c211..01dd2ce 100644
--- a/cts/agents/Makefile.am
+++ b/cts/agents/Makefile.am
@@ -32,15 +32,24 @@
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
+SOURCES =
TEST_AGENTS = cpg_test_agent confdb_test_agent
if INSTALL_TESTAGENTS
agentdir = $(datadir)/$(PACKAGE)/tests
bin_PROGRAMS = $(TEST_AGENTS)
dist_agent_SCRIPTS = mem_leak_test.sh net_breaker.sh
+
+AM_CFLAGS = -fPIC
+SERVICE_LCRSO = syncv2
+SOURCES += $(SERVICE_LCRSO:%=%.c)
+EXTRA_DIST = $(SOURCES)
+LCRSO = $(SERVICE_LCRSO:%=service_%.lcrso)
+LCRSO_OBJS = $(SOURCES:%.c=%.o)
else
noinst_PROGRAMS = $(TEST_AGENTS)
noinst_SCRIPTS = mem_leak_test.sh net_breaker.sh
+LCRSO =
endif
noinst_HEADERS = common_test_agent.h
@@ -53,6 +62,44 @@ confdb_test_agent_SOURCES = confdb_test_agent.c common_test_agent.c
confdb_test_agent_LDADD = -lconfdb -lcoroipcc ../../exec/coropoll.o
confdb_test_agent_LDFLAGS = -L../../lib
+
+if BUILD_DARWIN
+
+service_%.lcrso: %.o
+ $(CC) $(CFLAGS) -L$(top_builddir)/exec -llogsys -bundle -bundle_loader $(top_builddir)/exec/corosync $^ -o $@
+
+else
+if BUILD_SOLARIS
+
+service_%.lcrso: %.o
+ $(LD) $(LDFLAGS) -G $^ -o $@
+
+else
+
+service_%.lcrso: %.o
+ $(CC) $(CFLAGS) $(COVERAGE_LCRSO_EXTRA_LDFLAGS) -shared -Wl,-soname=$@ $^ -o $@
+endif
+endif
+
+
+
+if INSTALL_TESTAGENTS
+all-local: $(LCRSO_OBJS) $(LCRSO)
+ @echo Built Service Engines
+
+install-exec-local:
+ $(INSTALL) -d $(DESTDIR)/$(LCRSODIR)
+ $(INSTALL) -m 755 $(LCRSO) $(DESTDIR)/$(LCRSODIR)
+
+uninstall-local:
+ cd $(DESTDIR)/$(LCRSODIR) && \
+ rm -f $(LCRSO)
+
+endif
+
+clean-local:
+ rm -f *.o *.a *.so* *.da *.bb *.bbg *.lcrso
+
lint:
-splint $(LINT_FLAGS) $(CFLAGS) *.c
diff --git a/cts/agents/syncv2.c b/cts/agents/syncv2.c
new file mode 100644
index 0000000..e5645a4
--- /dev/null
+++ b/cts/agents/syncv2.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2010 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Angus Salkeld <asalkeld at redhat.com>
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#include <corosync/swab.h>
+#include <corosync/corotypes.h>
+#include <corosync/coroipc_types.h>
+#include <corosync/corodefs.h>
+#include <corosync/lcr/lcr_comp.h>
+#include <corosync/mar_gen.h>
+#include <corosync/engine/coroapi.h>
+#include <corosync/list.h>
+#include <corosync/engine/logsys.h>
+
+#include "../exec/tlist.h"
+
+LOGSYS_DECLARE_SUBSYS ("TST2");
+
+/*
+ * Service Interfaces required by service_message_handler struct
+ */
+static int tst_sv2_exec_init_fn (
+ struct corosync_api_v1 *corosync_api);
+
+static void tst_sv2_confchg_fn (
+ enum totem_configuration_type configuration_type,
+ const unsigned int *member_list, size_t member_list_entries,
+ const unsigned int *left_list, size_t left_list_entries,
+ const unsigned int *joined_list, size_t joined_list_entries,
+ const struct memb_ring_id *ring_id);
+
+static int tst_sv2_lib_init_fn (void *conn);
+static int tst_sv2_lib_exit_fn (void *conn);
+static struct corosync_api_v1 *api;
+
+static void tst_sv2_sync_init_v2 (
+ const unsigned int *member_list,
+ size_t member_list_entries,
+ const struct memb_ring_id *ring_id);
+
+static int tst_sv2_sync_process (void);
+
+static void tst_sv2_sync_activate (void);
+
+static void tst_sv2_sync_abort (void);
+
+struct corosync_service_engine tst_sv2_service_engine = {
+ .name = "corosync test synv2 service",
+ .id = TST_SV2_SERVICE,
+ .priority = 1,
+ .private_data_size = 0,
+ .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED,
+ .lib_init_fn = tst_sv2_lib_init_fn,
+ .lib_exit_fn = tst_sv2_lib_exit_fn,
+ .lib_engine = NULL,
+ .lib_engine_count = 0,
+ .exec_engine = NULL,
+ .exec_engine_count = 0,
+ .confchg_fn = tst_sv2_confchg_fn,
+ .exec_init_fn = tst_sv2_exec_init_fn,
+ .exec_dump_fn = NULL,
+ .sync_mode = CS_SYNC_V2,
+ .sync_init = tst_sv2_sync_init_v2,
+ .sync_process = tst_sv2_sync_process,
+ .sync_activate = tst_sv2_sync_activate,
+ .sync_abort = tst_sv2_sync_abort
+};
+
+static unsigned int my_member_list[PROCESSOR_COUNT_MAX];
+
+static unsigned int my_member_list_entries;
+
+static unsigned int my_old_member_list[PROCESSOR_COUNT_MAX];
+
+static unsigned int my_old_member_list_entries = 0;
+static int num_sync_processes = 0;
+
+static DECLARE_LIST_INIT (confchg_notify);
+
+/*
+ * Dynamic loading descriptor
+ */
+
+static struct corosync_service_engine *tst_sv2_get_service_engine_ver0 (void);
+
+static struct corosync_service_engine_iface_ver0 tst_sv2_service_engine_iface = {
+ .corosync_get_service_engine_ver0 = tst_sv2_get_service_engine_ver0
+};
+
+static struct lcr_iface corosync_tst_sv2_ver0[1] = {
+ {
+ .name = "corosync_tst_sv2",
+ .version = 0,
+ .versions_replace = 0,
+ .versions_replace_count = 0,
+ .dependencies = 0,
+ .dependency_count = 0,
+ .constructor = NULL,
+ .destructor = NULL,
+ .interfaces = NULL,
+ }
+};
+
+static struct lcr_comp tst_sv2_comp_ver0 = {
+ .iface_count = 1,
+ .ifaces = corosync_tst_sv2_ver0
+};
+
+static struct corosync_service_engine *tst_sv2_get_service_engine_ver0 (void)
+{
+ return (&tst_sv2_service_engine);
+}
+
+#ifdef COROSYNC_SOLARIS
+void corosync_lcr_component_register (void);
+
+void corosync_lcr_component_register (void) {
+#else
+__attribute__ ((constructor)) static void corosync_lcr_component_register (void) {
+#endif
+ lcr_interfaces_set (&corosync_tst_sv2_ver0[0], &tst_sv2_service_engine_iface);
+
+ lcr_component_register (&tst_sv2_comp_ver0);
+}
+
+static int tst_sv2_exec_init_fn (
+ struct corosync_api_v1 *corosync_api)
+{
+#ifdef COROSYNC_SOLARIS
+ logsys_subsys_init();
+#endif
+ api = corosync_api;
+
+ return 0;
+}
+
+static void tst_sv2_confchg_fn (
+ enum totem_configuration_type configuration_type,
+ const unsigned int *member_list, size_t member_list_entries,
+ const unsigned int *left_list, size_t left_list_entries,
+ const unsigned int *joined_list, size_t joined_list_entries,
+ const struct memb_ring_id *ring_id)
+{
+ int j;
+ for (j = 0; j < left_list_entries; j++) {
+ log_printf (LOGSYS_LEVEL_INFO,
+ "Member left: %s", api->totem_ifaces_print (left_list[j]));
+ }
+ for (j = 0; j < joined_list_entries; j++) {
+ log_printf (LOGSYS_LEVEL_INFO,
+ "Member joined: %s", api->totem_ifaces_print (joined_list[j]));
+ }
+}
+
+static int tst_sv2_lib_init_fn (void *conn)
+{
+ return (0);
+}
+
+static int tst_sv2_lib_exit_fn (void *conn)
+{
+ return (0);
+}
+
+
+static void tst_sv2_sync_init_v2 (
+ const unsigned int *member_list,
+ size_t member_list_entries,
+ const struct memb_ring_id *ring_id)
+{
+ unsigned int lowest_nodeid = 0xffffffff;
+ int i, j;
+ int found;
+
+ num_sync_processes = 0;
+
+ memcpy (my_member_list, member_list, member_list_entries *
+ sizeof (unsigned int));
+ my_member_list_entries = member_list_entries;
+
+ for (i = 0; i < my_member_list_entries; i++) {
+ if (my_member_list[i] < lowest_nodeid) {
+ lowest_nodeid = my_member_list[i];
+ }
+ }
+
+ log_printf (LOGSYS_LEVEL_INFO,
+ "tst_sv2_sync_init_v2 %s",
+ api->totem_ifaces_print (lowest_nodeid));
+
+ /* look for new (joined) nodes */
+ for (j = 0; j < member_list_entries; j++) {
+ found = 0;
+ for (i = 0; i < my_old_member_list_entries; i++) {
+ if (my_old_member_list[i] == member_list[j]) {
+ found = 1;
+ break;
+ }
+ }
+ if (found == 0) {
+ log_printf (LOGSYS_LEVEL_INFO,
+ "sync: node joined %s",
+ api->totem_ifaces_print (member_list[j]));
+ }
+ }
+ /* look for old (left) nodes */
+ for (i = 0; i < my_old_member_list_entries; i++) {
+ found = 0;
+ for (j = 0; j < member_list_entries; j++) {
+ if (my_old_member_list[i] == member_list[j]) {
+ found = 1;
+ break;
+ }
+ }
+ if (found == 0) {
+ log_printf (LOGSYS_LEVEL_INFO,
+ "sync: node left %s",
+ api->totem_ifaces_print (my_old_member_list[i]));
+ }
+ }
+
+}
+
+static int tst_sv2_sync_process (void)
+{
+ num_sync_processes++;
+
+ log_printf (LOGSYS_LEVEL_INFO, "sync: process %d", num_sync_processes);
+
+ if (num_sync_processes > 3) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+static void tst_sv2_sync_activate (void)
+{
+ memcpy (my_old_member_list, my_member_list,
+ my_member_list_entries * sizeof (unsigned int));
+ my_old_member_list_entries = my_member_list_entries;
+
+ if (num_sync_processes <= 3) {
+ log_printf (LOGSYS_LEVEL_ERROR,
+ "sync: activate called before process is done %d",
+ num_sync_processes);
+ } else {
+ log_printf (LOGSYS_LEVEL_INFO,
+ "sync: activate correctly %d",
+ num_sync_processes);
+ }
+
+ num_sync_processes = 0;
+}
+
+static void tst_sv2_sync_abort (void)
+{
+ log_printf (LOGSYS_LEVEL_INFO, "sync: abort");
+}
+
diff --git a/cts/corosync.py b/cts/corosync.py
index f54af4d..6962f39 100644
--- a/cts/corosync.py
+++ b/cts/corosync.py
@@ -141,6 +141,8 @@ class corosync_flatiron(ClusterManager):
self.node_to_ip = {}
self.new_config = {}
+ self.new_config['service[0]/name'] = 'corosync_tst_sv2'
+ self.new_config['service[0]/ver'] = '0'
self.applied_config = {}
for n in self.Env["nodes"]:
ip = socket.gethostbyname(n)
diff --git a/cts/corotests.py b/cts/corotests.py
index 95bef01..1d80722 100644
--- a/cts/corotests.py
+++ b/cts/corotests.py
@@ -179,6 +179,83 @@ class CpgCfgChgOnNodeLeave(CpgConfigChangeBase):
return self.wait_for_config_change()
###################################################################
+class CpgCfgChgOnLowestNodeJoin(CTSTest):
+ '''
+ 1) stop all nodes
+ 2) start all but the node with the smallest ip address
+ 3) start recording events
+ 4) start the last node
+ '''
+ def __init__(self, cm):
+ CTSTest.__init__(self, cm)
+ self.name="CpgCfgChgOnLowestNodeJoin"
+ self.start = StartTest(cm)
+ self.stop = StopTest(cm)
+ self.config = {}
+ self.config['compatibility'] = 'none'
+
+ def lowest_ip_set(self):
+ self.lowest = None
+ for n in self.CM.Env["nodes"]:
+ if self.lowest is None:
+ self.lowest = n
+
+ self.CM.log("lowest node is " + self.lowest)
+
+ def setup(self, node):
+ # stop all nodes
+ for n in self.CM.Env["nodes"]:
+ self.CM.StopaCM(n)
+
+ self.lowest_ip_set()
+
+ # copy over any new config
+ for c in self.config:
+ self.CM.new_config[c] = self.config[c]
+
+ # install the config
+ self.CM.install_all_config()
+
+ # start all but lowest
+ self.listener = None
+ for n in self.CM.Env["nodes"]:
+ if n is not self.lowest:
+ if self.listener is None:
+ self.listener = n
+ self.incr("started")
+ self.CM.log("starting " + n)
+ self.start(n)
+ self.CM.cpg_agent[n].clean_start()
+ self.CM.cpg_agent[n].cpg_join(self.name)
+
+ # start recording events
+ pats = []
+ pats.append("%s .*sync: node joined.*" % self.listener)
+ pats.append("%s .*sync: activate correctly.*" % self.listener)
+ self.sync_log = self.create_watch(pats, 60)
+ self.sync_log.setwatch()
+
+ self.CM.log("setup done")
+
+ return CTSTest.setup(self, node)
+
+
+ def __call__(self, node):
+ self.incr("calls")
+
+ self.start(self.lowest)
+ self.CM.cpg_agent[self.lowest].clean_start()
+ self.CM.cpg_agent[self.lowest].cpg_join(self.name)
+ self.wobbly_id = self.CM.cpg_agent[self.lowest].cpg_local_get()
+
+ self.CM.log("waiting for sync events")
+ if not self.sync_log.lookforall():
+ return self.failure("Patterns not found: " + repr(self.sync_log.unmatched))
+ else:
+ return self.success()
+
+
+###################################################################
class CpgCfgChgOnExecCrash(CpgConfigChangeBase):
def __init__(self, cm):
@@ -495,6 +572,7 @@ GenTestClasses.append(CpgCfgChgOnExecCrash)
GenTestClasses.append(CpgCfgChgOnGroupLeave)
GenTestClasses.append(CpgCfgChgOnNodeLeave)
GenTestClasses.append(CpgCfgChgOnNodeIsolate)
+GenTestClasses.append(CpgCfgChgOnLowestNodeJoin)
AllTestClasses = []
AllTestClasses.append(ConfdbReplaceTest)
@@ -585,7 +663,8 @@ def CoroTestList(cm, audits):
bound_test = testclass(cm)
if bound_test.is_applicable():
bound_test.Audits = audits
- bound_test.config = cfg
+ for c in cfg:
+ bound_test.config[c] = cfg[c]
bound_test.name = bound_test.name + '_' + str(num)
result.append(bound_test)
num = num + 1
diff --git a/exec/main.c b/exec/main.c
index 0b7982a..f109606 100644
--- a/exec/main.c
+++ b/exec/main.c
@@ -428,12 +428,12 @@ static void confchg_fn (
memcpy (&corosync_ring_id, ring_id, sizeof (struct memb_ring_id));
for (i = 0; i < left_list_entries; i++) {
- log_printf (LOGSYS_LEVEL_INFO,
+ log_printf (LOGSYS_LEVEL_DEBUG,
"Member left: %s\n", api->totem_ifaces_print (left_list[i]));
member_object_left (left_list[i]);
}
for (i = 0; i < joined_list_entries; i++) {
- log_printf (LOGSYS_LEVEL_INFO,
+ log_printf (LOGSYS_LEVEL_DEBUG,
"Member joined: %s\n", api->totem_ifaces_print (joined_list[i]));
member_object_joined (joined_list[i]);
}
diff --git a/include/corosync/corodefs.h b/include/corosync/corodefs.h
index 4af7c8a..57923e2 100644
--- a/include/corosync/corodefs.h
+++ b/include/corosync/corodefs.h
@@ -57,7 +57,9 @@ enum corosync_service_types {
TMR_SERVICE = 14,
VOTEQUORUM_SERVICE = 15,
NTF_SERVICE = 16,
- AMF_V2_SERVICE = 17
+ AMF_V2_SERVICE = 17,
+ TST_SV1_SERVICE = 18,
+ TST_SV2_SERVICE = 19
};
#ifdef HAVE_SMALL_MEMORY_FOOTPRINT
--
1.6.6.1
More information about the Openais
mailing list