Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=aab... Commit: aabd30fca943f8c865691bbc76ddb045c1ec0a33 Parent: 01af75d8f464e4c2d4a38c12e9a18c9b3d0008f4 Author: Fabio M. Di Nitto fdinitto@redhat.com AuthorDate: Thu Nov 25 10:21:00 2010 +0100 Committer: Fabio M. Di Nitto fdinitto@redhat.com CommitterDate: Thu Nov 25 10:21:00 2010 +0100
obsolete master branch
Signed-off-by: Fabio M. Di Nitto fdinitto@redhat.com --- Makefile.am | 32 - README | 3 + autogen.sh | 4 - bindings/Makefile.am | 3 - bindings/perl/Makefile.am | 3 - bindings/perl/ccs/CCS.pm.in | 145 -- bindings/perl/ccs/CCS.xs | 82 - bindings/perl/ccs/MANIFEST | 7 - bindings/perl/ccs/META.yml.in | 13 - bindings/perl/ccs/Makefile.PL | 28 - bindings/perl/ccs/Makefile.am | 59 - bindings/perl/ccs/test.pl | 20 - bindings/perl/ccs/typemap | 1 - cman/Makefile.am | 4 - cman/cman_tool/Makefile.am | 17 - cman/cman_tool/cman_tool.h | 100 -- cman/cman_tool/join.c | 335 ----- cman/cman_tool/main.c | 1014 ------------- cman/config/Makefile.am | 14 - cman/config/cman-preconfig.c | 1262 ---------------- cman/config/cman.h | 15 - cman/config/nodelist.h | 93 -- cman/init.d/cman.in | 748 ---------- cman/man/Makefile.am | 8 - cman/man/cman.5 | 222 --- cman/man/cman_tool.8 | 345 ----- cman/man/cmannotifyd.8 | 66 - cman/man/mkqdisk.8 | 31 - cman/man/qdisk.5 | 478 ------ cman/man/qdiskd.8 | 25 - cman/notifyd/Makefile.am | 41 - cman/notifyd/cman_notify.in | 40 - cman/notifyd/main.c | 506 ------- cman/qdisk/Makefile.am | 28 - cman/qdisk/bitmap.c | 93 -- cman/qdisk/daemon_init.c | 239 --- cman/qdisk/disk.c | 792 ---------- cman/qdisk/disk.h | 285 ---- cman/qdisk/disk_util.c | 267 ---- cman/qdisk/iostate.c | 145 -- cman/qdisk/iostate.h | 17 - cman/qdisk/main.c | 1879 ------------------------ cman/qdisk/mkqdisk.c | 95 -- cman/qdisk/platform.h | 40 - cman/qdisk/proc.c | 265 ---- cman/qdisk/scandisk.c | 766 ---------- cman/qdisk/scandisk.h | 86 -- cman/qdisk/score.c | 424 ------ cman/qdisk/score.h | 44 - cman/services/Makefile.am | 3 - cman/services/cman/Makefile.am | 3 - cman/services/cman/include/Makefile.am | 3 - cman/services/cman/include/corosync/cman.h | 39 - cman/services/cman/include/corosync/ipc_cman.h | 58 - cman/services/cman/lib/Makefile.am | 21 - cman/services/cman/lib/libcman.c | 1274 ---------------- cman/services/cman/lib/libcman.h | 418 ------ cman/services/cman/lib/libcman.pc.in | 11 - cman/services/cman/services/Makefile.am | 14 - cman/services/cman/services/cman.c | 571 ------- cman/tests/Makefile.am | 13 - cman/tests/client.c | 115 -- cman/tests/libtest.c | 134 -- cman/tests/qwait.c | 60 - cman/tests/sysman.c | 75 - cman/tests/sysmand.c | 472 ------ cman/tests/user_service.c | 287 ---- common/Makefile.am | 3 - common/liblogthread/Makefile.am | 14 - common/liblogthread/liblogthread.c | 336 ----- common/liblogthread/liblogthread.h | 19 - common/liblogthread/liblogthread.pc.in | 11 - config/Makefile.am | 3 - config/libs/Makefile.am | 3 - config/libs/libccsconfdb/Makefile.am | 24 - config/libs/libccsconfdb/ccs.h | 16 - config/libs/libccsconfdb/ccs_internal.h | 29 - config/libs/libccsconfdb/extras.c | 449 ------ config/libs/libccsconfdb/fullxpath.c | 327 ---- config/libs/libccsconfdb/libccs.c | 651 -------- config/libs/libccsconfdb/libccs.pc.in | 11 - config/libs/libccsconfdb/xpathlite.c | 426 ------ config/man/Makefile.am | 3 - config/man/cluster.conf.5 | 208 --- config/plugins/Makefile.am | 3 - config/plugins/ldap/99cluster.ldif | 138 -- config/plugins/ldap/Makefile.am | 15 - config/plugins/ldap/configldap.c | 288 ---- config/plugins/ldap/example.ldif | 137 -- config/plugins/xml/Makefile.am | 14 - config/plugins/xml/config.c | 150 -- config/tools/Makefile.am | 3 - config/tools/ccs_tool/Makefile.am | 24 - config/tools/ccs_tool/ccs_tool.c | 309 ---- config/tools/ccs_tool/editconf.c | 1252 ---------------- config/tools/ccs_tool/editconf.h | 8 - config/tools/ldap/Makefile.am | 9 - config/tools/ldap/confdb2ldif.c | 203 --- config/tools/man/Makefile.am | 4 - config/tools/man/ccs_tool.8 | 185 --- config/tools/man/confdb2ldif.8 | 64 - config/tools/mkconf/Makefile.am | 14 - config/tools/mkconf/mkconf.c | 248 ---- configure.ac | 308 ---- doc/COPYING.applications | 339 ----- doc/COPYING.libraries | 510 ------- doc/COPYRIGHT | 58 - doc/Makefile.am | 34 - doc/README.licence | 33 - doc/cluster.logrotate.in | 8 - doc/cman_notify_template.sh | 57 - doc/gfs2.txt | 45 - doc/journaling.txt | 155 -- doc/min-gfs.txt | 159 -- doc/usage.txt | 177 --- group/Makefile.am | 3 - group/man/Makefile.am | 3 - group/man/group_tool.8 | 61 - group/tool/Makefile.am | 5 - group/tool/main.c | 147 -- make/copyright.cf | 6 - make/lcrso.mk | 23 - 122 files changed, 3 insertions(+), 22529 deletions(-)
diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index b845c7a..0000000 --- a/Makefile.am +++ /dev/null @@ -1,32 +0,0 @@ -EXTRA_DIST = autogen.sh make/lcrso.mk - -AUTOMAKE_OPTIONS = foreign - -MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure depcomp \ - config.guess config.sub missing install-sh \ - autoheader automake autoconf libtool libtoolize \ - ltmain.sh compile make/clusterautoconfig.h.in \ - make/clusterautoconfig.h.in~ - -noinst_HEADERS = make/copyright.cf - -ACLOCAL_AMFLAGS = -I m4 - -SUBDIRS = common config cman group doc - -if BUILD_BINDINGS -SUBDIRS += bindings -endif - -install-exec-local: - $(INSTALL) -d $(DESTDIR)/$(LOGDIR) - $(INSTALL) -d $(DESTDIR)/$(CLUSTERVARRUN) - $(INSTALL) -d $(DESTDIR)/$(CLUSTERVARLIB) - -uninstall-local: - rmdir $(DESTDIR)/$(LOGDIR) || :; - rmdir $(DESTDIR)/$(CLUSTERVARRUN) || :; - rmdir $(DESTDIR)/$(CLUSTERVARLIB) || :; - -maintainer-clean-local: - rm -rf m4 diff --git a/README b/README new file mode 100644 index 0000000..d2d00c9 --- /dev/null +++ b/README @@ -0,0 +1,3 @@ +cluster.git master branch is no longer actively developed. + +Please refer to STABLE31 branch or RHEL6 branch for stable releases. diff --git a/autogen.sh b/autogen.sh deleted file mode 100755 index 3c5e1d9..0000000 --- a/autogen.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -# Run this to generate all the initial makefiles, etc. -mkdir -p m4 -autoreconf -i -v && echo Now run ./configure and make diff --git a/bindings/Makefile.am b/bindings/Makefile.am deleted file mode 100644 index 4e80eeb..0000000 --- a/bindings/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -SUBDIRS = perl diff --git a/bindings/perl/Makefile.am b/bindings/perl/Makefile.am deleted file mode 100644 index 5d953b3..0000000 --- a/bindings/perl/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -SUBDIRS = ccs diff --git a/bindings/perl/ccs/CCS.pm.in b/bindings/perl/ccs/CCS.pm.in deleted file mode 100644 index 1dc5c24..0000000 --- a/bindings/perl/ccs/CCS.pm.in +++ /dev/null @@ -1,145 +0,0 @@ -package Cluster::CCS; - -use strict; -use vars qw($VERSION @ISA @EXPORT @EXPORT_OK); - -require Exporter; -require DynaLoader; - -@ISA = qw(Exporter DynaLoader); -# Items to export into callers namespace by default. Note: do not export -# names by default without a very good reason. Use EXPORT_OK instead. -# Do not simply export all your public functions/methods/constants. -our %EXPORT_TAGS = ( 'all' => [qw( - -)]); -@EXPORT = qw( - -); -@EXPORT_OK = (@{$EXPORT_TAGS{'all'}}); - -our $VERSION = '_VERSION_'; - -require XSLoader; -XSLoader::load('Cluster::CCS', $VERSION); - -sub new { - my $class = shift; - my $self = bless { - @_ - }; - return $self; -} - -1; -__END__ - -=head1 NAME - -Cluster::CCS - Perl wrapper for the Cluster Configuration Service library - -=head1 SYNOPSIS - - use Cluster::CCS; - - my $ccs = new Cluster::CCS(); - - $ccs->fullxpath(1); - - my $ccshandle = $ccs->connect(); - - if ($ccshandle < 1) { - print "Cannot comunicate with libccs\n"; - exit $ccshandle; - } - - my $rtn; - my $err; - - $err = $ccs->get($ccshandle, '/cluster/@name', $rtn); - - if ($err != 0) { - print "Query is not valid\n"; - } - - print "My Cluster name is $rtn\n"; - - $err = $ccs->disconnect($ccshandle); - - if ($err != 0) { - print "Problems disconnecting from libccs\n"; - } - - exit $err; - -=head1 DESCRIPTION - - Cluster::CCS provides a perl XS wrapper for libccs. - -=head1 METHODS - -=head2 new - - Creates a new Cluster::CCS object. - -=head2 fullxpath(value) - - Enable or disable full xpath queries. Set 1 to enable, 0 to disable. - This has to be set before connect() or force_connect. - In order to change this value, a disconnect operation is required. - -=head2 connect(void) - - Initialize the connection to libccs/libconfdb/corosync objdb. - Returns 1 on success or negative on failure. - -=head2 force_connect(cluster_name, blocking) - - Initialize the connection to libccs/libconfdb/corosync objdb. - If blocking is set, it will retry the operation until it succeed. - Returns 1 on success or negative on failure. - -=head2 disconnect(desc) - - Disconnect and free resources allocated during opertaion. - Returns 0 on success. - -=head2 get(desc, query, rtn) - - Perform a simple xpath query. - Returns 0 on success, negative otherwise. On success rtn will contain the - requested data. - -=head2 get_list(desc, query, rtn) - - Perform a simple xpath query and retain some data to iterate over a list of - results. - Returns 0 on success, negative otherwise. On success rtn will contain the - requested data. - -=head2 set(desc, path, val) - - This operation is not yet implemented in libccs. - -=head2 lookup_nodename(desc, nodename, rtn) - - Perform a nodename lookup using several methods. - Return 0 on success and rtn will contain the requested data. - -=head1 EXPORTS - -Nothing is exported by default. - -=head1 BUGS - - https://bugzilla.redhat.com/ - -=head1 SEE ALSO - - cluster.conf(5), ccs(7), ccs_tool(8) - -=head1 AUTHOR - -Fabio M. Di Nitto fdinitto@redhat.com - -=cut diff --git a/bindings/perl/ccs/CCS.xs b/bindings/perl/ccs/CCS.xs deleted file mode 100644 index 21a651d..0000000 --- a/bindings/perl/ccs/CCS.xs +++ /dev/null @@ -1,82 +0,0 @@ -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" - -#include "ccs.h" - -MODULE = Cluster::CCS PACKAGE = Cluster::CCS - -PROTOTYPES: ENABLE - -void -fullxpath(self, value) - int value; - CODE: - fullxpath = value; - -int -connect(self) - CODE: - RETVAL = ccs_connect(); - OUTPUT: - RETVAL - -int -force_connect(self, cluster_name, blocking) - const char *cluster_name; - int blocking; - CODE: - RETVAL = ccs_force_connect(cluster_name, blocking); - OUTPUT: - RETVAL - -int -disconnect(self, desc) - int desc; - CODE: - RETVAL = ccs_disconnect(desc); - OUTPUT: - RETVAL - -int -get(self, desc, query, rtn) - int desc; - const char *query; - char *rtn; - CODE: - RETVAL = ccs_get(desc, query, &rtn); - OUTPUT: - RETVAL - rtn - -int -get_list(self, desc, query, rtn) - int desc; - const char *query; - char *rtn; - CODE: - RETVAL = ccs_get_list(desc, query, &rtn); - OUTPUT: - RETVAL - rtn - -int -set(self, desc, path, val) - int desc; - char *path; - char *val; - CODE: - RETVAL = ccs_set(desc, path, val); - OUTPUT: - RETVAL - -int -lookup_nodename(self, desc, nodename, rtn) - int desc; - const char *nodename; - char *rtn; - CODE: - RETVAL = ccs_lookup_nodename(desc, nodename, &rtn); - OUTPUT: - RETVAL - rtn diff --git a/bindings/perl/ccs/MANIFEST b/bindings/perl/ccs/MANIFEST deleted file mode 100644 index c089dd7..0000000 --- a/bindings/perl/ccs/MANIFEST +++ /dev/null @@ -1,7 +0,0 @@ -CCS.pm -CCS.xs -Makefile.PL -MANIFEST -test.pl -typemap -META.yml Module meta-data (added by MakeMaker) diff --git a/bindings/perl/ccs/META.yml.in b/bindings/perl/ccs/META.yml.in deleted file mode 100644 index 0bde4d4..0000000 --- a/bindings/perl/ccs/META.yml.in +++ /dev/null @@ -1,13 +0,0 @@ ---- #YAML:1.0 -name: Cluster-CCS -version: _VERSION_ -abstract: ~ -license: ~ -author: - - Fabio M. Di Nitto fdinitto@redhat.com -generated_by: ExtUtils::MakeMaker version 6.42 -distribution_type: module -requires: -meta-spec: - url: http://module-build.sourceforge.net/META-spec-v1.3.html - version: 1.3 diff --git a/bindings/perl/ccs/Makefile.PL b/bindings/perl/ccs/Makefile.PL deleted file mode 100644 index b5504ea..0000000 --- a/bindings/perl/ccs/Makefile.PL +++ /dev/null @@ -1,28 +0,0 @@ -use ExtUtils::MakeMaker; - -my %INFOS = ( - 'NAME' => 'Cluster::CCS', - 'VERSION_FROM' => 'CCS.pm', # finds $VERSION - 'AUTHOR' => 'Fabio M. Di Nitto fdinitto@redhat.com', - 'ABSTRACT' => 'Interface to Cluster Configuration Service library', -); - -# read extra configurations from the commandline -my %params; -@params{qw(DEBUG DEFINE EXTRALIBDIR GDOME INC LIBS SKIP_SAX_INSTALL XMLPREFIX)}=(); - -@ARGV = grep { - my ($key, $val) = split(/=/, $_, 2); - if (exists $params{$key}) { - $config{$key} = $val; 0 - } else { 1 } -} @ARGV; - -$extralibdir = $config{EXTRALIBDIR}; -delete $config{EXTRALIBDIR}; - -WriteMakefile( - %INFOS, - %config, -); - diff --git a/bindings/perl/ccs/Makefile.am b/bindings/perl/ccs/Makefile.am deleted file mode 100644 index 1fa5dcd..0000000 --- a/bindings/perl/ccs/Makefile.am +++ /dev/null @@ -1,59 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -PERL_TARGET = CCS.pm META.yml - -PERL_MAKEFILE = Makefile.perl - -PERL_MAKEFILEPL = Makefile.PL - -LINK_SRCS = CCS.xs typemap test.pl - -EXTRA_DIST = $(PERL_MAKEFILE_PL) $(LINK_SRCS) \ - CCS.pm.in META.yml.in - -AM_CPPFLAGS = -I$(top_srcdir)/config/libs/libccsconfdb/ - -AM_LDFLAGS = -L$(top_builddir)/config/libs/libccsconfdb/.libs -lccs - -all-local: linkcode $(PERL_MAKEFILE) $(PERL_TARGET) - ${MAKE} -f $(PERL_MAKEFILE) LD_RUN_PATH=""; - -%.pm: $(srcdir)/%.pm.in - cat $< | \ - sed \ - -e 's/_VERSION_/${PACKAGE_VERSION}/g' \ - > $@ - -%.yml: $(srcdir)/%.yml.in - cat $< | \ - sed \ - -e 's/_VERSION_/${PACKAGE_VERSION}/g' \ - > $@ - -$(PERL_MAKEFILE): linkcode $(PERL_TARGET) Makefile - perl $(PERL_MAKEFILEPL) \ - FIRST_MAKEFILE=$@ \ - INC='$(AM_CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)' \ - LIBS='$(AM_LDFLAGS) $(LDFLAGS)' \ - INSTALLDIRS=vendor - -linkcode: - if [ ! -e $(PERL_MAKEFILEPL) ]; then \ - for i in $(PERL_MAKEFILEPL) $(LINK_SRCS); do \ - $(LN_S) $(srcdir)/$$i $$i; \ - done; \ - touch linkcode; \ - fi - -clean-local: - -${MAKE} -f $(PERL_MAKEFILE) clean - rm -f $(PERL_TARGET) *.old - if [ -e linkcode ]; then \ - rm -f $(PERL_MAKEFILEPL) $(LINK_SRCS) linkcode; \ - fi - -install-exec-local: - ${MAKE} -f $(PERL_MAKEFILE) install ; - -uninstall-local: - echo "MakeMaker does not support uninstall." diff --git a/bindings/perl/ccs/test.pl b/bindings/perl/ccs/test.pl deleted file mode 100644 index 64d740d..0000000 --- a/bindings/perl/ccs/test.pl +++ /dev/null @@ -1,20 +0,0 @@ -# Before `make install' is performed this script should be runnable with -# `make test'. After `make install' it should work as `perl test.pl' - -######################### We start with some black magic to print on failure. - -# Change 1..1 below to 1..last_test_to_print . -# (It may become useful if the test is moved to ./t subdirectory.) - -BEGIN { $| = 1; print "1..1\n"; } -END {print "not ok 1\n" unless $loaded;} -use Cluster::CCS; -$loaded = 1; -print "ok 1\n"; - -######################### End of black magic. - -# Insert your test code below (better if it prints "ok 13" -# (correspondingly "not ok 13") depending on the success of chunk 13 -# of the test code): - diff --git a/bindings/perl/ccs/typemap b/bindings/perl/ccs/typemap deleted file mode 100644 index 02522e8..0000000 --- a/bindings/perl/ccs/typemap +++ /dev/null @@ -1 +0,0 @@ -TYPEMAP diff --git a/cman/Makefile.am b/cman/Makefile.am deleted file mode 100644 index 673ca3a..0000000 --- a/cman/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -# don't do init for now. -SUBDIRS = services cman_tool config qdisk notifyd man tests # init.d diff --git a/cman/cman_tool/Makefile.am b/cman/cman_tool/Makefile.am deleted file mode 100644 index 4972f1f..0000000 --- a/cman/cman_tool/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -sbin_PROGRAMS = cman_tool - -noinst_HEADERS = cman_tool.h - -cman_tool_SOURCES = main.c join.c - -cman_tool_CPPFLAGS = -I$(top_srcdir)/cman/services/cman/lib/ \ - -I$(top_srcdir)/config/libs/libccsconfdb/ - -cman_tool_CFLAGS = $(votequorum_CFLAGS) - -cman_tool_LDFLAGS = $(votequorum_LIBS) - -cman_tool_LDADD = $(top_builddir)/cman/services/cman/lib/libcman.la \ - $(top_builddir)/config/libs/libccsconfdb/libccs.la diff --git a/cman/cman_tool/cman_tool.h b/cman/cman_tool/cman_tool.h deleted file mode 100644 index 3766ee2..0000000 --- a/cman/cman_tool/cman_tool.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef __CMAN_TOOL_DOT_H__ -#define __CMAN_TOOL_DOT_H__ - -#include <sys/types.h> -#include <sys/uio.h> -#include <netinet/in.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/utsname.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <net/if.h> -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> -#include <stddef.h> -#include <stdint.h> -#include <fcntl.h> -#include <netdb.h> -#include <limits.h> -#include <unistd.h> - -extern char *prog_name; - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -#define die(fmt, args...) \ -do { \ - fprintf(stderr, "%s: ", prog_name); \ - fprintf(stderr, fmt "\n", ##args); \ - exit(EXIT_FAILURE); \ -} while (0) - -#define DEFAULT_VOTES 1 -#define MAX_INTERFACES 10 -#define MAX_FORMAT_OPTS 10 -#define MAX_NODE_NAME_LEN 65 -#define MAX_MCAST_NAME_LEN 256 -#define MAX_PATH_LEN 256 - -#define DEBUG_STARTUP_ONLY 32 - -enum format_opt -{ - FMT_NONE, - FMT_ID, - FMT_NAME, - FMT_TYPE, - FMT_ADDR, -}; - -struct commandline -{ - int operation; - int num_nodenames; - char *multicast_addr; - char *nodenames[MAX_INTERFACES]; - char *interfaces[MAX_INTERFACES]; - char *override_nodename; - char *key_filename; - char *filename; - char *format_opts; - char *config_lcrso; - int votes; - int expected_votes; - int two_node; - int port; - char clustername[MAX_CLUSTER_NAME_LEN]; - int remove; - int force; - int verbose; - int nodeid; - int timeout; - unsigned int config_version; - - int config_version_opt; - int votes_opt; - int expected_votes_opt; - int port_opt; - int nodeid_opt; - int clustername_opt; - int wait_opt; - int wait_quorate_opt; - int fence_opt; - int addresses_opt; - int noconfig_opt; - int nosetpri_opt; - int noopenais_opt; -}; -typedef struct commandline commandline_t; - -int join(commandline_t *comline, char *envp[]); -const char *cman_error(int err); - -#endif /* __CMAN_TOOL_DOT_H__ */ diff --git a/cman/cman_tool/join.c b/cman/cman_tool/join.c deleted file mode 100644 index fd6d743..0000000 --- a/cman/cman_tool/join.c +++ /dev/null @@ -1,335 +0,0 @@ -#include "clusterautoconfig.h" - -#include <sys/wait.h> -#include <stdint.h> -#include <signal.h> -#include <netinet/in.h> -#include "libcman.h" -#include "cman_tool.h" - -#define MAX_ARGS 128 - -static char *argv[MAX_ARGS]; -static char *envp[MAX_ARGS]; - -static void be_daemon(int close_stderr) -{ - int devnull = open("/dev/null", O_RDWR); - if (devnull == -1) { - perror("Can't open /dev/null"); - exit(3); - } - - /* Detach ourself from the calling environment */ - if (close(0) || close(1)) { - die("Error closing terminal FDs"); - } - - if (dup2(devnull, 0) < 0 || dup2(devnull, 1) < 0) { - die("Error setting terminal FDs to /dev/null: %m"); - } - - if (close_stderr) { - if (close(2)) { - die("Error closing stderr FD"); - } - if (!dup2(devnull, 2) < 0) { - die("Error setting stderr FD to /dev/null: %m"); - } - } - - setsid(); -} - - -static const char *corosync_exit_reason(signed char status) -{ - static char reason[256]; - switch (status) { - case -2: - return "Could not determine UID to run as"; - break; - case -3: - return "Could not determine GID to run as"; - break; - case -4: - return "Error initialising memory pool"; - break; - case -5: - return "Could not fork"; - break; - case -6: - return "Could not bind to libais socket"; - break; - case -7: - return "Could not bind to network socket"; - break; - case -8: - return "Could not read security key for communications"; - break; - case -9: - return "Could not read cluster configuration"; - break; - case -10: - return "Could not set up logging"; - break; - case -11: - return "Could not dynamically load modules"; - break; - case -12: - return "Could not load and initialise object database"; - break; - case -13: - return "Could not initialise all required services"; - break; - case -14: - return "Out of memory"; - break; - default: - sprintf(reason, "Error, reason code is %d", status); - return reason; - break; - } -} - -static int check_corosync_status(pid_t pid) -{ - int status; - int pidstatus; - - status = waitpid(pid, &pidstatus, WNOHANG); - if (status == -1 && errno == ECHILD) { - - return 0; - } - if ((status == 0 || status == pid) && pidstatus != 0) { - if (WIFEXITED(pidstatus)) - fprintf(stderr, "corosync died: %s\n", corosync_exit_reason(WEXITSTATUS(pidstatus))); - if (WIFSIGNALED(pidstatus)) - fprintf(stderr, "corosync died with signal: %d\n", WTERMSIG(pidstatus)); - exit(1); - } - return status; -} - -int join(commandline_t *comline, char *main_envp[]) -{ - int i, err; - int envptr = 0; - int argvptr = 0; - char scratch[1024]; - cman_handle_t h = NULL; - int status; - pid_t corosync_pid; - int p[2]; - - /* - * If we can talk to cman then we're already joined (or joining); - */ - h = cman_admin_init(NULL); - if (h) - die("Node is already active"); - - /* Set up environment variables for override */ - if (comline->multicast_addr) { - snprintf(scratch, sizeof(scratch), "CMAN_MCAST_ADDR=%s", comline->multicast_addr); - envp[envptr++] = strdup(scratch); - } - if (comline->votes_opt) { - snprintf(scratch, sizeof(scratch), "CMAN_VOTES=%d", comline->votes); - envp[envptr++] = strdup(scratch); - } - if (comline->expected_votes_opt) { - snprintf(scratch, sizeof(scratch), "CMAN_EXPECTEDVOTES=%d", comline->expected_votes); - envp[envptr++] = strdup(scratch); - } - if (comline->port) { - snprintf(scratch, sizeof(scratch), "CMAN_IP_PORT=%d", comline->port); - envp[envptr++] = strdup(scratch); - } - if (comline->nodeid) { - snprintf(scratch, sizeof(scratch), "CMAN_NODEID=%d", comline->nodeid); - envp[envptr++] = strdup(scratch); - } - if (comline->clustername_opt) { - snprintf(scratch, sizeof(scratch), "CMAN_CLUSTER_NAME=%s", comline->clustername); - envp[envptr++] = strdup(scratch); - } - if (comline->nodenames[0]) { - snprintf(scratch, sizeof(scratch), "CMAN_NODENAME=%s", comline->nodenames[0]); - envp[envptr++] = strdup(scratch); - } - if (comline->key_filename) { - snprintf(scratch, sizeof(scratch), "CMAN_KEYFILE=%s", comline->key_filename); - envp[envptr++] = strdup(scratch); - } - if (comline->two_node) { - snprintf(scratch, sizeof(scratch), "CMAN_2NODE=true"); - envp[envptr++] = strdup(scratch); - } - if (comline->verbose ^ DEBUG_STARTUP_ONLY) { - snprintf(scratch, sizeof(scratch), "CMAN_DEBUGLOG=%d", comline->verbose); - envp[envptr++] = strdup(scratch); - } - if (comline->noconfig_opt) { - envp[envptr++] = strdup("CMAN_NOCONFIG=true"); - snprintf(scratch, sizeof(scratch), "COROSYNC_DEFAULT_CONFIG_IFACE=cmanpreconfig%s", - comline->noopenais_opt?"":":openaisserviceenablestable"); - envp[envptr++] = strdup(scratch); - } - else { - snprintf(scratch, sizeof(scratch), "COROSYNC_DEFAULT_CONFIG_IFACE=%s:cmanpreconfig%s", comline->config_lcrso, - comline->noopenais_opt?"":":openaisserviceenablestable"); - envp[envptr++] = strdup(scratch); - } - - /* Copy any COROSYNC_* env variables to the new daemon */ - i=0; - while (i < MAX_ARGS && main_envp[i]) { - if (strncmp(main_envp[i], "COROSYNC_", 9) == 0) - envp[envptr++] = main_envp[i]; - i++; - } - - - /* Create a pipe to monitor cman startup progress */ - if (pipe(p) < 0) - die("unable to create pipe: %s", strerror(errno)); - fcntl(p[1], F_SETFD, 0); /* Don't close on exec */ - snprintf(scratch, sizeof(scratch), "CMAN_PIPE=%d", p[1]); - envp[envptr++] = strdup(scratch); - envp[envptr++] = NULL; - - /* Always run corosync -f because we have already forked twice anyway, and - we want to return any exit code that might happen */ - /* also strdup strings because it's otherwise virtually impossible to fix - * build warnings due to the way argv C implementation is done */ - argv[0] = strdup("corosync"); - argv[++argvptr] = strdup("-f"); - if (comline->nosetpri_opt) - argv[++argvptr] = strdup("-p"); - argv[++argvptr] = NULL; - - /* Fork/exec cman */ - switch ( (corosync_pid = fork()) ) - { - case -1: - die("fork of corosync daemon failed: %s", strerror(errno)); - - case 0: /* child */ - close(p[0]); - if (comline->verbose & DEBUG_STARTUP_ONLY) { - fprintf(stderr, "Starting %s", COROSYNCBIN); - for (i=0; i< argvptr; i++) { - fprintf(stderr, " %s", argv[i]); - } - fprintf(stderr, "\n"); - for (i=0; i<envptr-1; i++) { - fprintf(stderr, "%s\n", envp[i]); - } - } - be_daemon(!(comline->verbose & ~DEBUG_STARTUP_ONLY)); - - sprintf(scratch, "FORKED: %d\n", getpid()); - err = write(p[1], scratch, strlen(scratch)); - - execve(COROSYNCBIN, argv, envp); - - /* exec failed - tell the parent process */ - sprintf(scratch, "execve of " COROSYNCBIN " failed: %s", strerror(errno)); - err = write(p[1], scratch, strlen(scratch)); - exit(1); - break; - - default: /* parent */ - break; - - } - - /* Give the daemon a chance to start up, and monitor the pipe FD for messages */ - i = 0; - close(p[1]); - - /* Wait for the process to start or die */ - sleep(1); - do { - fd_set fds; - struct timeval tv={1, 0}; - char message[1024]; - char *messageptr = message; - - FD_ZERO(&fds); - FD_SET(p[0], &fds); - - status = select(p[0]+1, &fds, NULL, NULL, &tv); - - /* Did we get a cman-reported error? */ - if (status == 1) { - int len; - if ((len = read(p[0], message, sizeof(message)) > 0)) { - - /* Forked OK - get the real corosync pid */ - if (sscanf(messageptr, "FORKED: %d", &corosync_pid) == 1) { - if (comline->verbose & DEBUG_STARTUP_ONLY) - fprintf(stderr, "forked process ID is %d\n", corosync_pid); - status = 0; - - /* There might be a SUCCESS or error message in the pipe too. */ - messageptr = strchr(messageptr, '\n'); - if (messageptr && strlen(messageptr) > 1) - messageptr++; - else - continue; - } - /* Success! get the new PID of double-forked corosync */ - if (sscanf(messageptr, "SUCCESS: %d", &corosync_pid) == 1) { - if (comline->verbose & DEBUG_STARTUP_ONLY) - fprintf(stderr, "corosync running, process ID is %d\n", corosync_pid); - break; - } - else if (messageptr) { - fprintf(stderr, "%s\n", messageptr); - status = 1; - break; - } - } - else if (len < 0 && errno == EINTR) { - continue; - } - else { /* Error or EOF - check the child status */ - status = check_corosync_status(corosync_pid); - } - } - - } while (status == 0); - close(p[0]); - - /* If corosync has started, try to connect to cman ... if it's still there */ - if (status == 0) { - do { - if (status == 0) { - if (kill(corosync_pid, 0) < 0) { - status = check_corosync_status(corosync_pid); - die("corosync died during startup\n"); - } - - h = cman_admin_init(NULL); - if (!h && comline->verbose & DEBUG_STARTUP_ONLY) - { - fprintf(stderr, "waiting for cman to start\n"); - status = check_corosync_status(corosync_pid); - } - } - sleep (1); - } while (!h && ++i < 100); - } - - if (!h) - die("corosync daemon didn't start"); - - if ((comline->verbose & DEBUG_STARTUP_ONLY) && !cman_is_active(h)) - fprintf(stderr, "corosync started, but not joined the cluster yet.\n"); - - cman_finish(h); - return 0; -} diff --git a/cman/cman_tool/main.c b/cman/cman_tool/main.c deleted file mode 100644 index 4985e76..0000000 --- a/cman/cman_tool/main.c +++ /dev/null @@ -1,1014 +0,0 @@ -#include "clusterautoconfig.h" - -#include <inttypes.h> -#include <unistd.h> -#include <signal.h> -#include <time.h> -#include <netinet/in.h> -#include "copyright.cf" -#include "libcman.h" -#include "cman_tool.h" - -#define DEFAULT_CONFIG_MODULE "xmlconfig" - -#define OPTION_STRING ("m:n:v:e:2p:c:r:i:N:t:o:k:F:C:VAPwfqah?Xd::") -#define OP_JOIN 1 -#define OP_LEAVE 2 -#define OP_EXPECTED 3 -#define OP_VOTES 4 -#define OP_KILL 5 -#define OP_VERSION 6 -#define OP_WAIT 7 -#define OP_STATUS 8 -#define OP_NODES 9 -#define OP_SERVICES 10 -#define OP_DEBUG 11 - - -static void print_usage(int subcmd) -{ - printf("Usage:\n"); - printf("\n"); - printf("%s <join|leave|kill|expected|votes|version|wait|status|nodes|services|debug> [options]\n", - prog_name); - printf("\n"); - printf("Options:\n"); - printf(" -h Print this help, then exit\n"); - printf(" -V Print program version information, then exit\n"); - printf(" -d Enable debug output\n"); - printf("\n"); - - if (!subcmd || subcmd == OP_JOIN) { - printf("join\n"); - printf(" Cluster & node information is taken from configuration modules.\n"); - printf(" These switches are provided to allow those values to be overridden.\n"); - printf(" Use them with extreme care.\n\n"); - - printf(" -m <addr> Multicast address to use\n"); - printf(" -v <votes> Number of votes this node has\n"); - printf(" -e <votes> Number of expected votes for the cluster\n"); - printf(" -p <port> UDP port number for cman communications\n"); - printf(" -n <nodename> The name of this node (defaults to hostname)\n"); - printf(" -c <clustername> The name of the cluster to join\n"); - printf(" -N <id> Node id\n"); - printf(" -C <module> Config file reader (default: " DEFAULT_CONFIG_MODULE ")\n"); - printf(" -w Wait until node has joined a cluster\n"); - printf(" -q Wait until the cluster is quorate\n"); - printf(" -t Maximum time (in seconds) to wait\n"); - printf(" -k <file> Private key file for AIS communications\n"); - printf(" -P Don't set aisexec to realtime priority\n"); - printf(" -X Use internal cman defaults for configuration\n"); - printf(" -A Don't load openais services\n"); - printf("\n"); - } - - - if (!subcmd || subcmd == OP_WAIT) { - printf("wait Wait until the node is a member of a cluster\n"); - printf(" -q Wait until the cluster is quorate\n"); - printf(" -t Maximum time (in seconds) to wait\n"); - printf("\n"); - } - - if (!subcmd || subcmd == OP_LEAVE) { - printf("leave\n"); - printf(" -w If cluster is in transition, wait and keep trying\n"); - printf(" -t Maximum time (in seconds) to wait\n"); - printf(" remove Tell other nodes to ajust quorum downwards if necessary\n"); - printf(" force Leave even if cluster subsystems are active\n"); - printf("\n"); - } - - if (!subcmd || subcmd == OP_KILL) { - printf("kill\n"); - printf(" -n <nodename> The name of the node to kill (can specify multiple times)\n"); - printf("\n"); - } - - if (!subcmd || subcmd == OP_EXPECTED) { - printf("expected\n"); - printf(" -e <votes> New number of expected votes for the cluster\n"); - printf("\n"); - } - - if (!subcmd || subcmd == OP_VOTES) { - printf("votes\n"); - printf(" -v <votes> New number of votes for this node\n"); - printf("\n"); - } - - if (!subcmd || subcmd == OP_STATUS) { - printf("status Show local record of cluster status\n"); - printf("\n"); - } - - if (!subcmd || subcmd == OP_NODES) { - printf("nodes Show local record of cluster nodes\n"); - printf(" -f Also show when node was last fenced\n"); - printf(" -a Also show node address(es)\n"); - printf(" -n <nodename> Only show information for specific node\n"); - printf(" -F <format> Specify output format (see man page)\n"); - printf("\n"); - } - - if (!subcmd || subcmd == OP_SERVICES) { - printf("services Show local record of cluster services\n"); - printf("\n"); - } - - if (!subcmd || subcmd == OP_VERSION) { - printf("version\n"); - printf(" -r <config> A new config version to set on all members\n"); - printf("\n"); - } -} - -static void sigalarm_handler(int sig) -{ - fprintf(stderr, "Timed-out waiting for cluster\n"); - exit(2); -} - -static cman_handle_t open_cman_handle(int priv) -{ - cman_handle_t h; - - if (priv) - h = cman_admin_init(NULL); - else - h = cman_init(NULL); - if (!h) - { - if (errno == EACCES) - die("Cannot open connection to cman, permission denied."); - else - die("Cannot open connection to cman, is it running ?"); - } - return h; -} - -static void print_address(char *addr) -{ - char buf[INET6_ADDRSTRLEN]; - struct sockaddr_storage *ss = (struct sockaddr_storage *)addr; - struct sockaddr_in *sin = (struct sockaddr_in *)addr; - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; - void *saddr; - - if (ss->ss_family == AF_INET6) - saddr = &sin6->sin6_addr; - else - saddr = &sin->sin_addr; - - inet_ntop(ss->ss_family, saddr, buf, sizeof(buf)); - printf("%s", buf); -} - -static char *membership_state(char *buf, int buflen, int node_state) -{ - switch (node_state) { - case 1: - strncpy(buf, "Joining", buflen); - break; - case 2: - strncpy(buf, "Cluster-Member", buflen); - break; - case 3: - strncpy(buf, "Not-in-Cluster", buflen); - break; - case 4: - strncpy(buf, "Leaving", buflen); - break; - default: - sprintf(buf, "Unknown: code=%d", node_state); - break; - } - - return buf; -} - -static void show_status(void) -{ - cman_cluster_t info; - cman_version_t v; - cman_handle_t h; - cman_node_t node; - char info_buf[PIPE_BUF]; - char tmpbuf[1024]; - cman_extra_info_t *einfo = (cman_extra_info_t *)info_buf; - cman_qdev_info_t qinfo; - int numaddrs; - struct cman_node_address addrs[MAX_INTERFACES]; - int quorate; - int i; - - h = open_cman_handle(0); - - if (cman_get_cluster(h, &info) < 0) - die("Error getting cluster info: %s\n", cman_error(errno)); - if (cman_get_version(h, &v) < 0) - die("Error getting cluster version: %s\n", cman_error(errno)); - if (cman_get_extra_info(h, einfo, sizeof(info_buf)) < 0) - die("Error getting extra info: %s\n", cman_error(errno)); - - quorate = cman_is_quorate(h); - - printf("Version: %d.%d.%d\n", v.cv_major, v.cv_minor, v.cv_patch); - printf("Config Version: %d\n", v.cv_config); - printf("Cluster Name: %s\n", info.ci_name); - printf("Cluster Id: %d\n", info.ci_number); - printf("Cluster Member: Yes\n"); - printf("Cluster Generation: %d\n", info.ci_generation); - - printf("Membership state: %s\n", membership_state(tmpbuf, sizeof(tmpbuf), - einfo->ei_node_state)); - printf("Nodes: %d\n", einfo->ei_members); - printf("Expected votes: %d\n", einfo->ei_expected_votes); - if (cman_get_quorum_device(h, &qinfo) == 0 && qinfo.qi_state == 2) - printf("Quorum device votes: %d\n", qinfo.qi_votes); - printf("Total votes: %d\n", einfo->ei_total_votes); - printf("Node votes: %d\n", einfo->ei_node_votes); - - printf("Quorum: %d %s\n", einfo->ei_quorum, quorate?" ":"Activity blocked"); - printf("Flags:"); - if (einfo->ei_flags & CMAN_EXTRA_FLAG_2NODE) - printf(" 2node"); - if (einfo->ei_flags & CMAN_EXTRA_FLAG_DISALLOWED) - printf(" DisallowedNodes"); - if (einfo->ei_flags & CMAN_EXTRA_FLAG_HASSTATE) - printf(" HasState"); - if (einfo->ei_flags & CMAN_EXTRA_FLAG_NOCONFIG) - printf(" NoConfig"); - printf(" \n"); - - memset(&node, 0, sizeof(node)); - if (cman_get_node(h, CMAN_NODEID_US, &node) == 0) { - printf("Node name: %s\n", node.cn_name); - printf("Node ID: %u\n", node.cn_nodeid); - } - if (einfo->ei_num_addresses > 0) { - printf("Multicast addresses: %s\n", einfo->ei_addresses); - } - - if (cman_get_node_addrs(h, CMAN_NODEID_US, MAX_INTERFACES, &numaddrs, addrs) == 0) { - printf("Node addresses: "); - for (i = 0; i < numaddrs; i++) - { - print_address(addrs[i].cna_address); - printf(" "); - } - printf("\n"); - } - if (einfo->ei_flags & CMAN_EXTRA_FLAG_DISALLOWED) { - int count; - int numnodes; - cman_node_t *nodes; - - count = cman_get_node_count(h); - nodes = malloc(sizeof(cman_node_t) * count); - - if (cman_get_disallowed_nodes(h, count, &numnodes, nodes) == 0) { - printf("Disallowed nodes: "); - for (i=0; i<numnodes; i++) { - printf("%s ", nodes[i].cn_name); - } - printf("\n"); - } - } - - cman_finish(h); -} - -static int node_compare(const void *va, const void *vb) -{ - const cman_node_t *a = va; - const cman_node_t *b = vb; - return a->cn_nodeid - b->cn_nodeid; -} - -static int node_filter(commandline_t *comline, const char *node) -{ - int i; - - for (i = 0; i < comline->num_nodenames; i++) { - if (strcmp(comline->nodenames[i], node) == 0) { - return TRUE; - } - } - - return FALSE; -} - -static int get_format_opt(const char *opt) -{ - if (!opt) - return FMT_NONE; - - if (!strcmp(opt, "id")) - return FMT_ID; - if (!strcmp(opt, "name")) - return FMT_NAME; - if (!strcmp(opt, "type")) - return FMT_TYPE; - if (!strcmp(opt, "addr")) - return FMT_ADDR; - - return FMT_NONE; -} - - -static void print_node(commandline_t *comline, cman_handle_t h, int *format, struct cman_node *node) -{ - char member_type; - int i,j,k; - int numaddrs; - struct cman_node_address addrs[MAX_INTERFACES]; - - if (comline->num_nodenames > 0) { - if (node_filter(comline, node->cn_name) == 0) { - return; - } - } - - switch (node->cn_member) { - case 0: - member_type = 'X'; - break; - case 1: - member_type = 'M'; - break; - case 2: - member_type = 'd'; - break; - default: - member_type = '?'; - break; - } - - if (!comline->format_opts) { - printf("%8u %c %s\n", - node->cn_nodeid, member_type, - node->cn_name); - } - - if (comline->addresses_opt || comline->format_opts) { - if (!cman_get_node_addrs(h, node->cn_nodeid, MAX_INTERFACES, &numaddrs, addrs) && - numaddrs) - { - if (!comline->format_opts) { - printf(" Addresses: "); - for (i = 0; i < numaddrs; i++) - { - print_address(addrs[i].cna_address); - printf(" "); - } - printf("\n"); - } - } - } - if (comline->format_opts) { - for (j = 0; j < MAX_FORMAT_OPTS; j++) { - switch (format[j]) { - case FMT_NONE: - break; - case FMT_ID: - printf("%u ", node->cn_nodeid); - break; - case FMT_NAME: - printf("%s ", node->cn_name); - break; - case FMT_TYPE: - printf("%c ", member_type); - break; - case FMT_ADDR: - for (k = 0; k < numaddrs; k++) { - print_address(addrs[k].cna_address); - if (k != (numaddrs - 1)) { - printf(","); - } - } - printf(" "); - break; - default: - break; - } - } - printf("\n"); - } -} - -static void show_nodes(commandline_t *comline) -{ - cman_handle_t h; - int count; - int i; - int j; - int numnodes; - int dis_count; - int format[MAX_FORMAT_OPTS]; - cman_node_t *dis_nodes; - cman_node_t *nodes; - - h = open_cman_handle(0); - - count = cman_get_node_count(h); - if (count < 0) - die("cman_get_node_count failed: %s", cman_error(errno)); - - count += 2; /* Extra space! */ - - nodes = malloc(sizeof(cman_node_t) * count); - if (!nodes) - die("cannot allocate memory for nodes list\n"); - - if (comline->format_opts != NULL) { - char *format_str = comline->format_opts; - char *format_tmp; - for (i = 0; i < MAX_FORMAT_OPTS; i++) { - format_tmp = strtok(format_str, ","); - format_str = NULL; - format[i] = get_format_opt(format_tmp); - } - } - - if (cman_get_nodes(h, count, &numnodes, nodes) < 0) - die("cman_get_nodes failed: %s", cman_error(errno)); - - - /* Get Disallowed nodes, so we can show them as such */ - dis_nodes = malloc(sizeof(cman_node_t) * count); - - if (cman_get_disallowed_nodes(h, count, &dis_count, dis_nodes) == 0) { - for (i = 0; i < numnodes; i++) { - for (j = 0; j < dis_count; j++) { - if (dis_nodes[j].cn_nodeid == nodes[i].cn_nodeid) - nodes[i].cn_member = 2; - } - } - } - - /* Sort by nodeid to be friendly */ - qsort(nodes, numnodes, sizeof(cman_node_t), node_compare); - - if (dis_count) { - printf("NOTE: There are %d disallowed nodes,\n", dis_count); - printf(" members list may seem inconsistent across the cluster\n"); - } - - if (!comline->format_opts) { - printf(" Node Id Sts Name\n"); - } - - /* Print nodes */ - for (i = 0; i < numnodes; i++) { - print_node(comline, h, format, &nodes[i]); - } - - free(nodes); - free(dis_nodes); - cman_finish(h); -} - -static int show_services(void) -{ - return system("group_tool ls"); -} - - -const char *cman_error(int err) -{ - const char *die_error; - - switch (errno) { - case ENOTCONN: - die_error = "Cluster software not started"; - break; - case ENOENT: - die_error = "Node is not yet a cluster member"; - break; - default: - die_error = strerror(errno); - break; - } - return die_error; -} - -static void leave(commandline_t *comline) -{ - cman_handle_t h; - int result; - int flags = 0; - - h = open_cman_handle(1); - - /* "cman_tool leave remove" adjusts quorum downward */ - - if (comline->remove) - flags |= CMAN_SHUTDOWN_REMOVED; - - if (comline->force) - flags |= CMAN_SHUTDOWN_ANYWAY; - - if (comline->wait_opt && comline->timeout) { - signal(SIGALRM, sigalarm_handler); - alarm(comline->timeout); - } - - result = cman_shutdown(h, flags); - if (result && !comline->wait_opt) { - die("Error leaving cluster: %s", cman_error(errno)); - } - cman_finish(h); - - /* Wait until cman shuts down */ - if (comline->wait_opt) { - while ( (h = cman_admin_init(NULL)) ) { - cman_finish(h); - sleep(1); - } - } -} - -static void set_expected(commandline_t *comline) -{ - cman_handle_t h; - int result; - - if (comline->expected_votes == 0) { - die("expected_votes not specified"); - } - - h = open_cman_handle(1); - - if ((result = cman_set_expected_votes(h, comline->expected_votes))) - die("can't set expected votes: %s", cman_error(errno)); - - cman_finish(h); -} - -static void set_votes(commandline_t *comline) -{ - cman_handle_t h; - int result; - int nodeid; - struct cman_node node; - - - h = open_cman_handle(1); - - if (!comline->num_nodenames) { - nodeid = 0; /* This node */ - } - else { - /* Resolve node name into a number */ - node.cn_nodeid = 0; - strcpy(node.cn_name, comline->nodenames[0]); - if (cman_get_node(h, node.cn_nodeid, &node)) - die("Can't set votes for node %s : %s\n", node.cn_name, strerror(errno)); - nodeid = node.cn_nodeid; - } - - if ((result = cman_set_votes(h, comline->votes, nodeid))) - die("can't set votes: %s", cman_error(errno)); - - cman_finish(h); -} - - -/* This just tells corosync to reload the config file */ -static void version(commandline_t *comline) -{ - struct cman_version ver; - cman_handle_t h; - int result; - - h = open_cman_handle(1); - - if ((result = cman_get_version(h, &ver))) - die("can't get version: %s", cman_error(errno)); - - if (ver.cv_config == -1) { - printf("cman is running without a configuration file\n"); - goto out; - } - - if (!comline->config_version_opt) { - printf("%d.%d.%d config %d\n", ver.cv_major, ver.cv_minor, ver.cv_patch, - ver.cv_config); - goto out; - } - - ver.cv_config = comline->config_version; - - if ((result = cman_set_version(h, &ver))) - die("can't set version: %s", cman_error(errno)); - out: - cman_finish(h); -} - -static int cluster_wait(commandline_t *comline) -{ - cman_handle_t h; - int ret = 0; - - h = open_cman_handle(0); - - if (comline->wait_quorate_opt) { - while (cman_is_quorate(h) <= 0) { - sleep(1); - } - } - else { - while (cman_get_node_count(h) < 0) { - sleep(1); - } - } - - cman_finish(h); - - return ret; -} - -static void kill_node(commandline_t *comline) -{ - cman_handle_t h; - int i; - struct cman_node node; - - if (!comline->num_nodenames) { - die("No node name specified\n"); - } - - h = open_cman_handle(1); - - for (i=0; i<comline->num_nodenames; i++) { - - /* Resolve node name into a number */ - node.cn_nodeid = 0; - strcpy(node.cn_name, comline->nodenames[i]); - if (cman_get_node(h, node.cn_nodeid, &node)) { - fprintf(stderr, "Can't kill node %s : %s\n", node.cn_name, strerror(errno)); - continue; - } - - - if (cman_kill_node(h, node.cn_nodeid)) - perror("kill node failed"); - } - - cman_finish(h); -} - -static void set_debuglog(commandline_t *comline) -{ - cman_handle_t h; - - h = open_cman_handle(1); - -#if 0 -// TODO this should be done via cluster.conf ? -// or can we do something directly in objdb ?? -// - if (cman_set_debuglog(h, comline->verbose)) - perror("setting debuglog failed"); -#endif - cman_finish(h); -} - - -static int get_int_arg(char argopt, char *arg) -{ - char *tmp; - int val; - - val = strtol(arg, &tmp, 10); - if (tmp == arg || tmp != arg + strlen(arg)) - die("argument to %c (%s) is not an integer", argopt, arg); - - if (val < 0) - die("argument to %c cannot be negative", argopt); - - return val; -} - - -static void decode_arguments(int argc, char *argv[], commandline_t *comline) -{ - int cont = TRUE; - int optchar, i; - int show_help = 0; - - while (cont) { - optchar = getopt(argc, argv, OPTION_STRING); - - switch (optchar) { - - case 'm': - comline->multicast_addr = strdup(optarg); - break; - - case 'f': - comline->fence_opt = 1; - break; - - case 'a': - comline->addresses_opt = 1; - break; - - case 'n': - i = comline->num_nodenames; - if (i >= MAX_INTERFACES) - die("maximum of %d node names allowed", - MAX_INTERFACES); - if (strlen(optarg) > MAX_NODE_NAME_LEN) - die("maximum node name length is %d", - MAX_NODE_NAME_LEN); - comline->nodenames[i] = strdup(optarg); - comline->num_nodenames++; - break; - - case 'o': - comline->override_nodename = strdup(optarg); - break; - - case 'k': - comline->key_filename = strdup(optarg); - break; - - case 'C': - comline->config_lcrso = strdup(optarg); - break; - - case 'r': - comline->config_version = get_int_arg(optchar, optarg); - comline->config_version_opt = TRUE; - break; - - case 'v': - comline->votes = get_int_arg(optchar, optarg); - comline->votes_opt = TRUE; - break; - - case 'e': - comline->expected_votes = get_int_arg(optchar, optarg); - comline->expected_votes_opt = TRUE; - break; - - case '2': - comline->two_node = TRUE; - break; - - case 'p': - comline->port = get_int_arg(optchar, optarg); - comline->port_opt = TRUE; - break; - - case 'N': - comline->nodeid = get_int_arg(optchar, optarg); - comline->nodeid_opt = TRUE; - break; - - case 'c': - if (strlen(optarg) > MAX_NODE_NAME_LEN-1) - die("maximum cluster name length is %d", - MAX_CLUSTER_NAME_LEN-1); - strcpy(comline->clustername, optarg); - comline->clustername_opt = TRUE; - break; - - case 'F': - comline->format_opts = strdup(optarg); - break; - - case 'V': - printf("cman_tool %s (built %s %s)\n", - PACKAGE_VERSION, __DATE__, __TIME__); - printf("%s\n", REDHAT_COPYRIGHT); - exit(EXIT_SUCCESS); - break; - - case 'h': - show_help = 1; - break; - - case ':': - case '?': - fprintf(stderr, "Please use '-h' for usage.\n"); - exit(EXIT_FAILURE); - break; - - case 'd': - if (optarg) - comline->verbose = atoi(optarg); - else - comline->verbose = 255; - break; - - case 'w': - comline->wait_opt = TRUE; - break; - - case 'q': - comline->wait_quorate_opt = TRUE; - break; - - case 't': - comline->timeout = get_int_arg(optchar, optarg); - break; - - case EOF: - cont = FALSE; - break; - - case 'X': - comline->noconfig_opt = TRUE; - break; - - case 'A': - comline->noopenais_opt = TRUE; - break; - - case 'P': - comline->nosetpri_opt = TRUE; - break; - default: - die("unknown option: %c", optchar); - break; - }; - } - - if (comline->config_lcrso == NULL) - comline->config_lcrso = strdup(DEFAULT_CONFIG_MODULE); - - while (optind < argc) { - if (strcmp(argv[optind], "join") == 0) { - if (comline->operation) - die("can't specify two operations"); - comline->operation = OP_JOIN; - } else if (strcmp(argv[optind], "leave") == 0) { - if (comline->operation) - die("can't specify two operations"); - comline->operation = OP_LEAVE; - } else if (strcmp(argv[optind], "expected") == 0) { - if (comline->operation) - die("can't specify two operations"); - comline->operation = OP_EXPECTED; - } else if (strcmp(argv[optind], "votes") == 0) { - if (comline->operation) - die("can't specify two operations"); - comline->operation = OP_VOTES; - } else if (strcmp(argv[optind], "kill") == 0) { - if (comline->operation) - die("can't specify two operations"); - comline->operation = OP_KILL; - } else if (strcmp(argv[optind], "version") == 0) { - if (comline->operation) - die("can't specify two operations"); - comline->operation = OP_VERSION; - } else if (strcmp(argv[optind], "wait") == 0) { - if (comline->operation) - die("can't specify two operations"); - comline->operation = OP_WAIT; - } else if (strcmp(argv[optind], "status") == 0) { - if (comline->operation) - die("can't specify two operations"); - comline->operation = OP_STATUS; - } else if (strcmp(argv[optind], "nodes") == 0) { - if (comline->operation) - die("can't specify two operations"); - comline->operation = OP_NODES; - } else if (strcmp(argv[optind], "services") == 0) { - if (comline->operation) - die("can't specify two operations"); - comline->operation = OP_SERVICES; - } else if (strcmp(argv[optind], "debug") == 0) { - if (comline->operation) - die("can't specify two operations"); - comline->operation = OP_DEBUG; - } else if (strcmp(argv[optind], "remove") == 0) { - comline->remove = TRUE; - } else if (strcmp(argv[optind], "force") == 0) { - comline->force = TRUE; - } else - die("unknown option %s", argv[optind]); - - optind++; - } - - if (show_help) { - print_usage(comline->operation); - exit(EXIT_SUCCESS); - } - - if (!comline->operation) - die("no operation specified"); -} - -static void check_arguments(commandline_t *comline) -{ - if (comline->two_node && comline->expected_votes != 1) - die("expected_votes value (%d) invalid in two node mode", - comline->expected_votes); - - if (comline->port_opt && - (comline->port <= 0 || comline->port > 65535)) - die("Port must be a number between 1 and 65535"); - - /* This message looks like it contradicts the condition but - a nodeid of zero simply means "assign one for me" and is a - perfectly reasonable override */ - if (comline->nodeid < 0 || comline->nodeid > 4096) - die("Node id must be between 1 and 4096"); - - if (strlen(comline->clustername) > MAX_CLUSTER_NAME_LEN) { - die("Cluster name must be < %d characters long", - MAX_CLUSTER_NAME_LEN); - } - - if (comline->timeout && !comline->wait_opt && !comline->wait_quorate_opt) - die("timeout is only appropriate with wait"); -} - -int main(int argc, char *argv[], char *envp[]) -{ - commandline_t comline; - int ret; - - prog_name = argv[0]; - - memset(&comline, 0, sizeof(commandline_t)); - - decode_arguments(argc, argv, &comline); - - switch (comline.operation) { - case OP_JOIN: - check_arguments(&comline); - - if (comline.timeout) { - signal(SIGALRM, sigalarm_handler); - alarm(comline.timeout); - } - - join(&comline, envp); - if (comline.wait_opt || comline.wait_quorate_opt) { - do { - ret = cluster_wait(&comline); - if (ret == ENOTCONN) - join(&comline, envp); - - } while (ret == ENOTCONN); - } - break; - - case OP_LEAVE: - leave(&comline); - break; - - case OP_EXPECTED: - set_expected(&comline); - break; - - case OP_VOTES: - set_votes(&comline); - break; - - case OP_KILL: - kill_node(&comline); - break; - - case OP_VERSION: - version(&comline); - break; - - case OP_WAIT: - if (comline.timeout) { - signal(SIGALRM, sigalarm_handler); - alarm(comline.timeout); - } - cluster_wait(&comline); - break; - - case OP_STATUS: - show_status(); - break; - - case OP_NODES: - show_nodes(&comline); - break; - - case OP_SERVICES: - if (show_services() < 0) { - fprintf(stderr, "Unable to invoke group_tool\n"); - exit(EXIT_FAILURE); - } - break; - - case OP_DEBUG: - set_debuglog(&comline); - break; - } - - exit(EXIT_SUCCESS); -} - -char *prog_name; diff --git a/cman/config/Makefile.am b/cman/config/Makefile.am deleted file mode 100644 index 5bbec56..0000000 --- a/cman/config/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CFLAGS = -fPIC \ - $(cfg_CFLAGS) - -LCRSO = config_cmanpre.lcrso - -SOURCES = cman-preconfig.c - -EXTRA_DIST = $(SOURCES) - -noinst_HEADERS = cman.h nodelist.h - -include $(top_srcdir)/make/lcrso.mk diff --git a/cman/config/cman-preconfig.c b/cman/config/cman-preconfig.c deleted file mode 100644 index b22f359..0000000 --- a/cman/config/cman-preconfig.c +++ /dev/null @@ -1,1262 +0,0 @@ -#include "clusterautoconfig.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <sys/utsname.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/errno.h> -#include <netdb.h> -#define SYSLOG_NAMES -#include <sys/syslog.h> -#include <ifaddrs.h> -#include <arpa/inet.h> - -/* corosync headers */ -#include <corosync/engine/logsys.h> -#include <corosync/lcr/lcr_comp.h> -#include <corosync/engine/objdb.h> -#include <corosync/engine/config.h> - -#include "cman.h" -#define OBJDB_API struct objdb_iface_ver0 -#include "nodelist.h" - -#define MAX_PATH_LEN PATH_MAX - -static unsigned int debug; -static int cmanpre_readconfig(struct objdb_iface_ver0 *objdb, const char **error_string); -static int cmanpre_reloadconfig(struct objdb_iface_ver0 *objdb, int flush, const char **error_string); - -static char *nodename_env; -static int expected_votes; -static int node_votes=0; -static int num_interfaces; -static int startup_pipe; -static unsigned int cluster_id; -static char nodename[MAX_CLUSTER_MEMBER_NAME_LEN]; -static int nodeid; -static int two_node; -static unsigned int disable_openais; -static unsigned int portnum; -static int num_nodenames; -static char *key_filename=NULL; -static char *mcast_name; -static char *cluster_name; -static char error_reason[1024] = { '\0' }; -static hdb_handle_t cluster_parent_handle; - -/* - * Exports the interface for the service - */ -static struct config_iface_ver0 cmanpreconfig_iface_ver0 = { - .config_readconfig = cmanpre_readconfig, - .config_reloadconfig = cmanpre_reloadconfig -}; - -static struct lcr_iface ifaces_ver0[2] = { - { - .name = "cmanpreconfig", - .version = 0, - .versions_replace = 0, - .versions_replace_count = 0, - .dependencies = 0, - .dependency_count = 0, - .constructor = NULL, - .destructor = NULL, - .interfaces = NULL, - } -}; - -static struct lcr_comp cmanpre_comp_ver0 = { - .iface_count = 1, - .ifaces = ifaces_ver0, -}; - - - -__attribute__ ((constructor)) static void cmanpre_comp_register(void) { - lcr_interfaces_set(&ifaces_ver0[0], &cmanpreconfig_iface_ver0); - lcr_component_register(&cmanpre_comp_ver0); -} - -static char *facility_name_get (unsigned int facility) -{ - unsigned int i; - - for (i = 0; facilitynames[i].c_name != NULL; i++) { - if (facility == facilitynames[i].c_val) { - return (facilitynames[i].c_name); - } - } - return (NULL); -} - -static char *priority_name_get (unsigned int priority) -{ - unsigned int i; - - for (i = 0; prioritynames[i].c_name != NULL; i++) { - if (priority == prioritynames[i].c_val) { - return (prioritynames[i].c_name); - } - } - return (NULL); -} - - -#define LOCALHOST_IPV4 "127.0.0.1" -#define LOCALHOST_IPV6 "::1" - -/* Compare two addresses */ -static int ipaddr_equal(struct sockaddr_storage *addr1, struct sockaddr_storage *addr2) -{ - int addrlen = 0; - struct sockaddr *saddr1 = (struct sockaddr *)addr1; - struct sockaddr *saddr2 = (struct sockaddr *)addr2; - - if (addr1->ss_family != addr2->ss_family) - return 0; - - if (addr1->ss_family == AF_INET) { - addrlen = sizeof(struct sockaddr_in); - } - if (addr1->ss_family == AF_INET6) { - addrlen = sizeof(struct sockaddr_in6); - } - assert(addrlen); - - if (memcmp(saddr1, saddr2, addrlen) == 0) - return 1; - else - return 0; - -} - -/* Build a localhost ip_address */ -static int get_localhost(int family, struct sockaddr_storage *localhost) -{ - const char *addr_text; - struct addrinfo *ainfo; - struct addrinfo ahints; - int ret; - - if (family == AF_INET) { - addr_text = LOCALHOST_IPV4; - } else { - addr_text = LOCALHOST_IPV6; - } - - memset(&ahints, 0, sizeof(ahints)); - ahints.ai_socktype = SOCK_DGRAM; - ahints.ai_protocol = IPPROTO_UDP; - ahints.ai_family = family; - - /* Lookup the nodename address */ - ret = getaddrinfo(addr_text, NULL, &ahints, &ainfo); - if (ret) - return -1; - - memset(localhost, 0, sizeof(struct sockaddr_storage)); - memcpy(localhost, ainfo->ai_addr, ainfo->ai_addrlen); - - freeaddrinfo(ainfo); - return 0; -} - -/* Return the address family of an IP[46] name */ -static int address_family(char *addr, struct sockaddr_storage *ssaddr, int family_hint) -{ - struct addrinfo *ainfo; - struct addrinfo ahints; - int family; - int ret; - - memset(&ahints, 0, sizeof(ahints)); - ahints.ai_socktype = SOCK_DGRAM; - ahints.ai_protocol = IPPROTO_UDP; - ahints.ai_family = family_hint; - - /* Lookup the nodename address */ - ret = getaddrinfo(addr, NULL, &ahints, &ainfo); - if (ret) - return -1; - - memset(ssaddr, 0, sizeof(struct sockaddr_storage)); - memcpy(ssaddr, ainfo->ai_addr, ainfo->ai_addrlen); - family = ainfo->ai_family; - - freeaddrinfo(ainfo); - return family; -} - - -/* Find the "CMAN" logger_subsys object. Or create one if it does not - exist -*/ -static unsigned int find_cman_logger(struct objdb_iface_ver0 *objdb, hdb_handle_t object_handle) -{ - hdb_handle_t subsys_handle; - hdb_handle_t find_handle; - char *str; - - objdb->object_find_create(object_handle, "logger_subsys", strlen("logger_subsys"), &find_handle); - while (!objdb->object_find_next(find_handle, &subsys_handle)) { - if (!objdb_get_string(objdb, subsys_handle, "subsys", &str)) { - if (strncmp(str, CMAN_NAME, 4) == 0) { - objdb->object_find_destroy(find_handle); - return subsys_handle; - } - } - } - objdb->object_find_destroy(find_handle); - - return -1; - -} - -static int sum_expected(struct objdb_iface_ver0 *objdb) -{ - int vote_sum = 0; - hdb_handle_t nodes_handle; - hdb_handle_t find_handle=0; - - nodes_handle = nodeslist_init(objdb, cluster_parent_handle, &find_handle); - do { - int votes; - - objdb_get_int(objdb, nodes_handle, "votes", (unsigned int *)&votes, 1); - if (votes < 0) { - votes = 1; - } - vote_sum += votes; - nodes_handle = nodeslist_next(objdb, find_handle); - } while (nodes_handle); - objdb->object_find_destroy(find_handle); - - return vote_sum; -} - -static int add_ifaddr(struct objdb_iface_ver0 *objdb, char *mcast, char *ifaddr, int port, int broadcast) -{ - hdb_handle_t totem_object_handle; - hdb_handle_t find_handle; - hdb_handle_t interface_object_handle; - struct sockaddr_storage if_addr, localhost, mcast_addr; - char tmp[132]; - int ret = 0; - - /* Check the families match */ - if (address_family(mcast, &mcast_addr, 0) != - address_family(ifaddr, &if_addr, mcast_addr.ss_family)) { - sprintf(error_reason, "Node address family does not match multicast address family"); - return -1; - } - - /* Check it's not bound to localhost, sigh */ - get_localhost(if_addr.ss_family, &localhost); - if (ipaddr_equal(&localhost, &if_addr)) { - sprintf(error_reason, "Node address is localhost, please choose a real host address"); - return -1; - } - - objdb->object_find_create(OBJECT_PARENT_HANDLE, "totem", strlen("totem"), &find_handle); - if (objdb->object_find_next(find_handle, &totem_object_handle)) { - - objdb->object_create(OBJECT_PARENT_HANDLE, &totem_object_handle, - "totem", strlen("totem")); - } - objdb->object_find_destroy(find_handle); - - if (objdb->object_create(totem_object_handle, &interface_object_handle, - "interface", strlen("interface")) == 0) { - struct sockaddr_in *in = (struct sockaddr_in *)&if_addr; - struct sockaddr_in6 *in6= (struct sockaddr_in6 *)&if_addr; - void *addrptr; - - sprintf(tmp, "%d", num_interfaces); - objdb->object_key_create(interface_object_handle, "ringnumber", strlen("ringnumber"), - tmp, strlen(tmp)+1); - - if (if_addr.ss_family == AF_INET) - addrptr = &in->sin_addr; - else - addrptr = &in6->sin6_addr; - inet_ntop(if_addr.ss_family, addrptr, tmp, sizeof(tmp)); - objdb->object_key_create(interface_object_handle, "bindnetaddr", strlen("bindnetaddr"), - tmp, strlen(tmp)+1); - - if (broadcast) - objdb->object_key_create(interface_object_handle, "broadcast", strlen("broadcast"), - "yes", strlen("yes")+1); - else - objdb->object_key_create(interface_object_handle, "mcastaddr", strlen("mcastaddr"), - mcast, strlen(mcast)+1); - - sprintf(tmp, "%d", port); - objdb->object_key_create(interface_object_handle, "mcastport", strlen("mcastport"), - tmp, strlen(tmp)+1); - - num_interfaces++; - } - return ret; -} - -static uint16_t generate_cluster_id(char *name) -{ - int i; - int value = 0; - - for (i=0; i<strlen(name); i++) { - value <<= 1; - value += name[i]; - } - sprintf(error_reason, "Generated cluster id for '%s' is %d\n", name, value & 0xFFFF); - return value & 0xFFFF; -} - -static char *default_mcast(char *node, uint16_t clusterid) -{ - struct addrinfo *ainfo; - struct addrinfo ahints; - int ret; - int family; - static char addr[132]; - - memset(&ahints, 0, sizeof(ahints)); - - /* Lookup the the nodename address and use it's IP type to - default a multicast address */ - ret = getaddrinfo(node, NULL, &ahints, &ainfo); - if (ret) { - sprintf(error_reason, "Can't determine address family of nodename %s\n", node); - return NULL; - } - - family = ainfo->ai_family; - freeaddrinfo(ainfo); - - if (family == AF_INET) { - snprintf(addr, sizeof(addr), "239.192.%d.%d", clusterid >> 8, clusterid % 0xFF); - return addr; - } - if (family == AF_INET6) { - snprintf(addr, sizeof(addr), "ff15::%x", clusterid); - return addr; - } - - return NULL; -} - -static int verify_nodename(struct objdb_iface_ver0 *objdb, char *node) -{ - char nodename2[MAX_CLUSTER_MEMBER_NAME_LEN+1]; - char nodename3[MAX_CLUSTER_MEMBER_NAME_LEN+1]; - char *str, *dot = NULL; - struct ifaddrs *ifa, *ifa_list; - struct sockaddr *sa; - hdb_handle_t nodes_handle; - hdb_handle_t find_handle = 0; - int error; - - /* nodename is either from commandline or from uname */ - if (nodelist_byname(objdb, cluster_parent_handle, node)) - return 0; - - /* If nodename was from uname, try a domain-less version of it */ - strcpy(nodename2, node); - dot = strchr(nodename2, '.'); - if (dot) { - *dot = '\0'; - - if (nodelist_byname(objdb, cluster_parent_handle, nodename2)) { - strcpy(node, nodename2); - return 0; - } - } - - /* If nodename (from uname) is domain-less, try to match against - cluster.conf names which may have domainname specified */ - nodes_handle = nodeslist_init(objdb, cluster_parent_handle, &find_handle); - do { - int len; - - if (objdb_get_string(objdb, nodes_handle, "name", &str)) { - sprintf(error_reason, "Cannot get node name"); - nodes_handle = nodeslist_next(objdb, find_handle); - continue; - } - - strcpy(nodename3, str); - dot = strchr(nodename3, '.'); - if (dot) - len = dot-nodename3; - else - len = strlen(nodename3); - - if (strlen(nodename2) == len && - !strncmp(nodename2, nodename3, len)) { - strcpy(node, str); - return 0; - } - nodes_handle = nodeslist_next(objdb, find_handle); - } while (nodes_handle); - objdb->object_find_destroy(find_handle); - - - /* The cluster.conf names may not be related to uname at all, - they may match a hostname on some network interface. - NOTE: This is IPv4 only */ - error = getifaddrs(&ifa_list); - if (error) - return -1; - - for (ifa = ifa_list; ifa; ifa = ifa->ifa_next) { - socklen_t salen = 0; - - /* Restore this */ - strcpy(nodename2, node); - sa = ifa->ifa_addr; - if (!sa) - continue; - if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6) - continue; - - if (sa->sa_family == AF_INET) - salen = sizeof(struct sockaddr_in); - if (sa->sa_family == AF_INET6) - salen = sizeof(struct sockaddr_in6); - - error = getnameinfo(sa, salen, nodename2, - sizeof(nodename2), NULL, 0, 0); - if (!error) { - - if (nodelist_byname(objdb, cluster_parent_handle, nodename2)) { - strcpy(node, nodename2); - goto out; - } - - /* Truncate this name and try again */ - dot = strchr(nodename2, '.'); - if (dot) { - *dot = '\0'; - - if (nodelist_byname(objdb, cluster_parent_handle, nodename2)) { - strcpy(node, nodename2); - goto out; - } - } - } - - /* See if it's the IP address that's in cluster.conf */ - error = getnameinfo(sa, sizeof(*sa), nodename2, - sizeof(nodename2), NULL, 0, NI_NUMERICHOST); - if (error) - continue; - - if (nodelist_byname(objdb, cluster_parent_handle, nodename2)) { - strcpy(node, nodename2); - goto out; - } - } - - error = -1; - out: - freeifaddrs(ifa_list); - return error; -} - -/* Get any environment variable overrides */ -static int get_env_overrides(void) -{ - if (getenv("CMAN_CLUSTER_NAME")) { - cluster_name = strdup(getenv("CMAN_CLUSTER_NAME")); - } - - nodename_env = getenv("CMAN_NODENAME"); - - expected_votes = 0; - if (getenv("CMAN_EXPECTEDVOTES")) { - expected_votes = atoi(getenv("CMAN_EXPECTEDVOTES")); - if (expected_votes < 1) { - expected_votes = 0; - } - } - - /* optional port */ - if (getenv("CMAN_IP_PORT")) { - portnum = atoi(getenv("CMAN_IP_PORT")); - } - - /* optional security key filename */ - if (getenv("CMAN_KEYFILE")) { - key_filename = strdup(getenv("CMAN_KEYFILE")); - if (key_filename == NULL) { - sprintf(error_reason, "Cannot allocate memory for key filename"); - return -1; - } - } - - /* find our own number of votes */ - if (getenv("CMAN_VOTES")) { - node_votes = atoi(getenv("CMAN_VOTES")); - } - - /* nodeid */ - if (getenv("CMAN_NODEID")) { - nodeid = atoi(getenv("CMAN_NODEID")); - } - - if (getenv("CMAN_MCAST_ADDR")) { - mcast_name = getenv("CMAN_MCAST_ADDR"); - } - - if (getenv("CMAN_2NODE")) { - two_node = 1; - expected_votes = 1; - node_votes = 1; - } - if (getenv("CMAN_DEBUGLOG")) { - debug = atoi(getenv("CMAN_DEBUGLOG")); - if (debug > 0) - debug = 1; - } - - return 0; -} - - -static int get_nodename(struct objdb_iface_ver0 *objdb) -{ - char *nodeid_str = NULL; - char *votes_str; - hdb_handle_t object_handle; - hdb_handle_t find_handle; - hdb_handle_t node_object_handle; - hdb_handle_t alt_object; - int broadcast = 0; - char *str; - int error; - - if (!getenv("CMAN_NOCONFIG")) { - /* our nodename */ - if (nodename_env != NULL) { - if (strlen(nodename_env) >= sizeof(nodename)) { - sprintf(error_reason, "Overridden node name %s is too long", nodename); - error = -1; - goto out; - } - - strcpy(nodename, nodename_env); - - if (!(node_object_handle = nodelist_byname(objdb, cluster_parent_handle, nodename))) { - sprintf(error_reason, "Overridden node name %s is not in CCS", nodename); - error = -1; - goto out; - } - - } else { - struct utsname utsname; - - error = uname(&utsname); - if (error) { - sprintf(error_reason, "cannot get node name, uname failed"); - write_cman_pipe("Can't determine local node name, uname failed"); - error = -1; - goto out; - } - - if (strlen(utsname.nodename) >= sizeof(nodename)) { - sprintf(error_reason, "node name from uname is too long"); - write_cman_pipe("local node name is too long"); - error = -1; - goto out; - } - - strcpy(nodename, utsname.nodename); - } - if (verify_nodename(objdb, nodename)) { - write_cman_pipe("Cannot find node name in cluster.conf"); - return -1; - } - - } - - /* Add <cman> bits to pass down to the main module*/ - if ( (node_object_handle = nodelist_byname(objdb, cluster_parent_handle, nodename))) { - if (objdb_get_string(objdb, node_object_handle, "nodeid", &nodeid_str)) { - sprintf(error_reason, "This node has no nodeid in cluster.conf"); - return -1; - } - if (!objdb_get_string(objdb, node_object_handle, "votes", &votes_str)) { - node_votes=atoi(votes_str); - } - } - - objdb->object_find_create(cluster_parent_handle, "cman", strlen("cman"), &find_handle); - - if (objdb->object_find_next(find_handle, &object_handle) == 0) { - - hdb_handle_t mcast_handle; - hdb_handle_t find_handle2; - - if (!mcast_name) { - - objdb->object_find_create(object_handle, "multicast", strlen("multicast"), &find_handle2); - if (objdb->object_find_next(find_handle2, &mcast_handle) == 0) { - - objdb_get_string(objdb, mcast_handle, "addr", &mcast_name); - } - objdb->object_find_destroy(find_handle2); - } - - if (!mcast_name) { - mcast_name = default_mcast(nodename, cluster_id); - } - - /* See if the user wants our default set of openais services (default=yes) */ - objdb_get_int(objdb, object_handle, "disable_openais", &disable_openais, 0); - - objdb->object_key_create(object_handle, "nodename", strlen("nodename"), - nodename, strlen(nodename)+1); - } - objdb->object_find_destroy(find_handle); - - nodeid = atoi(nodeid_str); - error = 0; - - /* optional port */ - if (!portnum) { - objdb_get_int(objdb, object_handle, "port", &portnum, DEFAULT_PORT); - } - - /* Check for broadcast */ - if (!objdb_get_string(objdb, object_handle, "broadcast", &str)) { - if (strcmp(str, "yes") == 0) { - mcast_name = strdup("255.255.255.255"); - if (!mcast_name) - return -1; - broadcast = 1; - } - free(str); - } - - if (add_ifaddr(objdb, mcast_name, nodename, portnum, broadcast)) { - write_cman_pipe(error_reason); - return -1; - } - - /* Get all alternative node names */ - num_nodenames = 1; - objdb->object_find_create(node_object_handle,"altname", strlen("altname"), &find_handle); - while (objdb->object_find_next(find_handle, &alt_object) == 0) { - unsigned int port; - char *node; - char *mcast; - - if (objdb_get_string(objdb, alt_object, "name", &node)) { - continue; - } - - objdb_get_int(objdb, alt_object, "port", &port, portnum); - - if (objdb_get_string(objdb, alt_object, "mcast", &mcast)) { - mcast = mcast_name; - } - - if (add_ifaddr(objdb, mcast, node, portnum, broadcast)) { - write_cman_pipe(error_reason); - return -1; - } - - num_nodenames++; - } - objdb->object_find_destroy(find_handle); - -out: - return error; -} - -/* These are basically cman overrides to the totem config bits */ -static void add_cman_overrides(struct objdb_iface_ver0 *objdb) -{ - char *logstr; - char *logfacility; - char *loglevel; - hdb_handle_t object_handle; - hdb_handle_t find_handle; - char tmp[256]; - - /* "totem" key already exists, because we have added the interfaces by now */ - objdb->object_find_create(OBJECT_PARENT_HANDLE,"totem", strlen("totem"), &find_handle); - if (objdb->object_find_next(find_handle, &object_handle) == 0) - { - char *value; - - objdb->object_key_create(object_handle, "version", strlen("version"), - "2", 2); - - sprintf(tmp, "%d", nodeid); - objdb->object_key_create(object_handle, "nodeid", strlen("nodeid"), - tmp, strlen(tmp)+1); - - objdb->object_key_create(object_handle, "vsftype", strlen("vsftype"), - "none", strlen("none")+1); - - /* Set the token timeout is 10 seconds, but don't overrride anything that - might be in cluster.conf */ - if (objdb_get_string(objdb, object_handle, "token", &value)) { - snprintf(tmp, sizeof(tmp), "%d", DEFAULT_TOKEN_TIMEOUT); - objdb->object_key_create(object_handle, "token", strlen("token"), - tmp, strlen(tmp)+1); - } - if (objdb_get_string(objdb, object_handle, "token_retransmits_before_loss_const", &value)) { - objdb->object_key_create(object_handle, "token_retransmits_before_loss_const", - strlen("token_retransmits_before_loss_const"), - "20", strlen("20")+1); - } - - /* Extend consensus & join timeouts per bz#214290 */ - if (objdb_get_string(objdb, object_handle, "join", &value)) { - objdb->object_key_create(object_handle, "join", strlen("join"), - "60", strlen("60")+1); - } - if (objdb_get_string(objdb, object_handle, "consensus", &value)) { - objdb->object_key_create(object_handle, "consensus", strlen("consensus"), - "4800", strlen("4800")+1); - } - - /* Set RRP mode appropriately */ - if (objdb_get_string(objdb, object_handle, "rrp_mode", &value)) { - if (num_interfaces > 1) { - objdb->object_key_create(object_handle, "rrp_mode", strlen("rrp_mode"), - "active", strlen("active")+1); - } - else { - objdb->object_key_create(object_handle, "rrp_mode", strlen("rrp_mode"), - "none", strlen("none")+1); - } - } - - if (objdb_get_string(objdb, object_handle, "secauth", &value)) { - sprintf(tmp, "%d", 1); - objdb->object_key_create(object_handle, "secauth", strlen("secauth"), - tmp, strlen(tmp)+1); - } - - /* optional security key filename */ - if (!key_filename) { - objdb_get_string(objdb, object_handle, "keyfile", &key_filename); - } - else { - objdb->object_key_create(object_handle, "keyfile", strlen("keyfile"), - key_filename, strlen(key_filename)+1); - } - if (!key_filename) { - /* Use the cluster name as key, - * This isn't a good isolation strategy but it does make sure that - * clusters on the same port/multicast by mistake don't actually interfere - * and that we have some form of encryption going. - */ - - int keylen; - memset(tmp, 0, sizeof(tmp)); - - strcpy(tmp, cluster_name); - - /* Key length must be a multiple of 4 */ - keylen = (strlen(cluster_name)+4) & 0xFC; - objdb->object_key_create(object_handle, "key", strlen("key"), - tmp, keylen); - } - } - objdb->object_find_destroy(find_handle); - - /* Make sure mainconfig doesn't stomp on our logging options */ - objdb->object_find_create(OBJECT_PARENT_HANDLE, "logging", strlen("logging"), &find_handle); - if (objdb->object_find_next(find_handle, &object_handle)) { - - objdb->object_create(OBJECT_PARENT_HANDLE, &object_handle, - "logging", strlen("logging")); - } - objdb->object_find_destroy(find_handle); - - logfacility = facility_name_get(SYSLOGFACILITY); - loglevel = priority_name_get(SYSLOGLEVEL); - - /* enable timestamps on logging */ - if (objdb_get_string(objdb, object_handle, "timestamp", &logstr)) { - objdb->object_key_create(object_handle, "timestamp", strlen("timestamp"), - "on", strlen("on")+1); - } - - /* configure logfile */ - if (objdb_get_string(objdb, object_handle, "to_logfile", &logstr)) { - objdb->object_key_create(object_handle, "to_logfile", strlen("to_logfile"), - "yes", strlen("yes")+1); - } - - if (objdb_get_string(objdb, object_handle, "logfile", &logstr)) { - objdb->object_key_create(object_handle, "logfile", strlen("logfile"), - LOGDIR "/corosync.log", strlen(LOGDIR "/corosync.log")+1); - } - - if (objdb_get_string(objdb, object_handle, "logfile_priority", &logstr)) { - objdb->object_key_create(object_handle, "logfile_priority", strlen("logfile_priority"), - loglevel, strlen(loglevel)+1); - } - - /* syslog */ - if (objdb_get_string(objdb, object_handle, "to_syslog", &logstr)) { - objdb->object_key_create(object_handle, "to_syslog", strlen("to_syslog"), - "yes", strlen("yes")+1); - } - - if (objdb_get_string(objdb, object_handle, "syslog_facility", &logstr)) { - objdb->object_key_create(object_handle, "syslog_facility", strlen("syslog_facility"), - logfacility, strlen(logfacility)+1); - } - - if (objdb_get_string(objdb, object_handle, "syslog_priority", &logstr)) { - objdb->object_key_create(object_handle, "syslog_priority", strlen("syslog_priority"), - loglevel, strlen(loglevel)+1); - } - - if (!debug) { - hdb_handle_t logger_object_handle; - - if (!objdb_get_string(objdb, object_handle, "debug", &logstr)) { - if (!strncmp(logstr, "on", 2)) { - debug=1; - } - } - - logger_object_handle = find_cman_logger(objdb, object_handle); - if (logger_object_handle > -1) { - if (!objdb_get_string(objdb, logger_object_handle, "debug", &logstr)) { - if (!strncmp(logstr, "on", 2)) { - debug=1; - } - if (!strncmp(logstr, "off", 3)) { - debug=0; - } - } - } - } - - if (debug) { - objdb->object_key_create(object_handle, "to_stderr", strlen("to_stderr"), - "yes", strlen("yes")+1); - } - - /* Make sure we allow connections from user/group "ais" */ - objdb->object_find_create(OBJECT_PARENT_HANDLE, "aisexec", strlen("aisexec"), &find_handle); - if (objdb->object_find_next(find_handle, &object_handle) != 0) { - objdb->object_create(OBJECT_PARENT_HANDLE, &object_handle, - "aisexec", strlen("aisexec")); - } - objdb->object_find_destroy(find_handle); - objdb->object_key_create(object_handle, "user", strlen("user"), - "ais", strlen("ais") + 1); - objdb->object_key_create(object_handle, "group", strlen("group"), - "ais", strlen("ais") + 1); - - objdb->object_find_create(cluster_parent_handle, "cman", strlen("cman"), &find_handle); - if (objdb->object_find_next(find_handle, &object_handle) == 0) - { - char str[255]; - - sprintf(str, "%d", cluster_id); - - objdb->object_key_create(object_handle, "cluster_id", strlen("cluster_id"), - str, strlen(str) + 1); - } - objdb->object_find_destroy(find_handle); - - /* Load the quorum service */ - objdb->object_create(OBJECT_PARENT_HANDLE, &object_handle, - "service", strlen("service")); - objdb->object_key_create(object_handle, "name", strlen("name"), - "corosync_quorum", strlen("corosync_quorum") + 1); - objdb->object_key_create(object_handle, "ver", strlen("ver"), - "0", 2); - - /* Make sure we load our alter-ego - the main cman module */ - objdb->object_create(OBJECT_PARENT_HANDLE, &object_handle, - "service", strlen("service")); - objdb->object_key_create(object_handle, "name", strlen("name"), - "corosync_cman", strlen("corosync_cman") + 1); - objdb->object_key_create(object_handle, "ver", strlen("ver"), - "0", 2); - - /* Define cman as the quorum provider for corosync */ - objdb->object_find_create(OBJECT_PARENT_HANDLE, "quorum", strlen("quorum"), &find_handle); - if (objdb->object_find_next(find_handle, &object_handle) != 0) { - objdb->object_create(OBJECT_PARENT_HANDLE, &object_handle, - "quorum", strlen("quorum")); - } - objdb->object_find_destroy(find_handle); - - objdb->object_key_create(object_handle, "provider", strlen("provider"), - "corosync_votequorum", strlen("corosync_votequorum") + 1); - - if (!expected_votes) - expected_votes = sum_expected(objdb); - - sprintf(tmp, "%d", expected_votes); - objdb->object_key_create(object_handle, "expected_votes", strlen("expected_votes"), - tmp, strlen(tmp)+1); - - sprintf(tmp, "%d", node_votes); - objdb->object_key_create(object_handle, "votes", strlen("votes"), - tmp, strlen(tmp)+1); - - if (two_node) { - objdb->object_key_create(object_handle, "two_node", strlen("two_node"), - "1", strlen("1") + 1); - } -} - -/* If ccs is not available then use some defaults */ -static int set_noccs_defaults(struct objdb_iface_ver0 *objdb) -{ - char tmp[255]; - hdb_handle_t object_handle; - - /* Enforce key */ - key_filename = strdup(NOCCS_KEY_FILENAME); - if (!key_filename) { - sprintf(error_reason, "cannot allocate memory for key file name"); - return -1; - } - - if (!cluster_name) - cluster_name = strdup(DEFAULT_CLUSTER_NAME); - - if (!cluster_name) { - sprintf(error_reason, "cannot allocate memory for cluster_name"); - return -1; - } - - if (!cluster_id) - cluster_id = generate_cluster_id(cluster_name); - - if (!nodename_env) { - int error; - struct utsname utsname; - - error = uname(&utsname); - if (error) { - sprintf(error_reason, "cannot get node name, uname failed"); - return -1; - } - - nodename_env = (char *)&utsname.nodename; - } - strcpy(nodename, nodename_env); - num_nodenames = 1; - - if (!mcast_name) { - mcast_name = default_mcast(nodename, cluster_id); - } - - /* This will increase as nodes join the cluster */ - if (!expected_votes) - expected_votes = 1; - if (!node_votes) - node_votes = 1; - - if (!portnum) - portnum = DEFAULT_PORT; - - /* Invent a node ID */ - if (!nodeid) { - struct addrinfo *ainfo; - struct addrinfo ahints; - int ret; - - memset(&ahints, 0, sizeof(ahints)); - ret = getaddrinfo(nodename, NULL, &ahints, &ainfo); - if (ret) { - sprintf(error_reason, "Can't determine address family of nodename %s\n", nodename); - return -1; - } - - if (ainfo->ai_family == AF_INET) { - struct sockaddr_in *addr = (struct sockaddr_in *)ainfo->ai_addr; - memcpy(&nodeid, &addr->sin_addr, sizeof(int)); - } - if (ainfo->ai_family == AF_INET6) { - struct sockaddr_in6 *addr = (struct sockaddr_in6 *)ainfo->ai_addr; - memcpy(&nodeid, &addr->sin6_addr.s6_addr32[3], sizeof(int)); - } - freeaddrinfo(ainfo); - } - - /* Write a local <clusternode> entry to keep the rest of the code happy */ - objdb->object_create(cluster_parent_handle, &object_handle, - "clusternodes", strlen("clusternodes")); - objdb->object_create(object_handle, &object_handle, - "clusternode", strlen("clusternode")); - objdb->object_key_create(object_handle, "name", strlen("name"), - nodename, strlen(nodename)+1); - - sprintf(tmp, "%d", node_votes); - objdb->object_key_create(object_handle, "votes", strlen("votes"), - tmp, strlen(tmp)+1); - - sprintf(tmp, "%d", nodeid); - objdb->object_key_create(object_handle, "nodeid", strlen("nodeid"), - tmp, strlen(tmp)+1); - - /* Write the default cluster name */ - objdb->object_key_create(cluster_parent_handle, "name", strlen("name"), - cluster_name, strlen(cluster_name)+1); - - /* Add a dummy config_version */ - sprintf(tmp, "%d", -1); - objdb->object_key_create(cluster_parent_handle, "config_version", strlen("config_version"), - tmp, strlen(tmp)+1); - - /* A flag to show there is no configuration file */ - sprintf(tmp, "%d", 1); - objdb->object_key_create(cluster_parent_handle, "no_config", strlen("no_config"), - tmp, strlen(tmp)+1); - - - return 0; -} - -/* Move an object/key tree */ -static int copy_config_tree(struct objdb_iface_ver0 *objdb, hdb_handle_t source_object, hdb_handle_t target_parent_object, int always_create) -{ - hdb_handle_t object_handle; - hdb_handle_t new_object; - hdb_handle_t find_handle; - char object_name[1024]; - size_t object_name_len; - void *key_name; - size_t key_name_len; - void *key_value; - size_t key_value_len; - int res; - - /* Create new parent object if necessary */ - objdb->object_name_get(source_object, object_name, &object_name_len); - - objdb->object_find_create(target_parent_object, object_name, strlen(object_name), &find_handle); - if (always_create || objdb->object_find_next(find_handle, &new_object)) - objdb->object_create(target_parent_object, &new_object, object_name, object_name_len); - objdb->object_find_destroy(find_handle); - - /* Copy the keys */ - objdb->object_key_iter_reset(new_object); - - while (!objdb->object_key_iter(new_object, &key_name, &key_name_len, - &key_value, &key_value_len)) { - - objdb->object_key_create(new_object, key_name, key_name_len, - key_value, key_value_len); - } - - /* Create sub-objects */ - res = objdb->object_find_create(source_object, NULL, 0, &find_handle); - if (res) { - sprintf(error_reason, "error resetting object iterator for object "HDB_X_FORMAT": %d\n", source_object, res); - return -1; - } - - while ( (res = objdb->object_find_next(find_handle, &object_handle) == 0)) { - - /* Down we go ... */ - copy_config_tree(objdb, object_handle, new_object, 0); - } - objdb->object_find_destroy(find_handle); - - return 0; -} - -/* - * Copy trees from /cluster where they live in cluster.conf, into the root - * of the config tree where corosync expects to find them. - */ -static int copy_tree_to_root(struct objdb_iface_ver0 *objdb, const char *name, int always_create) -{ - hdb_handle_t find_handle; - hdb_handle_t object_handle; - int res=0; - - objdb->object_find_create(cluster_parent_handle, name, strlen(name), &find_handle); - while (objdb->object_find_next(find_handle, &object_handle) == 0) { - res = copy_config_tree(objdb, object_handle, OBJECT_PARENT_HANDLE, always_create); - } - objdb->object_find_destroy(find_handle); - - return res; -} - -static int get_cman_globals(struct objdb_iface_ver0 *objdb) -{ - hdb_handle_t object_handle; - hdb_handle_t find_handle; - - objdb_get_string(objdb, cluster_parent_handle, "name", &cluster_name); - - /* Get the <cman> bits that override <totem> bits */ - objdb->object_find_create(cluster_parent_handle, "cman", strlen("cman"), &find_handle); - if (objdb->object_find_next(find_handle, &object_handle) == 0) { - if (!portnum) - objdb_get_int(objdb, object_handle, "port", &portnum, DEFAULT_PORT); - - if (!key_filename) - objdb_get_string(objdb, object_handle, "keyfile", &key_filename); - - if (!cluster_id) - objdb_get_int(objdb, object_handle, "cluster_id", &cluster_id, 0); - - if (!cluster_id) - cluster_id = generate_cluster_id(cluster_name); - } - objdb->object_find_destroy(find_handle); - return 0; -} - -static int cmanpre_reloadconfig(struct objdb_iface_ver0 *objdb, int flush, const char **error_string) -{ - int ret = -1; - hdb_handle_t object_handle; - hdb_handle_t find_handle; - hdb_handle_t cluster_parent_handle_new; - - /* don't reload if we've been told to run configless */ - if (getenv("CMAN_NOCONFIG")) { - sprintf(error_reason, "Config not updated because we were run with cman_tool -X"); - ret = 0; - goto err; - } - - /* find both /cluster entries */ - objdb->object_find_create(OBJECT_PARENT_HANDLE, "cluster", strlen("cluster"), &find_handle); - objdb->object_find_next(find_handle, &cluster_parent_handle); - if (!cluster_parent_handle) { - sprintf (error_reason, "%s", "Cannot find old /cluster/ key in configuration\n"); - goto err; - } - objdb->object_find_next(find_handle, &cluster_parent_handle_new); - if (!cluster_parent_handle_new) { - sprintf (error_reason, "%s", "Cannot find new /cluster/ key in configuration\n"); - goto err; - } - objdb->object_find_destroy(find_handle); - - /* destroy the old one */ - objdb->object_destroy(cluster_parent_handle); - - /* update the reference to the new config */ - cluster_parent_handle = cluster_parent_handle_new; - - /* destroy top level /logging */ - objdb->object_find_create(OBJECT_PARENT_HANDLE, "logging", strlen("logging"), &find_handle); - objdb->object_find_next(find_handle, &object_handle); - objdb->object_find_destroy(find_handle); - if (object_handle) { - objdb->object_destroy(object_handle); - } - - /* copy /cluster/logging to /logging */ - ret = copy_tree_to_root(objdb, "logging", 0); - - /* destroy top level /totem */ - objdb->object_find_create(OBJECT_PARENT_HANDLE, "totem", strlen("totem"), &find_handle); - objdb->object_find_next(find_handle, &object_handle); - objdb->object_find_destroy(find_handle); - if (object_handle) { - objdb->object_destroy(object_handle); - } - - /* copy /cluster/totem to /totem */ - ret = copy_tree_to_root(objdb, "totem", 0); - - return 0; - -err: - *error_string = error_reason; - return ret; -} - -static int cmanpre_readconfig(struct objdb_iface_ver0 *objdb, const char **error_string) -{ - int ret = 0; - hdb_handle_t object_handle; - hdb_handle_t find_handle; - - if (getenv("CMAN_PIPE")) - startup_pipe = atoi(getenv("CMAN_PIPE")); - - objdb->object_find_create(OBJECT_PARENT_HANDLE, "cluster", strlen("cluster"), &find_handle); - objdb->object_find_next(find_handle, &cluster_parent_handle); - objdb->object_find_destroy(find_handle); - if (!cluster_parent_handle) { - objdb->object_create(OBJECT_PARENT_HANDLE, &cluster_parent_handle, - "cluster", strlen("cluster")); - } - else { - /* Move these to a place where corosync expects to find them */ - ret = copy_tree_to_root(objdb, "totem", 0); - ret = copy_tree_to_root(objdb, "logging", 0); - ret = copy_tree_to_root(objdb, "event", 0); - ret = copy_tree_to_root(objdb, "amf", 0); - ret = copy_tree_to_root(objdb, "aisexec", 0); - ret = copy_tree_to_root(objdb, "service", 1); - } - - objdb->object_find_create(cluster_parent_handle, "cman", strlen("cman"), &find_handle); - if (objdb->object_find_next(find_handle, &object_handle)) { - objdb->object_create(cluster_parent_handle, &object_handle, - "cman", strlen("cman")); - } - objdb->object_find_destroy(find_handle); - - /* This will create /libccs/@next_handle. - * next_handle will be atomically incremented by corosync to return ccs_handle down the pipe. - * We create it in cman-preconfig to avoid an "init" race in libccs. - */ - - objdb->object_find_create(OBJECT_PARENT_HANDLE, "libccs", strlen("libccs"), &find_handle); - if (objdb->object_find_next(find_handle, &object_handle)) { - int next_handle = 0; - - objdb->object_create(OBJECT_PARENT_HANDLE, &object_handle, - "libccs", strlen("libccs")); - - objdb->object_key_create(object_handle, "next_handle", strlen("next_handle"), - &next_handle, sizeof(int)); - } - objdb->object_find_destroy(find_handle); - - get_env_overrides(); - if (getenv("CMAN_NOCONFIG")) - ret = set_noccs_defaults(objdb); - else - ret = get_cman_globals(objdb); - - if (!ret) { - ret = get_nodename(objdb); - add_cman_overrides(objdb); - } - - if (!ret) { - sprintf (error_reason, "%s", "Successfully parsed cman config\n"); - } - else { - if (error_reason[0] == '\0') - sprintf (error_reason, "%s", "Error parsing cman config\n"); - } - *error_string = error_reason; - - return ret; -} diff --git a/cman/config/cman.h b/cman/config/cman.h deleted file mode 100644 index 8e04d21..0000000 --- a/cman/config/cman.h +++ /dev/null @@ -1,15 +0,0 @@ - -/* How we announce ourself in syslog */ -#define CMAN_NAME "CMAN" - -#define MAX_CLUSTER_MEMBER_NAME_LEN 255 - -/* Defaults for configuration variables */ -#define NOCCS_KEY_FILENAME DEFAULT_CONFIG_DIR "/cman_authkey" -#define DEFAULT_PORT 5405 -#define DEFAULT_CLUSTER_NAME "RHCluster" -#define DEFAULT_MAX_QUEUED 128 -#define DEFAULT_TOKEN_TIMEOUT 10000 -#define DEFAULT_QUORUMDEV_POLL 10000 -#define DEFAULT_SHUTDOWN_TIMEOUT 5000 -#define DEFAULT_CCSD_POLL 1000 diff --git a/cman/config/nodelist.h b/cman/config/nodelist.h deleted file mode 100644 index f004145..0000000 --- a/cman/config/nodelist.h +++ /dev/null @@ -1,93 +0,0 @@ -/* These just make the access a little neater */ -static inline int objdb_get_string(OBJDB_API *corosync, hdb_handle_t object_service_handle, - const char *key, char **value) -{ - int res; - - *value = NULL; - if ( !(res = corosync->object_key_get(object_service_handle, - key, - strlen(key), - (void *)value, - NULL))) { - if (*value) - return 0; - } - return -1; -} - -static inline void objdb_get_int(OBJDB_API *corosync, hdb_handle_t object_service_handle, - const char *key, unsigned int *intvalue, unsigned int default_value) -{ - char *value = NULL; - - *intvalue = default_value; - - if (!corosync->object_key_get(object_service_handle, key, strlen(key), - (void *)&value, NULL)) { - if (value) { - *intvalue = atoi(value); - } - } -} - - -/* Helper functions for navigating the nodes list */ -static inline hdb_handle_t nodeslist_init(OBJDB_API *corosync, - hdb_handle_t cluster_parent_handle, - hdb_handle_t *find_handle) -{ - hdb_handle_t object_handle; - hdb_handle_t find_handle1; - hdb_handle_t find_handle2; - - corosync->object_find_create(cluster_parent_handle,"clusternodes", strlen("clusternodes"), &find_handle1); - if (corosync->object_find_next(find_handle1, &object_handle) == 0) - { - hdb_handle_t nodes_handle; - corosync->object_find_destroy(find_handle1); - - corosync->object_find_create(object_handle,"clusternode", strlen("clusternode"), &find_handle2); - - if (corosync->object_find_next(find_handle2, &nodes_handle) == 0) - { - *find_handle = find_handle2; - return nodes_handle; - } - } - return 0; -} - -static inline hdb_handle_t nodeslist_next(OBJDB_API *corosync, hdb_handle_t find_handle) -{ - hdb_handle_t nodes_handle; - - if (corosync->object_find_next(find_handle, &nodes_handle) == 0) - return nodes_handle; - else - return 0; -} - -static inline hdb_handle_t nodelist_byname(OBJDB_API *corosync, - hdb_handle_t cluster_parent_handle, - char *name) -{ - char *nodename; - hdb_handle_t nodes_handle; - hdb_handle_t find_handle = 0; - - nodes_handle = nodeslist_init(corosync, cluster_parent_handle, &find_handle); - while (nodes_handle) { - if (objdb_get_string(corosync, nodes_handle, "name", &nodename)) { - nodes_handle = nodeslist_next(corosync, find_handle); - continue; - } - if (strcmp(nodename, name) == 0) - return nodes_handle; - - nodes_handle = nodeslist_next(corosync, find_handle); - } - corosync->object_find_destroy(find_handle); - - return 0; -} diff --git a/cman/init.d/cman.in b/cman/init.d/cman.in deleted file mode 100644 index ef89c85..0000000 --- a/cman/init.d/cman.in +++ /dev/null @@ -1,748 +0,0 @@ -#!/bin/bash -# -# cman - Cluster Manager init script -# -# chkconfig: - 21 79 -# description: Starts and stops cman -# -# -### BEGIN INIT INFO -# Provides: cman -# Required-Start: $network $time -# Required-Stop: $network $time -# Default-Start: -# Default-Stop: -# Short-Description: Starts and stops cman -# Description: Starts and stops the Cluster Manager set of daemons -### END INIT INFO - -# set secure PATH -PATH="/bin:/usr/bin:/sbin:/usr/sbin:@SBINDIR@" - -local_chkconfig() -{ - ls /etc/rc${2}.d/S*${3} > /dev/null 2>/dev/null - return $? -} - -success() -{ - echo -ne "[ OK ]\r" -} - -failure() -{ - echo -ne "[FAILED]\r" -} - -status() -{ - pid=$(pidof $1 2>/dev/null) - rtrn=$? - if [ $rtrn -ne 0 ]; then - echo "$1 is stopped" - else - echo "$1 (pid $pid) is running..." - fi - return $rtrn -} - -# rpm based distros -if [ -d /etc/sysconfig ]; then - [ -f @INITDDIR@/functions ] && . @INITDDIR@/functions - [ -f /etc/sysconfig/cluster ] && . /etc/sysconfig/cluster - [ -f /etc/sysconfig/cman ] && . /etc/sysconfig/cman - [ -z "$LOCK_FILE" ] && LOCK_FILE="/var/lock/subsys/cman" -fi - -# deb based distros -if [ -d /etc/default ]; then - [ -f /etc/default/cluster ] && . /etc/default/cluster - [ -f /etc/default/cman ] && . /etc/default/cman - [ -z "$LOCK_FILE" ] && LOCK_FILE="/var/lock/cman" - [ -z "$(which chkconfig)" ] && alias chkconfig=local_chkconfig -fi - -# CMAN_CLUSTER_TIMEOUT -- amount of time to wait for joinging a cluster -# before giving up. If CMAN_CLUSTER_TIMEOUT is positive, then we will -# wait CMAN_CLUSTER_TIMEOUT seconds before giving up and failing when -# a cluster is not joined. If CMAN_CLUSTER_TIMEOUT is zero, then -# wait indefinately for a cluster join. If CMAN_CLUSTER_TIMEOUT is -# negative, do not check to see that the cluster has been joined -[ -z "$CMAN_CLUSTER_TIMEOUT" ] && CMAN_CLUSTER_TIMEOUT=120 - -# CMAN_QUORUM_TIMEOUT -- amount of time to wait for a quorate cluster on -# startup quorum is needed by many other applications, so we may as -# well wait here. If CMAN_QUORUM_TIMEOUT is less than 1, quorum will -# be ignored. -[ -z "$CMAN_QUORUM_TIMEOUT" ] && CMAN_QUORUM_TIMEOUT=0 - -# CMAN_SHUTDOWN_TIMEOUT -- amount of time to wait for cman to become a -# cluster member before calling cman_tool leave during shutdown. -# The default is 60 seconds -[ -z "$CMAN_SHUTDOWN_TIMEOUT" ] && CMAN_SHUTDOWN_TIMEOUT=60 - -# CMAN_NOTIFYD_START - control the startup behaviour for cmannotifyd -# the variable can take 3 values: -# yes | will always start cmannotifyd -# no | will never start cmannotifyd -# conditional (default) | will start cmannotifyd only if scriptlets -# are found in @NOTIFYDDIR@ -[ -z "$CMAN_NOTIFYD_START" ] && CMAN_NOTIFYD_START=conditional - -# FENCE_JOIN_TIMEOUT -- seconds to wait for fence domain join to -# complete. If the join hasn't completed in this time, fence_tool join -# exits with an error, and this script exits with an error. To wait -# indefinitely set the value to -1. -[ -z "$FENCE_JOIN_TIMEOUT" ] && FENCE_JOIN_TIMEOUT=20 - -# FENCED_MEMBER_DELAY -- amount of time to delay fence_tool join to allow -# all nodes in cluster.conf to become cluster members. In seconds. -[ -z "$FENCED_MEMBER_DELAY" ] && FENCED_MEMBER_DELAY=45 - -# FENCE_JOIN -- boolean value used to control whether or not this node -# should join the fence domain. If FENCE_JOIN is set to "no", then -# the script will not attempt to the fence domain. If FENCE_JOIN is -# set to "yes", then the script will attempt to join the fence domain. -# If FENCE_JOIN is set to any other value, the default behavior is -# to join the fence domain (equivalent to "yes"). -[ -z "$FENCE_JOIN" ] && FENCE_JOIN="yes" - -# NETWORK_BRIDGE_SCRIPT -- script to use for xen network bridging. -# This script must exist in the /etc/xen/scripts directory. -# The default script is "network-bridge". -[ -z "$NETWORK_BRIDGE_SCRIPT" ] && NETWORK_BRIDGE_SCRIPT="network-bridge" - -[ -n "$CLUSTERNAME" ] && cman_join_opts="-c $CLUSTERNAME" - -[ -n "$NODENAME" ] && cman_join_opts+=" -n $NODENAME" - -# CONFIG_LOADER -- select default config parser. -# This can be: -# xmlconfig - read directly from cluster.conf and use ricci as default config -# propagation method. (default) -# ldapconfig - read configuration from an ldap server. -# Requires: LDAP_URL or/and LDAP_BASEDN envvar to be set. -# LDAP_BINDDN and LDAP_BINDPWD have to be either both set or both unset. -# corosync_parser - use internal corosync config file parser. -# openaisparser - use internal openais config file parser. -[ -n "$CONFIG_LOADER" ] && cman_join_opts+=" -C $CONFIG_LOADER" - -load_modules() -{ - errmsg=$( /sbin/modprobe configfs 2>&1 ) || return 1 - errmsg=$( /sbin/modprobe dlm 2>&1 ) || return 1 - errmsg=$( /sbin/modprobe lock_dlm 2>&1 ) || true - return 0 -} - -start_configfs() -{ - # configfs - awk '{ print $2 }' /etc/mtab | grep "/sys/kernel/config" > /dev/null 2>&1 \ - && awk '{ print $3 }' /etc/mtab | grep "configfs" > /dev/null 2>&1 - if [ $? -ne 0 ] - then - errmsg=$( /bin/mount -t configfs none /sys/kernel/config 2>&1 ) - return $? - fi - return 0 -} - -start_cman() -{ - # cman - @SBINDIR@/cman_tool status > /dev/null 2>&1 - if [ $? -ne 0 ] - then - case "$CONFIG_LOADER" in - ldapconfig) - if [ -n "$LDAP_URL" ] || [ -n "$LDAP_BASEDN" ]; then - if [ -n "$LDAP_BINDDN" ]; then - if [ -z "$LDAP_BINDPWD" ]; then - errmsg="ldadconfig has been select but LDAP_BINDPWD is not set" - return 1 - fi - fi - if [ -n "$LDAP_BINDPWD" ]; then - if [ -z "$LDAP_BINDDN" ]; then - errmsg="ldadconfig has been select but LDAP_BINDDN is not set" - return 1 - fi - fi - else - errmsg="ldadconfig has been select but neither LDAP_URL or LDAP_BASEDN have been set" - return 1 - fi - ;; - *) - # nothing to do for now - ;; - esac - errmsg=$( @SBINDIR@/cman_tool -t $CMAN_CLUSTER_TIMEOUT -w join \ - $cman_join_opts 2>&1 ) || return 1 - - if [ $CMAN_QUORUM_TIMEOUT -gt 0 ] - then - errmsg=$( @SBINDIR@/cman_tool -t $CMAN_QUORUM_TIMEOUT \ - -q wait 2>&1 ) || return 1 - fi - fi - return 0 -} - -unfence_self() -{ - fence_node -U > /dev/null 2>&1 - error=$? - - if [ $error -eq 0 ] - then - echo " Unfencing self... done" - return 0 - else - if [ $error -eq 1 ] - then - echo " Unfencing self... failed" - return 1 - else - return 0 - fi - fi -} - -start_qdiskd() -{ - status qdiskd > /dev/null 2>&1 - if [ $? -ne 0 ] && \ - ccs_tool query /cluster/quorumd >/dev/null 2>&1; then - errmsg=$( @SBINDIR@/qdiskd -Q 2>&1 ) || return 1 - fi - return 0 -} - - -start_daemons() -{ - status fenced > /dev/null 2>&1 - if [ $? -ne 0 ]; then - errmsg=$( @SBINDIR@/fenced 2>&1 ) || return 1 - fi - status dlm_controld > /dev/null 2>&1 - if [ $? -ne 0 ]; then - errmsg=$( @SBINDIR@/dlm_controld 2>&1 ) || return 1 - fi - status gfs_controld > /dev/null 2>&1 - if [ $? -ne 0 ]; then - errmsg=$( @SBINDIR@/gfs_controld 2>&1 ) || return 1 - fi - status cmannotifyd > /dev/null 2>&1 - if [ $? -ne 0 ]; then - case "$CMAN_NOTIFYD_START" in - yes) - errmsg=$(@SBINDIR@/cmannotifyd 2>&1 ) || return 1 - ;; - no) - # nothing to do - ;; - conditional) - if [ -n "$(ls -1 @NOTIFYDDIR@ 2>/dev/null)" ]; then - errmsg=$(@SBINDIR@/cmannotifyd 2>&1 ) || return 1 - fi - ;; - *) - errmsg="unknown CMAN_NOTIFYD_START option" - return 1 - ;; - esac - fi - return 0 -} - -start_fence() -{ - @SBINDIR@/cman_tool status | grep Flags | grep 2node > /dev/null 2>&1 - if [ $? -ne 0 ] - then - errmsg=$( @SBINDIR@/fence_tool join -w $FENCE_JOIN_TIMEOUT \ - > /dev/null 2>&1 ) || return 1 - else - errmsg=$( @SBINDIR@/fence_tool join -w $FENCE_JOIN_TIMEOUT \ - -m $FENCED_MEMBER_DELAY join \ - > /dev/null 2>&1 ) || return 1 - fi - return 0 -} - -start_fence_xvmd() -{ - status fence_xvmd > /dev/null 2>&1 - if [ $? -ne 0 ]; then - errmsg=$( @SBINDIR@/fence_xvmd $FENCE_XVMD_OPTS 2>&1 ) || return 1 - fi - return 0 -} - -xend_bridged_net_enabled() { - # Not a xen kernel - test -d /proc/xen || return 1 - - current_runlevel=$(/sbin/runlevel 2>/dev/null | awk '{ print $2 }' 2>/dev/null) - if [ -z "$current_runlevel" ]; then - errmsg='Unable to determine the current runlevel' - return 1 - fi - - chkconfig --levels "$current_runlevel" xend 2>/dev/null - if [ $? -ne 0 ]; then - # xend doesn't start at this runlevel. - return 1 - fi - - if [ ! -f /etc/xen/xend-config.sxp ]; then - # xend isn't configured to use bridged networking. - return 1 - fi - - egrep "^[[:blank:]]*([[:blank:]]*network-script[[:blank:]]+(')?[[:blank:]]*${NETWORK_BRIDGE_SCRIPT}([[:blank:]]*)|[[:blank:]]+)" /etc/xen/xend-config.sxp >&/dev/null - if [ $? -ne 0 ]; then - # xend isn't configured to use bridged networking. - return 1 - fi - return 0 -} - -xend_bridged_net_start() { - if [ ! -x /etc/xen/scripts/${NETWORK_BRIDGE_SCRIPT} ]; then - if [ -f /etc/xen/scripts/${NETWORK_BRIDGE_SCRIPT} ]; then - errmsg='The xend bridged network script cannot be run' - else - errmsg='The xend bridged network script is missing' - fi - return 1 - fi - - /sbin/modprobe netbk >& /dev/null - /sbin/modprobe netloop >& /dev/null - bridge_parms=`egrep -m 1 "^[[:blank:]]*([[:blank:]]*network-script[[:blank:]]+(')?[[:blank:]]*${NETWORK_BRIDGE_SCRIPT}([[:blank:]]*)|[[:blank:]]+)" /etc/xen/xend-config.sxp| sed -r "s/^[[:blank:]]*([[:blank:]]*network-script[[:blank:]]+'?[[:blank:]]*${NETWORK_BRIDGE_SCRIPT}[[:blank:]]*//; s/'?[[:blank:]]*).*//"` - errmsg=$(/etc/xen/scripts/${NETWORK_BRIDGE_SCRIPT} start $bridge_parms 2>&1) || return 1 - return 0 -} - -fence_xvmd_enabled() -{ - # - # Check the value of FENCE_JOIN. - # If FENCE_JOIN is set to "no", then we should disable fence_xvm. - # - if [ "$FENCE_JOIN" = "no" ]; then - return 1 - fi - - # - # Check for the 'xm' binary. If it's not here, we are not - # running on a machine capable of running xvmd. - # - which xm > /dev/null 2>&1 || return 1 - - # - # Check for presence of /cluster/fence_xvmd in cluster.conf - # (If -X is specified, it doesn't matter if it's in cluster.conf; - # we'll start it anyway since ccsd is not required) - # - @SBINDIR@/cman_tool status > /dev/null 2>&1 - if [ $? -eq 0 ] - then - if [ "$FENCE_XVMD_OPTS" = "${FENCE_XVMD_OPTS/-X/}" ]; then - @SBINDIR@/ccs_tool query /cluster/fence_xvmd || return 1 - fi - fi - - return 0 -} - -fence_join_enabled() -{ - # - # Check the value of FENCE_JOIN. - # If FENCE_JOIN is set to "no", we will not attempt to join - # the fence domain. If FENCE_JOIN is set to any other value, - # we will attempt to join the fence domain (default). - # - if [ "$FENCE_JOIN" = "no" ]; then - return 1 - else - return 0 - fi -} - -start() -{ - echo "Starting cluster: " - - # required for distributions that use tmpfs for /var/run - mkdir -p /var/run/cluster - - xend_bridged_net_enabled - if [ $? -eq 0 ] - then - echo -n " Enabling workaround for Xend bridged networking... " - xend_bridged_net_start - if [ $? -eq 0 ] - then - echo "done" - else - echo "failed: $errmsg" - return 1 - fi - fi - - echo -n " Loading modules... " - ulimit -c unlimited - load_modules - if [ $? -eq 0 ] - then - echo "done" - else - echo "failed" - return 1 - fi - - echo -n " Mounting configfs... " - start_configfs - if [ $? -eq 0 ] - then - echo "done" - else - echo "failed" - return 1 - fi - - echo -n " Starting cman... " - start_cman - if [ $? -eq 0 ] - then - echo "done" - else - echo "failed" - return 1 - fi - - unfence_self - if [ $? -eq 1 ] - then - return 1 - fi - - echo -n " Starting qdiskd... " - start_qdiskd - if [ $? -eq 0 ] - then - echo "done" - else - echo "failed" - return 1 - fi - - echo -n " Starting daemons... " - start_daemons - if [ $? -eq 0 ] - then - echo "done" - else - echo "failed" - return 1 - fi - - if fence_join_enabled; then - echo -n " Starting fencing... " - start_fence - if [ $? -eq 0 ] - then - echo "done" - else - echo "failed" - return 1 - fi - fi - - if fence_xvmd_enabled; then - echo -n " Starting virtual machine fencing host... " - start_fence_xvmd - if [ $? -eq 0 ] - then - echo "done" - else - echo "failed" - return 1 - fi - fi - - return 0 -} - -stop_configfs() -{ - awk '{ print $2 }' /etc/mtab | grep "/sys/kernel/config" > /dev/null 2>&1 \ - && awk '{ print $3 }' /etc/mtab | grep "configfs" > /dev/null 2>&1 - if [ $? -eq 0 ] && [ -z "$(ls -1 /sys/kernel/config)" ] - then - errmsg=$( /bin/umount /sys/kernel/config 2>&1 ) - if [ $? -ne 0 ] - then - echo -n $errmsg " " - fi - fi - return 0 -} - -stop_cman() -{ - @SBINDIR@/cman_tool status > /dev/null 2>&1 - if [ $? -eq 0 ] - then - errmsg=$( @SBINDIR@/cman_tool -t $CMAN_SHUTDOWN_TIMEOUT \ - -w leave $1 2>&1 ) || return 1 - fi - return 0 # all ok -} - -stop_daemons() -{ - if pid=$(pidof gfs_controld 2>&1); then - errmsg=$(kill $pid 2>&1) || return 1 - fi - if pid=$(pidof dlm_controld 2>&1); then - errmsg=$(kill $pid 2>&1) || return 1 - fi - if pid=$(pidof fenced 2>&1); then - errmsg=$(kill $pid 2>&1) || return 1 - fi - return 0 # all ok -} - -stop_cmannotifyd() -{ - if pid=$(pidof cmannotifyd 2>&1); then - errmsg=$(kill $pid 2>&1) || return 1 - fi - return 0 -} - -stop_qdiskd() -{ - retries=0 - - pid="$(pidof qdiskd)" - while [ -n "$pid" ] && [ $retries -lt 5 ]; do - kill $pid 2>&1 - sleep 1 - ((retries++)) - pid="$(pidof qdiskd)" - done - if [ -z "$(pidof qdiskd)" ]; then - return 0 - else - return 1 - fi -} - -stop_fence() -{ - if pidof fenced > /dev/null 2>&1 - then - @SBINDIR@/fence_tool leave -w 10 > /dev/null 2>&1 - rtrn=$? - return $rtrn - fi - return 0 # all ok -} - -stop_fence_xvmd() -{ - if pidof fence_xvmd > /dev/null 2>&1 - then - pkill -TERM fence_xvmd - sleep 1 # A bit of time for fenced to exit - fi - - [ -z "$(pidof fence_xvmd)" ] - return $? -} - -stop() -{ - echo "Stopping cluster: " - - if fence_xvmd_enabled; then - echo -n " Stopping virtual machine fencing host... " - stop_fence_xvmd - if [ $? -eq 0 ] - then - echo "done" - else - echo "failed" - return 1 - fi - fi - - if fence_join_enabled; then - echo -n " Stopping fencing... " - stop_fence - if [ $? -eq 0 ] - then - echo "done" - else - echo "failed" - return 1 - fi - fi - - echo -n " Stopping daemons... " - stop_daemons - if [ $? -eq 0 ] - then - echo "done" - else - echo "failed" - return 1 - fi - - echo -n " Stopping the Quorum Disk Daemon: " - stop_qdiskd - if [ $? -eq 0 ] - then - echo "done" - else - echo "failed" - return 1 - fi - - echo -n " Stopping cman... " - if [ $1 ]; then - stop_cman $1 - else - stop_cman - fi - if [ $? -eq 0 ] - then - echo "done" - else - echo "failed" - return 1 - fi - - echo -n " Stopping cmannotifyd... " - stop_cmannotifyd - if [ $? -eq 0 ] - then - echo "done" - else - echo "failed" - return 1 - fi - - echo -n " Unmounting configfs... " - stop_configfs - if [ $? -eq 0 ] - then - echo "done" - else - echo "failed" - return 1 - fi - - return 0 -} - -cmanstatus() -{ - errmsg=$( status fenced 2>&1) || return 1 - errmsg=$( status dlm_controld 2>&1) || return 1 - errmsg=$( status gfs_controld 2>&1) || return 1 - - case "$CMAN_NOTIFYD_START" in - yes) - errmsg=$( status cmannotifyd 2>&1) || return 1 - ;; - no) - # nothing to do - ;; - conditional) - if [ -n "$(ls -1 @NOTIFYDDIR@ 2>/dev/null)" ]; then - errmsg=$( status cmannotifyd 2>&1) || return 1 - fi - ;; - esac - - if ccs_tool query /cluster/quorumd >/dev/null 2>&1; then - errmsg=$( status qdiskd 2>&1) || return 1 - fi - - errmsg=$( status corosync 2>&1) || return 1 - - fence_xvmd_enabled || return 0 - errmsg=$( status fence_xvmd 2>&1) || return 1 - - return 0 -} - -rtrn=1 - -# See how we were called. -case "$1" in - start) - start - rtrn=$? - [ $rtrn = 0 ] && touch $LOCK_FILE - if [ $rtrn -ne 0 ] - then - echo $errmsg - failure "failed to start cman" - echo - else - success "start" - echo - fi - ;; - stop) - if [ $2 ]; then - stop - else - stop remove - fi - rtrn=$? - [ $rtrn = 0 ] && rm -f $LOCK_FILE - if [ $rtrn -ne 0 ] - then - echo $errmsg - failure "failed to stop cman" - echo - else - success "shutdown" - echo - fi - ;; - - restart|reload) - $0 stop restart - $0 start - rtrn=$? - ;; - - status) - cmanstatus - rtrn=$? - if [ $rtrn -ne 0 ] ; then - echo $errmsg - else - echo "cman is running." - fi - ;; - - *) - echo $"Usage: $0 {start|stop|reload|restart|status}" - ;; -esac - -exit $rtrn diff --git a/cman/man/Makefile.am b/cman/man/Makefile.am deleted file mode 100644 index a9e03ca..0000000 --- a/cman/man/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -dist_man_MANS = cman.5 \ - qdisk.5 \ - cman_tool.8 \ - qdiskd.8 \ - mkqdisk.8 \ - cmannotifyd.8 diff --git a/cman/man/cman.5 b/cman/man/cman.5 deleted file mode 100644 index 8e52226..0000000 --- a/cman/man/cman.5 +++ /dev/null @@ -1,222 +0,0 @@ -." groff -t -e -mandoc -Tlatin1 cman.5 | less - -.TH "cman" "5" "" "" "cluster.conf cman configuration section" - -.SH "NAME" -cman - cluster.conf cman configuration section - -.SH "DESCRIPTION" - -.in +7 -Cman configuration values are placed in the <cman> </cman> section of -\fBcluster.conf\fP. Per-node configuration related to cman is placed -in the standard <clusternode> </clusternode> sections. All cman -configuration settings are optional; usually none are used. The <cman> -section is placed under the <cluster> section in cluster.conf. - - <cluster> - <cman> - </cman> - ... - </cluster> -.in -7 - - -\fIUDP port\fR -.in +7 -By default, cman will use UDP port 5405/5404 for internode communication. This can -be changed by setting a port number as follows: - - <cman port="6809"> - </cman> - -This will cause cman to use ports 6809 and 6808 for cluster communications. - -.in -7 - - -\fIExpected votes\fR -.in +7 -The expected votes value is used by cman to determine quorum. The cluster is -quorate if the sum of votes of existing members is over half of the expected -votes value. By default, cman sets the expected votes value to be the sum -of votes of all nodes listed in cluster.conf. This can be overridden by setting -an explicit expected_votes value as follows: - - <cman expected_votes="3"> - </cman> - -If the cluster becomes partitioned, improper use of this option can result -in more than one partition gaining quorum. In that event, nodes in each -partition will enable cluster services. -.in -7 - - -\fITwo node clusters\fR -.in +7 -Ordinarily, the loss of quorum after one out of two nodes fails will prevent -the remaining node from continuing (if both nodes have one vote.) Special -configuration options can be set to allow the one remaining node to continue -operating if the other fails. To do this only two nodes, each with one vote, -can be defined in cluster.conf. The two_node and expected_votes values must -then be set to 1 in the cman section as follows. - - <cman two_node="1" expected_votes="1"> - </cman> -.in -7 - - -\fINode votes\fR -.in +7 -By default, a node is given one vote toward the calculation of quorum. -This can be changed by giving a node a specific number of votes as -follows: - - <clusternode name="nd1" votes="2"> - </clusternode> -.in -7 - - -\fINode ID\fR -.in +7 - -All nodes must have a unique node ID. This is a single integer that identifies -it to the cluster. -A node's application to join the cluster may be rejected if you try to set -the nodeid to one that is already used. - - <clusternode name="nd1" nodeid="1"> - </clusternode> - -.in -7 -\fIMulti-home configuration\fR -.in +7 -It is quite common to use multiple ethernet adapters for cluster nodes, so -they will tolerate the failure of one link. A common way to do this is to use -ethernet bonding. Alternatively you can get corosync to run in redundant ring -mode by specifying an 'altname' for the node. This is an alternative name by -which the node is known, that resolves to another IP address used on the -other ethernet adapter(s). You can optionally specify a different port and/or -multicast address for each altname in use. Up to 9 altnames (10 interfaces -in total) can be used. - -Note that if you are using the DLM with Corosync then you MUST tell it -to use SCTP as it's communications protocol as TCP does not support multihoming. - - <clusternode name="nd1" nodeid="1"> - <altname name="nd1a" port="6809" mcast="229.192.0.2"/> - </clusternode> - - <dlm protocol="sctp"/> -.in -7 - - -\fIMulticast network configuration\fR -.in +7 -cman uses multicast UDP packets to communicate with other nodes in the cluster. -By default it will generate a multicast address using 239.192.x.x where x.x is -the 16bit cluster ID number split into bytes. This, in turn is generated from a -hash of the cluster name though it can be specified explicitly. The purpose -of this is to allow multiple clusters to share the same subnet - they will each -use a different multicast address. You might also/instead want to isolate -clusters using the port number as shown above. - -It is possible to override the multicast address by specifying it in cluster.conf -as shown: - - <cman> - <multicast addr="229.192.0.1"/> - </cman> - -.in -7 - -\fICluster ID\fR -.in +7 -The cluster ID number is used to isolate clusters in the same subnet. Usually it -is generated from a hash of the cluster name, but it can be overridden here if -you feel the need. Sometimes cluster names can hash to the same ID. - - <cman cluster_id="669"> - </cman> - -.in -7 - -\fICorosync security key\fR -.in +7 -All traffic sent out by Corosync is encrypted. By default the security key -used is simply the cluster name. If you need more security you can specify a -key file that contains the key used to encrypt cluster communications. -Of course, the contents of the key file must be the same on all nodes in the -cluster. It is up to you to securely copy the file to the nodes. - - <cman keyfile="/etc/corosync.key"> - </cman> - -Note that this only applies to cluster communication. The DLM does not encrypt -traffic. -.in -7 - - -\fIOther Corosync parameters\fR -.in +7 -When Corosync is started by cman (cman_tool runs corosync), the corosync.conf -file is not used. Many of the configuration parameters listed in -corosync.conf can be set in cluster.conf instead. Cman will read -corosync parameters from the following sections in cluster.conf and load -them into corosync: - - <cluster> - <totem /> - <logging /> - <event /> - <aisexec /> - <group /> - </cluster> - -See the -.B corosync.conf(5) -man page for more information on keys that are valid for these sections. -Note that settings in the <clusternodes> section will override settings in -the sections above, and options on the cman_tool command line will -override both. In particular, settings like bindnetaddr, mcastaddr, -mcastport and nodeid will always be replaced by values in <clusternodes>. - -Cman uses different defaults for some of the corosync parameters listed in -corosync.conf(5). If you wish to use a non-default setting, they can be -configured in cluster.conf as shown above. Cman uses the following -default values: - - <totem - vsftype="none" - token="10000" - token_retransmits_before_loss_const="20" - join="60" - consensus="4800" - rrp_mode="none" - <!-- or rrp_mode="active" if altnames are present > - /> - <logging syslog_facility="local4" /> - <aisexec user="root" group="root" /> - -Here's how to set the token timeout to five seconds: - - <totem token="5000"/> - -And this is how to add extra corosync logging options to CMAN and CPG: - - <logging to_stderr="yes"> - <logger_subsys subsys="CPG" debug="on" to_stderr="yes"> - </logger_subsys> - <logger_subsys subsys="CMAN" debug="on" to_stderr="yes"> - </logger_subsys> - </logging> - -.in -7 - - -.sp - -.SH "SEE ALSO" - -cluster.conf(5), corosync.conf(5), ccs(7), cman_tool(8) - diff --git a/cman/man/cman_tool.8 b/cman/man/cman_tool.8 deleted file mode 100644 index d9bc224..0000000 --- a/cman/man/cman_tool.8 +++ /dev/null @@ -1,345 +0,0 @@ -.TH CMAN_TOOL 8 "Nov 8 2007" "Cluster utilities" - -.SH NAME -cman_tool - Cluster Management Tool -.SH SYNOPSIS -.B cman_tool join | leave | kill | expected | votes | version | wait | status | nodes | services | debug [options] -.br -.SH DESCRIPTION -.PP -.B cman_tool -is a program that manages the cluster management subsystem CMAN. cman_tool -can be used to join the node to a cluster, leave the cluster, kill another -cluster node or change the value of expected votes of a cluster. -.br -Be careful that you understand the consequences of the commands issued via cman_tool -as they can affect all nodes in your cluster. Most of the time the cman_tool -will only be invoked from your startup and shutdown scripts. -.br -.SH SUBCOMMANDS -.TP -.I join -This is the main use of cman_tool. It instructs the cluster manager to attempt -to join an existing cluster or (if no existing cluster exists) then to form -a new one on its own. -.br -If no options are given to this command then it will take the cluster -configuration information from cluster.conf. However, it is possible to provide -all the information on the command-line or to override cluster.conf values by using -the command line. - -.TP -.I leave -Tells CMAN to leave the cluster. You cannot do this if there are subsystems -(eg DLM, GFS) active. You should dismount all GFS filesystems, -shutdown CLVM, fenced and anything else using the cluster manager before -using -.B cman_tool leave. -Look at 'cman_tool status' and group_tool to see how many (and which) -subsystems are active. -.br -When a node leaves the cluster, the remaining nodes recalculate quorum and this -may block cluster activity if the required number of votes is not present. -If this node is to be down for an extended period of time and you need to -keep the cluster running, add the -.B remove -option, and the remaining nodes will recalculate quorum such that activity -can continue. - -.TP -.I kill -Tells CMAN to kill another node in the cluster. This will cause the local -node to send a "KILL" message to that node and it will shut down. Recovery -will occur for the killed node as if it had failed. This is a sort of remote -version of "leave force" so only use if if you really know what you are doing. - -.TP -.I expected -Tells CMAN a new value of expected votes and instructs it to recalculate -quorum based on this value. -.br -Use this option if your cluster has lost quorum due to nodes failing and -you need to get it running again in a hurry. - -.TP -.I version -Used alone this will report the major, minor, patch and config versions -used by CMAN (also displayed in 'cman_tool status'). It can also be used -with -r to tell cluster members to update. - -.TP -.I wait -Waits until the node is a member of the cluster and then returns. - -.TP -.I status -Displays the local view of the cluster status. - -.TP -.I nodes -Displays the local view of the cluster nodes. - -.TP -.I services -Displays the local view of subsystems using cman (deprecated, group_tool -should be used instead). - -.TP -.I debug -Sets the debug level of the running cman daemon. Debug output will be -sent to syslog level LOG_DEBUG. the -.B -d -switch specifies the new logging level. This is the same bitmask used -for cman_tool join -d -.br -.SH "LEAVE" OPTIONS -.TP -.I -w -Normally, "cman_tool leave" will fail if the cluster is in transition (ie -another node is joining or leaving the cluster). By adding the -w flag, -cman_tool will wait and retry the leave operation repeatedly until it succeeds -or a more serious error occurs. -.TP -.I -t <seconds> -If -w is also specified then -t dictates the maximum amount of time cman_tool -is prepared to wait. If the operation times out then a status of 2 is returned. -.TP -.I force -Shuts down the cluster manager without first telling any of the subsystems -to close down. Use this option with extreme care as it could easily cause data -loss. -.TP -.I remove -Tells the rest of the cluster to recalculate quorum such that activity can -continue without this node. - -.SH "EXPECTED" OPTIONS -.TP -.I -e <expected-votes> -The new value of expected votes to use. This will usually be enough -to bring the cluster back to life. Values that would cause incorrect -quorum will be rejected. - -.SH "KILL" OPTIONS -.TP -.I -n <nodename> -The node name of the node to be killed. This should be the unqualified node -name as it appears in 'cman_tool nodes'. - -.SH "VERSION" OPTIONS -.TP -.I -r <config_version> -Update config version. You don't need to use this when adding a new node, -the new cman node will tell the rest of the cluster to read the latest -version of the config file automatically. -.br -In fact the argument to -r might look as though it is ignored. -Its presence simply tells cman to re-read the configuration file and look -for that version in the file. cman will keep re-reading the file -until a version number >= the passed version is found. -.br -cman_tool version on its own will always show the current version -and not the one being looked for. So be aware that the display -will possible not update immediately after you have run -cman_tool version -r. -.SH "WAIT" OPTIONS -.TP -.I -q -Waits until the cluster is quorate before returning. -.I -t <seconds> -Dictates the maximum amount of time cman_tool is prepared to wait. -If the operation times out then a status of 2 is returned. - -.br -.SH "JOIN" OPTIONS -.TP -.I -c <clustername> -Provides a text name for the cluster. You can have several clusters on one -LAN and they are distinguished by this name. Note that the name is hashed to -provide a unique number which is what actually distinguishes the cluster, so -it is possible that two different names can clash. If this happens, the node -will not be allowed into the existing cluster and you will have to pick -another name or use different port number for cluster communication. -.TP -.I -p <port> -UDP port number used for cluster communication. This defaults to 5405. -.TP -.I -v <votes> -Number of votes this node has in the cluster. Defaults to 1. -.TP -.I -e <expected votes> -Number of expected votes for the whole cluster. If different nodes -provide different values then the highest is used. The cluster will -only operate when quorum is reached - that is more than half the -available votes are available to the cluster. The default for -this value is the total number of votes for all nodes in the configuration file. -.TP -.I -2 -Sets the cluster up for a special "two node only" mode. Because of the -quorum requirements mentioned above, a two-node cluster cannot be valid. -This option tells the cluster manager that there will only ever be two -nodes in the cluster and relies on fencing to ensure cluster integrity. -If you specify this you cannot add more nodes without taking down the -existing cluster and reconfiguring it. Expected votes should be set to -1 for a two-node cluster. -.TP -.I -n <nodename> -Overrides the node name. By default the unqualified hostname is used. This -option is also used to specify which interface is used for cluster -communication. -.TP -.I -N <nodeid> -Overrides the node ID for this node. Normally, nodes are assigned a -node id in cluster.conf. If you specify an incorrect node ID here, the -node might not be allowed to join the cluster. Setting node IDs in the -configuration is a far better way to do this. -.BR -Note that the node's application to join the cluster may be rejected if you -try to set the nodeid to one that has already been used, or if the node -was previously a member of the cluster but with a different nodeid. -.TP -.I -o <nodename> -Override the name this node will have in the cluster. This will -normally be the hostname or the first name specified by -n. -Note how this differs from -n: -n tells cman_tool how to find -the host address and/or the entry in the configuration file. -o simply -changes the name the node will have in the cluster and has no -bearing on the actual name of the machine. Use this option -will extreme caution. -.BR -.TP -.I -m <multicast-address> -Specifies a multicast address to use for cluster communication. This -is required for IPv6 operation. You should also specify an ethernet -interface to bind to this multicast address using the -i option. -.TP -.I -w -Join and wait until the node is a cluster member. -.TP -.I -q -Join and wait until the cluster is quorate. -If the cluster join fails and -w (or -q) is specified, then it will be retried. Note that -cman_tool cannot tell whether the cluster join was rejected by another node for a good reason -or that it timed out for some benign reason; so it is strongly recommended that a timeout -is also given with the wait options to join. If you don't want join to retry on failure but -do want to wait, use the -.B cman_tool join -command without -w followed by -.B cman_tool wait. -.TP -.I -k <keyfile> -All traffic sent out by Corosync is encrypted. By default the security key -used is simply the cluster name. If you need more security you can specify a -key file that contains the key used to encrypt cluster communications. -Of course, the contents of the key file must be the same on all nodes in the -cluster. It is up to you to securely copy the file to the nodes. -.TP -.I -t <seconds> -If -w or -q is also specified then -t dictates the maximum amount of time cman_tool -is prepared to wait. If the operation times out then a status of 2 is returned. -Note that just because cman_tool has given up, does not mean that cman itself -has stopped trying to join a cluster. -.TP -.I -X -Tells cman not to use the configuration file to get cluster information. If you use this option then cman will -apply several defaults to the cluster to get it going. The cluster name will be -"RHCluster", node IDs will default to the IP address of the node and remote node -names will show up as Node<nodeid>. All of these, apart from the node names can -be overridden on the cman_tool command-line if required. -.br -If you have to set up fence devices, services or anything else in cluster.conf then -this option is probably not worthwhile to you - the extra readability of sensible node -names and numbers will make it worth using cluster.conf for the cluster too. But for a simple -failover cluster this might save you some effort. -.br -On each node using this configuration you will need to have the same authorization key -installed. To create this key run -.br -corosync-keygen -.br -mv /etc/ais/authkey /etc/cluster/cman_authkey -.br -then copy that file to all nodes you want to join the cluster. -.br -.TP -.I -C -Overrides the default configuration module. Usually cman uses cluster.conf to load its -configuration. If you have your configuration database held elsewhere (eg LDAP) and -have a configuration plugin for it, then you should specify the name of the module -(see the documentation for the module for the name of it - it's not necessarily the -same as the filename) here. -.br -It is possible to chain configuration modules by separating them with colons. So to -add two modules (eg) 'ldapconfig' and 'ldappreproc' to the chain start cman with --C ldapconfig:ldappreproc -.br -The default value for this is 'xmlconfig'. Note that if the -X is on the command-line -then -C will be ignored. -.TP -.I -A -Don't load openais services. Normally cman_tool join will load the configuration -module 'openaisserviceenablestable' which will load the services installed by openais. -If you don't want to use these services or have not installed openais then -this switch will disable them. -.SH "NODES" OPTIONS -.TP -.I -f -Shows the date/time the node was last fenced (if it has bee fenced), and also -the fence system that was used. -.br -.TP -.I -a -Shows the IP address(es) the nodes are communicating on. -.br -.TP -.I -n <nodename> -Shows node information for a specific node. This should be the unqualified node -name as it appears in 'cman_tool nodes'. -.br -.TP -.I -F <format> -Specify the format of the output. The format string may contain one or -more format options, each separated by a comma. Valid format options -include: id, name, type, and addr. -.br -.SH "DEBUG" OPTIONS -.TP -.I -d <value> -Currently only a value of 1 is supported. -.br -.SH NOTES -.br -the -.B nodes -subcommand shows a list of nodes known to cman. the state is one of the following: -.br -M The node is a member of the cluster -.br -X The node is not a member of the cluster -.br -d The node is known to the cluster but disallowed access to it. -.br -.SH ENVIRONMENT VARIABLES -cman_tool removes most environment variables before forking and running Corosync, as well as adding some of its own for setting up -configuration parameters that were overridden on the command-line, the exception to this is that variable with names starting -COROSYNC_ will be passed down intact as they are assumed to be used for configuring the daemon. - -.SH CONFIGURATION SYSTEMS -This section details how the configuration systems work in cman. You might need to know this if you are using the -C option -to cman_tool, or writing your own configuration subsystem. -.br -By default cman uses two configuration plugins to Corosync. The first, 'xmlconfig', reads the configuration information -stored in cluster.conf and stores it in an internal database, in the same schema as it finds in cluster.conf. -The second plugin, 'cmanpreconfig', takes the information in that the database, adds several cman defaults, determines -the Corosync node name and nodeID -and formats the information in a similar manner to corosync.conf(5). Corosync then reads those keys to start the cluster protocol. -cmanpreconfig also reads several environment variables that might be set by cman_tool which can override information in the -configuration. -.br -In the absence of xmlconfig, ie when 'cman_tool join' is run with -X switch (this removes xmlconfig from the module list), -cmanpreconfig also generates several defaults so that the cluster can be got running without any configuration information - see above -for the details. -.br -Note that cmanpreconfig will not overwrite Corosync keys that are explicitly set in the configuration file, allowing you to provide -custom values for token timeouts etc, even though cman has its own defaults for some of those values. The exception to this is the node -name/address and multicast values, which are always taken from the cman configuration keys. diff --git a/cman/man/cmannotifyd.8 b/cman/man/cmannotifyd.8 deleted file mode 100644 index 56ad353..0000000 --- a/cman/man/cmannotifyd.8 +++ /dev/null @@ -1,66 +0,0 @@ -.TH "cmannotifyd" "8" "November 2008" "" "CMAN Notification Daemon" -.SH "NAME" -cmannotifyd - CMAN Notification Daemon -.SH "SYNOPSIS" -\fBcmannotifyd [-f] [-d] -.SH "DESCRIPTION" -.PP -The \fBcmannotifyd\fP daemon talks to CMAN and provides a mechanism to notify -external entities about cluster changes. - -CMAN dispatches 3 kind of notifications: - -- CMAN_REASON_TRY_SHUTDOWN when cman requests to all clients if it is allowed -to shutdown. - -- CMAN_REASON_STATECHANGE when cman detects a node joining or leaving the -cluster. - -- CMAN_REASON_CONFIG_UPDATE when a configuration change event has been -detected/requested. - -These notifications are then dispatched to the shell script -.B cman_notify -in the environment variable CMAN_NOTIFICATION. - -.B cman_notify -will then execute all the scripts in the configured notification -directory (default: /etc/cluster/cman-notify.d) passing a very minimal set of -envvars including, of course, the CMAN_NOTIFICATION= type. -The execution order is set by the filename as shown by "LC_ALL=C ls -las". - -.B cmannotifyd -logs are stored in the default log file -(/var/log/cluster/cmannotifyd.log). - -.B cman_notify -logs are stored in the default log file -(/var/log/cluster/cman_notify.log). By default the output from the scripts -executed by -.B cman_notify -is redirected to /dev/null. -Users can either set CMAN_NOTIFICATION_DEBUG=1 in their environment or -set proper debug configuration in cluster.conf to redirect scripts output -to the cman_notify log file. - -.SH "NOTES" -cmannotifyd does not block on cman_notify nor check the exit -status of the script. - -Notifications are dispatched in the same order as they -arrive, one by one. - -CMAN_REASON_TRY_SHUTDOWN is passed to scripts for information only, they -can not influence cman's decsion about whether or not to shut down. - -CMAN_REASON_STATECHANGE also implies CMAN_NOTIFICATION_QUORUM exported -in the environment. CMAN_NOTIFICATION_QUORUM will be set to 1 (when the node -is part of a quorate cluster) or 0 (otherwise). - -A template for cman_notify scripts can be found in the doc/ directory. - -.SH "OPTIONS" -.IP "-f" -Run in the foreground (do not fork / daemonize). -.IP "-d" -Enable debug output. diff --git a/cman/man/mkqdisk.8 b/cman/man/mkqdisk.8 deleted file mode 100644 index a097680..0000000 --- a/cman/man/mkqdisk.8 +++ /dev/null @@ -1,31 +0,0 @@ -.TH "mkqdisk" "8" "July 2006" "" "Quorum Disk Management" -.SH "NAME" -mkqdisk - Cluster Quorum Disk Utility -.SH "WARNING" -Use of this command can cause the cluster to malfunction. -.SH "SYNOPSIS" -\fBmkqdisk [-?|-h] | [-L] | [-f \fPlabel\fB] [-c \fPdevice \fB -l \fPlabel\fB] [-d [-d ...]] -.SH "DESCRIPTION" -.PP -The \fBmkqdisk\fP command is used to create a new quorum disk or display -existing quorum disks accessible from a given cluster node. -.SH "OPTIONS" -.IP "-c device -l label" -Initialize a new cluster quorum disk. This will destroy all data on the given -device. If a cluster is currently using that device as a quorum disk, the -entire cluster will malfunction. Do not run this on an active cluster when -qdiskd is running. Only one device on the SAN should ever have the given -label; using multiple different devices is currently not supported (it is -expected a RAID array is used for quorum disk redundancy). The label can be -any textual string up to 127 characters - and is therefore enough space to hold -a UUID created with uuidgen(1). -.IP "-f label" -Find the cluster quorum disk with the given label and display information about it. -.IP "-L" -Display information on all accessible cluster quorum disks. -.IP "-d" -Increase debugging level. Specify multiple times for more information. -Currently, specifying more than twice has no effect. - -.SH "SEE ALSO" -qdisk(5), qdiskd(8), uuidgen(1) diff --git a/cman/man/qdisk.5 b/cman/man/qdisk.5 deleted file mode 100644 index 7a00a25..0000000 --- a/cman/man/qdisk.5 +++ /dev/null @@ -1,478 +0,0 @@ -.TH "QDisk" "5" "20 Feb 2007" "" "Cluster Quorum Disk" -.SH "NAME" -qdisk - a disk-based quorum daemon for CMAN / Linux-Cluster -.SH "1. Overview" -.SH "1.1 Problem" -In some situations, it may be necessary or desirable to sustain -a majority node failure of a cluster without introducing the need for -asymmetric cluster configurations (e.g. client-server, or heavily-weighted -voting nodes). - -.SH "1.2. Design Requirements" -* Ability to sustain 1..(n-1)/n simultaneous node failures, without the -danger of a simple network partition causing a split brain. That is, we -need to be able to ensure that the majority failure case is not merely -the result of a network partition. - -* Ability to use external reasons for deciding which partition is the -the quorate partition in a partitioned cluster. For example, a user may -have a service running on one node, and that node must always be the master -in the event of a network partition. Or, a node might lose all network -connectivity except the cluster communication path - in which case, a -user may wish that node to be evicted from the cluster. - -* Integration with CMAN. We must not require CMAN to run with us (or -without us). Linux-Cluster does not require a quorum disk normally - -introducing new requirements on the base of how Linux-Cluster operates -is not allowed. - -* Data integrity. In order to recover from a majority failure, fencing -is required. The fencing subsystem is already provided by Linux-Cluster. - -* Non-reliance on hardware or protocol specific methods (i.e. SCSI -reservations). This ensures the quorum disk algorithm can be used on the -widest range of hardware configurations possible. - -* Little or no memory allocation after initialization. In critical paths -during failover, we do not want to have to worry about being killed during -a memory pressure situation because we request a page fault, and the Linux -OOM killer responds... - -.SH "1.3. Hardware Considerations and Requirements" -.SH "1.3.1. Concurrent, Synchronous, Read/Write Access" -This quorum daemon requires a shared block device with concurrent read/write -access from all nodes in the cluster. The shared block device can be -a multi-port SCSI RAID array, a Fiber-Channel RAID SAN, a RAIDed iSCSI -target, or even GNBD. The quorum daemon uses O_DIRECT to write to the -device. - -.SH "1.3.2. Bargain-basement JBODs need not apply" -There is a minimum performance requirement inherent when using disk-based -cluster quorum algorithms, so design your cluster accordingly. Using a -cheap JBOD with old SCSI2 disks on a multi-initiator bus will cause -problems at the first load spike. Plan your loads accordingly; a node's -inability to write to the quorum disk in a timely manner will cause the -cluster to evict the node. Using host-RAID or multi-initiator parallel -SCSI configurations with the qdisk daemon is unlikely to work, and will -probably cause administrators a lot of frustration. That having been -said, because the timeouts are configurable, most hardware should work -if the timeouts are set high enough. - -.SH "1.3.3. Fencing is Required" -In order to maintain data integrity under all failure scenarios, use of -this quorum daemon requires adequate fencing, preferably power-based -fencing. Watchdog timers and software-based solutions to reboot the node -internally, while possibly sufficient, are not considered 'fencing' for -the purposes of using the quorum disk. - -.SH "1.4. Limitations" -* At this time, this daemon supports a maximum of 16 nodes. This is -primarily a scalability issue: As we increase the node count, we increase -the amount of synchronous I/O contention on the shared quorum disk. - -* Cluster node IDs must be statically configured in cluster.conf and -must be numbered from 1..16 (there can be gaps, of course). - -* Cluster node votes should be more or less equal. - -* CMAN must be running before the qdisk program can operate in full -capacity. If CMAN is not running, qdisk will wait for it. - -* CMAN's eviction timeout should be at least 2x the quorum daemon's -to give the quorum daemon adequate time to converge on a master during a -failure + load spike situation. - -* For 'all-but-one' failure operation, the total number of votes assigned -to the quorum device should be equal to or greater than the total number -of node-votes in the cluster. While it is possible to assign only one -(or a few) votes to the quorum device, the effects of doing so have not -been explored. - -* For 'tiebreaker' operation in a two-node cluster, unset CMAN's two_node -flag (or set it to 0), set CMAN's expected votes to '3', set each node's -vote to '1', and set qdisk's vote count to '1' as well. This will allow -the cluster to operate if either both nodes are online, or a single node & -the heuristics. - -* Currently, the quorum disk daemon is difficult to use with CLVM if -the quorum disk resides on a CLVM logical volume. CLVM requires a -quorate cluster to correctly operate, which introduces a chicken-and-egg -problem for starting the cluster: CLVM needs quorum, but the quorum daemon -needs CLVM (if and only if the quorum device lies on CLVM-managed storage). -One way to work around this is to *not* set the cluster's expected votes -to include the quorum daemon's votes. Bring all nodes online, and start -the quorum daemon *after* the whole cluster is running. This will allow -the expected votes to increase naturally. - -.SH "2. Algorithms" -.SH "2.1. Heartbeating & Liveliness Determination" -Nodes update individual status blocks on the quorum disk at a user- -defined rate. Each write of a status block alters the timestamp, which -is what other nodes use to decide whether a node has hung or not. If, -after a user-defined number of 'misses' (that is, failure to update a -timestamp), a node is declared offline. After a certain number of 'hits' -(changed timestamp + "i am alive" state), the node is declared online. - -The status block contains additional information, such as a bitmask of -the nodes that node believes are online. Some of this information is -used by the master - while some is just for performance recording, and -may be used at a later time. The most important pieces of information -a node writes to its status block are: - -.in 12 -- Timestamp -.br -- Internal state (available / not available) -.br -- Score -.br -- Known max score (may be used in the future to detect invalid configurations) -.br -- Vote/bid messages -.br -- Other nodes it thinks are online -.in 0 - -.SH "2.2. Scoring & Heuristics" -The administrator can configure up to 10 purely arbitrary heuristics, and -must exercise caution in doing so. At least one administrator- -defined heuristic is required for operation, but it is generally a good -idea to have more than one heuristic. By default, only nodes scoring over -1/2 of the total maximum score will claim they are available via the -quorum disk, and a node (master or otherwise) whose score drops too low -will remove itself (usually, by rebooting). - -The heuristics themselves can be any command executable by 'sh -c'. For -example, in early testing the following was used: - -.ti 12 -<\fBheuristic \fP\fIprogram\fP\fB="\fP[ -f /quorum ]\fB" \fP\fIscore\fP\fB="\fP10\fB" \fP\fIinterval\fP\fB="\fP2\fB"/>\fP - -This is a literal sh-ism which tests for the existence of a file called -"/quorum". Without that file, the node would claim it was unavailable. -This is an awful example, and should never, ever be used in production, -but is provided as an example as to what one could do... - -Typically, the heuristics should be snippets of shell code or commands which -help determine a node's usefulness to the cluster or clients. Ideally, you -want to add traces for all of your network paths (e.g. check links, or -ping routers), and methods to detect availability of shared storage. - -.SH "2.3. Master Election" -Only one master is present at any one time in the cluster, regardless of -how many partitions exist within the cluster itself. The master is -elected by a simple voting scheme in which the lowest node which believes -it is capable of running (i.e. scores high enough) bids for master status. -If the other nodes agree, it becomes the master. This algorithm is -run whenever no master is present. - -If another node comes online with a lower node ID while a node is still -bidding for master status, it will rescind its bid and vote for the lower -node ID. If a master dies or a bidding node dies, the voting algorithm -is started over. The voting algorithm typically takes two passes to -complete. - -Master deaths take marginally longer to recover from than non-master -deaths, because a new master must be elected before the old master can -be evicted & fenced. - -.SH "2.4. Master Duties" -The master node decides who is or is not in the master partition, as -well as handles eviction of dead nodes (both via the quorum disk and via -the linux-cluster fencing system by using the cman_kill_node() API). - -.SH "2.5. How it All Ties Together" -When a master is present, and if the master believes a node to be online, -that node will advertise to CMAN that the quorum disk is available. The -master will only grant a node membership if: - -.in 12 -(a) CMAN believes the node to be online, and -.br -(b) that node has made enough consecutive, timely writes -.in 16 -to the quorum disk, and -.in 12 -(c) the node has a high enough score to consider itself online. -.in 0 - -.SH "3. Configuration" -.SH "3.1. The <quorumd> tag" -This tag is a child of the top-level <cluster> tag. - -.in 8 -\fB<quorumd\fP -.in 9 -\fIinterval\fP\fB="\fP1\fB"\fP -.in 12 -This is the frequency of read/write cycles, in seconds. - -.in 9 -\fItko\fP\fB="\fP10\fB"\fP -.in 12 -This is the number of cycles a node must miss in order to be declared dead. - -.in 9 -\fItko_up\fP\fB="\fPX\fB"\fP -.in 12 -This is the number of cycles a node must be seen in order to be declared -online. Default is \fBfloor(tko/3)\fP. - -.in 9 -\fIupgrade_wait\fP\fB="\fP2\fB"\fP -.in 12 -This is the number of cycles a node must wait before initiating a bid -for master status after heuristic scoring becomes sufficient. The -default is 2. This can not be set to 0, and should not exceed \fBtko\fP. - -.in 9 -\fImaster_wait\fP\fB="\fPX\fB"\fP -.in 12 -This is the number of cycles a node must wait for votes before declaring -itself master after making a bid. Default is \fBfloor(tko/2)\fP. -This can not be less than 2, must be greater than tko_up, and should not -exceed \fBtko\fP. - -.in 9 -\fIvotes\fP\fB="\fP3\fB"\fP -.in 12 -This is the number of votes the quorum daemon advertises to CMAN when it -has a high enough score. - -.in 9 -\fIlog_level\fP\fB="\fP4\fB"\fP -.in 12 -This controls the verbosity of the quorum daemon in the system logs. -0 = emergencies; 7 = debug. This option is deprecated. - -.in 9 -\fIlog_facility\fP\fB="\fPdaemon\fB"\fP -.in 12 -This controls the syslog facility used by the quorum daemon when logging. -For a complete list of available facilities, see \fBsyslog.conf(5)\fP. -The default value for this is 'daemon'. This option is deprecated. - -.in 9 -\fIstatus_file\fP\fB="\fP/foo\fB"\fP -.in 12 -Write internal states out to this file periodically ("-" = use stdout). -This is primarily used for debugging. The default value for this -attribute is undefined. This option can be changed while qdiskd is -running. - -.in 9 -\fImin_score\fP\fB="\fP3\fB"\fP -.in 12 -Absolute minimum score to be consider one's self "alive". If omitted, -or set to 0, the default function "floor((n+1)/2)" is used, where \fIn\fP -is the total of all of defined heuristics' \fIscore\fP attribute. This -must never exceed the sum of the heuristic scores, or else the quorum -disk will never be available. - -.in 9 -\fIreboot\fP\fB="\fP1\fB"\fP -.in 12 -If set to 0 (off), qdiskd will *not* reboot after a negative transition -as a result in a change in score (see section 2.2). The default for -this value is 1 (on). This option can be changed while qdiskd is -running. - -.in 9 -\fIallow_kill\fP\fB="\fP1\fB"\fP -.in 12 -If set to 0 (off), qdiskd will *not* instruct to kill nodes it thinks -are dead (as a result of not writing to the quorum disk). The default -for this value is 1 (on). This option can be changed while qdiskd -is running. - -.in 9 -\fIparanoid\fP\fB="\fP0\fB"\fP -.in 12 -If set to 1 (on), qdiskd will watch internal timers and reboot the node -if it takes more than (interval * tko) seconds to complete a quorum disk -pass. The default for this value is 0 (off). This option can be changed -while qdiskd is running. - -.in 9 -\fIio_timeout\fP\fB="\fP0\fB"\fP -.in 12 -If set to 1 (on), qdiskd will watch internal timers and reboot the node -if qdisk is not able to write to disk after (interval * tko) seconds. -The default for this value is 0 (off). If io_timeout is active -max_error_cycles is overridden and set to off. - -.in 9 -\fIscheduler\fP\fB="\fPrr\fB"\fP -.in 12 -Valid values are 'rr', 'fifo', and 'other'. Selects the scheduling queue -in the Linux kernel for operation of the main & score threads (does not -affect the heuristics; they are always run in the 'other' queue). Default -is 'rr'. See sched_setscheduler(2) for more details. - -.in 9 -\fIpriority\fP\fB="\fP1\fB"\fP -.in 12 -Valid values for 'rr' and 'fifo' are 1..100 inclusive. Valid values -for 'other' are -20..20 inclusive. Sets the priority of the main & score -threads. The default value is 1 (in the RR and FIFO queues, higher numbers -denote higher priority; in OTHER, lower values denote higher priority). -This option can be changed while qdiskd is running. - -.in 9 -\fIstop_cman\fP\fB="\fP0\fB"\fP -.in 12 -Ordinarily, cluster membership is left up to CMAN, not qdisk. -If this parameter is set to 1 (on), qdiskd will tell CMAN to leave the -cluster if it is unable to initialize the quorum disk during startup. This -can be used to prevent cluster participation by a node which has been -disconnected from the SAN. The default for this value is 0 (off). -This option can be changed while qdiskd is running. - -.in 9 -\fIuse_uptime\fP\fB="\fP1\fB"\fP -.in 12 -If this parameter is set to 1 (on), qdiskd will use values from -/proc/uptime for internal timings. This is a bit less precise -than \fBgettimeofday(2)\fP, but the benefit is that changing the -system clock will not affect qdiskd's behavior - even if \fBparanoid\fP -is enabled. If set to 0, qdiskd will use \fBgettimeofday(2)\fP, which -is more precise. The default for this value is 1 (on / use uptime). - -.in 9 -\fIdevice\fP\fB="\fP/dev/sda1\fB"\fP -.in 12 -This is the device the quorum daemon will use. This device must be the -same on all nodes. - -.in 9 -\fIlabel\fP\fB="\fPmylabel\fB"\fP -.in 12 -This overrides the device field if present. If specified, the quorum -daemon will read /proc/partitions and check for qdisk signatures -on every block device found, comparing the label against the specified -label. This is useful in configurations where the block device name -differs on a per-node basis. - -.in 9 -\fIcman_label\fP\fB="\fPmylabel\fB"/>\fP -.in 12 -This overrides the label advertised to CMAN if present. If specified, -the quorum daemon will register with this name instead of the actual -device name. - -.in 9 -\fImax_error_cycles\fP\fB="\fP0\fB"/>\fP -.in 12 -If we receive an I/O error during a cycle, we do not poll CMAN and tell -it we are alive. If specified, this value will cause qdiskd to exit -after the specified number of consecutive cycles during which I/O errors -occur. The default is 0 (no maximum). This option can be changed while -qdiskd is running. This option is ignored if io_timeout is set to 1. - -.in 8 -\fB/>\fP -.in 0 - -.SH "3.2. The <heuristic> tag" -This tag is a child of the <quorumd> tag. Heuristics may not be changed -while qdiskd is running. - -.in 8 -\fB<heuristic\fP -.in 9 -\fIprogram\fP\fB="\fP/test.sh\fB"\fP -.in 12 -This is the program used to determine if this heuristic is alive. This -can be anything which may be executed by \fI/bin/sh -c\fP. A return -value of zero indicates success; anything else indicates failure. This -is required. - -.in 9 -\fIscore\fP\fB="\fP1\fB"\fP -.in 12 -This is the weight of this heuristic. Be careful when determining scores -for heuristics. The default score for each heuristic is 1. - -.in 9 -\fIinterval\fP\fB="\fP2\fB"\fP -.in 12 -This is the frequency (in seconds) at which we poll the heuristic. The -default interval for every heuristic is 2 seconds. -.in 0 - -.in 9 -\fItko\fP\fB="\fP1\fB"\fP -.in 12 -After this many failed attempts to run the heuristic, it is considered DOWN, -and its score is removed. The default tko for each heuristic is 1, which -may be inadequate for things such as 'ping'. -.in 8 -\fB/>\fP -.in 0 - - -.SH "3.3. Examples" -.SH "3.3.1. 3 cluster nodes & 3 routers" -.in 8 -<cman expected_votes="6" .../> -.br -<clusternodes> -.in 12 -<clusternode name="node1" votes="1" ... /> -.br -<clusternode name="node2" votes="1" ... /> -.br -<clusternode name="node3" votes="1" ... /> -.in 8 -</clusternodes> -.br -<quorumd interval="1" tko="10" votes="3" label="testing"> -.in 12 -<heuristic program="ping A -c1 -t1" score="1" interval="2" tko="3"/> -.br -<heuristic program="ping B -c1 -t1" score="1" interval="2" tko="3"/> -.br -<heuristic program="ping C -c1 -t1" score="1" interval="2" tko="3"/> -.br -.in 8 -</quorumd> - -.SH "3.3.2. 2 cluster nodes & 1 IP tiebreaker" -.in 8 -<cman two_node="0" expected_votes="3" .../> -.br -<clusternodes> -.in 12 -<clusternode name="node1" votes="1" ... /> -.br -<clusternode name="node2" votes="1" ... /> -.in 8 -</clusternodes> -.br -<quorumd interval="1" tko="10" votes="1" label="testing"> -.in 12 -<heuristic program="ping A -c1 -t1" score="1" interval="2" tko="3"/> -.br -.in 8 -</quorumd> -.in 0 - - -.SH "3.4. Heuristic score considerations" -* Heuristic timeouts should be set high enough to allow the previous run -of a given heuristic to complete. - -* Heuristic scripts returning anything except 0 as their return code -are considered failed. - -* The worst-case for improperly configured quorum heuristics is a race -to fence where two partitions simultaneously try to kill each other. - -.SH "3.5. Creating a quorum disk partition" -The mkqdisk utility can create and list currently configured quorum disks -visible to the local node; see -.B mkqdisk(8) -for more details. - -.SH "SEE ALSO" -mkqdisk(8), qdiskd(8), cman(5), syslog.conf(5), gettimeofday(2) diff --git a/cman/man/qdiskd.8 b/cman/man/qdiskd.8 deleted file mode 100644 index 21bccbf..0000000 --- a/cman/man/qdiskd.8 +++ /dev/null @@ -1,25 +0,0 @@ -.TH "qdiskd" "8" "July 2006" "" "Quorum Disk Management" -.SH "NAME" -qdiskd - Cluster Quorum Disk Daemon -.SH "SYNOPSIS" -\fBqdiskd [-f] [-d] -.SH "DESCRIPTION" -.PP -The \fBqdiskd\fP daemon talks to CMAN and provides a mechanism for determining -node-fitness in a cluster environment. See -.B -qdisk(5) -for configuration information. -.SH "OPTIONS" -.IP "-f" -Run in the foreground (do not fork / daemonize). -.IP "-d" -Enable debug output. -.IP "-Q" -Close stdin/out/err immediately before doing validations. This -is primarily for use when being called from an init script. Using -this option will stop all output, and can not be used with the -d -option. - -.SH "SEE ALSO" -mkqdisk(8), qdisk(5), cman(5) diff --git a/cman/notifyd/Makefile.am b/cman/notifyd/Makefile.am deleted file mode 100644 index 5c80177..0000000 --- a/cman/notifyd/Makefile.am +++ /dev/null @@ -1,41 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -sbin_PROGRAMS = cmannotifyd - -notifyscript = cman_notify - -sbin_SCRIPTS = $(notifyscript) - -EXTRA_DIST = $(notifyscript).in - -cmannotifyd_SOURCES = main.c - -cmannotifyd_CPPFLAGS = -D_GNU_SOURCE \ - -I$(top_srcdir)/common/liblogthread/ \ - -I$(top_srcdir)/config/libs/libccsconfdb/ \ - $(cfg_CFLAGS) \ - $(quorum_CFLAGS) \ - $(confdb_CFLAGS) - - -cmannotifyd_LDADD = $(top_builddir)/common/liblogthread/liblogthread.la \ - $(top_builddir)/config/libs/libccsconfdb/libccs.la \ - $(cfg_LIBS) \ - $(quorum_LIBS) \ - $(confdb_LIBS) - -$(notifyscript): $(notifyscript).in - cat $^ | sed \ - -e 's#_NOTIFYDDIR_#${NOTIFYDDIR}#g' \ - -e 's#_LOGDIR_#${LOGDIR}#g' \ - > $@ - chmod a+x $@ - -install-exec-local: - $(INSTALL) -d $(DESTDIR)/$(NOTIFYDDIR) - -uninstall-local: - rmdir $(DESTDIR)/$(NOTIFYDDIR) || :; - -clean-generic: - rm -f $(notifyscript) diff --git a/cman/notifyd/cman_notify.in b/cman/notifyd/cman_notify.in deleted file mode 100644 index 447657b..0000000 --- a/cman/notifyd/cman_notify.in +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -# concept from Debian run-parts and similar from fedora crontabs - -# keep going when something fails -set +e - -if [ ! -d "_NOTIFYDDIR_" ]; then - exit 0 -fi - -LOGFILE="_LOGDIR_/cman_notify.log" - -if [ "$CMAN_NOTIFICATION_DEBUG" = "1" ]; then - OUT="$LOGFILE" -fi - -# Ignore *~ and *, scripts -for i in $(LC_ALL=C; echo _NOTIFYDDIR_/*[^~,]); do - [ -d $i ] && continue - # skip know scripts - [ "${i%.cfsaved}" != "${i}" ] && continue - [ "${i%.rpmsave}" != "${i}" ] && continue - [ "${i%.rpmorig}" != "${i}" ] && continue - [ "${i%.rpmnew}" != "${i}" ] && continue - [ "${i%.swp}" != "${i}" ] && continue - [ "${i%,v}" != "${i}" ] && continue - [ "${i%.dpkg-old}" != "${i}" ] && continue - [ "${i%.dpkg-dist}" != "${i}" ] && continue - [ "${i%.dpkg-new}" != "${i}" ] && continue - - if [ -x $i ]; then - echo "starting $(basename $i)" >> $LOGFILE - [ -n "$OUT" ] && $i >> $OUT - [ -z "$OUT" ] && $i > /dev/null 2>&1 - echo "finished $(basename $i)" >> $LOGFILE - fi -done - -exit 0 diff --git a/cman/notifyd/main.c b/cman/notifyd/main.c deleted file mode 100644 index 0668e59..0000000 --- a/cman/notifyd/main.c +++ /dev/null @@ -1,506 +0,0 @@ -#include "clusterautoconfig.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <signal.h> -#include <errno.h> -#include <limits.h> -#include <sched.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/select.h> - -#include <corosync/cfg.h> -#include <corosync/quorum.h> -#include <corosync/confdb.h> -#include "liblogthread.h" -#include "ccs.h" - -#include "copyright.cf" - -int debug = 0; -int daemonize = 1; -int daemon_quit = 0; -int rr = 0; - - -#define LOCKFILE_NAME CLUSTERVARRUN "/cmannotifyd.pid" - -#define OPTION_STRING "hdfVr" - -#ifndef MAX_ARGS -#define MAX_ARGS 128 -#endif - -static corosync_cfg_handle_t cfg_handle; -static quorum_handle_t quorum_handle; -static confdb_handle_t confdb_handle; - -static void corosync_cfg_shutdown_callback ( - corosync_cfg_handle_t cfg_handle, - corosync_cfg_shutdown_flags_t flags); - -static void quorum_notification_callback ( - quorum_handle_t handle, - uint32_t quorate, - uint64_t ring_seq, - uint32_t view_list_entries, - uint32_t *view_list); - -static void confdb_reload_callback ( - confdb_handle_t handle, - confdb_reload_type_t type); - - -static corosync_cfg_callbacks_t cfg_callbacks = -{ - .corosync_cfg_state_track_callback = NULL, - .corosync_cfg_shutdown_callback = corosync_cfg_shutdown_callback -}; - -static quorum_callbacks_t quorum_callbacks = -{ - .quorum_notify_fn = quorum_notification_callback -}; - -static confdb_callbacks_t confdb_callbacks = -{ - .confdb_reload_notify_fn = confdb_reload_callback -}; - - - -static void print_usage(void) -{ - printf("Usage:\n\n"); - printf("cmannotifyd [options]\n\n"); - printf("Options:\n\n"); - printf(" -f Do not fork in background\n"); - printf(" -d Enable debugging output\n"); - printf(" -r Run Real Time priority\n"); - printf(" -h This help\n"); - printf(" -V Print program version information\n"); - return; -} - -static void read_arguments(int argc, char **argv) -{ - int cont = 1; - int optchar; - - while (cont) { - optchar = getopt(argc, argv, OPTION_STRING); - - switch (optchar) { - - case 'd': - debug = 1; - break; - - case 'f': - daemonize = 0; - break; - - case 'r': - rr = 1; - break; - - case 'h': - print_usage(); - exit(EXIT_SUCCESS); - break; - - case 'V': - printf("cmannotifyd %s (built %s %s)\n%s\n", - PACKAGE_VERSION, __DATE__, __TIME__, - REDHAT_COPYRIGHT); - exit(EXIT_SUCCESS); - break; - - case EOF: - cont = 0; - break; - - default: - fprintf(stderr, "unknown option: %c\n", optchar); - print_usage(); - exit(EXIT_FAILURE); - break; - - } - - } - - if (getenv("CMANNOTIFYD_DEBUG")) - debug = 1; - -} - -static void remove_lockfile(void) -{ - unlink(LOCKFILE_NAME); -} - -static void lockfile(void) -{ - int fd, error; - struct flock lock; - char buf[128]; - - memset(buf, 0, 128); - - fd = open(LOCKFILE_NAME, O_CREAT | O_WRONLY, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (fd < 0) { - fprintf(stderr, "cannot open/create lock file %s\n", - LOCKFILE_NAME); - exit(EXIT_FAILURE); - } - - lock.l_type = F_WRLCK; - lock.l_start = 0; - lock.l_whence = SEEK_SET; - lock.l_len = 0; - - error = fcntl(fd, F_SETLK, &lock); - if (error) { - fprintf(stderr, "cmannotifyd is already running\n"); - exit(EXIT_FAILURE); - } - - error = ftruncate(fd, 0); - if (error) { - fprintf(stderr, "cannot clear lock file %s\n", LOCKFILE_NAME); - exit(EXIT_FAILURE); - } - - sprintf(buf, "%d\n", getpid()); - - error = write(fd, buf, strlen(buf)); - if (error <= 0) { - fprintf(stderr, "cannot write lock file %s\n", LOCKFILE_NAME); - exit(EXIT_FAILURE); - } - - atexit(remove_lockfile); -} - -static void sigterm_handler(int sig) -{ - daemon_quit = 1; -} - -static void set_oom_adj(int val) -{ - FILE *fp; - - fp = fopen("/proc/self/oom_adj", "w"); - if (!fp) - return; - - fprintf(fp, "%i", val); - fclose(fp); -} - -static void set_scheduler(void) -{ - struct sched_param sched_param; - int rv; - - rv = sched_get_priority_max(SCHED_RR); - if (rv != -1) { - sched_param.sched_priority = rv; - rv = sched_setscheduler(0, SCHED_RR, &sched_param); - if (rv == -1) - logt_print(LOG_WARNING, - "could not set SCHED_RR priority %d err %d", - sched_param.sched_priority, errno); - } else { - logt_print(LOG_WARNING, - "could not get maximum scheduler priority err %d", - errno); - } -} - -static void init_logging(int reconf) -{ - int ccs_handle; - int mode = LOG_MODE_OUTPUT_FILE | LOG_MODE_OUTPUT_SYSLOG; - int syslog_facility = SYSLOGFACILITY; - int syslog_priority = SYSLOGLEVEL; - char logfile[PATH_MAX]; - int logfile_priority = SYSLOGLEVEL; - - memset(logfile, 0, PATH_MAX); - sprintf(logfile, LOGDIR "/cmannotifyd.log"); - - ccs_handle = ccs_connect(); - if (ccs_handle > 0) { - ccs_read_logging(ccs_handle, "cmannotifyd", &debug, &mode, - &syslog_facility, &syslog_priority, &logfile_priority, logfile); - ccs_disconnect(ccs_handle); - } - - if (!daemonize) - mode |= LOG_MODE_OUTPUT_STDERR; - - if (!reconf) - logt_init("cmannotifyd", mode, syslog_facility, syslog_priority, logfile_priority, logfile); - else - logt_conf("cmannotifyd", mode, syslog_facility, syslog_priority, logfile_priority, logfile); -} - -static void dispatch_notification(const char *str, uint32_t quorum) -{ - char *envp[MAX_ARGS]; - char *argv[MAX_ARGS]; - int envptr = 0; - int argvptr = 0; - char scratch[PATH_MAX]; - pid_t notify_pid; - int pidstatus; - int err = 0; - - if (!str) - return; - - /* pass notification type */ - snprintf(scratch, sizeof(scratch), "CMAN_NOTIFICATION=%s", str); - envp[envptr++] = strdup(scratch); - - if (quorum) { - snprintf(scratch, sizeof(scratch), "CMAN_NOTIFICATION_QUORUM=%d", quorum); - envp[envptr++] = strdup(scratch); - } - - if (debug) - envp[envptr++] = strdup("CMAN_NOTIFICATION_DEBUG=1"); - - envp[envptr--] = NULL; - - argv[argvptr++] = strdup("cman_notify"); - - argv[argvptr--] = NULL; - - switch ( (notify_pid = fork()) ) - { - case -1: - /* unable to fork */ - err = 1; - goto out; - break; - - case 0: /* child */ - execve(SBINDIR "/cman_notify", argv, envp); - /* unable to execute cman_notify */ - err = 1; - goto out; - break; - - default: /* parent */ - waitpid(notify_pid, &pidstatus, 0); - break; - } - -out: - while(envptr >= 0) { - if (envp[envptr]) - free(envp[envptr]); - - envptr--; - } - while(argvptr >= 0) { - if (argv[argvptr]) - free(argv[argvptr]); - - argvptr--; - } - if (err) - exit(EXIT_FAILURE); -} - -static void corosync_cfg_shutdown_callback(corosync_cfg_handle_t handle, - corosync_cfg_shutdown_flags_t flags) -{ - logt_print(LOG_DEBUG, "Received a CFG shutdown request\n"); - - corosync_cfg_replyto_shutdown(handle, COROSYNC_CFG_SHUTDOWN_FLAG_YES); - - dispatch_notification("CMAN_REASON_TRY_SHUTDOWN", 0); -} - - -static void quorum_notification_callback(quorum_handle_t handle, - uint32_t quorate, - uint64_t ring_seq, - uint32_t view_list_entries, - uint32_t *view_list) -{ - logt_print(LOG_DEBUG, - "Received a quorum notification\n"); - dispatch_notification("CMAN_REASON_STATECHANGE", quorate); -} - -static void confdb_reload_callback ( - confdb_handle_t handle, - confdb_reload_type_t type) -{ - logt_print(LOG_DEBUG, - "Received a config reload notification, type=%d\n", type); - dispatch_notification("CMAN_REASON_CONFIG_UPDATE", 0); -} - -static void byebye_corosync(void) -{ - if (cfg_handle) - { - corosync_cfg_finalize(cfg_handle); - cfg_handle = 0LL; - } - if (quorum_handle) - { - quorum_finalize(quorum_handle); - quorum_handle = 0LL; - } - if (confdb_handle) - { - confdb_finalize(confdb_handle); - confdb_handle = 0LL; - } -} - -static void setup_corosync(int forever) -{ - int init = 0; - cs_error_t cs_err; - -retry_init: - - if (!cfg_handle) { - cs_err = corosync_cfg_initialize(&cfg_handle, &cfg_callbacks); - if (cs_err != CS_OK) - goto init_fail; - } - - if (!quorum_handle) { - cs_err = quorum_initialize(&quorum_handle, &quorum_callbacks); - if (cs_err != CS_OK) - goto init_fail; - cs_err = quorum_trackstart(quorum_handle, CS_TRACK_CHANGES); - } - - if (!confdb_handle) { - cs_err = confdb_initialize(&confdb_handle, &confdb_callbacks); - if (cs_err != CS_OK) - goto init_fail; - cs_err = confdb_track_changes(confdb_handle, OBJECT_PARENT_HANDLE, CONFDB_TRACK_DEPTH_ONE); - } - goto out_ok; - -init_fail: - if ((init++ < 5) || (forever)) { - if (daemon_quit) - goto out; - - sleep(1); - goto retry_init; - } - logt_print(LOG_CRIT, "corosync_init error %d\n", errno); - exit(EXIT_FAILURE); - -out: - byebye_corosync(); -out_ok: - return; -} - -static void loop(void) -{ - cs_error_t cs_result; - int select_result; - fd_set read_fds; - int cfg_fd; - int quorum_fd; - int confdb_fd; - - do { - FD_ZERO (&read_fds); - corosync_cfg_fd_get(cfg_handle, &cfg_fd); - confdb_fd_get(confdb_handle, &confdb_fd); - quorum_fd_get(quorum_handle, &quorum_fd); - FD_SET (cfg_fd, &read_fds); - FD_SET (confdb_fd, &read_fds); - FD_SET (quorum_fd, &read_fds); - select_result = select(FD_SETSIZE, &read_fds, 0, 0, 0); - - if (daemon_quit) - goto out; - - if (select_result == -1) { - logt_print(LOG_CRIT, "Unable to select on corosync fds: %s\n", strerror(errno)); - byebye_corosync(); - logt_print(LOG_DEBUG, "waiting for corosync to reappear..\n"); - setup_corosync(1); - logt_print(LOG_DEBUG, "corosync is back..\n"); - } - - if (FD_ISSET(cfg_fd, &read_fds)) { - cs_result = corosync_cfg_dispatch(cfg_handle, CS_DISPATCH_ONE); - if (cs_result != CS_OK) { - byebye_corosync(); - logt_print(LOG_DEBUG, "waiting for corosync to reappear..\n"); - setup_corosync(1); - logt_print(LOG_DEBUG, "corosync is back..\n"); - } - } - if (FD_ISSET(confdb_fd, &read_fds)) { - cs_result = confdb_dispatch(confdb_handle, CS_DISPATCH_ONE); - if (cs_result != CS_OK) { - byebye_corosync(); - logt_print(LOG_DEBUG, "waiting for corosync to reappear..\n"); - setup_corosync(1); - logt_print(LOG_DEBUG, "corosync is back..\n"); - } - } - if (FD_ISSET(quorum_fd, &read_fds)) { - cs_result = quorum_dispatch(quorum_handle, CS_DISPATCH_ONE); - if (cs_result != CS_OK) { - byebye_corosync(); - logt_print(LOG_DEBUG, "waiting for corosync to reappear..\n"); - setup_corosync(1); - logt_print(LOG_DEBUG, "corosync is back..\n"); - } - } - } while (select_result && !daemon_quit); - -out: - logt_print(LOG_DEBUG, "shutting down...\n"); - byebye_corosync(); -} - -int main(int argc, char **argv) -{ - - read_arguments(argc, argv); - if (daemonize) { - if (daemon(0, 0) < 0) { - perror("Unable to daemonize"); - exit(EXIT_FAILURE); - } - } - lockfile(); - init_logging(0); - signal(SIGTERM, sigterm_handler); - set_oom_adj(-16); - if (rr) - set_scheduler(); - - setup_corosync(0); - loop(); - - return 0; -} diff --git a/cman/qdisk/Makefile.am b/cman/qdisk/Makefile.am deleted file mode 100644 index 3ba8d98..0000000 --- a/cman/qdisk/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -D_GNU_SOURCE \ - -I$(top_srcdir)/common/liblogthread/ \ - -I$(top_srcdir)/config/libs/libccsconfdb/ \ - -I$(top_srcdir)/cman/services/cman/lib/ - -AM_LDFLAGS = -lpthread -lz -lrt - -sbin_PROGRAMS = qdiskd mkqdisk - -noinst_HEADERS = disk.h iostate.h platform.h scandisk.h score.h - -shared_SOURCES = disk.c disk_util.c proc.c scandisk.c iostate.c - -qdiskd_SOURCES = main.c score.c bitmap.c daemon_init.c \ - $(shared_SOURCES) - -mkqdisk_SOURCES = mkqdisk.c \ - $(shared_SOURCES) - -shared_LDADD = $(top_builddir)/common/liblogthread/liblogthread.la - -qdiskd_LDADD = $(top_builddir)/config/libs/libccsconfdb/libccs.la \ - $(top_builddir)/cman/services/cman/lib/libcman.la \ - $(shared_LDADD) - -mkqdisk_LDADD = $(shared_LDADD) diff --git a/cman/qdisk/bitmap.c b/cman/qdisk/bitmap.c deleted file mode 100644 index d893c98..0000000 --- a/cman/qdisk/bitmap.c +++ /dev/null @@ -1,93 +0,0 @@ -/** @file - * Bitmap and membership mask handling routines. - */ -#include "clusterautoconfig.h" - -#include <stdint.h> - -int clear_bit(uint8_t *mask, uint32_t bitidx, uint32_t masklen); -int set_bit(uint8_t *mask, uint32_t bitidx, uint32_t masklen); -int is_bit_set(uint8_t *mask, uint32_t bitidx, uint32_t masklen); - -/** - * Clear a bit in a bitmap / bitmask. - * - * @param mask Bitmask to modify. - * @param bitidx Bit to modify. - * @param masklen Bitmask length (in uint8_t units) - * @return -1 if the index exceeds the number of bits in the - * bitmap, otherwise 0. - */ -int -clear_bit(uint8_t *mask, uint32_t bitidx, uint32_t masklen) -{ - uint32_t idx; - uint32_t bit; - - /* Index into array */ - idx = bitidx >> 3; - bit = 1 << (bitidx & 0x7); - - if (idx >= masklen) - return -1; - - mask[idx] &= ~bit; - - return 0; -} - - -/** - * Set a bit in a bitmap / bitmask. - * - * @param mask Bitmask to modify. - * @param bitidx Bit to modify. - * @param masklen Bitmask length (in uint8_t units). - * @return -1 if the index exceeds the number of bits in the - * bitmap, otherwise 0. - */ -int -set_bit(uint8_t *mask, uint32_t bitidx, uint32_t masklen) -{ - uint32_t idx; - uint32_t bit; - - /* Index into array */ - idx = bitidx >> 3; - bit = 1 << (bitidx & 0x7); - - if (idx >= masklen) - return -1; - - mask[idx] |= bit; - - return 0; -} - - -/** - * Check the status of a bit in a bitmap / bitmask. - * - * @param mask Bitmask to check. - * @param bitidx Bit to to check. - * @param masklen Bitmask length (in uint8_t units). - * @return -1 if the index exceeds the number of bits in the - * bitmap, 0 if not set, or 1 if set. - */ -int -is_bit_set(uint8_t *mask, uint32_t bitidx, uint32_t masklen) -{ - uint32_t idx; - uint32_t bit; - - /* Index into array */ - idx = bitidx >> 3; - bit = 1 << (bitidx & 0x7); - - if (idx >= masklen) - return -1; - - return !!(mask[idx]&bit); -} - - diff --git a/cman/qdisk/daemon_init.c b/cman/qdisk/daemon_init.c deleted file mode 100644 index 1b71738..0000000 --- a/cman/qdisk/daemon_init.c +++ /dev/null @@ -1,239 +0,0 @@ -/** @file - * daemon_init function, does sanity checks and calls daemon(). - * - * Author: Jeff Moyer jmoyer@redhat.com - */ -/* - * TODO: Clean this up so that only one function constructs the - * pidfile /var/run/loggerd.PID, and perhaps only one function - * forms the /proc/PID/ path. - * - * Also need to add file locking for the pid file. - */ - -#include "clusterautoconfig.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/param.h> -#include <fcntl.h> -#include <dirent.h> -#include <sys/mman.h> -#include <sys/errno.h> -#include <libgen.h> -#include <signal.h> -#include <liblogthread.h> - -/* - * This should ultimately go in a header file. - */ -void daemon_init(char *prog); -void daemon_cleanup(void); -int check_process_running(char *prog, pid_t * pid); - -/* - * Local prototypes. - */ -static void update_pidfile(char *prog); -static int setup_sigmask(void); -static char pid_filename[PATH_MAX]; - -static int -check_pid_valid(pid_t pid, char *prog) -{ - FILE *fp; - DIR *dir; - char filename[PATH_MAX]; - char dirpath[PATH_MAX]; - char proc_cmdline[64]; /* yank this from kernel somewhere */ - char *s = NULL; - - memset(filename, 0, PATH_MAX); - memset(dirpath, 0, PATH_MAX); - - snprintf(dirpath, sizeof (dirpath), "/proc/%d", pid); - if ((dir = opendir(dirpath)) == NULL) { - closedir(dir); - return 0; /* Pid has gone away. */ - } - closedir(dir); - - /* - * proc-pid directory exists. Now check to see if this - * PID corresponds to the daemon we want to start. - */ - snprintf(filename, sizeof (filename), "/proc/%d/cmdline", pid); - fp = fopen(filename, "r"); - if (fp == NULL) { - perror("check_pid_valid"); - return 0; /* Who cares.... Let's boogy on. */ - } - - if (!fgets(proc_cmdline, sizeof (proc_cmdline) - 1, fp)) { - /* - * Okay, we've seen processes keep a reference to a - * /proc/PID/stat file and not let go. Then when - * you try to read /proc/PID/cmline, you get either - * \000 or -1. In either case, we can safely assume - * the process has gone away. - */ - fclose(fp); - return 0; - } - fclose(fp); - - s = &(proc_cmdline[strlen(proc_cmdline)]); - if (*s == '\n') - *s = 0; - - /* - * Check to see if this is the same executable. - */ - if ((s = strstr(proc_cmdline, prog)) == NULL) { - return 0; - } else { - return 1; - } -} - - -int -check_process_running(char *prog, pid_t * pid) -{ - pid_t oldpid; - FILE *fp; - char filename[PATH_MAX]; - char *cmd; - int ret; - struct stat st; - - *pid = -1; - - /* - * Now see if there is a pidfile associated with this cmd in /var/run - */ - fp = NULL; - memset(filename, 0, PATH_MAX); - - cmd = basename(prog); - snprintf(filename, sizeof (filename), CLUSTERVARRUN "/%s.pid", cmd); - - ret = stat(filename, &st); - if ((ret < 0) || (!st.st_size)) - return 0; - - /* - * Read the pid from the file. - */ - fp = fopen(filename, "r"); - if (fp == NULL) { /* error */ - return 0; - } - - ret = fscanf(fp, "%d\n", &oldpid); - fclose(fp); - - if ((ret == EOF) || (ret != 1)) - return 0; - - if (check_pid_valid(oldpid, cmd)) { - *pid = oldpid; - return 1; - } - return 0; -} - - -static void -update_pidfile(char *prog) -{ - FILE *fp = NULL; - char *cmd; - - memset(pid_filename, 0, PATH_MAX); - - cmd = basename(prog); - snprintf(pid_filename, sizeof (pid_filename), "/var/run/%s.pid", cmd); - - fp = fopen(pid_filename, "w"); - if (fp == NULL) { - exit(1); - } - - fprintf(fp, "%d", getpid()); - fclose(fp); -} - - -static int -setup_sigmask(void) -{ - sigset_t set; - - sigfillset(&set); - - /* - * Dont't block signals which would cause us to dump core. - */ - sigdelset(&set, SIGQUIT); - sigdelset(&set, SIGILL); - sigdelset(&set, SIGTRAP); - sigdelset(&set, SIGABRT); - sigdelset(&set, SIGFPE); - sigdelset(&set, SIGSEGV); - sigdelset(&set, SIGBUS); - - /* - * Don't block SIGTERM or SIGCHLD - */ - sigdelset(&set, SIGTERM); - sigdelset(&set, SIGCHLD); - - return (sigprocmask(SIG_BLOCK, &set, NULL)); -} - - -void -daemon_init(char *prog) -{ - uid_t uid; - pid_t pid; - - uid = getuid(); - if (uid) { - logt_print(LOG_ERR, - "daemon_init: Sorry, only root wants to run this.\n"); - exit(1); - } - - if (check_process_running(prog, &pid) && (pid != getpid())) { - logt_print(LOG_ERR, - "daemon_init: Process "%s" already running.\n", - prog); - exit(1); - } - if (setup_sigmask() < 0) { - logt_print(LOG_ERR, "daemon_init: Unable to set signal mask.\n"); - exit(1); - } - - if(daemon(0, 0)) { - logt_print(LOG_ERR, "daemon_init: Unable to daemonize.\n"); - exit(1); - } - - - update_pidfile(prog); -} - - -void -daemon_cleanup(void) -{ - if (strlen(pid_filename)) - unlink(pid_filename); -} diff --git a/cman/qdisk/disk.c b/cman/qdisk/disk.c deleted file mode 100644 index 8e9bb4b..0000000 --- a/cman/qdisk/disk.c +++ /dev/null @@ -1,792 +0,0 @@ -/** @file - * Single-block Raw/Direct I/O Functions - */ -/* - * author: Tim Burke <tburke at redhat.com> - * description: Raw IO Interfaces. - * - * The RAW IO code we are using from 2.2.13 requires user buffers and - * disk offsets to be 512 byte aligned. So this code consists of a - * read and write routine which check to see if the user buffer is - * aligned. If it isn't a temporary aligned buffer is allocated, a data - * copy is performed along with the IO operation itself. - */ - -#include "clusterautoconfig.h" - -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/ioctl.h> -#include <string.h> -#include <errno.h> -#include <disk.h> -#include <platform.h> -#include <unistd.h> -#include <time.h> -#include <linux/fs.h> -#include <liblogthread.h> -#include <zlib.h> -#include "iostate.h" - -static int diskRawRead(target_info_t *disk, char *buf, int len); - -/** - * Calculate CRC32 of a data set. - * - * @param data Data set for building CRC32 - * @param count Size of data set, in bytes. - * @return CRC32 of data set. - */ -static uint32_t clu_crc32(const char *data, size_t count) -{ - return (uint32_t)crc32(0L, (const Bytef *)data, (uInt)count); -} - - -/** - * Swap the bytes of a shared header so that it's always in big-endian form - * when stored on disk. - * - * @param hdr Header to encode. - */ -static void -header_encode(shared_header_t *hdr) -{ - /* sanity check - LE machine -> already encoded. */ - if (hdr->h_magic == le_swap32(SHARED_HEADER_MAGIC)) - return; - - hdr->h_magic = le_swap32(hdr->h_magic); - hdr->h_hcrc = le_swap32(hdr->h_hcrc); - hdr->h_dcrc = le_swap32(hdr->h_dcrc); - hdr->h_length = le_swap32(hdr->h_length); - hdr->h_view = le_swap64(hdr->h_view); - hdr->h_timestamp = le_swap64(hdr->h_timestamp); -} - - -/** - * Swap the bytes of a shared header so that it's always in host-byte order - * after we read it. This should be a macro calling header_encode. - * - * @param hdr Header to decode. - */ -static void -header_decode(shared_header_t *hdr) -{ - /* sanity check - LE machine -> already decoded. */ - if (hdr->h_magic == SHARED_HEADER_MAGIC) - return; - - hdr->h_magic = le_swap32(hdr->h_magic); - hdr->h_hcrc = le_swap32(hdr->h_hcrc); - hdr->h_dcrc = le_swap32(hdr->h_dcrc); - hdr->h_length = le_swap32(hdr->h_length); - hdr->h_view = le_swap64(hdr->h_view); - hdr->h_timestamp = le_swap64(hdr->h_timestamp); -} - - -/** - * Generate a shared header suitable for storing data. This includes: - * header magic, header crc, data crc, header length, timestamp. - * The header CRC is generated *after* the data CRC; so the header, - * in effect, ensures that the data CRC is valid before we even look - * at the data. Thus, if the header CRC decodes properly, then we - * assume that there's a very very high chance that the data CRC is valid. - * If the data CRC doesn't match the data, it's indicative of a problem. - * - * @param hdr Preallocated pointer to shared_header_t structure. - * @param data Data to be stored with hdr. - * @param count Size of data. - * @return -1 if CRC32 generation fails, or 0 on success. - */ -static int -header_generate(shared_header_t *hdr, const char *data, size_t count) -{ - memset(hdr,0,sizeof(*hdr)); - - hdr->h_magic = SHARED_HEADER_MAGIC; - - if (data && count) { - hdr->h_dcrc = clu_crc32(data, count); - hdr->h_length = (uint32_t)count; - - if (hdr->h_dcrc == 0) { - logt_print(LOG_ERR, "Invalid CRC32 generated on data!\n"); - return -1; - } - } - - hdr->h_timestamp = (uint64_t)time(NULL); - header_encode(hdr); - hdr->h_hcrc = 0; - hdr->h_hcrc = le_swap32(clu_crc32((char *)hdr, sizeof(*hdr))); - - if (hdr->h_hcrc == 0) { - logt_print(LOG_ERR, "Invalid CRC32 generated on header!\n"); - return -1; - } - - return 0; -} - - -/** - * Verify the integrity of a shared header. Basically, check the CRC32 - * information against the data and header. A better name for this would - * be "shared_block_verify". - * - * @param hdr Preallocated pointer to shared_header_t structure. - * @param data Data to be stored with hdr. - * @param count Size of data. - * @return -1 if CRC32 generation fails, or 0 on success. - */ -static int -header_verify(shared_header_t *hdr, const char *data, size_t count) -{ - uint32_t crc; - uint32_t bkupcrc; - - /* - * verify the header's CRC32. Ok, we know it's overkill taking - * the CRC32 of a friggin' 16-byte (12 bytes, really) structure, - * but why not? - */ - bkupcrc = hdr->h_hcrc; - - /* BUG: Headers are stored in little-endian form */ - bkupcrc = le_swap32(hdr->h_hcrc); - - hdr->h_hcrc = 0; - crc = clu_crc32((char *)hdr, sizeof(*hdr)); - hdr->h_hcrc = bkupcrc; - if (bkupcrc != crc) { - logt_print(LOG_DEBUG, "Header CRC32 mismatch; Exp: 0x%08x " - "Got: 0x%08x\n", bkupcrc, crc); - return -1; - } - - header_decode(hdr); - - /* - * Verify the magic number. - */ - if (hdr->h_magic != SHARED_HEADER_MAGIC) { - logt_print(LOG_DEBUG, "Magic mismatch; Exp: 0x%08x " - "Got: 0x%08x\n", SHARED_HEADER_MAGIC, hdr->h_magic); - return -1; - } - - /* - * If there's no data or no count, or perhaps the length fed in is less - * then the expected length, bail. - */ - if (!data || !count || (count < hdr->h_length)) - return 0; - - crc = clu_crc32(data, (count > hdr->h_length) ? - hdr->h_length : count); - - if (hdr->h_dcrc != crc) { - logt_print(LOG_DEBUG, "Data CRC32 mismatch; Exp: 0x%08x " - "Got: 0x%08x\n", hdr->h_dcrc, crc); - return -1; - } - - return 0; -} - - - -/* - * qdisk_open - * Called to open the shared state partition with appropriate mode. - * Returns - (the file descriptor), a value >= 0 on success. - */ -int -qdisk_open(char *name, target_info_t *disk) -{ - int ret; - int ssz; - - /* - * Open for synchronous writes to insure all writes go directly - * to disk. - */ - disk->d_fd = open(name, O_RDWR | O_SYNC | O_DIRECT); - if (disk->d_fd < 0) - return disk->d_fd; - - ret = ioctl(disk->d_fd, BLKSSZGET, &ssz); - if (ret < 0) { - logt_print(LOG_ERR, "qdisk_open: ioctl(BLKSSZGET)"); - close(disk->d_fd); - return -1; - } - - disk->d_blksz = ssz; - disk->d_pagesz = sysconf(_SC_PAGESIZE); - - /* Check to verify that the partition is large enough.*/ - io_state(STATE_LSEEK); - ret = lseek(disk->d_fd, END_OF_DISK(disk->d_blksz), SEEK_SET); - io_state(STATE_NONE); - if (ret < 0) { - logt_print(LOG_DEBUG, "open_partition: seek"); - close(disk->d_fd); - return -1; - } - - if (ret < END_OF_DISK(disk->d_blksz)) { - logt_print(LOG_ERR, "Partition %s too small\n", name); - errno = EINVAL; - close(disk->d_fd); - return -1; - } - - /* Set close-on-exec bit */ - ret = fcntl(disk->d_fd, F_GETFD, 0); - if (ret < 0) { - logt_print(LOG_ERR, "open_partition: fcntl(F_GETFD)"); - close(disk->d_fd); - return -1; - } - - ret |= FD_CLOEXEC; - if (fcntl(disk->d_fd, F_SETFD, ret) < 0) { - logt_print(LOG_ERR, "open_partition: fcntl(F_SETFD)"); - close(disk->d_fd); - return -1; - } - - return 0; -} - - -/* - * qdisk_close - * Closes the shared state disk partition. - * Returns - value from close syscall. - */ -int -qdisk_close(target_info_t *disk) -{ - int retval; - - if (!disk || disk->d_fd < 0) { - errno = EINVAL; - return -1; - } - - retval = close(disk->d_fd); - disk->d_fd = -1; - - return retval; -} - -/* - * qdisk_validate - * Called to verify that the specified device special file representing - * the partition appears to be a valid device. - * Returns: 0 - success, 1 - failure - */ -int -qdisk_validate(char *name) -{ - struct stat stat_st, *stat_ptr; - target_info_t disk; - stat_ptr = &stat_st; - - if (stat(name, stat_ptr) < 0) { - logt_print(LOG_ERR, "stat"); - return -1; - } - /* - * Verify that its a block or character special file. - */ - if (S_ISCHR(stat_st.st_mode) == 0 && S_ISBLK(stat_st.st_mode) == 0) { -/* - errno = EINVAL; - return -1; -*/ - logt_print(LOG_WARNING, "Warning: %s is not a block device\n", - name); - } - - /* - * Verify read/write permission. - */ - if (qdisk_open(name, &disk) < 0) { - logt_print(LOG_DEBUG, "%s: open of %s for RDWR failed: %s\n", - __FUNCTION__, name, strerror(errno)); - return -1; - } - qdisk_close(&disk); - return 0; -} - - -static int -diskRawReadShadow(target_info_t *disk, off_t readOffset, char *buf, int len) -{ - int ret; - shared_header_t *hdrp; - char *data; - - io_state(STATE_LSEEK); - ret = lseek(disk->d_fd, readOffset, SEEK_SET); - io_state(STATE_NONE); - if (ret != readOffset) { - logt_print(LOG_DEBUG, - "diskRawReadShadow: can't seek to offset %d.\n", - (int) readOffset); - errno = ENODATA; - return -1; - } - - ret = diskRawRead(disk, buf, len); - if (ret != len) { - logt_print(LOG_DEBUG, "diskRawReadShadow: aligned read " - "returned %d, not %d.\n", ret, len); - errno = ENODATA; - return -1; - } - - /* Decode the header portion so we can run a checksum on it. */ - hdrp = (shared_header_t *)buf; - data = (char *)buf + sizeof(*hdrp); - - if (header_verify(hdrp, data, len)) { - logt_print(LOG_DEBUG, "diskRawReadShadow: bad CRC32, " - "offset = %d len = %d\n", - (int) readOffset, len); - errno = EPROTO; - return -1; - } - - return 0; -} - - -/* - * The RAW IO implementation requires buffers to be 512 byte aligned. - * Here we check for alignment and do a bounceio if necessary. - */ -static int -diskRawRead(target_info_t *disk, char *buf, int len) -{ - void *alignedBuf; - int readret; - int extraLength; - int readlen; - int bounceNeeded = 1; - - - /* was 3ff, which is (512<<1-1) */ - if ((((unsigned long) buf & - (unsigned long) ((disk->d_blksz << 1) -1)) == 0) && - ((len % (disk->d_blksz)) == 0)) { - bounceNeeded = 0; - } - - if (bounceNeeded == 0) { - /* Already aligned and even multiple of 512, no bounceio - * required. */ - io_state(STATE_READ); - readret = read(disk->d_fd, buf, len); - io_state(STATE_NONE); - return readret; - } - - if (len > disk->d_blksz) { - logt_print(LOG_ERR, - "diskRawRead: not setup for reads larger than %d.\n", - (int)disk->d_blksz); - return (-1); - } - /* - * All IOs must be of size which is a multiple of 512. Here we - * just add in enough extra to accommodate. - * XXX - if the on-disk offsets don't provide enough room we're cooked! - */ - extraLength = 0; - if (len % disk->d_blksz) { - extraLength = disk->d_blksz - (len % disk->d_blksz); - } - - readlen = len; - if (extraLength) { - readlen += extraLength; - } - - readret = posix_memalign((void **)&alignedBuf, disk->d_pagesz, disk->d_blksz); - if (readret < 0) { - return -1; - } - - io_state(STATE_READ); - readret = read(disk->d_fd, alignedBuf, readlen); - io_state(STATE_NONE); - if (readret > 0) { - if (readret > len) { - memcpy(alignedBuf, buf, len); - readret = len; - } else { - memcpy(alignedBuf, buf, readret); - } - } - - free(alignedBuf); - if (readret != len) { - logt_print(LOG_ERR, "diskRawRead: read err, len=%d, readret=%d\n", - len, readret); - } - - return (readret); -} - - -/* - * The RAW IO implementation requires buffers to be 512 byte aligned. - * Here we check for alignment and do a bounceio if necessary. - */ -static int -diskRawWrite(target_info_t *disk, char *buf, int len) -{ - void *alignedBuf; - int ret; - int extraLength; - int writelen; - int bounceNeeded = 1; - - /* was 3ff, which is (512<<1-1) */ - if ((((unsigned long) buf & - (unsigned long) ((disk->d_blksz << 1) -1)) == 0) && - ((len % (disk->d_blksz)) == 0)) { - bounceNeeded = 0; - } - - if (bounceNeeded == 0) { - /* Already aligned and even multiple of 512, no bounceio - * required. */ - io_state(STATE_WRITE); - ret = write(disk->d_fd, buf, len); - io_state(STATE_NONE); - return ret; - } - - if (len > disk->d_blksz) { - logt_print(LOG_ERR, - "diskRawRead: not setup for reads larger than %d.\n", - (int)disk->d_blksz); - return (-1); - } - /* - * All IOs must be of size which is a multiple of 512. Here we - * just add in enough extra to accommodate. - * XXX - if the on-disk offsets don't provide enough room we're cooked! - */ - extraLength = 0; - if (len % disk->d_blksz) { - extraLength = disk->d_blksz - (len % disk->d_blksz); - } - - writelen = len; - if (extraLength) { - writelen += extraLength; - } - - ret = posix_memalign((void **)&alignedBuf, disk->d_pagesz, disk->d_blksz); - if (ret < 0) { - return -1; - } - - if (len > disk->d_blksz) { - logt_print(LOG_ERR, - "diskRawWrite: not setup for larger than %d.\n", - (int)disk->d_blksz); - return (-1); - } - - memcpy(buf, alignedBuf, len); - io_state(STATE_WRITE); - ret = write(disk->d_fd, alignedBuf, writelen); - io_state(STATE_NONE); - if (ret > len) { - ret = len; - } - - free(alignedBuf); - if (ret != len) { - logt_print(LOG_ERR, "diskRawWrite: write err, len=%d, ret=%dn", - len, ret); - } - - return (ret); -} - - -static int -diskRawWriteShadow(target_info_t *disk, __off64_t writeOffset, char *buf, int len) -{ - off_t retval_seek; - ssize_t retval_write; - - if ((writeOffset < 0) || (len < 0)) { - logt_print(LOG_ERR, - "diskRawWriteShadow: writeOffset=%08x, " - "len=%08x.\n", (int)writeOffset, len); - return (-1); - } - - io_state(STATE_LSEEK); - retval_seek = lseek(disk->d_fd, writeOffset, SEEK_SET); - io_state(STATE_NONE); - if (retval_seek != writeOffset) { - logt_print(LOG_ERR, - "diskRawWriteShadow: can't seek to offset %d\n", - (int) writeOffset); - return (-1); - } - - retval_write = diskRawWrite(disk, buf, len); - if (retval_write != len) { - if (retval_write == -1) { - logt_print(LOG_ERR, "%s: %s\n", __FUNCTION__, - strerror(errno)); - } - logt_print(LOG_ERR, - "diskRawWriteShadow: aligned write returned %d" - ", not %d\n", (int)retval_write, (int)len); - return (-1); - } - - return 0; -} - - -int -qdisk_read(target_info_t *disk, __off64_t offset, void *bufin, int count) -{ - shared_header_t *hdrp; - void *ptr; - char *data; - size_t total; - int rv; - char *buf = (char *)bufin; - - /* - * Calculate the total length of the buffer, including the header. - * Raw blocks are 512 byte aligned. - */ - total = count + sizeof(shared_header_t); - if (total < disk->d_blksz) - total = disk->d_blksz; - - /* Round it up */ - if (total % disk->d_blksz) - total = total + (disk->d_blksz * !!(total % disk->d_blksz)) - (total % disk->d_blksz); - - ptr = NULL; - rv = posix_memalign((void **)&ptr, disk->d_pagesz, disk->d_blksz); - if (rv < 0) - return -1; - - if (ptr == NULL) - return -1; - - hdrp = (shared_header_t *)ptr; - data = (char *)hdrp + sizeof(shared_header_t); - - rv = diskRawReadShadow(disk, offset, (char *)hdrp, disk->d_blksz); - - if (rv == -1) { - return -1; - } - - /* Copy out the data */ - memcpy(buf, data, hdrp->h_length); - - /* Zero out the remainder. */ - if (hdrp->h_length < count) { - memset(buf + hdrp->h_length, 0, - count - hdrp->h_length); - } - - free(hdrp); - return count; -} - - -int -qdisk_write(target_info_t *disk, __off64_t offset, const void *buf, int count) -{ - size_t maxsize; - shared_header_t *hdrp; - void *ptr; - char *data; - size_t total = 0, rv = -1, psz = disk->d_blksz; //sysconf(_SC_PAGESIZE); - - maxsize = psz - (sizeof(shared_header_t)); - if (count >= (maxsize + sizeof(shared_header_t))) { - logt_print(LOG_ERR, "error: count %d >= (%d + %d)\n", (int)count, - (int)maxsize, (int)sizeof(shared_header_t)); - errno = ENOSPC; - return -1; - } - - /* - * Calculate the total length of the buffer, including the header. - */ - total = count + sizeof(shared_header_t); - if (total < psz) - total = psz; - - /* Round it up */ - if (total % psz) - total = total + (psz * !!(total % psz)) - (total % psz); - - ptr = NULL; - rv = posix_memalign((void **)&ptr, disk->d_pagesz, total); - if (rv < 0) { - logt_print(LOG_ERR, "posix_memalign"); - return -1; - } - - /* - * Copy the data into our new buffer - */ - hdrp = (shared_header_t *)ptr; - data = (char *)hdrp + sizeof(shared_header_t); - memcpy(data, buf, count); - - if (header_generate(hdrp, buf, count) == -1) { - free((char *)hdrp); - return -1; - } - - /* - * Locking must be performed elsewhere. We make no assumptions - * about locking here. - */ - if (total == psz) - rv = diskRawWriteShadow(disk, offset, (char *)hdrp, psz); - - if (rv == -1) - logt_print(LOG_ERR, "diskRawWriteShadow"); - - free((char *)hdrp); - if (rv == -1) - return -1; - return count; -} - - -static int -header_init(target_info_t *disk, char *label) -{ - quorum_header_t qh; - - if (qdisk_read(disk, OFFSET_HEADER, &qh, sizeof(qh)) == sizeof(qh)) { - swab_quorum_header_t(&qh); - if (qh.qh_magic == HEADER_MAGIC_OLD) { - printf("Warning: Red Hat Cluster Manager 1.2.x " - "header found\n"); - } else if (qh.qh_magic == HEADER_MAGIC_NUMBER) { - printf("Warning: Initializing previously " - "initialized partition\n"); - } - } - - if (gethostname(qh.qh_updatehost, sizeof(qh.qh_updatehost)) < 0) { - logt_print(LOG_ERR, "gethostname"); - return -1; - } - - /* Copy in the cluster/label name */ - snprintf(qh.qh_cluster, sizeof(qh.qh_cluster)-1, "%s", label); - - qh.qh_version = VERSION_MAGIC_V2; - if ((qh.qh_timestamp = (uint64_t)time(NULL)) <= 0) { - logt_print(LOG_ERR, "time"); - return -1; - } - - qh.qh_magic = HEADER_MAGIC_NUMBER; - qh.qh_blksz = disk->d_blksz; - qh.qh_kernsz = 0; - - swab_quorum_header_t(&qh); - if (qdisk_write(disk, OFFSET_HEADER, &qh, sizeof(qh)) != sizeof(qh)) { - return -1; - } - - return 0; -} - - -int -qdisk_init(char *partname, char *label) -{ - target_info_t disk; - status_block_t ps, wps; - int nid, ret; - time_t t; - - ret = qdisk_validate(partname); - if (ret < 0) { - logt_print(LOG_DEBUG, "qdisk_verify"); - return -1; - } - - ret = qdisk_open(partname, &disk); - if (ret < 0) { - logt_print(LOG_ERR, "qdisk_open"); - return -1; - } - - if (header_init(&disk, label) < 0) { - return -1; - } - - time(&t); - - ps.ps_magic = STATE_MAGIC_NUMBER; - ps.ps_updatenode = 0; - ps.pad0 = 0; - ps.ps_timestamp = (uint64_t)t; - ps.ps_state = (uint8_t)S_NONE; - ps.pad1[0] = 0; - ps.ps_flags = 0; - ps.ps_score = 0; - ps.ps_scoremax = 0; - ps.ps_ca_sec = 0; - ps.ps_ca_usec = 0; - ps.ps_lc_sec = 0; - ps.ps_ca_usec = 0; - - /* Node IDs 1..N */ - for (nid = 1; nid <= MAX_NODES_DISK; nid++) { - ps.ps_nodeid = nid; - - printf("Initializing status block for node %d...\n", nid); - wps = ps; - swab_status_block_t(&wps); - - if (qdisk_write(&disk, qdisk_nodeid_offset(nid, disk.d_blksz), &wps, sizeof(wps)) < 0) { - printf("Error writing node ID block %d\n", nid); - qdisk_close(&disk); - return -1; - } - } - - qdisk_close(&disk); - - return 0; -} - diff --git a/cman/qdisk/disk.h b/cman/qdisk/disk.h deleted file mode 100644 index b00c580..0000000 --- a/cman/qdisk/disk.h +++ /dev/null @@ -1,285 +0,0 @@ -/** - @file Main quorum daemon include file - */ -#ifndef _QUORUM_DISK_H -#define _QUORUM_DISK_H - -#include <stdint.h> -#include <pthread.h> -#include <arpa/inet.h> -#include <libcman.h> - -#define MAX_NODES_DISK 16 -#define MEMB_MASK_LEN ((MAX_NODES_DISK / 8) + \ - (!!(MAX_NODES_DISK % 8))) -#define DISK_MEMB_MASK_LEN ((MEMB_MASK_LEN + 7) & ~7) - -/** The membership bitmask type */ -typedef uint8_t memb_mask_t [DISK_MEMB_MASK_LEN]; - -typedef enum { - S_NONE = 0x0, // Shutdown / not quorate / not running - S_EVICT = 0x1, // Voted out / about to be fenced. - /* ^^^ Fencing OK */ - S_INIT = 0x2, // Initializing. Hold your fire. - /* vvv Fencing will kill a node */ - S_RUN = 0x5, // I think I'm running. - S_MASTER= 0x6 // I know I'm running, and have advertised to - // CMAN the availability of the disk vote for my - // partition. -} disk_node_state_t; - - -typedef enum { - M_NONE = 0x0, - M_BID = 0x1, - M_ACK = 0x2, - M_NACK = 0x3, - M_MASK = 0x4 -} disk_msg_id_t; - - -typedef enum { - FL_MSG = 0x1, - FL_BID = 0x2, - FL_VOTE = 0x4 -} disk_state_flag_t; - - -typedef enum { - RF_REBOOT = 0x1, /* Reboot if we go from master->none */ - RF_STOP_CMAN = 0x2, - RF_DEBUG = 0x4, - RF_PARANOID = 0x8, - RF_ALLOW_KILL = 0x10, - RF_UPTIME = 0x20, - RF_CMAN_LABEL = 0x40, - RF_IOTIMEOUT = 0x80 -} run_flag_t; - - -/* RHEL 2.1 / RHCS3 old magic numbers */ -#define HEADER_MAGIC_OLD 0x39119FCD /* partition header */ -#define STATE_MAGIC_OLD 0xF1840DCE /* Status block */ -#define SHARED_HEADER_MAGIC_OLD 0x00DEBB1E /* Per-block header */ - -/* Conversion */ -#define HEADER_MAGIC_NUMBER 0xeb7a62c2 /* Partition header */ -#define STATE_MAGIC_NUMBER 0x47bacef8 /* Status block */ -#define SHARED_HEADER_MAGIC 0x00DEBB1E /* Per-block headeer */ - -/* Version magic. */ -#define VERSION_MAGIC_V2 0x389fabc4 - - -typedef struct __attribute__ ((packed)) { - uint32_t ps_magic; - /* 4 */ - uint32_t ps_updatenode; // Last writer - /* 8 */ - uint64_t ps_timestamp; // time of last update - /* 16 */ - uint32_t ps_nodeid; - uint32_t pad0; - /* 24 */ - uint8_t ps_state; // running or stopped - uint8_t pad1[1]; - uint16_t ps_flags; - /* 26 */ - uint16_t ps_score; // Local points - uint16_t ps_scoremax; // What we think is our max - // points, if other nodes - // disagree, we may be voted - // out - /* 28 */ - uint32_t ps_ca_sec; // Cycle speed (average) - uint32_t ps_ca_usec; - /* 36 */ - uint32_t ps_lc_sec; // Cycle speed (last) - uint32_t ps_lc_usec; - uint64_t ps_incarnation; // Token to detect hung + - // restored node - /* 44 */ - uint16_t ps_msg; // Vote/bid mechanism - uint16_t ps_seq; - uint32_t ps_arg; - /* 52 */ - memb_mask_t ps_mask; // Bitmap - memb_mask_t ps_master_mask; // Bitmap - /* 60 */ -} status_block_t; - -#define swab_status_block_t(ptr) \ -{\ - swab32((ptr)->ps_magic);\ - swab32((ptr)->ps_updatenode);\ - swab64((ptr)->ps_timestamp);\ - swab32((ptr)->ps_nodeid);\ - swab32((ptr)->pad0);\ - /* state + pad */ \ - swab16((ptr)->ps_flags);\ - swab16((ptr)->ps_score);\ - swab16((ptr)->ps_scoremax);\ - /* Cycle speeds */ \ - swab32((ptr)->ps_ca_sec);\ - swab32((ptr)->ps_ca_usec);\ - swab32((ptr)->ps_lc_sec);\ - swab32((ptr)->ps_lc_usec);\ - /* Message */ \ - swab16((ptr)->ps_msg); \ - swab16((ptr)->ps_seq); \ - swab32((ptr)->ps_arg); \ - } - - -/* - * Shared state disk header. Describes cluster global information. - */ -typedef struct __attribute__ ((packed)) { - uint32_t qh_magic; - uint32_t qh_version; // - uint64_t qh_timestamp; // time of last update - char qh_updatehost[128];// Hostname who put this here... - char qh_cluster[120]; // Cluster name; CMAN only - // supports 16 chars. - uint32_t qh_blksz; // Known block size @ creation - uint32_t qh_kernsz; // Ingored -} quorum_header_t; - -#define swab_quorum_header_t(ptr) \ -{\ - swab32((ptr)->qh_magic); \ - swab32((ptr)->qh_version); \ - swab32((ptr)->qh_blksz); \ - swab32((ptr)->qh_kernsz); \ - swab64((ptr)->qh_timestamp); \ -} - - - -/* - * The user data is stored with this header prepended. - * The header ONLY contains CRC information and the length of the data. - * The data blocks themselves contain their own respective magic numbers. - */ -typedef struct __attribute__ ((packed)) { - uint32_t h_magic; /* Header magic */ - uint32_t h_hcrc; /* Header CRC */ - uint32_t h_dcrc; /* CRC32 of data */ - uint32_t h_length; /* Length of real data */ - uint64_t h_view; /* View # of real data */ - uint64_t h_timestamp; /* Timestamp */ -} shared_header_t; - -#define SHARED_HEADER_INITIALIZER = {0, 0, 0, 0, 0, 0} - -#define swab_shared_header_t(ptr) \ -{\ - swab32((ptr)->h_magic);\ - swab32((ptr)->h_hcrc);\ - swab32((ptr)->h_dcrc);\ - swab32((ptr)->h_length);\ - swab64((ptr)->h_view);\ - swab64((ptr)->h_timestamp);\ -} - - -/* Offsets from RHCM 1.2.x */ -#define OFFSET_HEADER 0 -#define HEADER_SIZE(ssz) (ssz<4096?4096:ssz) - -#define OFFSET_FIRST_STATUS_BLOCK(ssz) (OFFSET_HEADER + HEADER_SIZE(ssz)) -#define SPACE_PER_STATUS_BLOCK(ssz) (ssz<4096?4096:ssz) -#define STATUS_BLOCK_COUNT MAX_NODES_DISK - -#define END_OF_DISK(ssz) (OFFSET_FIRST_STATUS_BLOCK(ssz) + \ - (MAX_NODES_DISK + 1) * \ - SPACE_PER_STATUS_BLOCK(ssz)) \ - - -typedef struct { - int d_fd; - int _pad_; - size_t d_blksz; - size_t d_pagesz; -} target_info_t; - - -/* From disk.c */ -int qdisk_open(char *name, target_info_t *disk); -int qdisk_close(target_info_t *disk); -int qdisk_init(char *name, char *clustername); -int qdisk_validate(char *name); -int qdisk_read(target_info_t *disk, __off64_t ofs, void *buf, int len); -int qdisk_write(target_info_t *disk, __off64_t ofs, const void *buf, int len); - -#define qdisk_nodeid_offset(nodeid, ssz) \ - (OFFSET_FIRST_STATUS_BLOCK(ssz) + (SPACE_PER_STATUS_BLOCK(ssz) * (nodeid - 1))) - -/* From disk_utils.c */ -#define HISTORY_LENGTH 60 -typedef struct { - disk_msg_id_t m_msg; /* this is an int, but will be stored as 16bit*/ - uint32_t m_arg; - uint16_t m_seq; - uint16_t pad0; -} disk_msg_t; - - -typedef struct { - uint64_t qc_incarnation; - struct timeval qc_average; - struct timeval qc_last[HISTORY_LENGTH]; - target_info_t qc_disk; - int qc_my_id; - int qc_writes; - int qc_interval; - int qc_tko; - int qc_tko_up; - int qc_upgrade_wait; - int qc_master_wait; - int qc_votes; - int qc_scoremin; - int qc_sched; - int qc_sched_prio; - int qc_max_error_cycles; - int qc_master; /* Master?! */ - int qc_config; - int qc_pad; - disk_node_state_t qc_disk_status; - disk_node_state_t qc_status; - run_flag_t qc_flags; - cman_handle_t qc_cman_admin; - cman_handle_t qc_cman_user; - char *qc_device; - char *qc_label; - char *qc_status_file; - char *qc_cman_label; - char *qc_status_sockname; -} qd_ctx; - -typedef struct { - uint64_t ni_incarnation; - uint64_t ni_evil_incarnation; - time_t ni_last_seen; - int ni_misses; - int ni_seen; - disk_msg_t ni_msg; - disk_msg_t ni_last_msg; - disk_node_state_t ni_state; - status_block_t ni_status; -} node_info_t; - -int qd_write_status(qd_ctx *ctx, int nid, disk_node_state_t state, - disk_msg_t *msg, memb_mask_t mask, memb_mask_t master); -int qd_init(qd_ctx *ctx, cman_handle_t ch_admin, - cman_handle_t ch_user, int me); -void qd_destroy(qd_ctx *ctx); - -/* proc.c */ -int find_partitions(const char *label, - char *devname, size_t devlen, int print); -int check_device(char *device, char *label, quorum_header_t *qh, int flags); - - -#endif diff --git a/cman/qdisk/disk_util.c b/cman/qdisk/disk_util.c deleted file mode 100644 index fc56d1d..0000000 --- a/cman/qdisk/disk_util.c +++ /dev/null @@ -1,267 +0,0 @@ -/** - @file Misc. Quorum daemon context utilities / high-level functions - */ - -#include "clusterautoconfig.h" - -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/ioctl.h> -#include <string.h> -#include <errno.h> -#include <disk.h> -#include <platform.h> -#include <unistd.h> -#include <sys/time.h> -#include <time.h> -#include <liblogthread.h> - -inline void _diff_tv(struct timeval *dest, struct timeval *start, struct timeval *end); -inline int get_time(struct timeval *tv, int use_uptime); - -inline void -_diff_tv(struct timeval *dest, struct timeval *start, struct timeval *end) -{ - dest->tv_sec = end->tv_sec - start->tv_sec; - dest->tv_usec = end->tv_usec - start->tv_usec; - - if (dest->tv_usec < 0) { - dest->tv_usec += 1000000; - dest->tv_sec--; - } -} - - -/** - * - * Grab the uptime from /proc/uptime. - * - * @param tv Timeval struct to store time in. The sec - * field contains seconds, the usec field - * contains the hundredths-of-seconds (converted - * to micro-seconds) - * @return -1 on failure, 0 on success. - */ -static inline int -getuptime(struct timeval *tv) -{ - FILE *fp; - struct timeval junk; - int rv; - - fp = fopen("/proc/uptime","r"); - if (!fp) - return -1; - -#if defined(__sparc__) - rv = fscanf(fp,"%ld.%d %ld.%d\n", &tv->tv_sec, &tv->tv_usec, - &junk.tv_sec, &junk.tv_usec); -#else - rv = fscanf(fp,"%ld.%ld %ld.%ld\n", &tv->tv_sec, &tv->tv_usec, - &junk.tv_sec, &junk.tv_usec); -#endif - fclose(fp); - - if (rv != 4) { - return -1; - } - - tv->tv_usec *= 10000; - - return 0; -} - - -inline int -get_time(struct timeval *tv, int use_uptime) -{ - if (use_uptime) { - return getuptime(tv); - } else { - return gettimeofday(tv, NULL); - } -} - - -/** - Update write times and calculate a new average time - */ -static void -qd_update_wtime(qd_ctx *ctx, struct timeval *newtime) -{ - int x; - int max = HISTORY_LENGTH; - uint64_t sum = 0; - - /* Store the thing */ - ctx->qc_writes++; - ctx->qc_last[ctx->qc_writes % HISTORY_LENGTH].tv_sec = newtime->tv_sec; - ctx->qc_last[ctx->qc_writes % HISTORY_LENGTH].tv_usec = newtime->tv_usec; - - if (ctx->qc_writes < HISTORY_LENGTH) - max = ctx->qc_writes; - - for (x = 0; x < max; x++) { - sum += (ctx->qc_last[x].tv_sec * 1000000); - sum += ctx->qc_last[x].tv_usec; - } - - sum /= max; - - ctx->qc_average.tv_sec = (sum / 1000000); - ctx->qc_average.tv_usec = (sum % 1000000); -} - - -/** - Write a status block to disk, given state, nodeid, message, and the - membership mask. - */ -int -qd_write_status(qd_ctx *ctx, int nid, disk_node_state_t state, - disk_msg_t *msg, memb_mask_t mask, memb_mask_t master) -{ - status_block_t ps; - struct timeval start, end; - int utime_ok = 1; - - if (!ctx) { - errno = EINVAL; - return -1; - } - - if (nid <= 0) { - errno = EINVAL; - return -1; - } - - ps.ps_magic = STATE_MAGIC_NUMBER; - ps.ps_nodeid = nid; - ps.ps_updatenode = ctx->qc_my_id; - ps.pad0 = 0; - ps.ps_timestamp = (uint64_t)time(NULL); - ps.ps_state = (uint8_t)state; - ps.pad1[0] = 0; - ps.ps_flags = 0; - ps.ps_score = 0; - ps.ps_scoremax = 0; - ps.ps_ca_sec = ctx->qc_average.tv_sec; - ps.ps_ca_usec = ctx->qc_average.tv_usec; - ps.ps_incarnation = ctx->qc_incarnation; - if (mask) { - memcpy(ps.ps_mask, mask, sizeof(memb_mask_t)); - } else { - memset(ps.ps_mask, 0, sizeof(memb_mask_t)); - } - if (master) { - memcpy(ps.ps_master_mask, master, sizeof(memb_mask_t)); - } else { - memset(ps.ps_master_mask, 0, sizeof(memb_mask_t)); - } - - if (ctx->qc_writes) { - ps.ps_lc_sec = - ctx->qc_last[(ctx->qc_writes - 1) % HISTORY_LENGTH].tv_sec; - ps.ps_lc_usec = - ctx->qc_last[(ctx->qc_writes - 1) % HISTORY_LENGTH].tv_usec; - } else { - ps.ps_lc_sec = ps.ps_lc_usec = 0; - } - ps.ps_nodeid = nid; - - /* Argh! */ - if (msg) { - ps.ps_msg = msg->m_msg; - ps.ps_seq = msg->m_seq; - ps.ps_arg = msg->m_arg; - } else { - ps.ps_msg = 0; - ps.ps_seq = 0; - ps.ps_arg = 0; - } - - if (get_time(&start, ctx->qc_flags&RF_UPTIME) < 0) - utime_ok = 0; - swab_status_block_t(&ps); - if (qdisk_write(&ctx->qc_disk, - qdisk_nodeid_offset(nid, ctx->qc_disk.d_blksz), - &ps, sizeof(ps)) < 0) { - logt_print(LOG_ERR, "Error writing node ID block %d\n", nid); - return -1; - } - if (utime_ok && (get_time(&end, ctx->qc_flags&RF_UPTIME) < 0)) - utime_ok = 0; - - if (utime_ok) { - _diff_tv(&start,&start,&end); - } else { - /* Use heuristic */ - start.tv_sec = ctx->qc_average.tv_sec; - start.tv_usec = ctx->qc_average.tv_usec; - } - qd_update_wtime(ctx, &start); - - return 0; -} - - -/** - Generate a token based on the current system time. - */ -static uint64_t -generate_token(void) -{ - uint64_t my_token = 0; - struct timeval tv; - - while(my_token == 0) { - gettimeofday(&tv, NULL); - - my_token = ((uint64_t) (tv.tv_sec) << 32) | - (uint64_t) (tv.tv_sec & 0x00000000ffffffff); - } - - return my_token; -} - - -/** - Initialize a quorum disk context, given a CMAN handle and a nodeid. - */ -int -qd_init(qd_ctx *ctx, cman_handle_t ch_admin, cman_handle_t ch, int me) -{ - if (!ctx || !ch || !me) { - errno = EINVAL; - return -1; - } - - memset(ctx, 0, sizeof(*ctx)); - ctx->qc_incarnation = generate_token(); - ctx->qc_cman_admin = ch_admin; - ctx->qc_cman_user = ch; - ctx->qc_my_id = me; - ctx->qc_config = 0; - - return 0; -} - - -/** - Destroy a quorum disk context - */ -void -qd_destroy(qd_ctx *ctx) -{ - if (ctx->qc_my_id == 0) - return; - if (ctx->qc_device) { - free(ctx->qc_device); - ctx->qc_device = NULL; - } - qdisk_close(&ctx->qc_disk); -} diff --git a/cman/qdisk/iostate.c b/cman/qdisk/iostate.c deleted file mode 100644 index 3d861ec..0000000 --- a/cman/qdisk/iostate.c +++ /dev/null @@ -1,145 +0,0 @@ -#include "clusterautoconfig.h" - -#include <pthread.h> -#include <iostate.h> -#include <unistd.h> -#include <time.h> -#include <sys/time.h> -#include <liblogthread.h> -#include "iostate.h" - -static iostate_t main_state = 0; -static int main_incarnation = 0; -static int qdisk_timeout = 0, sleeptime = 0; -static int thread_active = 0; -static pthread_t io_nanny_tid = 0; -static pthread_mutex_t state_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t state_cond = PTHREAD_COND_INITIALIZER; - -struct state_table { - iostate_t state; - const char *value; -}; - -static struct state_table io_state_table[] = { -{ STATE_NONE, "none" }, -{ STATE_WRITE, "write" }, -{ STATE_READ, "read" }, -{ STATE_LSEEK, "seek" }, -{ -1, NULL } }; - -static const char * -state_to_string(iostate_t state) -{ - static const char *ret = "unknown"; - int i; - - for (i=0; io_state_table[i].value; i++) { - if (io_state_table[i].state == state) { - ret = io_state_table[i].value; - break; - } - } - - return ret; -} - - -void -io_state(iostate_t state) -{ - pthread_mutex_lock(&state_mutex); - main_state = state; - main_incarnation++; /* it does not matter if this wraps. */ - - /* Optimization: Don't signal on STATE_NONE */ - if (state != STATE_NONE) - pthread_cond_broadcast(&state_cond); - - pthread_mutex_unlock(&state_mutex); -} - - -static void * -io_nanny_thread(void *arg) -{ - struct timespec wait_time; - iostate_t last_main_state = 0, current_main_state = 0; - int last_main_incarnation = 0, current_main_incarnation = 0; - int logged_incarnation = 0; - - /* Start with wherever we're at now */ - pthread_mutex_lock(&state_mutex); - current_main_state = last_main_state = main_state; - current_main_incarnation = last_main_incarnation = main_incarnation; - pthread_mutex_unlock(&state_mutex); - - while (thread_active) { - pthread_mutex_lock(&state_mutex); - clock_gettime(CLOCK_REALTIME, &wait_time); - wait_time.tv_sec += sleeptime; - pthread_cond_timedwait(&state_cond, &state_mutex, &wait_time); - current_main_state = main_state; - current_main_incarnation = main_incarnation; - pthread_mutex_unlock(&state_mutex); - - if (!thread_active) - break; - - if (!current_main_state) - continue; - - /* if the state or incarnation changed, the main qdiskd - * thread is healthy */ - if (current_main_state != last_main_state || - current_main_incarnation != last_main_incarnation) { - last_main_state = current_main_state; - last_main_incarnation = current_main_incarnation; - continue; - } - - /* Don't log things twice */ - if (logged_incarnation == current_main_incarnation) - continue; - logged_incarnation = current_main_incarnation; - - logt_print(LOG_WARNING, "qdiskd: %s " - "(system call) has hung for %d seconds\n", - state_to_string(current_main_state), sleeptime); - logt_print(LOG_WARNING, - "In %d more seconds, we will be evicted\n", - (qdisk_timeout-sleeptime)); - } - - return NULL; -} - - -int -io_nanny_start(int timeout) -{ - int ret; - - pthread_mutex_lock(&state_mutex); - - sleeptime = timeout / 2; - qdisk_timeout = timeout; - thread_active = 1; - - ret = pthread_create(&io_nanny_tid, NULL, io_nanny_thread, NULL); - pthread_mutex_unlock(&state_mutex); - - return ret; -} - - -int -io_nanny_stop(void) -{ - thread_active = 0; - pthread_cond_broadcast(&state_cond); - pthread_join(io_nanny_tid, NULL); - io_nanny_tid = 0; - - return 0; -} diff --git a/cman/qdisk/iostate.h b/cman/qdisk/iostate.h deleted file mode 100644 index 7dd7bf6..0000000 --- a/cman/qdisk/iostate.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _IOSTATE_H -#define _IOSTATE_H - -typedef enum { - STATE_NONE = 0, - STATE_READ = 1, - STATE_WRITE = 2, - STATE_LSEEK = 3, - STATE_UNKNOWN = 4 -} iostate_t; - -void io_state(iostate_t state); - -int io_nanny_start(int timeout); -int io_nanny_stop(void); - -#endif diff --git a/cman/qdisk/main.c b/cman/qdisk/main.c deleted file mode 100644 index e07e76c..0000000 --- a/cman/qdisk/main.c +++ /dev/null @@ -1,1879 +0,0 @@ -/** - @file Main loop / functions for disk-based quorum daemon. - */ - -#include "clusterautoconfig.h" - -#define SYSLOG_NAMES -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/ioctl.h> -#include <string.h> -#include <errno.h> -#include <disk.h> -#include <platform.h> -#include <unistd.h> -#include <time.h> -#include <sys/reboot.h> -#include <sys/time.h> -#include <sys/un.h> -#include <linux/reboot.h> -#include <sched.h> -#include <signal.h> -#include <ccs.h> -#include <liblogthread.h> -#include "score.h" -#include <sys/syslog.h> - -#define LOG_DAEMON_NAME "qdiskd" -#define LOG_MODE_DEFAULT LOG_MODE_OUTPUT_SYSLOG|LOG_MODE_OUTPUT_FILE -#include "iostate.h" - - -/* from main.c */ -void set_priority(int queue, int prio); - -/* from daemon_init.c */ -extern int daemon_init(char *); -extern void daemon_cleanup(void); -extern int check_process_running(char *, pid_t *); - -/* from proc.c */ -extern const char *state_str(disk_node_state_t s); - -/* - TODO: - 1) Take into account timings to gracefully extend node timeouts during - node spikes (that's why they are there!). - 2) Poll ccsd for configuration changes. - 3) Logging. - */ - -/* From bitmap.c */ -extern int clear_bit(uint8_t *mask, uint32_t bitidx, uint32_t masklen); -extern int set_bit(uint8_t *mask, uint32_t bitidx, uint32_t masklen); -extern int is_bit_set(uint8_t *mask, uint32_t bitidx, uint32_t masklen); - -/* From disk_utils.c */ -extern inline int get_time(struct timeval *tv, int use_uptime); -extern inline void _diff_tv(struct timeval *dest, struct timeval *start, - struct timeval *end); - -static int _running = 1, _reconfig = 0, _cman_shutdown = 0; -static int _debug = 0, _foreground = 0; - -/* */ -#define DEBUG_CONF 0x1 -#define DEBUG_CMDLINE 0x2 - -static void update_local_status(qd_ctx *ctx, node_info_t *ni, int max, int score, - int score_req, int score_max); -static int get_config_data(qd_ctx *ctx, struct h_data *h, int maxh, int *cfh); -static int cman_wait(cman_handle_t ch, struct timeval *_tv); - - -static void -int_handler(int sig) -{ - _running = 0; -} - - -static void -hup_handler(int sig) -{ - _reconfig = 1; -} - - -static void -usr1_handler(int sig) -{ - if (_debug) - /* Shut up debug mode */ - _debug = 0; - else - _debug = DEBUG_CMDLINE; -} - - -/** - Simple thing to see if a node is running. - */ -static inline int -state_run(disk_node_state_t state) -{ - return (state >= S_INIT ? state : 0); -} - - -/** - Clear out / initialize node info block. - */ -static void -node_info_init(node_info_t *ni, int max) -{ - int x; - time_t t = time(NULL); - - memset(ni, 0, sizeof(*ni) * max); - for (x = 0; x < max; x++) { - ni[x].ni_status.ps_nodeid = (x + 1); /* node ids are 1-based */ - ni[x].ni_status.ps_timestamp = t; - ni[x].ni_misses = 0; - ni[x].ni_last_seen = t; - } -} - - -/** - Check to see if someone tried to evict us but we were out to lunch. - Rare case; usually other nodes would put up the 'Undead' message and - re-evict us. - */ -static void -check_self(qd_ctx *ctx, status_block_t *sb) -{ - if (!sb->ps_updatenode || - (sb->ps_updatenode == ctx->qc_my_id)) { - return; - } - - /* I did not update this??! */ - switch(sb->ps_state) { - case S_EVICT: - /* Someone told us to die. */ - reboot(RB_AUTOBOOT); - default: - logt_print(LOG_EMERG, "Unhandled state: %d\n", sb->ps_state); - raise(SIGSTOP); - } -} - - -/** - Read in the node blocks off of the quorum disk and see if anyone has - or has not updated their timestamp recently. See check_transitions as - well. - */ -static int -read_node_blocks(qd_ctx *ctx, node_info_t *ni, int max) -{ - int x, errors = 0; - status_block_t *sb; - - for (x = 0; x < max; x++) { - - sb = &ni[x].ni_status; - - if (qdisk_read(&ctx->qc_disk, - qdisk_nodeid_offset(x+1, ctx->qc_disk.d_blksz), - sb, sizeof(*sb)) < 0) { - logt_print(LOG_WARNING,"Error reading node ID block %d\n", - x+1); - ++errors; - continue; - } - swab_status_block_t(sb); - - if (sb->ps_nodeid == ctx->qc_my_id) { - check_self(ctx, sb); - continue; - } - /* message. */ - memcpy(&(ni[x].ni_last_msg), &(ni[x].ni_msg), - sizeof(ni[x].ni_last_msg)); - ni[x].ni_msg.m_arg = sb->ps_arg; - ni[x].ni_msg.m_msg = sb->ps_msg; - ni[x].ni_msg.m_seq = sb->ps_seq; - - if (!state_run(sb->ps_state)) - continue; - - /* Unchanged timestamp: miss */ - if (sb->ps_timestamp == ni[x].ni_last_seen) { - /* XXX check for average + allow grace */ - ni[x].ni_misses++; - if (ni[x].ni_misses > 1) { - logt_print(LOG_DEBUG, - "Node %d missed an update (%d/%d)\n", - x+1, ni[x].ni_misses, ctx->qc_tko); - } - continue; - } - - /* Got through? The node is good. */ - ni[x].ni_misses = 0; - ni[x].ni_seen++; - ni[x].ni_last_seen = sb->ps_timestamp; - } - - return errors; -} - - -/** - Check for node transitions. - */ -static void -check_transitions(qd_ctx *ctx, node_info_t *ni, int max, memb_mask_t mask) -{ - int x; - - if (mask) - memset(mask, 0, sizeof(memb_mask_t)); - - for (x = 0; x < max; x++) { - - /* - Case 1: check to see if the node is still up - according to our internal state, but has been - evicted by the master or cleanly shut down - (or restarted). - - Transition from Evicted/Shutdown -> Offline - */ - if ((ni[x].ni_state >= S_EVICT && - ni[x].ni_status.ps_state <= S_EVICT) || - (ni[x].ni_incarnation && - (ni[x].ni_incarnation != - ni[x].ni_status.ps_incarnation))) { - - if (ni[x].ni_status.ps_state == S_EVICT) { - logt_print(LOG_NOTICE, "Node %d evicted\n", - ni[x].ni_status.ps_nodeid); - } else { - /* State == S_NONE or incarnation change */ - logt_print(LOG_INFO, "Node %d shutdown\n", - ni[x].ni_status.ps_nodeid); - ni[x].ni_evil_incarnation = 0; - } - - ni[x].ni_incarnation = 0; - ni[x].ni_seen = 0; - ni[x].ni_misses = 0; - ni[x].ni_state = S_NONE; - - /* Clear our master mask for the node after eviction - * or shutdown */ - if (mask) - clear_bit(mask, (ni[x].ni_status.ps_nodeid-1), - sizeof(memb_mask_t)); - continue; - } - - /* - Case 2: Check for a heartbeat timeout. Write an eviction - notice if we're the master. If this is our first notice - of the heartbeat timeout, update our internal state - accordingly. When the master evicts this node, we will - hit case 1 above. - - Transition from Online -> Evicted - */ - if (ni[x].ni_misses > ctx->qc_tko && - state_run(ni[x].ni_status.ps_state)) { - - /* - Mark our internal views as dead if nodes miss too - many heartbeats... This will cause a master - transition if no live master exists. - */ - if (ni[x].ni_status.ps_state >= S_RUN && - ni[x].ni_seen) { - logt_print(LOG_DEBUG, "Node %d DOWN\n", - ni[x].ni_status.ps_nodeid); - ni[x].ni_seen = 0; - } - - ni[x].ni_state = S_EVICT; - ni[x].ni_status.ps_state = S_EVICT; - ni[x].ni_evil_incarnation = - ni[x].ni_incarnation; - - /* - Write eviction notice if we're the master. - */ - if (ctx->qc_status == S_MASTER) { - logt_print(LOG_NOTICE, - "Writing eviction notice for node %d\n", - ni[x].ni_status.ps_nodeid); - qd_write_status(ctx, ni[x].ni_status.ps_nodeid, - S_EVICT, NULL, NULL, NULL); - if (ctx->qc_flags & RF_ALLOW_KILL) { - logt_print(LOG_DEBUG, "Telling CMAN to " - "kill the node\n"); - cman_kill_node(ctx->qc_cman_admin, - ni[x].ni_status.ps_nodeid); - } - } - - /* Clear our master mask for the node after eviction */ - if (mask) - clear_bit(mask, (ni[x].ni_status.ps_nodeid-1), - sizeof(memb_mask_t)); - continue; - } - - /* - Case 3: Check for node who is supposed to be dead, but - has started writing to the disk again with the same - incarnation. - - Transition from Offline -> Undead (BAD!!!) - */ - if (ni[x].ni_evil_incarnation && - (ni[x].ni_evil_incarnation == - ni[x].ni_status.ps_incarnation) && - (ni[x].ni_status.ps_updatenode == - ni[x].ni_status.ps_nodeid)) { - logt_print(LOG_CRIT, "Node %d is undead.\n", - ni[x].ni_status.ps_nodeid); - - logt_print(LOG_ALERT, - "Writing eviction notice (again) for node %d\n", - ni[x].ni_status.ps_nodeid); - qd_write_status(ctx, ni[x].ni_status.ps_nodeid, - S_EVICT, NULL, NULL, NULL); - ni[x].ni_status.ps_state = S_EVICT; - - /* XXX Need to fence it again */ - if (ctx->qc_flags & RF_ALLOW_KILL) { - logt_print(LOG_DEBUG, "Telling CMAN to " - "kill the node\n"); - cman_kill_node(ctx->qc_cman_admin, - ni[x].ni_status.ps_nodeid); - } - continue; - } - - - /* - Case 4: Check for a node who has met our minimum # of - 'seen' requests. - - Transition from Offline -> Online - */ - if (ni[x].ni_seen > ctx->qc_tko_up && - !state_run(ni[x].ni_state)) { - /* - Node-join - everyone just kind of "agrees" - there's no consensus to just have a node join - right now. - */ - ni[x].ni_state = S_RUN; - logt_print(LOG_DEBUG, "Node %d is UP\n", - ni[x].ni_status.ps_nodeid); - ni[x].ni_incarnation = - ni[x].ni_status.ps_incarnation; - ni[x].ni_evil_incarnation = 0; - - if (mask) - set_bit(mask, (ni[x].ni_status.ps_nodeid-1), - sizeof(memb_mask_t)); - - continue; - } - - /* - Case 5: Check for a node becoming master. Not really a - transition. - */ - if (ni[x].ni_state == S_RUN && - ni[x].ni_status.ps_state == S_MASTER) { - logt_print(LOG_INFO, "Node %d is the master\n", - ni[x].ni_status.ps_nodeid); - ni[x].ni_state = S_MASTER; - if (mask) - set_bit(mask, (ni[x].ni_status.ps_nodeid-1), - sizeof(memb_mask_t)); - continue; - } - - /* - Case 6: Check for a node which has changed its - incarnation # quickly (e.g. killall -9 qdiskd; - qdiskd). Not a transition. - */ - if (state_run(ni[x].ni_state) && - ni[x].ni_incarnation != ni[x].ni_status.ps_incarnation) { - - logt_print(LOG_DEBUG, "Node %d incarnation # changed\n", - ni[x].ni_status.ps_nodeid); - ni[x].ni_incarnation = - ni[x].ni_status.ps_incarnation; - ni[x].ni_evil_incarnation = 0; - - continue; - } - - /* - All other cases: Believe the node's reported state - */ - if (state_run(ni[x].ni_state)) { - ni[x].ni_state = ni[x].ni_status.ps_state; - if (mask) - set_bit(mask, (ni[x].ni_status.ps_nodeid-1), - sizeof(memb_mask_t)); - } - } -} - - -/** - Checks for presence of an online master. If there is no - Returns - */ -static int -master_exists(qd_ctx *ctx, node_info_t *ni, int max, int *low_id, int *count) -{ - int x; - int masters = 0; - int ret = 0; - - if (count) - *count = 0; - *low_id = ctx->qc_my_id; - - for (x = 0; x < max; x++) { - - /* See if this one's a master */ - if (ni[x].ni_state >= S_RUN && - ni[x].ni_status.ps_state == S_MASTER && - ni[x].ni_status.ps_nodeid != ctx->qc_my_id) { - if (!ret) - ret = ni[x].ni_status.ps_nodeid; - ++masters; - continue; - } - - /* See if it's us... */ - if (ni[x].ni_status.ps_nodeid == ctx->qc_my_id && - ni[x].ni_status.ps_state == S_MASTER) { - if (!ret) - ret = ctx->qc_my_id; - ++masters; - continue; - } - - /* Look for dead master */ - if (ni[x].ni_state < S_RUN && - ni[x].ni_status.ps_state == S_MASTER) { - logt_print(LOG_DEBUG, - "Node %d is marked master, but is dead.\n", - ni[x].ni_status.ps_nodeid); - continue; - } - - if (ni[x].ni_state < S_RUN) - continue; - - if (ni[x].ni_status.ps_nodeid < *low_id) - *low_id = ni[x].ni_status.ps_nodeid; - } - - if (count) - *count = masters; - /* - else if (masters == 1) { - printf("Node %d is the master\n", ret); - } else { - printf("No master found; node %d should be the master\n", - *low_id); - } - */ - - return ret; -} - - -/** - initialize node information blocks and wait to see if there is already - a cluster running using this QD. Note that this will delay master - election if multiple nodes start with a second or two of each other. - */ -static int -quorum_init(qd_ctx *ctx, node_info_t *ni, int max, struct h_data *h, int maxh) -{ - int x = 0, score, maxscore, score_req = 0; - struct timeval tv; - - logt_print(LOG_INFO, "Quorum Daemon Initializing\n"); - - if (mlockall(MCL_CURRENT|MCL_FUTURE) != 0) { - logt_print(LOG_ERR, "Unable to mlockall()\n"); - } - - if (qdisk_validate(ctx->qc_device) < 0) - return -1; - - if (qdisk_open(ctx->qc_device, &ctx->qc_disk) < 0) { - logt_print(LOG_CRIT, "Failed to open %s: %s\n", ctx->qc_device, - strerror(errno)); - return -1; - } - - logt_print(LOG_DEBUG, "I/O Size: %lu Page Size: %lu\n", - (unsigned long)ctx->qc_disk.d_blksz, (unsigned long)ctx->qc_disk.d_pagesz); - - if (h && maxh) { - start_score_thread(ctx, h, maxh); - } else { - logt_print(LOG_DEBUG, "Permanently setting score to 1/1\n"); - fudge_scoring(); - } - - node_info_init(ni, max); - ctx->qc_status = S_INIT; - if (qd_write_status(ctx, ctx->qc_my_id, - S_INIT, NULL, NULL, NULL) != 0) { - logt_print(LOG_CRIT, "Could not initialize status block!\n"); - return -1; - } - - while (++x <= ctx->qc_tko && _running) { - read_node_blocks(ctx, ni, max); - check_transitions(ctx, ni, max, NULL); - - if (qd_write_status(ctx, ctx->qc_my_id, - S_INIT, NULL, NULL, NULL) != 0) { - logt_print(LOG_CRIT, "Initialization failed\n"); - return -1; - } - - get_my_score(&score, &maxscore); - score_req = ctx->qc_scoremin; - if (score_req <= 0) - score_req = (maxscore/2 + 1); - update_local_status(ctx, ni, max, score, score_req, maxscore); - - tv.tv_sec = ctx->qc_interval; - tv.tv_usec = 0; - cman_wait(ctx->qc_cman_user, &tv); - } - - if (!_running) { - return 1; - } - - get_my_score(&score, &maxscore); - logt_print(LOG_INFO, "Initial score %d/%d\n", score, maxscore); - if ((ctx->qc_flags & RF_STOP_CMAN) && (score < score_req)) - return -1; - logt_print(LOG_INFO, "Initialization complete\n"); - - return 0; -} - - -/** - Vote for a master if it puts a bid in. - */ -static void -do_vote(qd_ctx *ctx, node_info_t *ni, int max, disk_msg_t *msg) -{ - int x; - - for (x = 0; x < max; x++) { - if (ni[x].ni_state != S_RUN) - continue; - - if (ni[x].ni_status.ps_msg == M_BID && - ni[x].ni_status.ps_nodeid < ctx->qc_my_id) { - - /* Vote for lowest bidding ID that is lower - than us */ - msg->m_msg = M_ACK; - msg->m_arg = ni[x].ni_status.ps_nodeid; - msg->m_seq = ni[x].ni_status.ps_seq; - - return; - } - } -} - - -/* - Check to match nodes in mask with nodes online according to CMAN. - Only the master needs to do this. - */ -static void -check_cman(qd_ctx *ctx, memb_mask_t mask, memb_mask_t master_mask) -{ - cman_node_t nodes[MAX_NODES_DISK]; - int retnodes, x; - - if (cman_get_nodes(ctx->qc_cman_admin, MAX_NODES_DISK, - &retnodes, nodes) <0 ) - return; - - memset(master_mask, 0, sizeof(master_mask)); - for (x = 0; x < retnodes; x++) { - if (is_bit_set(mask, nodes[x].cn_nodeid-1, sizeof(mask)) && - nodes[x].cn_member) { - set_bit(master_mask, nodes[x].cn_nodeid-1, - sizeof(master_mask)); - } else { - /* Not in CMAN output = not allowed */ - clear_bit(master_mask, (nodes[x].cn_nodeid-1), - sizeof(memb_mask_t)); - } - } -} - - -/* - returns: - 3: all acks received - you are the master. - 2: nacked (not highest score?) might not happen - 1: other node with lower ID is bidding and we should rescind our - bid. - 0: still waiting; don't clear bid; just wait another round. - Modifies: - *msg - it will store the vote for the lowest bid if we should - clear our bid. - */ -static int -check_votes(qd_ctx *ctx, node_info_t *ni, int max, disk_msg_t *msg) -{ - int x, running = 0, acks = 0, nacks = 0, low_id = ctx->qc_my_id; - - for (x = 0; x < max; x++) { - if (state_run(ni[x].ni_state)) - ++running; - else - continue; - - if (ni[x].ni_status.ps_msg == M_ACK && - ni[x].ni_status.ps_arg == ctx->qc_my_id) { - ++acks; - } - - if (ni[x].ni_status.ps_msg == M_NACK && - ni[x].ni_status.ps_arg == ctx->qc_my_id) { - ++nacks; - } - - /* If there's someone with a lower ID who is also - bidding for master, change our message to vote - for the lowest bidding node ID */ - if (ni[x].ni_status.ps_msg == M_BID && - ni[x].ni_status.ps_nodeid < low_id) { - low_id = ni[x].ni_status.ps_nodeid; - msg->m_msg = M_ACK; - msg->m_arg = ni[x].ni_status.ps_nodeid; - msg->m_seq = ni[x].ni_status.ps_seq; - } - } - - if (acks == running) - return 3; - if (nacks) - return 2; - if (low_id != ctx->qc_my_id) - return 1; - return 0; -} - -static void -print_node_info(FILE *fp, node_info_t *ni) -{ - uint64_t incarnation; - - fprintf(fp, "node_info_t [node %d] {\n", ni->ni_status.ps_nodeid); - - incarnation = be_swap64(ni->ni_incarnation); - fprintf(fp, " ni_incarnation = 0x%08x%08x\n", - ((int)(incarnation>>32))&0xffffffff, - ((int)(incarnation)&0xffffffff)); - - incarnation = be_swap64(ni->ni_evil_incarnation); - fprintf(fp, " ni_evil_incarnation = 0x%08x%08x\n", - ((int)(incarnation>>32))&0xffffffff, - ((int)(incarnation)&0xffffffff)); - fprintf(fp, " ni_last_seen = %s", ctime(&ni->ni_last_seen)); - fprintf(fp, " ni_misses = %d\n", ni->ni_misses); - fprintf(fp, " ni_seen = %d\n", ni->ni_seen); - fprintf(fp, " ni_msg = {\n"); - fprintf(fp, " m_msg = 0x%08x\n", ni->ni_msg.m_msg); - fprintf(fp, " m_arg = %d\n", ni->ni_msg.m_arg); - fprintf(fp, " m_seq = %d\n", ni->ni_msg.m_seq); - fprintf(fp, " }\n"); - fprintf(fp, " ni_last_msg = {\n"); - fprintf(fp, " m_msg = 0x%08x\n", ni->ni_last_msg.m_msg); - fprintf(fp, " m_arg = %d\n", ni->ni_last_msg.m_arg); - fprintf(fp, " m_seq = %d\n", ni->ni_last_msg.m_seq); - fprintf(fp, " }\n"); - fprintf(fp, " ni_state = 0x%08x (%s)\n", ni->ni_state, - state_str(ni->ni_state)); - fprintf(fp, "}\n\n"); -} - - -static void -update_local_status(qd_ctx *ctx, node_info_t *ni, int max, int score, - int score_req, int score_max) -{ - FILE *fp; - int x, need_close = 0; - time_t now; - long flags; - int fd; - - if (!ctx->qc_status_file) - return; - - if (strcmp(ctx->qc_status_file, "-") == 0) { - fp = stdout; - } else { - fp = fopen(ctx->qc_status_file, "w+"); - if (fp == NULL) - return; - need_close = 1; - } - - /* Don't block while writing to this file - * XXX Not set O_NONBLOCK twice on stdout? - */ - fd = fileno(fp); - flags = fcntl(fd, F_GETFD, 0); - if (fcntl(fd, F_SETFD, flags | O_NONBLOCK) != 0) { - if (need_close) - fclose(fp); - return; - } - - now = time(NULL); - fprintf(fp, "Time Stamp: %s", ctime(&now)); - fprintf(fp, "Node ID: %d\n", ctx->qc_my_id); - - fprintf(fp, "Score: %d/%d (Minimum required = %d)\n", - score, score_max, score_req); - fprintf(fp, "Current state: %s\n", state_str(ctx->qc_status)); - - /* - fprintf(fp, "Current disk state: %s\n", - state_str(ctx->qc_disk_status)); - */ - fprintf(fp, "Initializing Set: {"); - for (x=0; x<max; x++) { - if (ni[x].ni_status.ps_state == S_INIT && ni[x].ni_seen) - fprintf(fp," %d", ni[x].ni_status.ps_nodeid); - } - fprintf(fp, " }\n"); - - fprintf(fp, "Visible Set: {"); - for (x=0; x<max; x++) { - if (ni[x].ni_state >= S_RUN || ni[x].ni_status.ps_nodeid == - ctx->qc_my_id) - fprintf(fp," %d", ni[x].ni_status.ps_nodeid); - } - fprintf(fp, " }\n"); - - if (ctx->qc_status == S_INIT) - goto out; - - if (ctx->qc_master) - fprintf(fp, "Master Node ID: %d\n", ctx->qc_master); - else - fprintf(fp, "Master Node ID: (none)\n"); - - if (!ctx->qc_master) - goto out; - - fprintf(fp, "Quorate Set: {"); - for (x=0; x<max; x++) { - if (is_bit_set(ni[ctx->qc_master-1].ni_status.ps_master_mask, - ni[x].ni_status.ps_nodeid-1, - sizeof(memb_mask_t))) { - fprintf(fp," %d", ni[x].ni_status.ps_nodeid); - } - } - - fprintf(fp, " }\n"); - -out: - if (ctx->qc_flags & RF_DEBUG) { - for (x = 0; x < max; x++) - print_node_info(fp, &ni[x]); - } - - fprintf(fp, "\n"); - if (need_close) - fclose(fp); -} - -static inline int -_cmp_tv(struct timeval *left, struct timeval *right) -{ - if (left->tv_sec > right->tv_sec) - return -1; - - if (left->tv_sec < right->tv_sec) - return 1; - - if (left->tv_usec > right->tv_usec) - return -1; - - if (left->tv_usec < right->tv_usec) - return 1; - - return 0; -} - - -void -set_priority(int queue, int prio) -{ - struct sched_param s; - int ret; - const char *func = "nice"; - - if (queue == SCHED_OTHER) { - s.sched_priority = 0; - ret = sched_setscheduler(0, queue, &s); - errno = 0; - ret = nice(prio); - } else { - memset(&s,0,sizeof(s)); - s.sched_priority = prio; - ret = sched_setscheduler(0, queue, &s); - func = "sched_setscheduler"; - } - - if (ret < 0 && errno) { - logt_print(LOG_WARNING, "set_priority [%s] failed: %s\n", func, - strerror(errno)); - } -} - - -static int -cman_wait(cman_handle_t ch, struct timeval *_tv) -{ - fd_set rfds; - int fd = cman_get_fd(ch); - struct timeval tv_local = {0, 0}; - struct timeval *tv = _tv; - - if (!_tv) - tv = &tv_local; - - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - if (select(fd + 1, &rfds, NULL, NULL, tv) == 1) { - if (cman_dispatch(ch, CMAN_DISPATCH_ALL) < 0) { - if (errno == EAGAIN) - return 0; - return -1; - } - } - return 0; -} - - -/* - Listen for cman events - */ -static void -process_cman_event(cman_handle_t handle, void *private, int reason, int arg) -{ - qd_ctx *ctx = (qd_ctx *)private; - - switch(reason) { - case CMAN_REASON_PORTOPENED: - break; - case CMAN_REASON_TRY_SHUTDOWN: - _running = 0; - _cman_shutdown = 1; - break; - case CMAN_REASON_CONFIG_UPDATE: - get_config_data(ctx, NULL, 0, NULL); - break; - case CMAN_REASON_PORTCLOSED: - break; - case CMAN_REASON_STATECHANGE: - /* Not used */ - break; - } -} - - -static int -quorum_loop(qd_ctx *ctx, node_info_t *ni, int max) -{ - disk_msg_t msg = {0, 0, 0}; - int low_id, bid_pending = 0, score, score_max, score_req, - upgrade = 0, count, errors, error_cycles = 0; - memb_mask_t mask, master_mask; - struct timeval maxtime, oldtime, newtime, diff, sleeptime, interval, rd_lastok, wr_lastok; - - ctx->qc_status = S_NONE; - - maxtime.tv_usec = 0; - maxtime.tv_sec = ctx->qc_interval * ctx->qc_tko; - - interval.tv_usec = 0; - interval.tv_sec = ctx->qc_interval; - - rd_lastok.tv_usec = 0; - rd_lastok.tv_sec = 0; - - wr_lastok.tv_usec = 0; - wr_lastok.tv_sec = 0; - - get_my_score(&score, &score_max); - if (score_max < ctx->qc_scoremin) { - logt_print(LOG_WARNING, "Minimum score (%d) is impossible to " - "achieve (heuristic total = %d)\n", - ctx->qc_scoremin, score_max); - } - - _running = 1; - while (_running) { - if (_reconfig) { - get_config_data(ctx, NULL, 0, NULL); - _reconfig = 0; - } - - /* XXX this was getuptime() in clumanager */ - get_time(&oldtime, (ctx->qc_flags&RF_UPTIME)); - - /* Read everyone else's status */ - if ((errors = read_node_blocks(ctx, ni, max)) == 0 ) - get_time(&rd_lastok, ctx->qc_flags&RF_UPTIME); - - /* Check for node transitions */ - check_transitions(ctx, ni, max, mask); - - /* Check heuristics and remove ourself if necessary */ - get_my_score(&score, &score_max); - - /* If we recently upgraded, decrement our wait time */ - if (upgrade > 0) - --upgrade; - - score_req = ctx->qc_scoremin; - if (score_req <= 0) - score_req = (score_max/2 + 1); - - if (score < score_req) { - clear_bit(mask, (ctx->qc_my_id-1), sizeof(mask)); - if (ctx->qc_status > S_NONE) { - logt_print(LOG_NOTICE, - "Score insufficient for master " - "operation (%d/%d; required=%d); " - "downgrading\n", - score, score_max, score_req); - ctx->qc_status = S_NONE; - msg.m_msg = M_NONE; - ++msg.m_seq; - bid_pending = 0; - if (cman_wait(ctx->qc_cman_user, NULL) < 0) { - logt_print(LOG_ERR, "cman: %s\n", - strerror(errno)); - } else { - cman_poll_quorum_device(ctx->qc_cman_admin, 0); - } - if (ctx->qc_flags & RF_REBOOT) - reboot(RB_AUTOBOOT); - } - } else { - set_bit(mask, (ctx->qc_my_id-1), sizeof(mask)); - if (ctx->qc_status == S_NONE) { - logt_print(LOG_NOTICE, - "Score sufficient for master " - "operation (%d/%d; required=%d); " - "upgrading\n", - score, score_max, score_req); - ctx->qc_status = S_RUN; - upgrade = ctx->qc_upgrade_wait; - bid_pending = 0; - msg.m_msg = M_NONE; - ++msg.m_seq; - } - } - - /* Find master */ - ctx->qc_master = master_exists(ctx, ni, max, &low_id, &count); - - /* Resolve master conflict, if one exists */ - if (count >= 1 && ctx->qc_status == S_MASTER && - ctx->qc_master != ctx->qc_my_id) { - logt_print(LOG_WARNING, "Master conflict: abdicating\n"); - - /* Handle just like a recent upgrade */ - ctx->qc_status = S_RUN; - upgrade = ctx->qc_upgrade_wait; - bid_pending = 0; - msg.m_msg = M_NONE; - ++msg.m_seq; - } - - /* Figure out what to do based on what we know */ - if (!ctx->qc_master && - low_id == ctx->qc_my_id && - ctx->qc_status == S_RUN && - !bid_pending && - !upgrade) { - /* - If there's no master, and we are the lowest node - ID, make a bid to become master if we're not - already bidding. We can't do this if we've just - upgraded. - */ - - logt_print(LOG_DEBUG,"Making bid for master\n"); - msg.m_msg = M_BID; - ++msg.m_seq; - bid_pending = 1; - - } else if (!ctx->qc_master && !bid_pending) { - - /* We're not the master, and we do not have a bid - pending. Check for voting on other nodes. */ - do_vote(ctx, ni, max, &msg); - } else if (!ctx->qc_master && bid_pending) { - - /* We're currently bidding for master. - See if anyone's voted, or if we should - rescind our bid */ - ++bid_pending; - - /* Yes, those are all deliberate fallthroughs */ - switch (check_votes(ctx, ni, max, &msg)) { - case 3: - /* - * Give ample time to become aware of other - * nodes - */ - if (bid_pending < (ctx->qc_master_wait)) - break; - - logt_print(LOG_INFO, - "Assuming master role\n"); - ctx->qc_status = S_MASTER; - case 2: - msg.m_msg = M_NONE; - case 1: - bid_pending = 0; - default: - break; - } - } else if (ctx->qc_status == S_MASTER && - ctx->qc_master != ctx->qc_my_id) { - - /* We think we're master, but someone else claims - that they are master. */ - - logt_print(LOG_CRIT, - "A master exists, but it's not me?!\n"); - /* XXX Handle this how? Should not happen*/ - /* reboot(RB_AUTOBOOT); */ - - } else if (ctx->qc_status == S_MASTER && - ctx->qc_master == ctx->qc_my_id) { - - /* We are the master. Poll the quorum device. - We can't be the master unless we score high - enough on our heuristics. */ - if (cman_wait(ctx->qc_cman_user, NULL) < 0) { - logt_print(LOG_ERR, "cman_dispatch: %s\n", - strerror(errno)); - logt_print(LOG_ERR, - "Halting qdisk operations\n"); - return -1; - } - check_cman(ctx, mask, master_mask); - if (!errors) - cman_poll_quorum_device(ctx->qc_cman_admin, 1); - - } else if (ctx->qc_status == S_RUN && ctx->qc_master && - ctx->qc_master != ctx->qc_my_id) { - - /* We're not the master, but a master exists - Check to see if the master thinks we are - online. If we are, tell CMAN so. */ - if (is_bit_set( - ni[ctx->qc_master-1].ni_status.ps_master_mask, - ctx->qc_my_id-1, - sizeof(memb_mask_t))) { - if (cman_wait(ctx->qc_cman_user, NULL) < 0) { - logt_print(LOG_ERR, "cman_dispatch: %s\n", - strerror(errno)); - logt_print(LOG_ERR, - "Halting qdisk operations\n"); - return -1; - } - if (!errors) - cman_poll_quorum_device(ctx->qc_cman_admin, 1); - } - } - - /* Write out our status */ - if (qd_write_status(ctx, ctx->qc_my_id, ctx->qc_status, - &msg, mask, master_mask) != 0) { - logt_print(LOG_ERR, "Error writing to quorum disk\n"); - errors++; /* this value isn't really used - at this point */ - } else { - get_time(&wr_lastok, ctx->qc_flags&RF_UPTIME); - } - - /* write out our local status */ - update_local_status(ctx, ni, max, score, score_req, score_max); - - /* Cycle. We could time the loop and sleep - (interval-looptime), but this is fine for now.*/ - get_time(&newtime, ctx->qc_flags&RF_UPTIME); - - /* - * Reboot if the last successful hearbeat was longer ago than interval*TKO_COUNT - */ - _diff_tv(&diff, &wr_lastok, &newtime); - if (_cmp_tv(&maxtime, &diff) == 1 && - ctx->qc_flags & RF_IOTIMEOUT) { - logt_print(LOG_EMERG, "Failed to send a heartbeat " - "within %d second%s (%d.%06d) - REBOOTING\n", - (int)maxtime.tv_sec, - maxtime.tv_sec==1?"":"s", - (int)diff.tv_sec, - (int)diff.tv_usec); - if (!(ctx->qc_flags & RF_DEBUG)) - reboot(RB_AUTOBOOT); - } - - /* - * Reboot if the last successful hearbeat was longer ago than interval*TKO_COUNT - */ - _diff_tv(&diff, &rd_lastok, &newtime); - if (_cmp_tv(&maxtime, &diff) == 1 && - ctx->qc_flags & RF_IOTIMEOUT) { - logt_print(LOG_EMERG, - "Failed to read from qdisk within " - "%d second%s (%d.%06d) - REBOOTING\n", - (int)maxtime.tv_sec, - maxtime.tv_sec==1?"":"s", - (int)diff.tv_sec, - (int)diff.tv_usec); - if (!(ctx->qc_flags & RF_DEBUG)) - reboot(RB_AUTOBOOT); - } - - /* - * Reboot if we didn't send a heartbeat in interval*TKO_COUNT - */ - _diff_tv(&diff, &oldtime, &newtime); - if (_cmp_tv(&maxtime, &diff) == 1 && - ctx->qc_flags & RF_PARANOID) { - logt_print(LOG_EMERG, "Failed to complete a cycle within " - "%d second%s (%d.%06d) - REBOOTING\n", - (int)maxtime.tv_sec, - maxtime.tv_sec==1?"":"s", - (int)diff.tv_sec, - (int)diff.tv_usec); - if (!(ctx->qc_flags & RF_DEBUG)) - reboot(RB_AUTOBOOT); - } - - /* - * If the amount we took to complete a loop is greater or less - * than our interval, we adjust by the difference each round. - * - * It's not really "realtime", but it helps! - */ - if (_cmp_tv(&diff, &interval) == 1) { - _diff_tv(&sleeptime, &diff, &interval); - } else { - logt_print(LOG_WARNING, "qdisk cycle took more " - "than %d second%s to complete (%d.%06d)\n", - ctx->qc_interval, ctx->qc_interval==1?"":"s", - (int)diff.tv_sec, (int)diff.tv_usec); - memcpy(&sleeptime, &interval, sizeof(sleeptime)); - } - - if (errors && ctx->qc_max_error_cycles) { - ++error_cycles; - if (error_cycles >= ctx->qc_max_error_cycles) { - logt_print(LOG_ALERT, - "Too many I/O errors; giving up.\n"); - _running = 0; - } - } else { - error_cycles = 0; - } - - /* Could hit a watchdog timer here if we wanted to */ - if (_running) { - cman_wait(ctx->qc_cman_user, &sleeptime); - } - } - - return !!errors; -} - - -/** - Tell the other nodes we're done (safely!). - */ -static int -quorum_logout(qd_ctx *ctx) -{ - /* Write out our status */ - if (qd_write_status(ctx, ctx->qc_my_id, S_NONE, - NULL, NULL, NULL) != 0) { - logt_print(LOG_WARNING, - "Error writing to quorum disk during logout\n"); - } - return 0; -} - - -static void -conf_logging(int debug, int logmode, int facility, int loglevel, - int filelevel, char *fname) -{ - static int _log_config = 0; - - if (debug) - _debug |= DEBUG_CONF; - else - _debug &= ~DEBUG_CONF; - if (_debug) - loglevel = LOG_DEBUG; - if (_foreground) - logmode |= LOG_MODE_OUTPUT_STDERR; - - if (!_log_config) { - logt_init(LOG_DAEMON_NAME, logmode, facility, loglevel, - filelevel, fname); - _log_config = 1; - return; - - } - - logt_conf(LOG_DAEMON_NAME, logmode, facility, loglevel, - filelevel, fname); -} - - -static int -ccs_read_old_logging(int ccsfd, int *facility, int *priority) -{ - char query[256]; - char *val; - int x, ret = 0; - - /* Get log log_facility */ - snprintf(query, sizeof(query), "/cluster/quorumd/@log_facility"); - if (ccs_get(ccsfd, query, &val) == 0) { - logt_print(LOG_WARNING, - "Use of quorumd/@log_facility is deprecated!\n"); - for (x = 0; facilitynames[x].c_name; x++) { - if (strcasecmp(val, facilitynames[x].c_name)) - continue; - *facility = facilitynames[x].c_val; - ret = 1; - break; - } - free(val); - } - - /* Get log level */ - snprintf(query, sizeof(query), "/cluster/quorumd/@log_level"); - if (ccs_get(ccsfd, query, &val) == 0) { - logt_print(LOG_WARNING, - "Use of quorumd/@log_level is deprecated!\n"); - *priority = atoi(val); - free(val); - if (*priority < 0) - *priority = SYSLOGLEVEL; - else - ret = 1; - } - - return ret; -} - - -/** - Grab logsys configuration data from libccs - */ -static int -get_log_config_data(int ccsfd) -{ - char fname[PATH_MAX]; - int debug = 0, logmode = LOG_MODE_OUTPUT_FILE | LOG_MODE_OUTPUT_SYSLOG; - int facility = SYSLOGFACILITY; - int loglevel = SYSLOGLEVEL, filelevel = SYSLOGLEVEL; - int need_close = 0; - - logt_print(LOG_DEBUG, "Loading logging configuration\n"); - - if (ccsfd < 0) { - ccsfd = ccs_connect(); - if (ccsfd < 0) { - logt_print(LOG_ERR, "Logging configuration " - "unavailable; using defaults\n"); - return -1; - } - need_close = 1; - } - - snprintf(fname, sizeof(fname)-1, LOGDIR "/qdiskd.log"); - if (ccs_read_old_logging(ccsfd, &facility, &loglevel)) - filelevel = loglevel; - - ccs_read_logging(ccsfd, (char *)"QDISKD", &debug, &logmode, - &facility, &loglevel, &filelevel, (char *)fname); - conf_logging(debug, logmode, facility, loglevel, filelevel, fname); - - if (need_close) - ccs_disconnect(ccsfd); - - return 0; -} - - -static int -get_dynamic_config_data(qd_ctx *ctx, int ccsfd) -{ - char *val = NULL; - char query[256]; - - if (ccsfd < 0) - return -1; - - logt_print(LOG_DEBUG, "Loading dynamic configuration\n"); - - /* Get status file */ - snprintf(query, sizeof(query), "/cluster/quorumd/@status_file"); - if (ccs_get(ccsfd, query, &val) == 0) { - ctx->qc_status_file = val; - } - - /* Get scheduling queue */ - snprintf(query, sizeof(query), "/cluster/quorumd/@scheduler"); - if (ccs_get(ccsfd, query, &val) == 0) { - switch(val[0]) { - case 'r': - case 'R': - ctx->qc_sched = SCHED_RR; - break; - case 'f': - case 'F': - ctx->qc_sched = SCHED_FIFO; - break; - case 'o': - case 'O': - ctx->qc_sched = SCHED_OTHER; - break; - default: - logt_print(LOG_WARNING, - "Invalid scheduling queue '%s'\n", val); - break; - } - free(val); - } - - /* Get priority */ - snprintf(query, sizeof(query), "/cluster/quorumd/@priority"); - if (ccs_get(ccsfd, query, &val) == 0) { - ctx->qc_sched_prio = atoi(val); - free(val); - } - set_priority(ctx->qc_sched, ctx->qc_sched_prio); - - /* Get reboot flag for when we transition -> offline */ - /* default = on, so, 0 to turn off */ - snprintf(query, sizeof(query), "/cluster/quorumd/@reboot"); - if (ccs_get(ccsfd, query, &val) == 0) { - if (!atoi(val)) - ctx->qc_flags &= ~RF_REBOOT; - free(val); - } - - /* - * Get flag to see if we're supposed to kill cman if qdisk is not - * available. - */ - /* default = off, so, 1 to turn on */ - snprintf(query, sizeof(query), "/cluster/quorumd/@stop_cman"); - if (ccs_get(ccsfd, query, &val) == 0) { - if (!atoi(val)) - ctx->qc_flags &= ~RF_STOP_CMAN; - else - ctx->qc_flags |= RF_STOP_CMAN; - free(val); - } - - /* default = off, so, 1 to turn on */ - snprintf(query, sizeof(query), "/cluster/quorumd/@io_timeout"); - if (ccs_get(ccsfd, query, &val) == 0) { - if (!atoi(val)) - ctx->qc_flags &= ~RF_IOTIMEOUT; - else - ctx->qc_flags |= RF_IOTIMEOUT; - free(val); - } - - /* - * Get flag to see if we're supposed to reboot if we can't complete - * a pass in failure time - */ - /* default = off, so, 1 to turn on */ - snprintf(query, sizeof(query), "/cluster/quorumd/@paranoid"); - if (ccs_get(ccsfd, query, &val) == 0) { - if (!atoi(val)) - ctx->qc_flags &= ~RF_PARANOID; - else - ctx->qc_flags |= RF_PARANOID; - free(val); - } - - /* - * Get flag to see if we're supposed to reboot if we can't complete - * a pass in failure time - */ - /* default = off, so, 1 to turn on */ - snprintf(query, sizeof(query), "/cluster/quorumd/@allow_kill"); - if (ccs_get(ccsfd, query, &val) == 0) { - if (!atoi(val)) - ctx->qc_flags &= ~RF_ALLOW_KILL; - else - ctx->qc_flags |= RF_ALLOW_KILL; - free(val); - } - - /* - * How many consecutive error cycles do we allow before - * giving up? - * - * Notice that max_error_cycles is disabled if io_timeout is - * active. - */ - /* default = no max */ - snprintf(query, sizeof(query), "/cluster/quorumd/@max_error_cycles"); - if (ccs_get(ccsfd, query, &val) == 0) { - ctx->qc_max_error_cycles = atoi(val); - if ((ctx->qc_max_error_cycles <= 0) || (ctx->qc_flags & RF_IOTIMEOUT)) - ctx->qc_max_error_cycles = 0; - free(val); - } - - return 0; -} - - -static int -get_static_config_data(qd_ctx *ctx, int ccsfd) -{ - char *val = NULL; - char query[256]; - - if (ccsfd < 0) - return -1; - - logt_print(LOG_DEBUG, "Loading static configuration\n"); - - /* Get interval */ - snprintf(query, sizeof(query), "/cluster/quorumd/@interval"); - if (ccs_get(ccsfd, query, &val) == 0) { - ctx->qc_interval = atoi(val); - free(val); - if (ctx->qc_interval < 1) - ctx->qc_interval = 1; - } - - /* Get tko */ - snprintf(query, sizeof(query), "/cluster/quorumd/@tko"); - if (ccs_get(ccsfd, query, &val) == 0) { - ctx->qc_tko = atoi(val); - free(val); - if (ctx->qc_tko < 3) - ctx->qc_tko = 3; - } - - /* Get up-tko (transition off->online) */ - ctx->qc_tko_up = (ctx->qc_tko / 3); - snprintf(query, sizeof(query), "/cluster/quorumd/@tko_up"); - if (ccs_get(ccsfd, query, &val) == 0) { - ctx->qc_tko_up = atoi(val); - free(val); - } - if (ctx->qc_tko_up < 2) - ctx->qc_tko_up = 2; - - /* After coming online, wait this many intervals before - being allowed to bid for master. */ - ctx->qc_upgrade_wait = 2; /* (ctx->qc_tko / 3); */ - snprintf(query, sizeof(query), "/cluster/quorumd/@upgrade_wait"); - if (ccs_get(ccsfd, query, &val) == 0) { - ctx->qc_upgrade_wait = atoi(val); - free(val); - } - if (ctx->qc_upgrade_wait < 1) - ctx->qc_upgrade_wait = 1; - - /* wait this many intervals after bidding for master before - becoming Caesar */ - ctx->qc_master_wait = (ctx->qc_tko / 2); - snprintf(query, sizeof(query), "/cluster/quorumd/@master_wait"); - if (ccs_get(ccsfd, query, &val) == 0) { - ctx->qc_master_wait = atoi(val); - free(val); - } - if (ctx->qc_master_wait <= ctx->qc_tko_up) - ctx->qc_master_wait = ctx->qc_tko_up + 1; - - /* Get votes */ - snprintf(query, sizeof(query), "/cluster/quorumd/@votes"); - if (ccs_get(ccsfd, query, &val) == 0) { - ctx->qc_votes = atoi(val); - free(val); - if (ctx->qc_votes < 0) - ctx->qc_votes = 0; - } - - /* Get device */ - snprintf(query, sizeof(query), "/cluster/quorumd/@device"); - if (ccs_get(ccsfd, query, &val) == 0) { - ctx->qc_device = val; - } - - /* Get label (overrides device) */ - snprintf(query, sizeof(query), "/cluster/quorumd/@label"); - if (ccs_get(ccsfd, query, &val) == 0) { - ctx->qc_label = val; - } - - /* Get min score */ - snprintf(query, sizeof(query), "/cluster/quorumd/@min_score"); - if (ccs_get(ccsfd, query, &val) == 0) { - ctx->qc_scoremin = atoi(val); - free(val); - if (ctx->qc_scoremin < 0) - ctx->qc_scoremin = 0; - } - - /* Get cman_label */ - snprintf(query, sizeof(query), "/cluster/quorumd/@cman_label"); - if (ccs_get(ccsfd, query, &val) == 0) { - if (strlen(val) > 0) { - ctx->qc_flags |= RF_CMAN_LABEL; - ctx->qc_cman_label = val; - } - } - - /* - * Get flag to see if we're supposed to use /proc/uptime instead of - * gettimeofday(2) - */ - /* default = off, so, 1 to turn on */ - snprintf(query, sizeof(query), "/cluster/quorumd/@use_uptime"); - if (ccs_get(ccsfd, query, &val) == 0) { - if (!atoi(val)) - ctx->qc_flags &= ~RF_UPTIME; - else - ctx->qc_flags |= RF_UPTIME; - free(val); - } - - - return 0; -} - - -/** - Grab all our configuration data from libccs - */ -static int -get_config_data(qd_ctx *ctx, struct h_data *h, int maxh, int *cfh) -{ - int ccsfd = -1; - - ccsfd = ccs_connect(); - if (ccsfd < 0) { - logt_print(LOG_CRIT, "Configuration unavailable; " - "cannot start\n"); - return -1; - } - - get_log_config_data(ccsfd); - - /* Initialize defaults if we are not reconfiguring */ - if (ctx->qc_config == 0) { - ctx->qc_interval = 1; - ctx->qc_tko = 10; - ctx->qc_scoremin = 0; - ctx->qc_flags = RF_REBOOT | RF_ALLOW_KILL | RF_UPTIME; - /* | RF_STOP_CMAN;*/ - - ctx->qc_sched = SCHED_RR; - ctx->qc_sched_prio = 1; - ctx->qc_max_error_cycles = 0; - } - - if (ctx->qc_config || - get_dynamic_config_data(ctx, ccsfd) < 0) - goto out; - - ctx->qc_config = 1; - - if (get_static_config_data(ctx, ccsfd) < 0) - goto out; - - *cfh = configure_heuristics(ccsfd, h, maxh); - - logt_print(LOG_DEBUG, "Quorum Daemon: %d heuristics, " - "%d interval, %d tko, %d votes\n", - *cfh, ctx->qc_interval, ctx->qc_tko, ctx->qc_votes); - logt_print(LOG_DEBUG, "%d tko_up, %d master_wait, " - "%d upgrade_wait\n", - ctx->qc_tko_up, ctx->qc_master_wait, ctx->qc_upgrade_wait); -out: - logt_print(LOG_DEBUG, "Run Flags: %08x\n", ctx->qc_flags); - - ccs_disconnect(ccsfd); - - return 0; -} - - -static void -check_stop_cman(qd_ctx *ctx) -{ - if (!(ctx->qc_flags & RF_STOP_CMAN)) - return; - - logt_print(LOG_WARNING, "Telling CMAN to leave the cluster; " - "qdisk is not available\n"); - if (cman_shutdown(ctx->qc_cman_admin, 0) < 0) { - logt_print(LOG_CRIT, - "Could not leave the cluster - rebooting\n"); - sleep(5); - if (ctx->qc_flags & RF_DEBUG) { - logt_print(LOG_CRIT, "Debug mode specified! " - "Reboot averted.\n"); - return; - } - reboot(RB_AUTOBOOT); - } -} - - -#define logt_print_once(level, fmt, args...) \ -do { static int _logged=0; if (!_logged) { _logged=1; logt_print(level, fmt, ##args); } } while(0) - - -int -main(int argc, char **argv) -{ - cman_node_t me; - int cfh = 0, rv, nfd = -1, ret = -1, active; - qd_ctx ctx; - cman_handle_t ch_admin = NULL; - cman_handle_t ch_user = NULL; - node_info_t ni[MAX_NODES_DISK]; - struct h_data h[10]; - char device[128]; - pid_t pid; - quorum_header_t qh; - - if (check_process_running(argv[0], &pid) && pid !=getpid()) { - printf("QDisk services already running\n"); - return 0; - } - - while ((rv = getopt(argc, argv, "fdQs")) != EOF) { - switch (rv) { - case 'd': - _debug = DEBUG_CMDLINE; - break; - case 'f': - _foreground = 1; - break; - case 'Q': - /* Make qdisk very quiet */ - nfd = open("/dev/null", O_RDWR); - close(0); - close(1); - close(2); - dup2(nfd, 0); - dup2(nfd, 1); - dup2(nfd, 2); - close(nfd); - break; - default: - break; - } - } - - if(getenv("QDISK_DEBUG")) - _debug = 1; - - if (!_foreground && daemon_init(argv[0]) < 0) { - fprintf(stderr, "Could not fork: %s\n", strerror(errno)); - goto out; - } - - conf_logging(0, LOG_MODE_OUTPUT_SYSLOG, SYSLOGFACILITY, - SYSLOGLEVEL, 0, NULL); - - while (_running && (ch_admin = cman_admin_init(NULL)) == NULL) { - logt_print_once(LOG_INFO, "Waiting for CMAN to start\n"); - sleep(1); - } - - while (_running && (active = cman_is_active(ch_admin)) <= 0) { - logt_print_once(LOG_INFO, - "Waiting for CMAN to become active\n"); - if (active < 0) { - logt_print(LOG_CRIT, "cman_is_active: %s\n", - strerror(errno)); - goto out; - } - sleep(1); - } - - if (!_running) - goto out; - - /* For cman notifications we need two sockets - one for events, - one for config change callbacks */ - ch_user = cman_init(&ctx); - if (cman_start_notification(ch_user, process_cman_event) != 0) { - logt_print(LOG_CRIT, "Could not register with CMAN: %s\n", - strerror(errno)); - goto out; - } - - memset(&me, 0, sizeof(me)); - if (cman_get_node(ch_admin, CMAN_NODEID_US, &me) < 0) { - logt_print(LOG_CRIT, "Could not determine local node ID: %s\n", - strerror(errno)); - goto out; - } - - qd_init(&ctx, ch_admin, ch_user, me.cn_nodeid); - - signal(SIGINT, int_handler); - signal(SIGTERM, int_handler); - signal(SIGHUP, hup_handler); - signal(SIGUSR1, usr1_handler); - - /* RF_DEBUG can only be set from the command line */ - if (_debug) - ctx.qc_flags |= RF_DEBUG; - - if (get_config_data(&ctx, h, 10, &cfh) < 0) { - logt_print(LOG_CRIT, "Configuration failed\n"); - check_stop_cman(&ctx); - goto out; - } - - if (ctx.qc_label) { - ret = find_partitions(ctx.qc_label, device, sizeof(device), 0); - if (ret < 0) { - logt_print(LOG_CRIT, "Unable to match label" - " '%s' to any device\n", - ctx.qc_label); - check_stop_cman(&ctx); - goto out; - } else if (ret > 0) { - logt_print(LOG_WARNING, "%d matches found for " - "label '%s'; please use 'device=' " - "instead!\n", ret, ctx.qc_label); - } - - if (ctx.qc_device) - free(ctx.qc_device); - ctx.qc_device = strdup(device); - - logt_print(LOG_INFO, "Quorum Partition: %s Label: %s\n", - ctx.qc_device, ctx.qc_label); - } else if (ctx.qc_device) { - if (check_device(ctx.qc_device, NULL, &qh, 0) != 0) { - logt_print(LOG_CRIT, - "Specified partition %s does not have a " - "qdisk label\n", ctx.qc_device); - check_stop_cman(&ctx); - goto out; - } - - if (qh.qh_version == VERSION_MAGIC_V2 && - qh.qh_blksz != qh.qh_kernsz) { - logt_print(LOG_CRIT, - "Specified device %s does not match kernel's " - "reported sector size (%lu != %lu)\n", - ctx.qc_device, - (unsigned long)qh.qh_blksz, - (unsigned long)qh.qh_kernsz); - check_stop_cman(&ctx); - goto out; - } - } - - ret = quorum_init(&ctx, ni, MAX_NODES_DISK, h, cfh); - if (ret < 0) { - logt_print(LOG_CRIT, "Initialization failed\n"); - check_stop_cman(&ctx); - goto out; - } else if (ret > 0) { - /* ret > 0 means we received a shutdown during initialization */ - /* Write our 'clean down' state to disk and get out of here */ - logt_print(LOG_INFO, "Shutdown request received during initialization\n"); - quorum_logout(&ctx); - goto out; - } - - ret = 0; - - if (!_running) - goto out; - - cman_register_quorum_device(ctx.qc_cman_admin, - (ctx.qc_flags&RF_CMAN_LABEL)? - ctx.qc_cman_label: - ctx.qc_device, - ctx.qc_votes); - /* - XXX this always returns -1 / EBUSY even when it works?!!! - - if ((rv = cman_register_quorum_device(ctx.qc_cman_admin, ctx.qc_device, - ctx.qc_votes)) < 0) { - logt_print(LOG_CRIT, - "Could not register %s with CMAN; " - "return = %d; error = %s\n", - ctx.qc_device, rv, strerror(errno)); - goto out; - } - */ - - io_nanny_start(ctx.qc_tko * ctx.qc_interval); - - if (quorum_loop(&ctx, ni, MAX_NODES_DISK) == 0) { - /* Only clean up if we're exiting w/o error) */ - cman_unregister_quorum_device(ctx.qc_cman_admin); - quorum_logout(&ctx); - } - - io_nanny_stop(); - -out: - /* free cman handle to avoid leak in cman */ - cman_finish(ch_admin); - if (_cman_shutdown) { - cman_replyto_shutdown(ch_user, 1); - cman_finish(ch_user); - } - qd_destroy(&ctx); - logt_exit(); - daemon_cleanup(); - return ret; -} - diff --git a/cman/qdisk/mkqdisk.c b/cman/qdisk/mkqdisk.c deleted file mode 100644 index 80d1f8a..0000000 --- a/cman/qdisk/mkqdisk.c +++ /dev/null @@ -1,95 +0,0 @@ -/** - @file Quorum disk utility - */ - -#include "clusterautoconfig.h" - -#include <stdio.h> -#include <stdlib.h> -#include <disk.h> -#include <errno.h> -#include <sys/types.h> -#include <platform.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <liblogthread.h> - -#define PROGRAM_NAME "mkqdisk" - -int -main(int argc, char **argv) -{ - char device[128]; - char *newdev = NULL, *newlabel = NULL; - int rv, verbose_level = 1; - - printf(PROGRAM_NAME " v" PACKAGE_VERSION "\n\n"); - - /* XXX this is horrible but we need to prioritize options as long as - * we can't queue messages properly - */ - while ((rv = getopt(argc, argv, "Ldf:c:l:h")) != EOF) { - switch (rv) { - case 'd': - ++verbose_level; - if (verbose_level > LOG_DEBUG) - verbose_level = LOG_DEBUG; - break; - } - } - - logt_init(PROGRAM_NAME, LOG_MODE_OUTPUT_STDERR, - verbose_level, verbose_level, verbose_level, NULL); - - /* reset the option index to reparse */ - optind = 0; - - while ((rv = getopt(argc, argv, "Ldf:c:l:h")) != EOF) { - switch (rv) { - case 'd': - /* processed above, needs to be here for compat */ - break; - case 'L': - /* List */ - return find_partitions(NULL, NULL, 0, verbose_level); - case 'f': - return find_partitions( optarg, device, - sizeof(device), verbose_level); - case 'c': - newdev = optarg; - break; - case 'l': - newlabel = optarg; - break; - case 'h': - printf("usage: mkqdisk -L | -f <label> | -c " - "<device> -l <label> [-d]\n"); - return 0; - default: - break; - } - } - - if (!newdev && !newlabel) { - printf("usage: mkqdisk -L | -f <label> | -c " - "<device> -l <label>\n"); - return 1; - } - - if (!newdev || !newlabel) { - printf("Both a device and a label are required\n"); - return 1; - } - - printf("Writing new quorum disk label '%s' to %s.\n", - newlabel, newdev); - printf("WARNING: About to destroy all data on %s; proceed [N/y] ? ", - newdev); - if (getc(stdin) != 'y') { - printf("Good thinking.\n"); - return 0; - } - - return qdisk_init(newdev, newlabel); -} diff --git a/cman/qdisk/platform.h b/cman/qdisk/platform.h deleted file mode 100644 index b1dfc64..0000000 --- a/cman/qdisk/platform.h +++ /dev/null @@ -1,40 +0,0 @@ -/** @file - * Defines for byte-swapping - */ -#ifndef __PLATFORM_H -#define __PLATFORM_H - -#include <endian.h> -#include <sys/param.h> -#include <byteswap.h> -#include <bits/wordsize.h> - -/* No swapping on little-endian machines */ -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define le_swap16(x) (x) -#define le_swap32(x) (x) -#define le_swap64(x) (x) -#else -#define le_swap16(x) bswap_16(x) -#define le_swap32(x) bswap_32(x) -#define le_swap64(x) bswap_64(x) -#endif - -/* No swapping on big-endian machines */ -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define be_swap16(x) bswap_16(x) -#define be_swap32(x) bswap_32(x) -#define be_swap64(x) bswap_64(x) -#else -#define be_swap16(x) (x) -#define be_swap32(x) (x) -#define be_swap64(x) (x) -#endif - - -#define swab16(x) x=be_swap16(x) -#define swab32(x) x=be_swap32(x) -#define swab64(x) x=be_swap64(x) - - -#endif /* __PLATFORM_H */ diff --git a/cman/qdisk/proc.c b/cman/qdisk/proc.c deleted file mode 100644 index 5f5f4b7..0000000 --- a/cman/qdisk/proc.c +++ /dev/null @@ -1,265 +0,0 @@ -/** - @file Quorum disk /proc/partition scanning functions - */ - -#include "clusterautoconfig.h" - -#include <stdio.h> -#include <stdlib.h> -#include <disk.h> -#include <errno.h> -#include <sys/types.h> -#include <platform.h> -#include <stdlib.h> -#include <string.h> -#include <liblogthread.h> -#include "scandisk.h" - -const char *state_str(disk_node_state_t s); - -struct device_args { - char *label; - struct devnode *devnode; - int sector_size; - int flags; - int count; - int pad; -}; - -int -check_device(char *device, char *label, quorum_header_t *qh, - int flags) -{ - int ret = -1; - quorum_header_t qh_local; - target_info_t disk; - - if (!qh) - qh = &qh_local; - - ret = qdisk_validate(device); - if (ret < 0) { - logt_print(LOG_DEBUG, "qdisk_verify"); - return -1; - } - - ret = qdisk_open(device, &disk); - if (ret < 0) { - logt_print(LOG_ERR, "qdisk_open"); - return -1; - } - - ret = -1; - if (qdisk_read(&disk, OFFSET_HEADER, qh, sizeof(*qh)) == sizeof(*qh)) { - swab_quorum_header_t(qh); - if (qh->qh_magic == HEADER_MAGIC_NUMBER) { - if (!label || !strcmp(qh->qh_cluster, label)) { - ret = 0; - } - } - } - - qh->qh_kernsz = disk.d_blksz; - - /* only flag now is 'strict device check'; i.e., - "block size recorded must match kernel's reported size" */ - if (flags && qh->qh_version == VERSION_MAGIC_V2 && - disk.d_blksz != qh->qh_blksz) { - ret = -1; - } - - qdisk_close(&disk); - - return ret; -} - - -static void -filter_devs(struct devnode *node, void *v_args) -{ - struct device_args *args = (struct device_args *)v_args; - quorum_header_t qh; - quorum_header_t *ret_qh = NULL; - int ret; - - if (!node->sysfsattrs.sysfs) - return; - if (!node->devpath) - return; - if (node->sysfsattrs.holders) - return; - /* Qdiskd doesn't work on soft-raid */ - if (node->md > 0) - return; - - ret = check_device(node->devpath->path, args->label, &qh, args->flags); - if (ret == 0) { - ret_qh = malloc(sizeof(qh)); - if (!ret_qh) - return; - memcpy(ret_qh, &qh, sizeof(qh)); - - node->filter = (void *)ret_qh; - if (!args->count) { - args->devnode = node; - } - ++args->count; - } -} - - -const char * -state_str(disk_node_state_t s) -{ - switch (s) { - case S_NONE: - return "None"; - case S_EVICT: - return "Evicted"; - case S_INIT: - return "Initializing"; - case S_RUN: - return "Running"; - case S_MASTER: - return "Master"; - default: - return "ILLEGAL"; - } -} - - -static void -print_status_block(status_block_t *sb) -{ - time_t timestamp = (time_t)sb->ps_timestamp; - uint64_t incarnation = be_swap64(sb->ps_incarnation); - - if (sb->ps_state == S_NONE) - return; - logt_print(LOG_INFO, "Status block for node %d\n", sb->ps_nodeid); - logt_print(LOG_INFO, "\tLast updated by node %d\n", sb->ps_updatenode); - logt_print(LOG_INFO, "\tLast updated on %s", ctime((time_t *)×tamp)); - logt_print(LOG_INFO, "\tState: %s\n", state_str(sb->ps_state)); - logt_print(LOG_INFO, "\tFlags: %04x\n", (be_swap16(sb->ps_flags))); - logt_print(LOG_INFO, "\tScore: %d/%d\n", sb->ps_score, sb->ps_scoremax); - logt_print(LOG_INFO, "\tAverage Cycle speed: %d.%06d seconds\n", - sb->ps_ca_sec, sb->ps_ca_usec); - logt_print(LOG_INFO, "\tLast Cycle speed: %d.%06d seconds\n", - sb->ps_lc_sec, sb->ps_lc_usec); - logt_print(LOG_INFO, "\tIncarnation: %08x%08x\n", - (int)(incarnation>>32&0xffffffff), - (int)(incarnation&0xffffffff)); - -} - - -static void -read_info(char *dev) -{ - target_info_t ti; - int x; - status_block_t sb; - - if (qdisk_open(dev, &ti) < 0) { - logt_print(LOG_ERR, "Could not read from %s: %s\n", - dev, strerror(errno)); - return; - } - - for (x = 0; x < MAX_NODES_DISK; x++) { - - if (qdisk_read(&ti, - qdisk_nodeid_offset(x+1, ti.d_blksz), - &sb, sizeof(sb)) < 0) { - logt_print(LOG_ERR, "Error reading node ID block %d\n", - x+1); - continue; - } - swab_status_block_t(&sb); - print_status_block(&sb); - } - - qdisk_close(&ti); -} - - -static void -print_qdisk_info(struct devnode *dn) -{ - quorum_header_t *qh = (quorum_header_t *)dn->filter; - struct devpath *dp; - time_t timestamp = (time_t)qh->qh_timestamp; - - for (dp = dn->devpath; dp; dp = dp->next) - printf("%s:\n", dp->path); - printf("\tMagic: %08x\n", qh->qh_magic); - printf("\tLabel: %s\n", qh->qh_cluster); - printf("\tCreated: %s", ctime(×tamp)); - printf("\tHost: %s\n", qh->qh_updatehost); - printf("\tKernel Sector Size: %d\n", qh->qh_kernsz); - if (qh->qh_version == VERSION_MAGIC_V2) { - printf("\tRecorded Sector Size: %d\n\n", (int)qh->qh_blksz); - } -} - -int -find_partitions(const char *label, char *devname, size_t devlen, int print) -{ - struct devlisthead *dh = NULL; - struct devnode *dn = NULL; - struct device_args dargs; - - memset(&dargs, 0, sizeof(dargs)); - dargs.label = (char *)label; - dargs.flags = 1; /* strict device check */ - dargs.devnode = NULL; /* First matching device */ - - dh = scan_for_dev(NULL, 5, filter_devs, (void *)(&dargs)); - if (!dh) - goto not_found; - if (!dargs.devnode) - goto not_found; - - if (dargs.count > 0 && print) { - for (dn = dh->devnode; dn; dn = dn->next) { - if (dn->filter == NULL) { - continue; - } - - print_qdisk_info(dn); - if (print >= 2) { - /* Print node stuff */ - read_info(dn->devpath->path); - } - } - } - - if (dargs.count >= 1 && label) { - snprintf(devname, devlen, "%s", dargs.devnode->devpath->path); - } - - for (dn = dh->devnode; dn; dn = dn->next) - if (dn->filter) - free(dn->filter); - free_dev_list(dh); - - if (print) - /* No errors if we're just printing stuff */ - return 0; - - if (dargs.count == 1 || !label) - return 0; - - /* more than one match */ - return dargs.count; - - not_found: - if (dh) { - for (dn = dh->devnode; dn; dn = dn->next) - if (dn->filter) - free(dn->filter); - free_dev_list(dh); - } - errno = ENOENT; - return -1; -} diff --git a/cman/qdisk/scandisk.c b/cman/qdisk/scandisk.c deleted file mode 100644 index 3825ec4..0000000 --- a/cman/qdisk/scandisk.c +++ /dev/null @@ -1,766 +0,0 @@ -#include "clusterautoconfig.h" - -#include <stdio.h> -#include <time.h> -#include <stdlib.h> -#include <string.h> -#include <sys/param.h> -#include <dirent.h> -#include <sys/sysmacros.h> -#include <sys/stat.h> - -#include "scandisk.h" - -/** search in cache helpers **/ - -/* - * match is 0 for exact match - * 1 to see if the string is contained and return the first match - */ - -static struct devnode *find_dev_by_path(struct devnode *startnode, char *path, - int match) -{ - struct devnode *nextnode; - struct devpath *nextpath; - - while (startnode) { - nextnode = startnode->next; - nextpath = startnode->devpath; - while (nextpath) { - if (match) { - if (strstr(nextpath->path, path)) - return startnode; - } else { - if (!strcmp(nextpath->path, path)) - return startnode; - } - nextpath = nextpath->next; - } - startnode = nextnode; - } - - return 0; -} - -static struct devnode *find_dev_by_majmin(struct devnode *startnode, int maj, - int min) -{ - struct devnode *nextnode; - - while (startnode) { - nextnode = startnode->next; - if ((startnode->maj == maj) && (startnode->min == min)) - return startnode; - startnode = nextnode; - } - - return 0; -} - -/** free the cache.. this one is easy ;) **/ - -/* free all the path associated to one node */ -static void flush_dev_list(struct devpath *startpath) -{ - struct devpath *nextpath; - - while (startpath) { - nextpath = startpath->next; - free(startpath); - startpath = nextpath; - } - - return; -} - -/* free all nodes associated with one devlist */ -static void flush_dev_cache(struct devlisthead *devlisthead) -{ - struct devnode *nextnode, *startnode = devlisthead->devnode; - - while (startnode) { - nextnode = startnode->next; - flush_dev_list(startnode->devpath); - free(startnode); - startnode = nextnode; - } - - return; -} - -/** list object allocation helpers **/ - -/* our only certain keys in the list are maj and min - * this function append a devnode obj to devlisthead - * and set maj and min - */ - -static struct devnode *alloc_list_obj(struct devlisthead *devlisthead, int maj, - int min) -{ - struct devnode *nextnode; - - nextnode = malloc(sizeof(struct devnode)); - if (!nextnode) - return 0; - - memset(nextnode, 0, sizeof(struct devnode)); - - if (!devlisthead->devnode) - devlisthead->devnode = nextnode; - else - devlisthead->tail->next = nextnode; - - devlisthead->tail = nextnode; - - nextnode->maj = maj; - nextnode->min = min; - - return nextnode; -} - -/* really annoying but we have no way to know upfront how - * many paths are linked to a certain maj/min combo. - * Once we find a device, we know maj/min and this new path. - * add_path_obj will add the given path to the devnode - */ -static int add_path_obj(struct devnode *startnode, const char *path) -{ - struct devpath *nextpath, *startpath; - - nextpath = malloc(sizeof(struct devpath)); - if (!nextpath) - return 0; - - memset(nextpath, 0, sizeof(struct devpath)); - - if (!startnode->devpath) { - startnode->devpath = startpath = nextpath; - } else { - startpath = startnode->devpath; - while (startpath->next) - startpath = startpath->next; - - /* always append what we find */ - startpath->next = nextpath; - startpath = nextpath; - } - - strncpy(startpath->path, path, MAXPATHLEN - 1); - - return 1; -} - -/* lsdev needs to add blocks in 2 conditions: if we have a real block device - * or if have a symlink to a block device. - * this function simply avoid duplicate code around. - */ -static int add_lsdev_block(struct devlisthead *devlisthead, struct stat *sb, - const char *path) -{ - int maj, min; - struct devnode *startnode; - - maj = major(sb->st_rdev); - min = minor(sb->st_rdev); - - startnode = find_dev_by_majmin(devlisthead->devnode, maj, min); - if (!startnode) { - startnode = alloc_list_obj(devlisthead, maj, min); - if (!startnode) - return 0; - } - - if (!add_path_obj(startnode, path)) - return 0; - - return 1; -} - -/* check if it is a device or a symlink to a device */ -static int dev_is_block(struct stat *sb, char *path) -{ - if (S_ISBLK(sb->st_mode)) - return 1; - - if (S_ISLNK(sb->st_mode)) - if (!stat(path, sb)) - if (S_ISBLK(sb->st_mode)) - return 1; - - return 0; -} - -/* lsdev does nothing more than ls -lR /dev - * dives into dirs (skips hidden directories) - * add block devices - * parse symlinks - * - * ret: - * 1 on success - * -1 for generic errors - * -2 -ENOMEM - */ -static int lsdev(struct devlisthead *devlisthead, const char *path) -{ - int i, n, err = 0; - struct dirent **namelist; - struct stat sb; - char newpath[MAXPATHLEN]; - - i = scandir(path, &namelist, 0, alphasort); - if (i < 0) - return -1; - - for (n = 0; n < i; n++) { - if (namelist[n]->d_name[0] != '.') { - snprintf(newpath, sizeof(newpath), "%s/%s", path, - namelist[n]->d_name); - - if (!lstat(newpath, &sb)) { - if (S_ISDIR(sb.st_mode)) - err = lsdev(devlisthead, newpath); - if (err < 0) - return err; - - if (dev_is_block(&sb, newpath)) - if (!add_lsdev_block - (devlisthead, &sb, newpath) < 0) - return -2; - } - } - free(namelist[n]); - } - free(namelist); - return 1; -} - -/* - * scan /proc/partitions and adds info into the list. - * It's able to add nodes if those are not found in sysfs. - * - * ret: - * 0 if we can't scan - * -2 -ENOMEM - * 1 if everything is ok - */ - -static int scanprocpart(struct devlisthead *devlisthead) -{ - char line[4096]; - FILE *fp; - int minor, major; - unsigned long long blkcnt; - char device[128]; - struct devnode *startnode; - fp = fopen("/proc/partitions", "r"); - if (!fp) - return 0; - while (fgets(line, sizeof(line), fp) - != NULL) { - - if (strlen(line) > 128 + (22)) - continue; - sscanf(line, "%4d %4d %10llu %s", - &major, &minor, &blkcnt, device); - - /* careful here.. if there is no device, we are scanning the - * first two lines that are not useful to us - */ - if (!strlen(device)) - continue; - startnode = - find_dev_by_majmin(devlisthead->devnode, major, minor); - if (!startnode) { - startnode = alloc_list_obj(devlisthead, major, minor); - if (!startnode) - return -2; - } - - startnode->procpart = 1; - strcpy(startnode->procname, device); - } - - fclose(fp); - return 1; -} - -/* scan /proc/mdstat and adds info to the list. At this point - * all the devices _must_ be already in the list. We don't add anymore - * since raids can only be assembled out of existing devices - * - * ret: - * 1 if we could scan - * 0 otherwise - */ -static int scanmdstat(struct devlisthead *devlisthead) -{ - char line[4096]; - FILE *fp; - char device[16]; - char separator[4]; - char status[16]; - char personality[16]; - char firstdevice[16]; - char devices[4096]; - char *tmp, *next; - struct devnode *startnode = NULL; - - fp = fopen("/proc/mdstat", "r"); - if (!fp) - return 0; - - while (fgets(line, sizeof(line), fp) != NULL) { - - /* i like things to be absolutely clean */ - memset(device, 0, sizeof(device)); - memset(separator, 0, sizeof(separator)); - memset(status, 0, sizeof(status)); - memset(personality, 0, sizeof(personality)); - memset(firstdevice, 0, sizeof(firstdevice)); - memset(devices, 0, sizeof(devices)); - - if (strlen(line) > sizeof(line)) - continue; - - /* we only parse stuff that starts with ^md - * that's supposed to point to raid */ - if (!(line[0] == 'm' && line[1] == 'd')) - continue; - - sscanf(line, "%s %s %s %s %s", - device, separator, status, personality, firstdevice); - - /* scan only raids that are active */ - if (strcmp(status, "active")) - continue; - - /* try to find *mdX and set the device as real raid. - * if we don't find the device we don't try to set the slaves */ - startnode = find_dev_by_path(devlisthead->devnode, device, 1); - if (!startnode) - continue; - - startnode->md = 1; - - /* trunkate the string from sdaX[Y] to sdaX and - * copy the whole device string over */ - memset(strstr(firstdevice, "["), 0, 1); - strcpy(devices, strstr(line, firstdevice)); - - /* if we don't find any slave (for whatever reason) - * keep going */ - if (!strlen(devices)) - continue; - - tmp = devices; - while ((tmp) && ((next = strstr(tmp, " ")) || strlen(tmp))) { - - memset(strstr(tmp, "["), 0, 1); - - startnode = - find_dev_by_path(devlisthead->devnode, tmp, 1); - if (startnode) - startnode->md = 2; - - tmp = next; - - if (tmp) - tmp++; - - } - } - - fclose(fp); - return 1; -} - -/* scanmapper parses /proc/devices to identify what maj are associated - * with device-mapper - * - * ret: - * can't fail for now - */ -static int scanmapper(struct devlisthead *devlisthead) -{ - struct devnode *startnode; - FILE *fp; - char line[4096]; - char major[4]; - char device[64]; - int maj, start = 0; - - fp = fopen("/proc/devices", "r"); - if (!fp) - return 0; - - while (fgets(line, sizeof(line), fp) != NULL) { - memset(major, 0, sizeof(major)); - memset(device, 0, sizeof(device)); - - if (strlen(line) > sizeof(line)) - continue; - - if (!strncmp(line, "Block devices:", 13)) { - start = 1; - continue; - } - - if (!start) - continue; - - sscanf(line, "%s %s", major, device); - - if (!strncmp(device, "device-mapper", 13)) { - maj = atoi(major); - startnode = devlisthead->devnode; - - while (startnode) { - if (startnode->maj == maj) - startnode->mapper = 1; - - startnode = startnode->next; - } - - } - - } - - fclose(fp); - return 1; -} - -/* scan through the list and execute the custom filter for each entry */ -static void run_filter(struct devlisthead *devlisthead, - devfilter filter, void *filter_args) -{ - struct devnode *startnode = devlisthead->devnode; - - while (startnode) { - filter(startnode, filter_args); - startnode = startnode->next; - } - return; -} - -/** sysfs helper functions **/ - -/* /sys/block/sda/dev or /sys/block/sda1/dev exists - * the device is real and dev contains maj/min info. - * - * ret: - * 1 on success and set maj/min - * 0 if no file is found - * -1 if we could not open the file - */ -static int sysfs_is_dev(char *path, int *maj, int *min) -{ - char newpath[MAXPATHLEN]; - struct stat sb; - FILE *f; - snprintf(newpath, sizeof(newpath), "%s/dev", path); - if (!lstat(newpath, &sb)) { - f = fopen(newpath, "r"); - if (f) { - int err; - - err = fscanf(f, "%d:%d", maj, min); - fclose(f); - if ((err == EOF) || (err != 2)) - return -1; - - return 1; - } else - return -1; - } - return 0; -} - -/* /sys/block/sda/removable tells us if a device can be ejected - * from the system or not. This is useful for USB pendrive that are - * both removable and disks. - * - * ret: - * 1 if is removable - * 0 if not - * -1 if we couldn't find the file. - */ -static int sysfs_is_removable(char *path) -{ - char newpath[MAXPATHLEN]; - struct stat sb; - int i = -1; - FILE *f; - snprintf(newpath, sizeof(newpath), "%s/removable", path); - if (!lstat(newpath, &sb)) { - f = fopen(newpath, "r"); - if (f) { - int err; - - err = fscanf(f, "%d\n", &i); - fclose(f); - if ((err == EOF) || (err != 1)) - i = -1; - } - } - return i; -} - -/* we use this function to scan /sys/block/sda{,1}/{holders,slaves} - * to know in what position of the foodchain this device is. - * NOTE: a device can have both holders and slaves at the same time! - * (for example an lvm volume on top of a raid device made of N real disks - * - * ret: - * always return the amount of entries in the dir if successful - * or any return value from scandir. - */ -static int sysfs_has_subdirs_entries(char *path, const char *subdir) -{ - char newpath[MAXPATHLEN]; - struct dirent **namelist; - struct stat sb; - int n, i, count = 0; - - snprintf(newpath, sizeof(newpath), "%s/%s", path, subdir); - if (!lstat(newpath, &sb)) { - if (S_ISDIR(sb.st_mode)) { - i = scandir(newpath, &namelist, 0, alphasort); - if (i < 0) - return i; - for (n = 0; n < i; n++) { - if (namelist[n]->d_name[0] != '.') - count++; - free(namelist[n]); - } - free(namelist); - } - } - return count; -} - -/* this is the best approach so far to make sure a block device - * is a disk and distinguish it from a cdrom or tape or etc. - * What we know for sure is that a type 0 is a disk. - * From an old piece code 0xe is an IDE disk and comes from media. - * NOTE: we scan also for ../ that while it seems stupid, it will - * allow to easily mark partitions as real disks. - * (see for example /sys/block/sda/device/type and - * /sys/block/sda1/../device/type) - * TODO: there might be more cases to evaluate. - * - * ret: - * -2 we were not able to open the file - * -1 no path found - * 0 we found the path but we have 0 clue on what it is - * 1 is a disk - */ -static int sysfs_is_disk(char *path) -{ - char newpath[MAXPATHLEN]; - struct stat sb; - int i = -1; - FILE *f; - - snprintf(newpath, sizeof(newpath), "%s/device/type", path); - if (!lstat(newpath, &sb)) - goto found; - - snprintf(newpath, sizeof(newpath), "%s/../device/type", path); - if (!lstat(newpath, &sb)) - goto found; - - snprintf(newpath, sizeof(newpath), "%s/device/media", path); - if (!lstat(newpath, &sb)) - goto found; - - snprintf(newpath, sizeof(newpath), "%s/../device/media", path); - if (!lstat(newpath, &sb)) - goto found; - - snprintf(newpath, sizeof(newpath), "%s/device/devtype", path); - if (!lstat(newpath, &sb)) - return 1; - - snprintf(newpath, sizeof(newpath), "%s/../device/devtype", path); - if (!lstat(newpath, &sb)) - return 1; - - return -1; - - found: - f = fopen(newpath, "r"); - if (f) { - int err; - - err = fscanf(f, "%d\n", &i); - fclose(f); - - if ((err == EOF) || (err != 1)) - return 0; - - switch (i) { - case 0x0: /* scsi type_disk */ - case 0xe: /* found on ide disks from old kernels.. */ - i = 1; - break; - default: - i = 0; /* by default we have no clue */ - break; - } - } else - i = -2; - - return i; -} - -/* recursive function that will scan and dive into /sys/block - * looking for devices and scanning for attributes. - * - * ret: - * 1 on success - * -1 on generic error - * -2 -ENOMEM - */ -static int scansysfs(struct devlisthead *devlisthead, const char *path, int level, int parent_holder) -{ - struct devnode *startnode; - int i, n, maj, min, has_holder; - struct dirent **namelist; - struct stat sb; - char newpath[MAXPATHLEN]; - - i = scandir(path, &namelist, 0, alphasort); - if (i < 0) - return -1; - - for (n = 0; n < i; n++) { - if (namelist[n]->d_name[0] != '.') { - snprintf(newpath, sizeof(newpath), - "%s/%s", path, namelist[n]->d_name); - - if (!lstat(newpath, &sb) && level) - if (S_ISLNK(sb.st_mode)) - continue; - - has_holder = parent_holder; - - if (sysfs_is_dev(newpath, &maj, &min) > 0) { - startnode = - alloc_list_obj(devlisthead, maj, - min); - if (!startnode) - return -2; - - startnode->sysfsattrs.sysfs = 1; - startnode->sysfsattrs.removable = - sysfs_is_removable(newpath); - - if (!parent_holder) - has_holder = - sysfs_has_subdirs_entries(newpath, - "holders"); - - startnode->sysfsattrs.holders = has_holder; - - startnode->sysfsattrs.slaves = - sysfs_has_subdirs_entries(newpath, - "slaves"); - startnode->sysfsattrs.disk = - sysfs_is_disk(newpath); - } - - if (!stat(newpath, &sb) && !level) - if (S_ISDIR(sb.st_mode)) - if (scansysfs(devlisthead, newpath, 1, has_holder) < 0) - return -1; - - if (!lstat(newpath, &sb)) - if (S_ISDIR(sb.st_mode)) - if (scansysfs(devlisthead, newpath, 1, has_holder) < 0) - return -1; - - } - free(namelist[n]); - } - - free(namelist); - return 1; -} - -/* - * devlisthead can be null if you are at init time. pass the old one if you are - * updating or scanning.. - * - * timeout is used only at init time to set the cache timeout value if default - * value is not good enough. We might extend its meaning at somepoint. - * Anything <= 0 means that the cache does not expire. - */ - -struct devlisthead *scan_for_dev(struct devlisthead *devlisthead, - time_t timeout, - devfilter filter, void *filter_args) -{ - int res; - time_t current; - - time(¤t); - - if (devlisthead) { - if ((current - devlisthead->cache_timestamp) < - devlisthead->cache_timeout) { - return devlisthead; - } - } else { - devlisthead = malloc(sizeof(struct devlisthead)); - if (!devlisthead) - return NULL; - memset(devlisthead, 0, sizeof(struct devlisthead)); - if (timeout) - devlisthead->cache_timeout = timeout; - else - devlisthead->cache_timeout = DEVCACHETIMEOUT; - } - - flush_dev_cache(devlisthead); - devlisthead->cache_timestamp = current; - - /* it's important we check those 3 errors and abort in case - * as it means that we are running out of mem, - */ - devlisthead->sysfs = res = scansysfs(devlisthead, SYSBLOCKPATH, 0, 0); - if (res < -1) - goto emergencyout; - - devlisthead->procpart = res = scanprocpart(devlisthead); - if (res < -1) - goto emergencyout; - - devlisthead->lsdev = res = lsdev(devlisthead, DEVPATH); - if (res < -1) - goto emergencyout; - - /* from now on we don't alloc mem ourselves but only add info */ - devlisthead->mdstat = scanmdstat(devlisthead); - devlisthead->mapper = scanmapper(devlisthead); - if (filter) - run_filter(devlisthead, filter, filter_args); - - return devlisthead; - - emergencyout: - free_dev_list(devlisthead); - return 0; -} - -/* free everything we used so far */ - -void free_dev_list(struct devlisthead *devlisthead) -{ - if (devlisthead) { - flush_dev_cache(devlisthead); - free(devlisthead); - } - return; -} diff --git a/cman/qdisk/scandisk.h b/cman/qdisk/scandisk.h deleted file mode 100644 index 031de26..0000000 --- a/cman/qdisk/scandisk.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef __SCANDISK_H__ -#define __SCANDISK_H__ - -#ifndef DEVPATH -#define DEVPATH "/dev" -#endif - -#ifndef SYSFSPATH -#define SYSFSPATH "/sys" -#endif - -#ifndef SYSBLOCKPATH -#define SYSBLOCKPATH SYSFSPATH "/block" -#endif - -#ifndef DEVCACHETIMEOUT -#define DEVCACHETIMEOUT 30 /* expressed in seconds */ -#endif - -/* each entry can be (generally): - * > 0 on success or good hit - * 0 on success with no hit - * < 0 on error - */ - -struct sysfsattrs { /* usual 0 | 1 game */ - int sysfs; /* did we find an entry in sysfs at all? */ - int slaves; /* device has slaves */ - int holders; /* device has holders */ - int removable; /* device is removable */ - int disk; /* device is a disk */ -}; - -/* this structure is required because we don't know upfront how many - * entries for a certain maj/min will be found in /dev, and so we need - * to alloc them dynamically. - */ -struct devpath { - struct devpath *next; - char path[MAXPATHLEN]; -}; - -/* this structure holds all the data for each maj/min found in the system - * that is a block device - */ -struct devnode { - struct devnode *next; - struct devpath *devpath; /* point to the first path entry */ - int maj; /* device major */ - int min; /* device minor */ - struct sysfsattrs sysfsattrs; /* like the others.. scanning /sys */ - int procpart; /* 0 if the device is not in proc/part or 1 on success. <0 on error */ - char procname[MAXPATHLEN]; /* non-NULL if we find a maj/min match */ - int md; /* 0 nothing to do with raid, 1 is raid, - * 2 is raid slave - data from /proc/mdstat */ - int mapper; /* 0 nothing, 1 we believe it's a devmap dev */ - void *filter; /* your filter output.. whatever it is */ -}; - -/* this is what you get after a scan... if you are lucky */ -/* each entry can be 0 if we can't scan or < 0 if there are errors */ - -struct devlisthead { - struct devnode *devnode; /* points to the first entry */ - struct devnode *tail; /* last entry (for fast append) */ - time_t cache_timestamp; /* this cache timestamp */ - int cache_timeout; /* for how long this cache is valid */ - int sysfs; /* set to 1 if we were able to scan - * /sys */ - int procpart; /* set to 1 if we were able to scan - * /proc/partitions */ - int lsdev; /* set to 1 if we were able to ls /dev */ - int mdstat; /* set to 1 if we were able to scan - * /proc/mdstat */ - int mapper; /* set to 1 if we were able to run - * something against mapper */ -}; - -typedef void (*devfilter) (struct devnode * cur, void *arg); - -struct devlisthead *scan_for_dev(struct devlisthead *devlisthead, - time_t timeout, - devfilter filter, void *filter_args); -void free_dev_list(struct devlisthead *devlisthead); - -#endif /* __SCANDISK_H__ */ diff --git a/cman/qdisk/score.c b/cman/qdisk/score.c deleted file mode 100644 index 70cd500..0000000 --- a/cman/qdisk/score.c +++ /dev/null @@ -1,424 +0,0 @@ -/** - @file Quorum daemon scoring functions + thread. - */ - -#include "clusterautoconfig.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <fcntl.h> -#include <pthread.h> -#include <string.h> -#include <ccs.h> -#include <liblogthread.h> -#include <sched.h> -#include <sys/mman.h> -#include "disk.h" -#include "score.h" - -static pthread_mutex_t sc_lock = PTHREAD_MUTEX_INITIALIZER; -static int _score = 0, _maxscore = 0, _score_thread_running = 0; -static pthread_t score_thread = (pthread_t)0; -extern void set_priority(int, int); - -struct h_arg { - struct h_data *h; - int sched_queue; - int sched_prio; - int count; -}; - -/* - XXX Messy, but works for now... - */ -static void -nullify(void) -{ - int fd[3]; - - close(0); - close(1); - close(2); - - fd[0] = open("/dev/null", O_RDONLY); - if (fd[0] != 0) - dup2(fd[0], 0); - fd[1] = open("/dev/null", O_WRONLY); - if (fd[1] != 1) - dup2(fd[1], 1); - fd[2] = open("/dev/null", O_WRONLY); - if (fd[2] != 2) - dup2(fd[2], 2); -} - - -/** - Set all signal handlers to default for exec of a script. - ONLY do this after a fork(). - */ -static void -restore_signals(void) -{ - sigset_t set; - int x; - - for (x = 1; x < _NSIG; x++) - signal(x, SIG_DFL); - - sigfillset(&set); - sigprocmask(SIG_UNBLOCK, &set, NULL); -} - - -/** - Spin off a user-defined heuristic - */ -static int -fork_heuristic(struct h_data *h) -{ - int pid; - char *argv[4]; - time_t now; - - if (h->childpid) { - errno = EINPROGRESS; - return -1; - } - - now = time(NULL); - if (now < h->nextrun) - return 0; - - h->nextrun = now + h->interval; - - pid = fork(); - if (pid < 0) - return -1; - - if (pid) { - h->childpid = pid; - return 0; - } - - /* - * always use SCHED_OTHER for the child processes - * nice -1 is fine; but we don't know what the child process - * might do, so leaving it (potentially) in SCHED_RR or SCHED_FIFO - * is out of the question - * - * XXX if you set SCHED_OTHER in the conf file and nice 20, the below - * will make the heuristics a higher prio than qdiskd. This should be - * fine in practice, because running qdiskd at nice 20 will cause all - * sorts of problems on a busy system. - */ - set_priority(SCHED_OTHER, -1); - munlockall(); - restore_signals(); - - argv[0] = strdup("/bin/sh"); - argv[1] = strdup("-c"); - argv[2] = h->program; - argv[3] = NULL; - - nullify(); - - execv("/bin/sh", argv); - - free(argv[0]); - free(argv[1]); - - logt_print(LOG_ERR, "Execv failed\n"); - return 0; -} - - -/** - Total our current score - */ -static void -total_score(struct h_data *h, int max, int *score, int *maxscore) -{ - int x; - - *score = 0; - *maxscore = 0; - - /* Allow operation w/o any heuristics */ - if (!max) { - *score = *maxscore = 1; - return; - } - - for (x = 0; x < max; x++) { - *maxscore += h[x].score; - if (h[x].available) - *score += h[x].score; - } -} - - -/** - Check for response from a user-defined heuristic / script - */ -static int -check_heuristic(struct h_data *h, int block) -{ - int ret; - int status; - - if (h->childpid == 0) - /* No child to check */ - return 0; - - ret = waitpid(h->childpid, &status, block?0:WNOHANG); - if (!block && ret == 0) - /* No children exited */ - return 0; - - h->childpid = 0; - if (ret < 0 && errno == ECHILD) - /* wrong child? */ - goto miss; - if (!WIFEXITED(status)) { - ret = 0; - goto miss; - } - if (WEXITSTATUS(status) != 0) { - ret = 0; - goto miss; - } - - /* Returned 0 and was not killed */ - if (!h->available) { - h->available = 1; - logt_print(LOG_INFO, "Heuristic: '%s' UP\n", h->program); - } - h->misses = 0; - return 0; - -miss: - if (h->available) { - h->misses++; - if (h->misses >= h->tko) { - logt_print(LOG_INFO, - "Heuristic: '%s' DOWN (%d/%d)\n", - h->program, h->misses, h->tko); - h->available = 0; - } else { - logt_print(LOG_DEBUG, - "Heuristic: '%s' missed (%d/%d)\n", - h->program, h->misses, h->tko); - } - } - - return ret; -} - - -/** - Kick off all available heuristics - */ -static int -fork_heuristics(struct h_data *h, int max) -{ - int x; - - for (x = 0; x < max; x++) - fork_heuristic(&h[x]); - return 0; -} - - -/** - Check all available heuristics - */ -static int -check_heuristics(struct h_data *h, int max, int block) -{ - int x; - - for (x = 0; x < max; x++) - check_heuristic(&h[x], block); - return 0; -} - - -/** - Read configuration data from CCS into the array provided - */ -int -configure_heuristics(int ccsfd, struct h_data *h, int max) -{ - int x = 0; - char *val; - char query[128]; - - if (!h || !max) - return -1; - - do { - h[x].program = NULL; - h[x].available = 0; - h[x].misses = 0; - h[x].interval = 2; - h[x].tko = 1; - h[x].score = 1; - h[x].childpid = 0; - h[x].nextrun = 0; - - /* Get program */ - snprintf(query, sizeof(query), - "/cluster/quorumd/heuristic[%d]/@program", x+1); - if (ccs_get(ccsfd, query, &val) != 0) - /* No more */ - break; - h[x].program = val; - - /* Get score */ - snprintf(query, sizeof(query), - "/cluster/quorumd/heuristic[%d]/@score", x+1); - if (ccs_get(ccsfd, query, &val) == 0) { - h[x].score = atoi(val); - free(val); - if (h[x].score <= 0) - h[x].score = 1; - } - - /* Get query interval */ - snprintf(query, sizeof(query), - "/cluster/quorumd/heuristic[%d]/@interval", x+1); - if (ccs_get(ccsfd, query, &val) == 0) { - h[x].interval = atoi(val); - free(val); - if (h[x].interval <= 0) - h[x].interval = 2; - } - - /* Get tko for this heuristic */ - snprintf(query, sizeof(query), - "/cluster/quorumd/heuristic[%d]/@tko", x+1); - if (ccs_get(ccsfd, query, &val) == 0) { - h[x].tko= atoi(val); - free(val); - if (h[x].tko <= 0) - h[x].tko = 1; - } - - logt_print(LOG_DEBUG, - "Heuristic: '%s' score=%d interval=%d tko=%d\n", - h[x].program, h[x].score, h[x].interval, h[x].tko); - - } while (++x < max); - - logt_print(LOG_DEBUG, "%d heuristics loaded\n", x); - - return x; -} - - -/** - Return the current score + maxscore to the caller - */ -int -get_my_score(int *score, int *maxscore) -{ - pthread_mutex_lock(&sc_lock); - *score = _score; - *maxscore = _maxscore; - pthread_mutex_unlock(&sc_lock); - - return 0; -} - - -/** - Call this if no heuristics are set to run in master-wins mode - */ -int -fudge_scoring(void) -{ - pthread_mutex_lock(&sc_lock); - _score = _maxscore = 1; - pthread_mutex_unlock(&sc_lock); - - return 0; -} - - -/** - Loop for the scoring thread. - */ -static void * -score_thread_main(void *arg) -{ - struct h_arg *args = (struct h_arg *)arg; - int score, maxscore; - - set_priority(args->sched_queue, args->sched_prio); - - while (_score_thread_running) { - fork_heuristics(args->h, args->count); - check_heuristics(args->h, args->count, 0); - total_score(args->h, args->count, &score, &maxscore); - - pthread_mutex_lock(&sc_lock); - _score = score; - _maxscore = maxscore; - pthread_mutex_unlock(&sc_lock); - - if (_score_thread_running) - sleep(1); - } - - free(args->h); - free(args); - logt_print(LOG_INFO, "Score thread going away\n"); - return (NULL); -} - - -/** - Start the score thread. h is copied into an argument which is - passed in as the arg parameter in the score thread, so it is safe - to pass in h if it was allocated on the stack. - */ -int -start_score_thread(qd_ctx *ctx, struct h_data *h, int count) -{ - pthread_attr_t attrs; - struct h_arg *args; - - if (!h || !count) - return -1; - - args = malloc(sizeof(struct h_arg)); - if (!args) - return -1; - - args->h = malloc(sizeof(struct h_data) * count); - if (!args->h) { - free(args); - return -1; - } - - memcpy(args->h, h, (sizeof(struct h_data) * count)); - args->count = count; - args->sched_queue = ctx->qc_sched; - args->sched_prio = ctx->qc_sched_prio; - - _score_thread_running = 1; - - pthread_attr_init(&attrs); - pthread_attr_setinheritsched(&attrs, PTHREAD_INHERIT_SCHED); - pthread_create(&score_thread, &attrs, score_thread_main, args); - pthread_attr_destroy(&attrs); - - if (score_thread) - return 0; - _score_thread_running = 0; - return -1; -} diff --git a/cman/qdisk/score.h b/cman/qdisk/score.h deleted file mode 100644 index 77e155b..0000000 --- a/cman/qdisk/score.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - @file Quorum daemon scoring functions + thread header file - */ -#ifndef _SCORE_H -#define _SCORE_H - -#include <time.h> -#include <sys/time.h> -#include <sys/types.h> - -struct h_data { - char * program; - int score; - int available; - int tko; - int interval; - int misses; - pid_t childpid; - time_t nextrun; -}; - -/* - Grab score data from CCSD - */ -int configure_heuristics(int ccsfd, struct h_data *hp, int max); - -/* - Start the thread which runs the scoring applets - */ -int start_score_thread(qd_ctx *ctx, struct h_data *h, int count); - -/* - Get our score + maxscore - */ -int get_my_score(int *score, int *maxscore); - -/* - Set score + maxscore to 1. Call if no heuristics are present - to enable master-wins mode - */ -int fudge_scoring(void); - - -#endif diff --git a/cman/services/Makefile.am b/cman/services/Makefile.am deleted file mode 100644 index 57fe042..0000000 --- a/cman/services/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -SUBDIRS = cman diff --git a/cman/services/cman/Makefile.am b/cman/services/cman/Makefile.am deleted file mode 100644 index 26df9bf..0000000 --- a/cman/services/cman/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -SUBDIRS = services lib include diff --git a/cman/services/cman/include/Makefile.am b/cman/services/cman/include/Makefile.am deleted file mode 100644 index 5226209..0000000 --- a/cman/services/cman/include/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -noinst_HEADERS = corosync/cman.h corosync/ipc_cman.h diff --git a/cman/services/cman/include/corosync/cman.h b/cman/services/cman/include/corosync/cman.h deleted file mode 100644 index baedf35..0000000 --- a/cman/services/cman/include/corosync/cman.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef CMAN_H_DEFINED -#define CMAN_H_DEFINED - -// Actually -- we return proper errnos -typedef enum { - CMAN_OK = 1, - CMAN_ERR_LIBRARY = 2, - CMAN_ERR_TIMEOUT = 5, - CMAN_ERR_TRY_AGAIN = 6, - CMAN_ERR_INVALID_PARAM = 7, - CMAN_ERR_NO_MEMORY = 8, - CMAN_ERR_BAD_HANDLE = 9, - CMAN_ERR_ACCESS = 11, - CMAN_ERR_NOT_EXIST = 12, - CMAN_ERR_EXIST = 14, - CMAN_ERR_NOT_SUPPORTED = 20, - CMAN_ERR_SECURITY = 29 -} cman_error_t; - -typedef unsigned int cman_handle_t; -typedef void (*cman_callback_t)(cman_handle_t handle, void *privdata, int reason, int arg); -typedef void (*cman_datacallback_t)(cman_handle_t handle, void *privdata, - char *buf, int len, uint8_t port, int nodeid); - -/* Shutdown flags */ -#define SHUTDOWN_ANYWAY 1 -#define SHUTDOWN_REMOVE 2 - -typedef enum {CMAN_REASON_PORTCLOSED, - CMAN_REASON_STATECHANGE, - CMAN_REASON_PORTOPENED, - CMAN_REASON_TRY_SHUTDOWN, - CMAN_REASON_CONFIG_UPDATE} cman_call_reason_t; - - - - - -#endif diff --git a/cman/services/cman/include/corosync/ipc_cman.h b/cman/services/cman/include/corosync/ipc_cman.h deleted file mode 100644 index d74f152..0000000 --- a/cman/services/cman/include/corosync/ipc_cman.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef IPC_CMAN_H_DEFINED -#define IPC_CMAN_H_DEFINED - -#include <netinet/in.h> - -#define CMAN_SERVICE 9 - -// These don't -enum req_cman_types { - MESSAGE_REQ_CMAN_SENDMSG = 0, - MESSAGE_REQ_CMAN_IS_LISTENING, - MESSAGE_REQ_CMAN_BIND, - MESSAGE_REQ_CMAN_UNBIND -}; - -enum res_cman_types { - MESSAGE_RES_CMAN_SENDMSG = 0, - MESSAGE_RES_CMAN_IS_LISTENING, - MESSAGE_RES_CMAN_BIND, - MESSAGE_RES_CMAN_UNBIND -}; - -#define TOTEMIP_ADDRLEN (sizeof(struct in6_addr)) - -struct req_lib_cman_bind { - coroipc_request_header_t header __attribute__((aligned(8))); - unsigned int port; -}; - -struct req_lib_cman_sendmsg { - coroipc_request_header_t header __attribute__((aligned(8))); - unsigned int to_port; - unsigned int to_node; - unsigned int msglen; - char message[]; -}; - -struct res_lib_cman_sendmsg { - coroipc_response_header_t header __attribute__((aligned(8))); - unsigned int from_port; - unsigned int from_node; - unsigned int msglen; - char message[]; -}; - -struct req_lib_cman_is_listening { - coroipc_request_header_t header __attribute__((aligned(8))); - unsigned int port; - unsigned int nodeid; -}; - -struct res_lib_cman_is_listening { - coroipc_response_header_t header __attribute__((aligned(8))); - unsigned int status; -}; - - -#endif diff --git a/cman/services/cman/lib/Makefile.am b/cman/services/cman/lib/Makefile.am deleted file mode 100644 index 0d7c74e..0000000 --- a/cman/services/cman/lib/Makefile.am +++ /dev/null @@ -1,21 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -libversion = 4:0:0 - -include_HEADERS = libcman.h - -pkgconfigdir = $(libdir)/pkgconfig - -pkgconfig_DATA = libcman.pc - -lib_LTLIBRARIES = libcman.la - -libcman_la_CPPFLAGS = -I$(top_srcdir)/config/libs/libccsconfdb \ - -I$(top_srcdir)/cman/services/cman/include - -libcman_la_CFLAGS = $(coroipcc_CFLAGS) $(cfg_CFLAGS) $(votequorum_CFLAGS) - -libcman_la_LDFLAGS = $(coroipcc_LIBS) $(cfg_LIBS) $(votequorum_LIBS) \ - -version-info $(libversion) - -libcman_la_LIBADD = $(top_builddir)/config/libs/libccsconfdb/libccs.la diff --git a/cman/services/cman/lib/libcman.c b/cman/services/cman/lib/libcman.c deleted file mode 100644 index aed5626..0000000 --- a/cman/services/cman/lib/libcman.c +++ /dev/null @@ -1,1274 +0,0 @@ -/* - * Provides a cman API using the corosync executive - */ - -#include "clusterautoconfig.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <pthread.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <errno.h> -#include <netdb.h> -#include <limits.h> - -#include <corosync/corotypes.h> -#include <corosync/coroipc_types.h> -#include <corosync/coroipcc.h> -#include <corosync/corodefs.h> -#include <corosync/hdb.h> -#include <corosync/cfg.h> -#include <corosync/confdb.h> -#include <corosync/votequorum.h> -#include <corosync/ipc_cman.h> - -#include "ccs.h" -#include "libcman.h" - -DECLARE_HDB_DATABASE(cman_handle_t_db,NULL); - -#define CMAN_MAGIC 0x434d414e - -#define IPC_REQUEST_SIZE 8192*128 -#define IPC_RESPONSE_SIZE 8192*128 -#define IPC_DISPATCH_SIZE 8192*128 - -#define CMAN_SHUTDOWN_ANYWAY 1 -#define CMAN_SHUTDOWN_REMOVED 2 - -struct cman_inst { - int magic; - hdb_handle_t handle; - int finalize; - void *privdata; - cman_datacallback_t data_callback; - cman_callback_t notify_callback; - - int node_count; - votequorum_node_t * node_list; - int node_list_size; - - corosync_cfg_handle_t cfg_handle; - votequorum_handle_t voteq_handle; -}; - -static void cfg_shutdown_callback( - corosync_cfg_handle_t handle, - corosync_cfg_shutdown_flags_t flags); - -static void votequorum_notification_callback( - votequorum_handle_t handle, - uint64_t context, - uint32_t quorate, - uint32_t node_list_entries, - votequorum_node_t node_list[]); - -static votequorum_callbacks_t cmq_callbacks = -{ - .votequorum_notify_fn = votequorum_notification_callback, -}; - -static corosync_cfg_callbacks_t cfg_callbacks = -{ - .corosync_cfg_state_track_callback = NULL, - .corosync_cfg_shutdown_callback = cfg_shutdown_callback, -}; - - -#define VALIDATE_HANDLE(h) do {if (!(h) || (h)->magic != CMAN_MAGIC) {errno = EINVAL; return -1;}} while (0) - -static struct cman_inst *admin_inst; - -static void cfg_shutdown_callback( - corosync_cfg_handle_t handle, - corosync_cfg_shutdown_flags_t flags) -{ - int cman_flags = 0; - - if (!admin_inst) - return; - - if (flags == COROSYNC_CFG_SHUTDOWN_FLAG_REGARDLESS) - cman_flags = CMAN_SHUTDOWN_ANYWAY; - - if (admin_inst->notify_callback) - admin_inst->notify_callback((void *)admin_inst, admin_inst->privdata, CMAN_REASON_TRY_SHUTDOWN, cman_flags); - -} - -static void votequorum_notification_callback( - votequorum_handle_t handle, - uint64_t context, - uint32_t quorate, - uint32_t node_list_entries, - votequorum_node_t node_list[]) -{ - struct cman_inst *cman_inst; - - votequorum_context_get(handle, (void **)&cman_inst); - - /* Save information for synchronous queries */ - cman_inst->node_count = node_list_entries; - if (cman_inst->node_list_size < node_list_entries) { - if (cman_inst->node_list) - free(cman_inst->node_list); - - cman_inst->node_list = malloc(sizeof(votequorum_node_t) * node_list_entries * 2); - if (cman_inst->node_list) { - memcpy(cman_inst->node_list, node_list, sizeof(votequorum_node_t) * node_list_entries); - cman_inst->node_list_size = node_list_entries; - } - } - - if (context && cman_inst->notify_callback) - cman_inst->notify_callback((void*)cman_inst, cman_inst->privdata, CMAN_REASON_STATECHANGE, quorate); -} - -static int votequorum_check_and_start(struct cman_inst *cman_inst) -{ - if (!cman_inst->voteq_handle) { - if (votequorum_initialize(&cman_inst->voteq_handle, &cmq_callbacks) != CS_OK) { - errno = ENOMEM; - return -1; - } - votequorum_context_set(cman_inst->voteq_handle, (void*)cman_inst); - } - return 0; -} - -static int refresh_node_list(struct cman_inst *cman_inst) -{ - int error; - - if (votequorum_check_and_start(cman_inst)) - return -1; - - votequorum_trackstart(cman_inst->voteq_handle, 0, CS_TRACK_CURRENT); - - error = votequorum_dispatch(cman_inst->voteq_handle, CS_DISPATCH_ONE); - return (error==CS_OK?0:-1); -} - -cman_handle_t cman_init ( - void *privdata) -{ - cs_error_t error; - hdb_handle_t handle; - struct cman_inst *cman_inst; - - error = hdb_handle_create (&cman_handle_t_db, sizeof (struct cman_inst), &handle); - if (error) { - goto error_no_destroy; - } - - error = hdb_handle_get (&cman_handle_t_db, handle, (void *)&cman_inst); - if (error) { - goto error_destroy; - } - - error = coroipcc_service_connect ( - COROSYNC_SOCKET_NAME, - CMAN_SERVICE, - IPC_REQUEST_SIZE, - IPC_RESPONSE_SIZE, - IPC_DISPATCH_SIZE, - &cman_inst->handle); - if (error != CS_OK) { - goto error_put_destroy; - } - - cman_inst->privdata = privdata; - cman_inst->magic = CMAN_MAGIC; - cman_inst->cfg_handle = (corosync_cfg_handle_t)0LL; - cman_inst->voteq_handle = (votequorum_handle_t)0LL; - - return (void *)cman_inst; - -error_put_destroy: - hdb_handle_put (&cman_handle_t_db, handle); -error_destroy: - hdb_handle_destroy (&cman_handle_t_db, handle); -error_no_destroy: - errno = ENOMEM; - return NULL; -} - -cman_handle_t cman_admin_init ( - void *privdata) -{ - if (admin_inst) { - errno = EBUSY; - return NULL; - } - - admin_inst = cman_init(privdata); - return admin_inst; -} - - -int cman_finish ( - cman_handle_t handle) -{ - struct cman_inst *cman_inst; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - if (cman_inst->voteq_handle) { - votequorum_finalize(cman_inst->voteq_handle); - cman_inst->voteq_handle = 0; - } - if (cman_inst->cfg_handle) { - corosync_cfg_finalize(cman_inst->cfg_handle); - cman_inst->cfg_handle = 0; - } - - if (handle == admin_inst) - admin_inst = NULL; - - /* - * Another thread has already started finalizing - */ - if (cman_inst->finalize) { - errno = EINVAL; - return -1; - } - - cman_inst->finalize = 1; - - /* - * Disconnect from the server - */ - coroipcc_service_disconnect (cman_inst->handle); - - return 0; -} - -/* These next four calls are the only ones that are specific to cman in the release. Everything else - * uses standard corosync or 'ccs' libraries. - * If you really want to do inter-node communications then CPG might be more appropriate to - * your needs. These functions are here partly to provide an API compatibility, but mainly - * to provide wire-protocol compatibility with older versions. - */ -int cman_start_recv_data ( - cman_handle_t handle, - cman_datacallback_t callback, - uint8_t port) -{ - int error; - struct cman_inst *cman_inst; - struct iovec iov[2]; - struct req_lib_cman_bind req_lib_cman_bind; - coroipc_response_header_t res; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - req_lib_cman_bind.header.size = sizeof (struct req_lib_cman_bind); - req_lib_cman_bind.header.id = MESSAGE_REQ_CMAN_BIND; - req_lib_cman_bind.port = port; - - iov[0].iov_base = (char *)&req_lib_cman_bind; - iov[0].iov_len = sizeof (struct req_lib_cman_bind); - - error = coroipcc_msg_send_reply_receive (cman_inst->handle, - iov, 1, - &res, sizeof (coroipc_response_header_t)); - - if (error != CS_OK) { - goto error_exit; - } - - errno = error = res.error; - -error_exit: - return (error==CS_OK?0:-1); -} - -int cman_end_recv_data ( - cman_handle_t handle) -{ - int error; - struct cman_inst *cman_inst; - struct iovec iov[2]; - coroipc_response_header_t req; - coroipc_response_header_t res; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - req.size = sizeof (coroipc_response_header_t); - req.id = MESSAGE_REQ_CMAN_UNBIND; - - iov[0].iov_base = (char *)&req; - iov[0].iov_len = sizeof (coroipc_response_header_t); - - error = coroipcc_msg_send_reply_receive (cman_inst->handle, - iov, 1, - &res, sizeof (coroipc_response_header_t)); - - if (error != CS_OK) { - goto error_exit; - } - - errno = error = res.error; - -error_exit: - - return (error?-1:0); -} - -int cman_send_data(cman_handle_t handle, const void *message, int len, int flags, uint8_t port, int nodeid) -{ - int error; - struct cman_inst *cman_inst; - struct iovec iov[2]; - char buf[len+sizeof(struct req_lib_cman_sendmsg)]; - struct req_lib_cman_sendmsg *req_lib_cman_sendmsg = (struct req_lib_cman_sendmsg *)buf; - coroipc_response_header_t res; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - req_lib_cman_sendmsg->header.size = sizeof (coroipc_response_header_t); - req_lib_cman_sendmsg->header.id = MESSAGE_REQ_CMAN_SENDMSG; - req_lib_cman_sendmsg->to_port = port; - req_lib_cman_sendmsg->to_node = nodeid; - req_lib_cman_sendmsg->msglen = len; - memcpy(req_lib_cman_sendmsg->message, message, len); - - iov[0].iov_base = buf; - iov[0].iov_len = len+sizeof(struct req_lib_cman_sendmsg); - - error = coroipcc_msg_send_reply_receive (cman_inst->handle, - iov, 1, - &res, sizeof (coroipc_response_header_t)); - - if (error != CS_OK) { - goto error_exit; - } - - errno = error = res.error; - -error_exit: - - return (error?-1:0); -} - -int cman_is_listening ( - cman_handle_t handle, - int nodeid, - uint8_t port) -{ - int error; - struct cman_inst *cman_inst; - struct iovec iov[2]; - struct res_lib_cman_is_listening res_lib_cman_is_listening; - struct req_lib_cman_is_listening req_lib_cman_is_listening; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - req_lib_cman_is_listening.header.size = sizeof (struct req_lib_cman_is_listening); - req_lib_cman_is_listening.header.id = MESSAGE_REQ_CMAN_IS_LISTENING; - req_lib_cman_is_listening.nodeid = nodeid; - req_lib_cman_is_listening.port = port; - - iov[0].iov_base = (char *)&req_lib_cman_is_listening; - iov[0].iov_len = sizeof (struct req_lib_cman_is_listening); - - error = coroipcc_msg_send_reply_receive (cman_inst->handle, - iov, 1, - &res_lib_cman_is_listening, sizeof (struct res_lib_cman_is_listening)); - - if (error != CS_OK) { - goto error_exit; - } - - errno = error = res_lib_cman_is_listening.header.error; - -error_exit: - - return (error?-1:0); -} - -/* This call is now handled by cfg */ -int cman_get_node_addrs ( - cman_handle_t handle, - int nodeid, - int max_addrs, - int *num_addrs, - struct cman_node_address *addrs) -{ - int error; - struct cman_inst *cman_inst; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - if (!cman_inst->cfg_handle) { - if (corosync_cfg_initialize(&cman_inst->cfg_handle, &cfg_callbacks) != CS_OK) { - errno = ENOMEM; - return -1; - } - } - - error = corosync_cfg_get_node_addrs(cman_inst->cfg_handle, nodeid, max_addrs, num_addrs, (corosync_cfg_node_address_t *)addrs); - - return (error==CS_OK?0:-1); -} - -/* - * An example of how we would query the quorum service. - * In fact we can use the lower-level quorum service if quorate all we - * needed to know - it provides the quorum state regardless of which - * quorum provider is loaded. - * Users of libcman typically are nosy and want to know all sorts of - * other things. - */ -int cman_is_quorate(cman_handle_t handle) -{ - struct cman_inst *cman_inst; - int quorate = -1; - struct votequorum_info info; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - if (votequorum_check_and_start(cman_inst)) - return -1; - - if (votequorum_getinfo(cman_inst->voteq_handle, 0, &info) != CS_OK) - errno = EINVAL; - else - quorate = ((info.flags & VOTEQUORUM_INFO_FLAG_QUORATE) != 0); - - return quorate; -} - -/* This call is now handled by cfg */ -int cman_shutdown(cman_handle_t handle, int flags) -{ - struct cman_inst *cman_inst; - int error; - corosync_cfg_shutdown_flags_t cfg_flags = 0; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - if (!cman_inst->cfg_handle) { - if (corosync_cfg_initialize(&cman_inst->cfg_handle, &cfg_callbacks) != CS_OK) { - errno = ENOMEM; - return -1; - } - } - - if (flags && CMAN_LEAVEFLAG_REMOVED) { - if (votequorum_check_and_start(cman_inst)) - return -1; - - votequorum_leaving(cman_inst->voteq_handle); - } - - if (flags == CMAN_SHUTDOWN_ANYWAY) - cfg_flags = COROSYNC_CFG_SHUTDOWN_FLAG_REGARDLESS; - - error = corosync_cfg_try_shutdown(cman_inst->cfg_handle, cfg_flags); - - /* ERR_LIBRARY happens because corosync shuts down while we are connected */ - if (error == CS_ERR_LIBRARY || error == CS_OK) - error = 0; - - return error; -} -/* - * This call is now mostly handled by cfg. - * However if we want to do a "leave remove" then we need to tell - * votequorum first. - */ -int cman_leave_cluster(cman_handle_t handle, int flags) -{ - struct cman_inst *cman_inst; - int error; - corosync_cfg_shutdown_flags_t cfg_flags = 0; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - if (!cman_inst->cfg_handle) { - if (corosync_cfg_initialize(&cman_inst->cfg_handle, &cfg_callbacks) != CS_OK) { - errno = ENOMEM; - return -1; - } - } - - /* Tell votequorum to reduce quorum when we go */ - if (flags && CMAN_LEAVEFLAG_REMOVED) { - if (votequorum_check_and_start(cman_inst)) - return -1; - - votequorum_leaving(cman_inst->voteq_handle); - } - - - cfg_flags = COROSYNC_CFG_SHUTDOWN_FLAG_IMMEDIATE; - - error = corosync_cfg_try_shutdown(cman_inst->cfg_handle, cfg_flags); - /* ERR_LIBRARY happens because corosync shuts down while we are connected */ - if (error == CS_ERR_LIBRARY || error == CS_OK) - error = 0; - - return error; -} - -/* This call is now handled by cfg */ -int cman_replyto_shutdown(cman_handle_t handle, int flags) -{ - struct cman_inst *cman_inst; - int error; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - if (!cman_inst->cfg_handle) { - if (corosync_cfg_initialize(&cman_inst->cfg_handle, &cfg_callbacks) != CS_OK) { - errno = ENOMEM; - return -1; - } - } - - error = corosync_cfg_replyto_shutdown(cman_inst->cfg_handle, flags); - - return error; -} - -/* This call is now handled by cfg */ -int cman_kill_node(cman_handle_t handle, int nodeid) -{ - struct cman_inst *cman_inst; - int error; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - if (!cman_inst->cfg_handle) { - if (corosync_cfg_initialize(&cman_inst->cfg_handle, &cfg_callbacks) != CS_OK) { - errno = ENOMEM; - return -1; - } - } - - error = corosync_cfg_kill_node(cman_inst->cfg_handle, nodeid, "Killed by cman_tool"); - - return (error==CS_OK?0:-1); -} - -/* This call is handled by votequorum */ -int cman_set_votes(cman_handle_t handle, int votes, int nodeid) -{ - struct cman_inst *cman_inst; - int error; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - if (votequorum_check_and_start(cman_inst)) - return -1; - - error = votequorum_setvotes(cman_inst->voteq_handle, nodeid, votes); - - return (error==CS_OK?0:-1); -} - -/* This call is handled by votequorum */ -int cman_set_expected_votes(cman_handle_t handle, int expected) -{ - struct cman_inst *cman_inst; - int error; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - if (votequorum_check_and_start(cman_inst)) - return -1; - - error = votequorum_setexpected(cman_inst->voteq_handle, expected); - - return (error==CS_OK?0:-1); -} - -int cman_get_fd ( - cman_handle_t handle) -{ - struct cman_inst *cman_inst; - int fd; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - coroipcc_fd_get (cman_inst->handle, &fd); - - return fd; -} - -int cman_getprivdata( - cman_handle_t handle, - void **context) -{ - struct cman_inst *cman_inst; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - *context = cman_inst->privdata; - - return (CS_OK); -} - -int cman_setprivdata( - cman_handle_t handle, - void *context) -{ - struct cman_inst *cman_inst; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - cman_inst->privdata = context; - - return (CS_OK); -} - -/* This call is handled by votequorum */ -int cman_register_quorum_device(cman_handle_t handle, char *name, int votes) -{ - struct cman_inst *cman_inst; - int error; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - if (votequorum_check_and_start(cman_inst)) - return -1; - - error = votequorum_qdisk_register(cman_inst->voteq_handle, name, votes); - - return error; -} - -/* This call is handled by votequorum */ -int cman_unregister_quorum_device(cman_handle_t handle) -{ - struct cman_inst *cman_inst; - int error; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - if (votequorum_check_and_start(cman_inst)) - return -1; - - error = votequorum_qdisk_unregister(cman_inst->voteq_handle); - - return error; -} - -/* This call is handled by votequorum */ -int cman_poll_quorum_device(cman_handle_t handle, int isavailable) -{ - struct cman_inst *cman_inst; - int error; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - if (votequorum_check_and_start(cman_inst)) - return -1; - - error = votequorum_qdisk_poll(cman_inst->voteq_handle, 1); - - return error; -} - -/* This call is handled by votequorum */ -int cman_get_quorum_device(cman_handle_t handle, struct cman_qdev_info *info) -{ - struct cman_inst *cman_inst; - int error; - struct votequorum_qdisk_info qinfo; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - if (votequorum_check_and_start(cman_inst)) - return -1; - - error = votequorum_qdisk_getinfo(cman_inst->voteq_handle, &qinfo); - - if (!error) { - info->qi_state = qinfo.state; - info->qi_votes = qinfo.votes; - strcpy(info->qi_name, qinfo.name); - } - - return error; -} - -/* This call is handled by votequorum */ -int cman_set_dirty(cman_handle_t handle) -{ - struct cman_inst *cman_inst; - int error; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - if (votequorum_check_and_start(cman_inst)) - return -1; - - error = votequorum_setstate(cman_inst->voteq_handle); - - return error; -} - - -struct res_overlay { - coroipc_response_header_t header __attribute__((aligned(8))); - char data[512000]; -}; - - -int cman_dispatch ( - cman_handle_t handle, - int dispatch_types) -{ - int timeout = -1; - cs_error_t error = CS_OK; - int cont = 1; /* always continue do loop except when set to 0 */ - int dispatch_avail; - struct cman_inst *cman_inst; - struct res_overlay dispatch_data; - struct res_lib_cman_sendmsg *res_lib_cman_sendmsg; - - if (dispatch_types != CS_DISPATCH_ONE && - dispatch_types != CS_DISPATCH_ALL && - dispatch_types != CS_DISPATCH_BLOCKING) { - - errno = EINVAL; - return -1; - } - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - /* - * Timeout instantly for SA_DISPATCH_ONE or CS_DISPATCH_ALL and - * wait indefinately for CS_DISPATCH_BLOCKING - */ - if (dispatch_types == CS_DISPATCH_ALL) { - timeout = 0; - } - - do { - dispatch_avail = coroipcc_dispatch_get (cman_inst->handle, - (void *)&dispatch_data, timeout); - - if (error != CS_OK) { - goto error_put; - } - - if (dispatch_avail == 0 && dispatch_types == CMAN_DISPATCH_ALL) { - break; /* exit do while cont is 1 loop */ - } else - if (dispatch_avail == 0) { - continue; /* next poll */ - } - if (dispatch_avail == -1) { - if (cman_inst->finalize == 1) { - error = 0; - } else { - errno = EINVAL; - error = -1; - } - goto error_put; - } - - /* - * Dispatch incoming message - */ - switch (dispatch_data.header.id) { - - case MESSAGE_RES_CMAN_SENDMSG: - if (cman_inst->data_callback == NULL) { - continue; - } - res_lib_cman_sendmsg = (struct res_lib_cman_sendmsg *)&dispatch_data; - - cman_inst->data_callback ( handle, - cman_inst->privdata, - res_lib_cman_sendmsg->message, - res_lib_cman_sendmsg->msglen, - res_lib_cman_sendmsg->from_port, - res_lib_cman_sendmsg->from_node); - break; - - default: - error = -1; - errno = EINVAL; - goto error_put; - break; - } - - /* - * Determine if more messages should be processed - * */ - switch (dispatch_types) { - case CS_DISPATCH_ONE: - cont = 0; - break; - case CS_DISPATCH_ALL: - break; - case CS_DISPATCH_BLOCKING: - break; - } - } while (cont); - - goto error_put; - -error_put: - return (error); -} - -/* - * This call expects to get a listing of all nodes known to the - * system so we query ccs rather than corosync, as some nodes - * might not be up yet - */ -int cman_get_node_count(cman_handle_t handle) -{ - struct cman_inst *cman_inst; - int ccs_handle; - int num_nodes = 0; - char path[PATH_MAX]; - char *value; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - /* Returns the number of nodes known to ccs, not cman! */ - ccs_handle = ccs_connect(); - - sprintf(path, "/cluster/clusternodes/clusternode[%d]/@name", num_nodes+1); - - while (!ccs_get(ccs_handle, path, &value)) - { - num_nodes++; - sprintf(path, "/cluster/clusternodes/clusternode[%d]/@name", num_nodes+1); - }; - - ccs_disconnect(ccs_handle); - return num_nodes; -} - -int cman_is_active(cman_handle_t handle) -{ - struct cman_inst *cman_inst; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - /* If we have connected, then 'cman' is active */ - return 1; -} - -/* - * Here we just read values from ccs - */ -int cman_get_cluster(cman_handle_t handle, cman_cluster_t *clinfo) -{ - struct cman_inst *cman_inst; - int ccs_handle; - char *value; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - ccs_handle = ccs_connect(); - if (!ccs_get(ccs_handle, "/cluster/@name", &value)) { - strcpy(clinfo->ci_name, value); - free(value); - } - if (!ccs_get(ccs_handle, "/cluster/cman/@cluster_id", &value)) { - clinfo->ci_number = atoi(value); - free(value); - } - else { - clinfo->ci_number = 0; - } - clinfo->ci_generation = 0; // CC: TODO ??? - - ccs_disconnect(ccs_handle); - - return 0; -} - -/* - * libccs doesn't do writes yet so we need to use confdb to - * change the config version. - * This will signal votequorum to reload the configuration 'file' - */ -int cman_set_version(cman_handle_t handle, const cman_version_t *version) -{ - struct cman_inst *cman_inst; - confdb_handle_t confdb_handle; - unsigned int ccs_handle; - char *value; - char error[256]; - int ret = 0; - int cur_version=0; - confdb_callbacks_t callbacks = { - .confdb_key_change_notify_fn = NULL, - .confdb_object_create_change_notify_fn = NULL, - .confdb_object_delete_change_notify_fn = NULL - }; - - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - ccs_handle = ccs_connect(); - if (!ccs_get(ccs_handle, "/cluster/@config_version", &value)) { - cur_version = atoi(value); - free(value); - } - ccs_disconnect(ccs_handle); - - if (cur_version && cur_version >= version->cv_config) { - errno = EINVAL; - return -1; - } - - if (confdb_initialize(&confdb_handle, &callbacks) != CS_OK) { - errno = EINVAL; - return -1; - } - - if (confdb_reload(confdb_handle, 0, error, sizeof(error)) != CS_OK) { - errno = EINVAL; - ret = -1; - } - - confdb_finalize(confdb_handle); - return ret; -} - - -/* This mainly just retreives values from ccs */ -int cman_get_version(cman_handle_t handle, cman_version_t *version) -{ - struct cman_inst *cman_inst; - int ccs_handle; - char *value; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - ccs_handle = ccs_connect(); - if (!ccs_get(ccs_handle, "/cluster/@config_version", &value)) { - version->cv_config = atoi(value); - free(value); - } - - /* These are cman_tool versions now ;-) */ - version->cv_major = 7; - version->cv_minor = 0; - version->cv_patch = 1; - ccs_disconnect(ccs_handle); - - return 0; -} - - - -static char *node_name(corosync_cfg_node_address_t *addr) -{ - static char name[256]; - - if (getnameinfo((struct sockaddr *)addr->address, addr->address_length, name, sizeof(name), NULL, 0, NI_NAMEREQD)) - return NULL; - else - return name; -} - -/* - * This is a slightly complicated mix of ccs and votequorum queries. - * votequorum only knows about active nodes and does not hold node names. - * so once we have a list of active nodes we fill in the names - * and also the nodes that have never been seen by corosync. - */ -int cman_get_nodes(cman_handle_t handle, int maxnodes, int *retnodes, cman_node_t *nodes) -{ - struct cman_inst *cman_inst; - int ccs_handle; - char *value; - int ret; - int i; - int num_nodes = 0; - char path[PATH_MAX]; - int noconfig_flag=0; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - refresh_node_list(cman_inst); - ccs_handle = ccs_connect(); - - if (!ccs_get(ccs_handle, "/cluster/@no_config", &value)) { - noconfig_flag = atoi(value); - free(value); - } - - /* If we don't have a config file we will have to look up node names */ - if (noconfig_flag) { - int max_addrs = 4; - corosync_cfg_node_address_t addrs[max_addrs]; - int num_addrs; - char *name = NULL; - int error; - - if (!cman_inst->cfg_handle) { - if (corosync_cfg_initialize(&cman_inst->cfg_handle, &cfg_callbacks) != CS_OK) { - errno = ENOMEM; - return -1; - } - } - - for (i=0; i < cman_inst->node_count; i++) { - nodes[i].cn_nodeid = cman_inst->node_list[i].nodeid; - name = NULL; - - error = corosync_cfg_get_node_addrs(cman_inst->cfg_handle, nodes[i].cn_nodeid, max_addrs, &num_addrs, addrs); - if (error == CS_OK) { - name = node_name(&addrs[0]); - } - if (name) { - sprintf(nodes[i].cn_name, "%s", name); - } - else { - sprintf(nodes[i].cn_name, "Node-%x", nodes[i].cn_nodeid); - } - - nodes[i].cn_member = (cman_inst->node_list[i].state == NODESTATE_MEMBER); - } - } - else { - - /* We DO have a config file, reconcile in-memory with configuration */ - do { - sprintf(path, "/cluster/clusternodes/clusternode[%d]/@name", num_nodes+1); - ret = ccs_get(ccs_handle, path, &value); - if (!ret) { - strcpy(nodes[num_nodes].cn_name, value); - free(value); - } - - sprintf(path, "/cluster/clusternodes/clusternode[%d]/@nodeid", num_nodes+1); - ret = ccs_get(ccs_handle, path, &value); - if (!ret) { - nodes[num_nodes].cn_nodeid = atoi(value); - free(value); - } - - /* Reconcile with active nodes list. */ - for (i=0; i < cman_inst->node_count; i++) { - if (cman_inst->node_list[i].nodeid == nodes[num_nodes].cn_nodeid) { - nodes[num_nodes].cn_member = (cman_inst->node_list[i].state == NODESTATE_MEMBER); - } - } - - num_nodes++; - } while (ret == 0 && num_nodes < maxnodes); - } - - *retnodes = num_nodes-1; - if (cman_inst->node_count > *retnodes) - *retnodes = cman_inst->node_count; - ccs_disconnect(ccs_handle); - return 0; -} - -int cman_get_disallowed_nodes(cman_handle_t handle, int maxnodes, int *retnodes, cman_node_t *nodes) -{ - struct cman_inst *cman_inst; - int i; - int num_nodes = 0; - int ccs_handle; - char *value; - int ret; - char path[PATH_MAX]; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - refresh_node_list(cman_inst); - ccs_handle = ccs_connect(); - - for (i=0; i < cman_inst->node_count; i++) { - if (cman_inst->node_list[i].state == NODESTATE_DISALLOWED) { - nodes[num_nodes].cn_nodeid = cman_inst->node_list[i].nodeid; - - /* Find the name: */ - sprintf(path, "/cluster/clusternodes/clusternode[@nodeid="%d"]/@name", cman_inst->node_list[i].nodeid); - ret = ccs_get(ccs_handle, path, &value); - if (!ret) { - strcpy(nodes[num_nodes].cn_name, value); - free(value); - } - else { - sprintf(nodes[i].cn_name, "Node-%x", nodes[i].cn_nodeid); - } - } - } - *retnodes = num_nodes; - ccs_disconnect(ccs_handle); - return 0; - -} - -int cman_get_node(cman_handle_t handle, int nodeid, cman_node_t *node) -{ - struct cman_inst *cman_inst; - struct votequorum_info qinfo; - int i; - int ccs_handle; - int ret = 0; - char *value; - char path[PATH_MAX]; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - refresh_node_list(cman_inst); - ccs_handle = ccs_connect(); - - if (node->cn_name[0] == '\0') { - /* Query by node ID */ - if (nodeid == CMAN_NODEID_US) { - if (votequorum_getinfo(cman_inst->voteq_handle, 0, &qinfo) != CS_OK) { - return -1; - } - nodeid = node->cn_nodeid = qinfo.node_id; - } - - sprintf(path, "/cluster/clusternodes/clusternode[@nodeid="%d"]/@name", nodeid); - ret = ccs_get(ccs_handle, path, &value); - if (!ret) { - strcpy(node->cn_name, value); - free(value); - } - } - else { - /* Query by node name */ - sprintf(path, "/cluster/clusternodes/clusternode[@name="%s"]/@nodeid", node->cn_name); - ret = ccs_get(ccs_handle, path, &value); - if (!ret) { - node->cn_nodeid = atoi(value); - free(value); - } - } - - /* Fill in state */ - node->cn_member = 3; /* Not in cluster */ - for (i=0; i < cman_inst->node_count; i++) { - if (cman_inst->node_list[i].nodeid == node->cn_nodeid) { - if (cman_inst->node_list[i].state == NODESTATE_MEMBER) - node->cn_member = 2; - } - } - - return 0; -} - -int cman_start_notification(cman_handle_t handle, cman_callback_t callback) -{ - struct cman_inst *cman_inst; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - if (votequorum_check_and_start(cman_inst)) - return -1; - - cman_inst->notify_callback = callback; - - if (votequorum_trackstart(cman_inst->voteq_handle, (uint64_t)(long)handle, CS_TRACK_CURRENT) != CS_OK) - return -1; - - return 0; -} - -int cman_stop_notification(cman_handle_t handle) -{ - struct cman_inst *cman_inst; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - votequorum_trackstop(cman_inst->voteq_handle); - cman_inst->notify_callback = NULL; - - return 0; -} - - -/* This is not complete ... but that's my problem, not yours */ -int cman_get_extra_info(cman_handle_t handle, cman_extra_info_t *info, int maxlen) -{ - struct cman_inst *cman_inst; - unsigned int ccs_handle; - char *value; - struct votequorum_info qinfo; - - cman_inst = (struct cman_inst *)handle; - VALIDATE_HANDLE(cman_inst); - - refresh_node_list(cman_inst); - - if (votequorum_getinfo(cman_inst->voteq_handle, 0, &qinfo) != CS_OK) { - return -1; - } - - memset(info, 0, sizeof(cman_extra_info_t)); - info->ei_flags = qinfo.flags; - info->ei_node_votes = qinfo.node_votes; - info->ei_total_votes = qinfo.total_votes; - info->ei_expected_votes = qinfo.node_expected_votes; - info->ei_quorum = qinfo.quorum; - info->ei_members = cman_inst->node_count; - info->ei_node_state = 2; - info->ei_num_addresses = 1; - - ccs_handle = ccs_connect(); - if (!ccs_get(ccs_handle, "/totem/interface/@broadcast", &value)) { - strcpy(info->ei_addresses, "255.255.255.255"); - free(value); - } - else if (!ccs_get(ccs_handle, "/totem/interface/@mcastaddr", &value)) { - strcpy(info->ei_addresses, value); - free(value); - } - - if (!ccs_get(ccs_handle, "/cluster/@no_config", &value)) { - free(value); - info->ei_flags |= CMAN_EXTRA_FLAG_NOCONFIG; - } - - - ccs_disconnect(ccs_handle); - - return 0; -} - diff --git a/cman/services/cman/lib/libcman.h b/cman/services/cman/lib/libcman.h deleted file mode 100644 index 3489025..0000000 --- a/cman/services/cman/lib/libcman.h +++ /dev/null @@ -1,418 +0,0 @@ -#ifndef _LIBCMAN_H_ -#define _LIBCMAN_H_ - -#include <netinet/in.h> - -#define LIBCMAN_VERSION 3 - -/* - * Some maxima - */ -#define CMAN_MAX_ADDR_LEN sizeof(struct sockaddr_in6) -#define CMAN_MAX_NODENAME_LEN 255 -#define MAX_CLUSTER_NAME_LEN 16 -#define CMAN_MAX_FENCE_AGENT_NAME_LEN 255 - -/* - * Pass this into cman_get_node() as the nodeid to get local node information - */ -#define CMAN_NODEID_US 0 - -/* - * Pass this into cman_get_node() as the nodeid to get quorum device information - */ -#define CMAN_NODEID_QDISK -1 - - -/* Pass this into cman_send_data to send a message to all nodes */ -#define CMAN_NODEID_ALL 0 - -/* - * Hang onto this, it's your key into the library. get one from cman_init() or - * cman_admin_init() - */ -typedef void *cman_handle_t; - -/* - * Reasons we get an event callback. - * PORTOPENED & TRY_SHUTDOWN only exist when LIBCMAN_VERSION >= 2 - * - * The 'arg' parameter varies depending on the callback type. - * for PORTCLOSED/PORTOPENED arg == the port opened/closed - * for STATECHANGE arg is quorum state (1=quorate, 0=not) - * for TRY_SHUTDOWN arg == 1 for ANYWAY, otherwise 0 (ie if arg == 1 - * then cman WILL shutdown regardless - * of your response, think of this as advance warning) - * for CONFIG_UPDATE arg will be the new config version - */ -typedef enum {CMAN_REASON_PORTCLOSED, - CMAN_REASON_STATECHANGE, - CMAN_REASON_PORTOPENED, - CMAN_REASON_TRY_SHUTDOWN, - CMAN_REASON_CONFIG_UPDATE} cman_call_reason_t; - -/* - * Reason flags for cman_leave - */ -#define CMAN_LEAVEFLAG_DOWN 0 -#define CMAN_LEAVEFLAG_REMOVED 3 -#define CMAN_LEAVEFLAG_FORCE 0x10 - -/* - * Flags for cman_shutdown - * ANYWAY - cman will shutdown regardless of clients' responses (but they - * will still get told) - * REMOVED - the rest of the cluster will adjust quorum to stay quorate - */ -#define CMAN_SHUTDOWN_ANYWAY 1 -#define CMAN_SHUTDOWN_REMOVED 2 - -/* - * Flags passed to cman_dispatch(): - * CMAN_DISPATCH_ONE dispatches a single message then returns, - * CMAN_DISPATCH_ALL dispatches all outstanding messages (ie till EAGAIN) then - * returns, - * CMAN_DISPATCH_BLOCKING forces it to wait for a message (clears MSG_DONTWAIT - * in recvmsg) - * CMAN_DISPATCH_IGNORE_* allows the caller to select which messages to process. - */ -#define CMAN_DISPATCH_ONE 0 -#define CMAN_DISPATCH_ALL 1 -#define CMAN_DISPATCH_BLOCKING 2 -#define CMAN_DISPATCH_IGNORE_REPLY 4 -#define CMAN_DISPATCH_IGNORE_DATA 8 -#define CMAN_DISPATCH_IGNORE_EVENT 16 -#define CMAN_DISPATCH_TYPE_MASK 3 -#define CMAN_DISPATCH_IGNORE_MASK 46 - -/* - * A node address. This is a complete sockaddr_in[6] - * To explain: - * If you cast cna_address to a 'struct sockaddr', the sa_family field - * will be AF_INET or AF_INET6. Armed with that knowledge you can then - * cast it to a sockaddr_in or sockaddr_in6 and pull out the address. - * No other sockaddr fields are valid. - * Also, you must ignore any part of the sockaddr beyond the length supplied - */ -typedef struct cman_node_address -{ - int cna_addrlen; - char cna_address[CMAN_MAX_ADDR_LEN]; -} cman_node_address_t; - -/* - * Return from cman_get_node() - */ -typedef struct cman_node -{ - int cn_nodeid; - cman_node_address_t cn_address; - char cn_name[CMAN_MAX_NODENAME_LEN+1]; - int cn_member; - int cn_incarnation; - struct timeval cn_jointime; -} cman_node_t; - -/* - * Returned from cman_get_version(), - * input to cman_set_version(), though only cv_config can be changed - */ -typedef struct cman_version -{ - unsigned int cv_major; - unsigned int cv_minor; - unsigned int cv_patch; - unsigned int cv_config; -} cman_version_t; - -/* - * Return from cman_get_cluster() - */ -typedef struct cman_cluster -{ - char ci_name[MAX_CLUSTER_NAME_LEN+1]; - uint16_t ci_number; - uint32_t ci_generation; -} cman_cluster_t; - -/* - * This is returned from cman_get_extra_info - it's really - * only for use by cman_tool, don't depend on this not changing - */ - -/* Flags in ei_flags - NOTE: These have changed from Cluster2/3! */ -#define CMAN_EXTRA_FLAG_HASSTATE 1 -#define CMAN_EXTRA_FLAG_DISALLOWED 2 -#define CMAN_EXTRA_FLAG_2NODE 4 -#define CMAN_EXTRA_FLAG_QUORATE 8 -#define CMAN_EXTRA_FLAG_NOCONFIG 256 - -typedef struct cman_extra_info { - int ei_node_state; - int ei_flags; - int ei_node_votes; - int ei_total_votes; - int ei_expected_votes; - int ei_quorum; - int ei_members; - char ei_ports[32]; - int ei_num_addresses; - char ei_addresses[1]; /* Array of num_addresses*sockaddr_storage*2 - First batch is the multicast address list */ -} cman_extra_info_t; - -/* Quorum device info, returned from cman_get_quorum_device() */ -typedef struct cman_qdev_info { - char qi_name[CMAN_MAX_NODENAME_LEN+1]; - int qi_state; - int qi_votes; -} cman_qdev_info_t; - -/* - * NOTE: Apart from cman_replyto_shutdown(), you must not - * call other cman_* functions while in these two callbacks: - */ - -/* Callback routine for a membership or other event */ -typedef void (*cman_callback_t)(cman_handle_t handle, void *privdata, int reason, int arg); - -/* Callback routine for data received */ -typedef void (*cman_datacallback_t)(cman_handle_t handle, void *privdata, - char *buf, int len, uint8_t port, int nodeid); - -/* Callback for nodes joining/leaving */ -typedef void (*cman_confchgcallback_t)(cman_handle_t handle, void *privdata, - unsigned int *member_list, int member_list_entries, - unsigned int *left_list, int left_list_entries, - unsigned int *joined_list, int joined_list_entries); - -/* - * cman_init returns the handle you need to pass to the other API calls. - * cman_admin_init opens admin socket for privileged operations. - * cman_finish destroys that handle. - * - * Note that admin sockets can't send data messages or receive callbacks. - */ -cman_handle_t cman_init(void *privdata); -cman_handle_t cman_admin_init(void *privdata); -int cman_finish(cman_handle_t handle); - -/* Update/retrieve the private data */ -int cman_setprivdata(cman_handle_t h, void *privdata); -int cman_getprivdata(cman_handle_t h, void **privdata); - -/* - * Notification of membership change events. Note that these are sent after - * a transition, so multiple nodes may have left or joined the cluster. - */ -int cman_start_notification(cman_handle_t handle, cman_callback_t callback); -int cman_stop_notification(cman_handle_t handle); - -/* - * Start/stop AIS-style confchg callbacks. These are less racy than the - * old cman callbacks in that the caller will get one for each AIS - * confchg message and it will contain all of the nodes that joined & - * left in that transition. - */ -int cman_start_confchg(cman_handle_t handle, cman_confchgcallback_t callback); -int cman_stop_confchg(cman_handle_t handle); - -/* Call this if you get a TRY_SHUTDOWN event to signal whether you - * will let cman shutdown or not. - * Note that getting this callback does not mean that cman WILL shutdown, - * only that it might. To detect a cman shutdown see cman_dispatch() below. - */ -int cman_replyto_shutdown(cman_handle_t, int yesno); - - -/* - * Get the internal CMAN fd so you can pass it into poll() or select(). - * When it's active then call cman_dispatch() on the handle to process the event - * NOTE: This fd can change between calls to cman_dispatch() so always call this - * routine to get the latest one. (This is mainly due to message caching). - * One upshot of this is that you must never read or write this FD (it may on - * occasion point to /dev/zero if you have messages cached!) - */ -int cman_get_fd(cman_handle_t handle); - -/* - * cman_dispatch() will return -1 with errno == EHOSTDOWN if the cluster is - * shut down, 0 if nothing was read, or a positive number if something was - * dispatched. - */ - -int cman_dispatch(cman_handle_t handle, int flags); - - -/* - * ----------------------------------------------------------------------------- - * Get info calls. - */ - -/* Return the number of nodes we know about. This will normally - * be the number of nodes in CCS - */ -int cman_get_node_count(cman_handle_t handle); - -/* Returns the number of connected clients. This isn't as useful as a it used to - * be as a count >1 does not automatically mean cman won't shut down. Subsystems - * can decide for themselves whether a clean shutdown is possible. - */ -int cman_get_subsys_count(cman_handle_t handle); - -/* Returns an array of node info structures. Call cman_get_node_count() first - * to determine how big your array needs to be - */ -int cman_get_nodes(cman_handle_t handle, int maxnodes, int *retnodes, cman_node_t *nodes); - -/* Returns a list of nodes that are known to AIS but blocked from joining the - * CMAN cluster because they rejoined with cluster without a cman_tool join - */ -int cman_get_disallowed_nodes(cman_handle_t handle, int maxnodes, int *retnodes, cman_node_t *nodes); - -/* - * cman_get_node() can get node info by nodeid OR by name. If the first - * char of node->cn_name is zero then the nodeid will be used, otherwise - * the name will be used. I'll say this differently: If you want to look - * up a node by nodeid, you MUST clear out the cman_node_t structure passed - * into cman_get_node(). nodeid can be CMAN_NODEID_US. - */ -int cman_get_node(cman_handle_t handle, int nodeid, cman_node_t *node); - -/* cman_get_node() only returns the first address of a node (whatever /that/ - * may mean). If you want to know all of them you need to call this. - * max_addrs is the size of the 'addrs' array. num_addrs will be filled in by - * the number of addresses the node has, regardless of the size of max_addrs. - * So if you don't allocate enough space for the first call, you should know how - * much is needed for a second! - */ -int cman_get_node_addrs(cman_handle_t handle, int nodeid, int max_addrs, int *num_addrs, struct cman_node_address *addrs); - -/* Returns 1 if cman has completed initialisation and aisexec is running */ -int cman_is_active(cman_handle_t handle); - -/* - * Returns 1 if a client is registered for data callbacks on a particular - * port on a particular node. if cman returns -1 (errno==EBUSY) then it - * doesn't currently know the status but has requested it, so try again - * later or wait for a PORTOPENED notification. - * nodeid can be CMAN_NODEID_US - */ -int cman_is_listening(cman_handle_t handle, int nodeid, uint8_t port); - -/* Do we have quorum? */ -int cman_is_quorate(cman_handle_t handle); - -/* Return software & config (cluster.conf file) version */ -int cman_get_version(cman_handle_t handle, cman_version_t *version); - -/* Get cluster name and number */ -int cman_get_cluster(cman_handle_t handle, cman_cluster_t *clinfo); - -/* Get fence information for a node. - * 'int *fenced' is only valid if the node is down, it is set to - * 1 if the node has been fenced since it left the cluster. - * agent should be CMAN_MAX_FENCE_AGENT_NAME_LEN - */ -int cman_get_fenceinfo(cman_handle_t handle, int nodeid, uint64_t *fence_time, int *fenced, char *agent); - -/* Get stuff for cman_tool. Nobody else should use this */ -int cman_get_extra_info(cman_handle_t handle, cman_extra_info_t *info, int maxlen); - -/* Dump the objdb contents (only works if compiled with DEBUG enabled) */ -int cman_dump_objdb(cman_handle_t handle, char *filename); - -/* - * ----------------------------------------------------------------------------- - * Admin functions. You will need privileges and have a handle created by - * cman_admin_init() to use them. - */ - -/* Change the config file version. This should be needed much less now, as - * cman will re-read the config file if a new node joins with a new config - * version */ -int cman_set_version(cman_handle_t handle, const cman_version_t *version); - -/* Deprecated in favour of cman_shutdown(). Use cman_tool anyway please. */ -int cman_leave_cluster(cman_handle_t handle, int reason); - -/* Change the number of votes for this node. NOTE: a CCS update will - overwrite this, so make sure you change both. Or, better, change CCS - and call set_version() */ -int cman_set_votes(cman_handle_t handle, int votes, int nodeid); - -/* As above, for expected_votes */ -int cman_set_expected_votes(cman_handle_t handle, int expected_votes); - -/* Tell a particular node to leave the cluster NOW */ -int cman_kill_node(cman_handle_t handle, int nodeid); - -/* Tell CMAN a node has been fenced, when and by what means. */ -int cman_node_fenced(cman_handle_t handle, int nodeid, uint64_t fence_time, char *agent); - -/* - * cman_shutdown() will send a REASON_TRY_SHUTDOWN event to all - * clients registered for notifications. They should respond by calling - * cman_replyto_shutdown() to indicate whether they will allow - * cman to close down or not. If cman gets >=1 "no" (0) replies or the - * request times out (default 5 seconds) then shutdown will be - * cancelled and cman_shutdown() will return -1 with errno == EBUSY. - * - * Set flags to CMAN_SHUTDOWN_ANYWAY to force shutdown. Clients will still - * be notified /and/ they will know you want a forced shutdown. - * - * Setting flags to CMAN_SHUTDOWN_REMOVED will tell the rest of the - * cluster to adjust quorum to keep running with this node has left - */ -int cman_shutdown(cman_handle_t, int flags); - -/* ----------------------------------------------------------------------------- - * Data transmission API. Uses the same FD as the rest of the calls. - * If the nodeid passed to cman_send_data() is zero then it will be - * broadcast to all nodes in the cluster. - * cman_start_recv_data() is like a bind(), and marks the port - * as "listening". See cman_is_listening() above. - */ -int cman_send_data(cman_handle_t handle, const void *buf, int len, int flags, uint8_t port, int nodeid); -int cman_start_recv_data(cman_handle_t handle, cman_datacallback_t, uint8_t port); -int cman_end_recv_data(cman_handle_t handle); - -/* - * Barrier API. - * Here for backwards compatibility. Most of the things you would achieve - * with this can now be better done using openAIS services or just messaging. - */ -int cman_barrier_register(cman_handle_t handle, const char *name, int flags, int nodes); -int cman_barrier_change(cman_handle_t handle, const char *name, int flags, int arg); -int cman_barrier_wait(cman_handle_t handle, const char *name); -int cman_barrier_delete(cman_handle_t handle, const char *name); - -/* - * Add your own quorum device here, needs an admin socket - * - * After creating a quorum device you will need to call 'poll_quorum_device' - * at least once every (default) 10 seconds (this can be changed in CCS) - * otherwise it will time-out and the cluster will lose its vote. - */ -int cman_register_quorum_device(cman_handle_t handle, char *name, int votes); -int cman_unregister_quorum_device(cman_handle_t handle); -int cman_poll_quorum_device(cman_handle_t handle, int isavailable); -int cman_get_quorum_device(cman_handle_t handle, struct cman_qdev_info *info); - -/* - * Sets the dirty bit inside cman. This indicates that the node has - * some internal 'state' (eg in a daemon, filesystem or lock manager) - * and cannot merge with another cluster that already has state. - * This needs an admin socket. It cannot be reset. - */ -int cman_set_dirty(cman_handle_t handle); - -/* - * From STABLE3 branch this call tells corosync to execute: - * logsys_config_debug_set(CMAN_NAME, value); - * and debugging for all CMAN subsystems is on. - */ -int cman_set_debuglog(cman_handle_t handle, int value); - -#endif diff --git a/cman/services/cman/lib/libcman.pc.in b/cman/services/cman/lib/libcman.pc.in deleted file mode 100644 index 7e9342c..0000000 --- a/cman/services/cman/lib/libcman.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=${prefix} -libdir=@libdir@ -includedir=${prefix}/include - -Name: libcman -Version: @VERSION@ -Description: Cluster Manager library -Requires: -Libs: -L${libdir} -lcman -Cflags: -I${includedir} diff --git a/cman/services/cman/services/Makefile.am b/cman/services/cman/services/Makefile.am deleted file mode 100644 index 6e4f611..0000000 --- a/cman/services/cman/services/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -I$(top_srcdir)/cman/services/cman/include - -AM_CFLAGS = -fPIC \ - $(cfg_CFLAGS) - -LCRSO = service_cmanbits.lcrso - -SOURCES = cman.c - -EXTRA_DIST = $(SOURCES) - -include $(top_srcdir)/make/lcrso.mk diff --git a/cman/services/cman/services/cman.c b/cman/services/cman/services/cman.c deleted file mode 100644 index eb8ce25..0000000 --- a/cman/services/cman/services/cman.c +++ /dev/null @@ -1,571 +0,0 @@ -#include "clusterautoconfig.h" - -#ifndef COROSYNC_BSD -#include <alloca.h> -#endif -#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 <signal.h> -#include <limits.h> -#include <time.h> -#include <unistd.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <corosync/corotypes.h> -#include <corosync/coroipc_types.h> -#include <corosync/cfg.h> -#include <corosync/list.h> -#include <corosync/lcr/lcr_comp.h> -#include <corosync/engine/logsys.h> -#include <corosync/engine/coroapi.h> -#include <corosync/ipc_cman.h> -#include <corosync/cman.h> - -#define CMAN_MAJOR_VERSION 6 -#define CMAN_MINOR_VERSION 3 -#define CMAN_PATCH_VERSION 0 - -#define MAX_INTERFACES 4 - -LOGSYS_DECLARE_SUBSYS ("CMAN"); - -/* Messages we send on port 0 */ -#define CLUSTER_MSG_PORTOPENED 2 -#define CLUSTER_MSG_PORTCLOSED 3 -#define CLUSTER_MSG_PORTENQ 9 -#define CLUSTER_MSG_PORTSTATUS 10 - -/* This structure is tacked onto the start of a cluster message packet for our - * own nefarious purposes. */ -struct cman_protheader { - unsigned char tgtport; /* Target port number */ - unsigned char srcport; /* Source (originating) port number */ - unsigned short pad; - unsigned int flags; - int srcid; /* Node ID of the sender */ - int tgtid; /* Node ID of the target */ -}; - -static hdb_handle_t group_handle; -static struct corosync_tpg_group cman_group[1] = { - { .group = "CMAN", .group_len = 4}, -}; - -struct cman_pd { - void *conn; - unsigned char port; /* Bound port number */ - struct list_head list; -}; - -struct cluster_node { - int nodeid; -#define NODE_FLAG_PORTS_VALID 1 - int flags; -#define PORT_BITS_SIZE 32 - unsigned char port_bits[PORT_BITS_SIZE]; /* bitmap of ports open on this node */ - struct list_head list; -}; - -/* An array of open 'ports' containing the connection to send - responses to */ -static void *ports[256]; -static struct cluster_node our_node; -static struct corosync_api_v1 *corosync_api; -static struct list_head conn_list; -static struct list_head node_list; - -#define list_iterate(v, head) \ - for (v = (head)->next; v != head; v = v->next) - - -/* - * Service Interfaces required by service_message_handler struct - */ - -static void cman_deliver_fn(unsigned int nodeid, const void *buf, unsigned int buf_len, - int endian_conversion_required); - -static void cman_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 cman_exec_init_fn (struct corosync_api_v1 *corosync_api); - -static int cman_lib_init_fn (void *conn); - -static int cman_lib_exit_fn (void *conn); - -static void message_handler_req_lib_cman_is_listening (void *conn, const void *msg); -static void message_handler_req_lib_cman_sendmsg (void *conn, const void *msg); -static void message_handler_req_lib_cman_unbind (void *conn, const void *msg); -static void message_handler_req_lib_cman_bind (void *conn, const void *msg); - -/* - * Library Handler Definition - */ -static struct corosync_lib_handler cman_lib_service[] = -{ - { /* 0 */ - .lib_handler_fn = message_handler_req_lib_cman_sendmsg, - .flow_control = COROSYNC_LIB_FLOW_CONTROL_REQUIRED - }, - { /* 1 */ - .lib_handler_fn = message_handler_req_lib_cman_is_listening, - .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED - }, - { /* 2 */ - .lib_handler_fn = message_handler_req_lib_cman_bind, - .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED - }, - { /* 3 */ - .lib_handler_fn = message_handler_req_lib_cman_unbind, - .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED - } -}; - -static struct corosync_service_engine cman_service_handler = { - .name = "corosync cluster cman service v3.01", - .id = CMAN_SERVICE, - .private_data_size = sizeof (struct cman_pd), - .allow_inquorate = CS_LIB_ALLOW_INQUORATE, - .flow_control = COROSYNC_LIB_FLOW_CONTROL_REQUIRED, - .lib_init_fn = cman_lib_init_fn, - .lib_exit_fn = cman_lib_exit_fn, - .lib_engine = cman_lib_service, - .lib_engine_count = sizeof (cman_lib_service) / sizeof (struct corosync_lib_handler), - .exec_init_fn = cman_exec_init_fn, - .exec_engine = NULL, - .exec_engine_count = 0, - .sync_mode = CS_SYNC_V1, -}; - -/* - * Dynamic loader definition - */ -static struct corosync_service_engine *cman_get_service_handler_ver0 (void); - -static struct corosync_service_engine_iface_ver0 cman_service_handler_iface = { - .corosync_get_service_engine_ver0 = cman_get_service_handler_ver0 -}; - -static struct lcr_iface corosync_cman_ver0[1] = { - { - .name = "corosync_cman", - .version = 0, - .versions_replace = 0, - .versions_replace_count = 0, - .dependencies = 0, - .dependency_count = 0, - .constructor = NULL, - .destructor = NULL, - .interfaces = NULL - } -}; - -static struct lcr_comp cman_comp_ver0 = { - .iface_count = 1, - .ifaces = corosync_cman_ver0 -}; - - -static struct corosync_service_engine *cman_get_service_handler_ver0 (void) -{ - return (&cman_service_handler); -} - -__attribute__ ((constructor)) static void cman_comp_register (void) { - lcr_interfaces_set (&corosync_cman_ver0[0], &cman_service_handler_iface); - - lcr_component_register (&cman_comp_ver0); -} - - - -/* These just make the access a little neater */ -static inline int objdb_get_string(struct corosync_api_v1 *corosync, hdb_handle_t object_service_handle, - char *key, char **value) -{ - int res; - - *value = NULL; - if ( !(res = corosync->object_key_get(object_service_handle, - key, - strlen(key), - (void *)value, - NULL))) { - if (*value) - return 0; - } - return -1; -} - -static inline void objdb_get_int(struct corosync_api_v1 *corosync, hdb_handle_t object_service_handle, - char *key, unsigned int *intvalue, unsigned int default_value) -{ - char *value = NULL; - - *intvalue = default_value; - - if (!corosync->object_key_get(object_service_handle, key, strlen(key), - (void *)&value, NULL)) { - if (value) { - *intvalue = atoi(value); - } - } -} - -static void set_port_bit(struct cluster_node *node, uint8_t port) -{ - int byte; - int bit; - - byte = port/8; - bit = port%8; - - node->port_bits[byte] |= 1<<bit; -} - -static void clear_port_bit(struct cluster_node *node, uint8_t port) -{ - int byte; - int bit; - - byte = port/8; - bit = port%8; - - node->port_bits[byte] &= ~(1<<bit); -} - -static int get_port_bit(struct cluster_node *node, uint8_t port) -{ - int byte; - int bit; - - byte = port/8; - bit = port%8; - - return ((node->port_bits[byte] & (1<<bit)) != 0); -} - -static struct cluster_node *find_node(int nodeid, int allocate) -{ - struct list_head *tmp; - struct cluster_node *node; - - list_iterate(tmp, &node_list) { - node = list_entry(tmp, struct cluster_node, list); - if (node->nodeid == nodeid) - return node; - } - if (allocate) { - node = malloc(sizeof(struct cluster_node)); - if (node) { - memset(node, 0, sizeof(*node)); - node->nodeid = nodeid; - list_add(&node->list, &node_list); - } - } - else { - node = NULL; - } - - return node; -} - - -static int cman_send_message(int fromport, int toport, int tonode, void *message, int len) -{ - struct iovec iov[2]; - struct cman_protheader header; - - header.tgtport = toport; - header.srcport = fromport; - header.flags = 0; - header.srcid = our_node.nodeid; - header.tgtid = tonode; - - iov[0].iov_base = &header; - iov[0].iov_len = sizeof(header); - iov[1].iov_base = message; - iov[1].iov_len = len; - - return corosync_api->tpg_joined_mcast(group_handle, iov, 2, TOTEM_AGREED); -} - -static int cman_exec_init_fn (struct corosync_api_v1 *api) -{ - hdb_handle_t find_handle; - - log_printf(LOGSYS_LEVEL_NOTICE, "cman_exec_init_fn \n"); - - corosync_api = api; - - memset(ports, 0, sizeof(ports)); - memset(&our_node, 0, sizeof(our_node)); - list_init(&conn_list); - list_init(&node_list); - - our_node.nodeid = corosync_api->totem_nodeid_get(); - list_add(&our_node.list, &node_list); - set_port_bit(&our_node, 1); - our_node.flags |= NODE_FLAG_PORTS_VALID; - - /* Get configuration variables */ - corosync_api->object_find_create(OBJECT_PARENT_HANDLE, "cman", strlen("cman"), &find_handle); - // TODO ?? - corosync_api->object_find_destroy(find_handle); - - api->tpg_init(&group_handle, cman_deliver_fn, cman_confchg_fn); - api->tpg_join(group_handle, cman_group, 1); - return (0); -} - -static int cman_lib_init_fn (void *conn) -{ - struct cman_pd *cman_pd = (struct cman_pd *)corosync_api->ipc_private_data_get (conn); - - list_add(&cman_pd->list, &conn_list); - return 0; -} - -static int cman_lib_exit_fn (void *conn) -{ - struct cman_pd *cman_pd = (struct cman_pd *)corosync_api->ipc_private_data_get (conn); - - if (cman_pd->port) { - char portmsg[2]; - - ports[cman_pd->port] = NULL; - - /* Tell the cluster */ - portmsg[0] = CLUSTER_MSG_PORTCLOSED; - portmsg[1] = cman_pd->port; - cman_send_message(0,0, 0, portmsg, 2); - } - - list_del(&cman_pd->list); - return (0); -} - -static void cman_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 i; - struct cluster_node *node; - - /* Clear out removed nodes */ - for (i=0; i<left_list_entries; i++) { - node = find_node(left_list[i], 0); - if (node) - node->flags &= ~NODE_FLAG_PORTS_VALID; - } -} - - -static void cman_deliver_fn(unsigned int nodeid, const void *msg, unsigned int buf_len, - int endian_conversion_required) -{ - const struct cman_protheader *inheader = msg; - struct cman_protheader header; - const char *buf = msg; - - if (endian_conversion_required) { - header.srcid = swab32(inheader->srcid); - header.tgtid = swab32(inheader->tgtid); - header.flags = swab32(inheader->flags); - } - else { - memcpy(&header, buf, sizeof(header)); - } - - /* Messages to be sent to clients */ - if (header.tgtport != 0 && - (header.tgtid == our_node.nodeid || - header.tgtid == 0)) { - buf += sizeof(struct cman_protheader); - - if (ports[header.tgtport]) { - corosync_api->ipc_response_send(ports[header.tgtport], buf, buf_len - sizeof(struct cman_protheader)); - } - } - - /* Our messages. Careful here, messages for the quorum module on port 0 also - arrive here and must be ignored */ - if (header.tgtport == 0 && - (header.tgtid == our_node.nodeid || - header.tgtid == 0)) { - struct cluster_node *node; - - buf += sizeof(struct cman_protheader); - node = find_node(header.tgtid, 1); - - switch (*buf) { - case CLUSTER_MSG_PORTOPENED: - if (node) { - if (!(node->flags & NODE_FLAG_PORTS_VALID)) { - char reqmsg = CLUSTER_MSG_PORTENQ; - cman_send_message(0,0, nodeid, &reqmsg, 1); - } - set_port_bit(node, buf[2]); - } - break; - case CLUSTER_MSG_PORTCLOSED: - if (node) { - if (!(node->flags & NODE_FLAG_PORTS_VALID)) { - char reqmsg = CLUSTER_MSG_PORTENQ; - cman_send_message(0,0, nodeid, &reqmsg, 1); - } - clear_port_bit(node, buf[2]); - } - break; - case CLUSTER_MSG_PORTENQ: - if (node) { - char portresult[PORT_BITS_SIZE+1]; - - portresult[0] = CLUSTER_MSG_PORTSTATUS; - memcpy(portresult+1, our_node.port_bits, PORT_BITS_SIZE); - cman_send_message(0,0, 0, portresult, PORT_BITS_SIZE+1); - } - break; - case CLUSTER_MSG_PORTSTATUS: - if (node && node != &our_node) { - memcpy(node->port_bits, buf+1, PORT_BITS_SIZE); - node->flags |= NODE_FLAG_PORTS_VALID; - } - break; - } - } -} - -static void message_handler_req_lib_cman_bind (void *conn, const void *msg) -{ - coroipc_response_header_t res; - struct req_lib_cman_bind *req_lib_cman_bind = (struct req_lib_cman_bind *)msg; - struct cman_pd *cman_pd = (struct cman_pd *)corosync_api->ipc_private_data_get (conn); - int error = 0; - char portmsg[2]; - - if (req_lib_cman_bind->port < 0 || - req_lib_cman_bind->port > 255) - error = EINVAL; - - if (cman_pd->port || ports[req_lib_cman_bind->port]) { - error = EADDRINUSE; - } - if (error == CS_OK) { - cman_pd->port = req_lib_cman_bind->port; - ports[cman_pd->port] = conn; - - /* Tell the cluster */ - portmsg[0] = CLUSTER_MSG_PORTOPENED; - portmsg[1] = cman_pd->port; - cman_send_message(0,0, 0, portmsg, 2); - } - - res.size = sizeof(res); - res.id = MESSAGE_RES_CMAN_BIND; - res.error = error; - corosync_api->ipc_response_send(conn, &res, sizeof(res)); -} - -static void message_handler_req_lib_cman_unbind (void *conn, const void *msg) -{ - coroipc_response_header_t res; - struct cman_pd *cman_pd = (struct cman_pd *)corosync_api->ipc_private_data_get (conn); - int error = 0; - char portmsg[2]; - - if (cman_pd->port) { - ports[cman_pd->port] = NULL; - cman_pd->port = 0; - - /* Tell the cluster */ - portmsg[0] = CLUSTER_MSG_PORTCLOSED; - portmsg[1] = cman_pd->port; - cman_send_message(0,0, 0, portmsg, 2); - } - - res.size = sizeof(res); - res.id = MESSAGE_RES_CMAN_UNBIND; - res.error = error; - corosync_api->ipc_response_send(conn, &res, sizeof(res)); -} - -static void message_handler_req_lib_cman_sendmsg (void *conn, const void *msg) -{ - struct req_lib_cman_sendmsg *req_lib_cman_sendmsg = (struct req_lib_cman_sendmsg *)msg; - coroipc_response_header_t res; - struct cman_pd *cman_pd = (struct cman_pd *)corosync_api->ipc_private_data_get (conn); - int error = CS_OK; - - - if (!cman_pd->port) { - error = EINVAL; - } - else { - error = cman_send_message(cman_pd->port, - req_lib_cman_sendmsg->to_port, - req_lib_cman_sendmsg->to_node, - req_lib_cman_sendmsg->message, - req_lib_cman_sendmsg->msglen); - } - - res.size = sizeof(res); - res.id = MESSAGE_RES_CMAN_SENDMSG; - res.error = error; - corosync_api->ipc_response_send(conn, &res, sizeof(res)); -} - -static void message_handler_req_lib_cman_is_listening (void *conn, const void *msg) -{ - struct req_lib_cman_is_listening *req_lib_cman_is_listening = (struct req_lib_cman_is_listening *)msg; - struct res_lib_cman_is_listening res_lib_cman_is_listening; - int error = CS_OK; - struct cluster_node *node; - -// How I think this should work: -// There's a flag on the node that says whether we have complete port info or not. -// If we do, then we can just return it. -// If not then we do a port_enquire to get it (and return EBUSY). -// If we get a PORTOPEN or PORTCLOSE and we don't have complete info then request it, -// otherwise just update the record. -// Remember - this needs to be backwards compatible - - node = find_node(req_lib_cman_is_listening->nodeid, 0); - if (!node) - error = ENOENT; - if (node && !(node->flags & NODE_FLAG_PORTS_VALID)) - error = EBUSY; - - if (error == EBUSY) { - char reqmsg = CLUSTER_MSG_PORTENQ; - cman_send_message(0,0, req_lib_cman_is_listening->nodeid, &reqmsg, 1); - } - else { - if (node) { - res_lib_cman_is_listening.status = get_port_bit(node, req_lib_cman_is_listening->port); - error = 0; - } - } - - res_lib_cman_is_listening.header.size = sizeof(res_lib_cman_is_listening); - res_lib_cman_is_listening.header.id = MESSAGE_RES_CMAN_SENDMSG; - res_lib_cman_is_listening.header.error = error; - corosync_api->ipc_response_send(conn, &res_lib_cman_is_listening, sizeof(res_lib_cman_is_listening)); -} diff --git a/cman/tests/Makefile.am b/cman/tests/Makefile.am deleted file mode 100644 index 1f91f89..0000000 --- a/cman/tests/Makefile.am +++ /dev/null @@ -1,13 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -noinst_PROGRAMS = client sysman sysmand #libtestc qwait user_service - -EXTRA_DIST = user_service.c - -AM_CPPFLAGS = -I$(top_srcdir)/cman/services/cman/lib - -libcman_LDADD = $(top_builddir)/cman/services/cman/lib/libcman.la - -client_LDADD = $(libcman_LDADD) -sysman_LDADD = $(libcman_LDADD) -sysmand_LDADD = $(libcman_LDADD) diff --git a/cman/tests/client.c b/cman/tests/client.c deleted file mode 100644 index 3eabb6d..0000000 --- a/cman/tests/client.c +++ /dev/null @@ -1,115 +0,0 @@ -/* test client */ -#include "clusterautoconfig.h" - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/uio.h> -#include <sys/time.h> -#include <sys/ioctl.h> -#include <sys/utsname.h> -#include <netinet/in.h> -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> - -#include "libcman.h" - -static cman_handle_t handle; -static void get_members(void); - -static void event_callback(cman_handle_t callback_handle, void *private, int reason, int arg) -{ - get_members(); -} - - -static void data_callback(cman_handle_t callback_handle, void *private, - char *buf, int len, uint8_t port, int nodeid) -{ - printf("Received from node %d port %d: '%s'\n", nodeid, port, buf); -} - - -int main(int argc, char *argv[]) -{ - - unsigned char port = 100; - char message[256]; - struct utsname ubuf; - - if (argc >= 2) - port = atoi(argv[1]); - - if (argc >= 3) - strcpy(message, argv[2]); - - printf("Cluster port number is %d\n", port); - uname(&ubuf); - sprintf(message, "Hello from %s", ubuf.nodename); - - handle = cman_init(NULL); - if (!handle) - { - perror("Can't connect to cman"); - return -1; - } - - - if (cman_start_recv_data(handle, data_callback, port)) - { - perror("Can't bind cluster socket"); - return -1; - } - cman_start_notification(handle, event_callback); - - while (1) - { - - if (cman_send_data(handle, message, strlen(message)+1,0, port, 0) < 0) - { - perror("write"); - cman_finish(handle); - exit(-1); - } - - while (1) - { - if (cman_dispatch(handle, CMAN_DISPATCH_ALL|CMAN_DISPATCH_BLOCKING) == -1) - break; - } - } - fprintf(stderr, "EOF: finished\n"); -} - - -void get_members(void) -{ - cman_node_t *nodes; - int i; - int num_nodes = cman_get_node_count(handle); - - if (num_nodes == -1) - { - perror("get nodes"); - } - else - { - printf("There are %d nodes: \n", num_nodes); - - nodes = malloc(num_nodes * sizeof(cman_node_t)); - if ( (cman_get_nodes(handle, num_nodes, &num_nodes, nodes))) - { - for (i=0; i<num_nodes; i++) - { - printf("%s %d\n", nodes[i].cn_name, nodes[i].cn_nodeid); - } - } - else - { - perror("get node details"); - } - } -} diff --git a/cman/tests/libtest.c b/cman/tests/libtest.c deleted file mode 100644 index ce007b7..0000000 --- a/cman/tests/libtest.c +++ /dev/null @@ -1,134 +0,0 @@ -#include "clusterautoconfig.h" - -#include <netinet/in.h> -#include <inttypes.h> -#include "libcman.h" - -#include <stdlib.h> -#include <stdio.h> - -static void cman_callback(cman_handle_t handle, void *private, int reason, int arg) -{ - printf("callback called reason = %d, arg=%d\n", reason, arg); -} - -static void confchg_callback(cman_handle_t handle, void *private, - unsigned int *member_list, int member_list_entries, - unsigned int *left_list, int left_list_entries, - unsigned int *joined_list, int joined_list_entries) -{ - int i; - printf("Confchg callback\n"); - printf("member_list: %d entries:\n", member_list_entries); - for (i=0; i<member_list_entries; i++) - printf(" %d\n", member_list[i]); - printf("left_list: %d entries:\n", left_list_entries); - for (i=0; i<left_list_entries; i++) - printf(" %d\n", left_list[i]); - printf("joined_list: %d entries:\n", joined_list_entries); - for (i=0; i<joined_list_entries; i++) - printf(" %d\n", joined_list[i]); -} - -static void print_node(cman_node_t *node) -{ - printf(" node id %d\n", node->cn_nodeid); - printf(" node member %d\n", node->cn_member); - printf(" node name %s\n", node->cn_name); - printf(" node incarn %d\n", node->cn_incarnation); - printf("\n"); -} - -int main() -{ - cman_handle_t h; - int num; - int retnodes; - cman_node_t *nodes; - cman_version_t ver; - cman_cluster_t clinfo; - - h = cman_init(0); - if (!h) - { - perror("cman_init failed"); - exit(1); - } - - num = cman_get_node_count(h); - if (num > 0) - printf("cluster has %d nodes\n", num); - else - perror("node count"); - - printf("cman is active: %d\n", cman_is_active(h)); - printf("cman is quorate: %d\n", cman_is_quorate(h)); - printf("cman is listening: %d\n", cman_is_listening(h, CMAN_NODEID_US, 1)); /* membership! */ - cman_get_version(h, &ver); - printf("cman version %d.%d.%d (config %d)\n", - ver.cv_minor, - ver.cv_major, - ver.cv_patch, - ver.cv_config); - - if (!cman_get_cluster(h, &clinfo)) - { - printf("Cluster '%s', number %d\n", clinfo.ci_name, clinfo.ci_number); - } - else - perror("cluster info failed"); - - nodes = malloc(num * sizeof(cman_node_t)); - if (!nodes) - { - perror("malloc"); - exit(1); - } - - if (!cman_get_nodes(h, num, &retnodes, nodes)) - { - int i; - printf("Getting all nodes:\n"); - for (i=0; i<retnodes; i++) - print_node(&nodes[i]); - } - else - { - perror("get_nodes failed"); - } - - // Need to clear this. - // Who wrote this rubbish? oh, I did. - nodes[0].cn_name[0] = '\0'; - if (!cman_get_node(h, CMAN_NODEID_US, &nodes[0])) - { - printf("Getting our info:\n"); - print_node(&nodes[0]); - } - else - { - perror("get_node failed"); - } - - if (cman_start_notification(h, cman_callback)) - { - perror("start_notification"); - } - - if (cman_start_confchg(h, confchg_callback)) - { - perror("start_confchg"); - } - - - while (1) { - int ret = cman_dispatch(h, CMAN_DISPATCH_BLOCKING | CMAN_DISPATCH_ALL); - if (ret == -1) { - perror("cman_dispatch"); - break; - } - } - cman_finish(h); - - return 0; -} diff --git a/cman/tests/qwait.c b/cman/tests/qwait.c deleted file mode 100644 index 1200307..0000000 --- a/cman/tests/qwait.c +++ /dev/null @@ -1,60 +0,0 @@ -#include "clusterautoconfig.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/uio.h> -#include <sys/un.h> -#include <sys/time.h> -#include <sys/ioctl.h> -#include <sys/utsname.h> -#include <netinet/in.h> -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <unistd.h> -#include <fcntl.h> - -#include "cnxman-socket.h" - -static int cluster_sock; - -static void signal_handler(int sig) -{ - - return; -} - - -int main(int argc, char *argv[]) -{ - struct sigaction sa; - sigset_t ss; - - cluster_sock = socket(AF_CLUSTER, SOCK_DGRAM, CLPROTO_CLIENT); - if (cluster_sock == -1) - { - perror("Can't open cluster socket"); - return -1; - } - sa.sa_handler = signal_handler; - sa.sa_mask = ss; - sa.sa_flags = 0; - sigaction(SIGUSR1, &sa, NULL); - - if (ioctl(cluster_sock, SIOCCLUSTER_NOTIFY, SIGUSR1) == -1) - { - perror("Can't set up cluster notification"); - close(cluster_sock); - return -1; - } - - while (!ioctl(cluster_sock, SIOCCLUSTER_ISQUORATE, 0)) - { - pause(); - } - - close(cluster_sock); - - return 0; -} diff --git a/cman/tests/sysman.c b/cman/tests/sysman.c deleted file mode 100644 index 1f61844..0000000 --- a/cman/tests/sysman.c +++ /dev/null @@ -1,75 +0,0 @@ -#include "clusterautoconfig.h" - -/* "sysman" client */ -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/uio.h> -#include <sys/un.h> -#include <sys/time.h> -#include <sys/ioctl.h> -#include <sys/utsname.h> -#include <netinet/in.h> -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <unistd.h> -#include <fcntl.h> -#include <limits.h> - -#define LOCAL_SOCKNAME CLUSTERVARRUN "/sysman" -static int open_local_sock(void); - -int main(int argc, char *argv[]) -{ - char message[PIPE_BUF]; - int local_sock; - int len; - - if (argc < 2) - { - printf("usage: sysman "command"\n"); - return 0; - } - - local_sock = open_local_sock(); - if (local_sock < 0) - exit(2); - - /* Send the command */ - write(local_sock, argv[1], strlen(argv[1])+1); - - /* Print the replies */ - while ( (len = read(local_sock, message, sizeof(message))) ) - { - write(STDOUT_FILENO, message, len); - } - printf("\n"); - return 0; -} - - -static int open_local_sock(void) -{ - int local_socket; - struct sockaddr_un sockaddr; - - // Open local socket - local_socket = socket(PF_UNIX, SOCK_STREAM, 0); - if (local_socket < 0) - { - perror("Can't create local socket"); - return -1; - } - - strcpy(sockaddr.sun_path, LOCAL_SOCKNAME); - sockaddr.sun_family = AF_UNIX; - if (connect(local_socket, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) - { - fprintf(stderr, "sysmand is not running\n"); - close(local_socket); - return -1; - } - return local_socket; -} - diff --git a/cman/tests/sysmand.c b/cman/tests/sysmand.c deleted file mode 100644 index 03591fa..0000000 --- a/cman/tests/sysmand.c +++ /dev/null @@ -1,472 +0,0 @@ -/* "sysman" server - - Listens on a cluster port and executes commands. - - This is just a demonstration piece of code, not for production use - - ************************************* - *** IT IS A MASSIVE SECURITY HOLE *** - ************************************* - - Any command passed to it will be run as root! - -*/ -#include "clusterautoconfig.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/uio.h> -#include <sys/un.h> -#include <sys/time.h> -#include <sys/ioctl.h> -#include <sys/utsname.h> -#include <sys/errno.h> -#include <syslog.h> -#include <netinet/in.h> -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <time.h> -#include <unistd.h> -#include <fcntl.h> -#include <limits.h> - -#include "libcman.h" -#define LOCAL_SOCKNAME CLUSTERVARRUN "/sysman" -#define CLUSTER_PORT_SYSMAN 12 - -static cman_node_t *nodes = NULL; -static int num_nodes; -static cman_handle_t ch; -static int expected_responses; - -/* Header for all commands sent to other sysmand servers */ -struct sysman_header -{ - int fd; /* local FD to return output to. in network byte order */ - int ret; /* Return code of command */ - char cmd; -#define SYSMAN_CMD_REQUEST 1 -#define SYSMAN_CMD_REPLY 2 -}; - -/* One of these for each fd we are listening on - some fields are specific to particular types. -*/ -struct read_fd -{ - int fd; - enum {CLUSTER_SOCK, LOCAL_RENDEZVOUS, LOCAL_SOCK} type; - int nodes_done; - time_t start_time; - struct read_fd *next; -}; -/* Head of the fd list. Also contains - the cluster_socket details */ -static struct read_fd read_fd_head; - - -static void get_members(void); -static int open_local_sock(void); -static int exec_command(char *cmd, char *reply, int *len); -static int name_from_nodeid(int nodeid, char *name); -static void remove_sock(struct read_fd *deadfd); -static struct read_fd *find_by_fd(int fd); -static int nodes_listening(int); - -static void event_callback(cman_handle_t handle, void *private, int reason, int arg) -{ - get_members(); -} - -static void data_callback(cman_handle_t handle, void *private, - char *buf, int len, uint8_t port, int nodeid) -{ - struct read_fd *replyfd = NULL; - char reply[PIPE_BUF]; - char title[PIPE_BUF]; - char nodename[CMAN_MAX_NODENAME_LEN]; - struct sysman_header *header; - int status; - int title_len; - struct sysman_header *inheader = (struct sysman_header *)buf; - - switch (inheader->cmd) - { - case SYSMAN_CMD_REQUEST: - - /* Execute command and capture stdout/stderr into 'reply'*/ - status = exec_command(buf+sizeof(struct sysman_header), reply+sizeof(struct sysman_header), &len); - - header = (struct sysman_header *)reply; - - /* Send reply */ - header->fd = inheader->fd; /* Already in the right format */ - header->cmd = SYSMAN_CMD_REPLY; - header->ret = htonl(status); - - cman_send_data(ch, reply, len, 0, port, nodeid); - break; - - case SYSMAN_CMD_REPLY: - name_from_nodeid(nodeid, nodename); - title_len = sprintf(title, "\nReply from %s:", nodename); - if (inheader->ret != 0) - title_len += sprintf(title+title_len, " (ret=%d)", ntohl(inheader->ret)); - strcat(title, "\n"); title_len++; - write(ntohl(inheader->fd), title, title_len); - write(ntohl(inheader->fd), buf+sizeof(struct sysman_header), - len - sizeof(struct sysman_header)); - - replyfd = find_by_fd(ntohl(inheader->fd)); - if (replyfd) - { - /* If we've done all nodes then close the client down */ - if (++replyfd->nodes_done == expected_responses) - { - close(replyfd->fd); - remove_sock(replyfd); - } - } - break; - - default: - name_from_nodeid(nodeid, nodename); - syslog(LOG_ERR, "Unknown sysman command received from %s: %d\n", - nodename, inheader->cmd); - break; - } -} - -int main(int argc, char *argv[]) -{ - unsigned char port = CLUSTER_PORT_SYSMAN; - int local_sock; - struct read_fd *newfd; - struct utsname nodeinfo; - - ch = cman_init(NULL); - if (!ch) - { - perror("Can't connect to cman"); - return -1; - } - - uname(&nodeinfo); - - if (cman_start_recv_data(ch, data_callback, port)) - { - perror("Can't bind cluster socket"); - return -1; - } - - cman_start_notification(ch, event_callback); - - read_fd_head.fd = cman_get_fd(ch); - read_fd_head.type = CLUSTER_SOCK; - - /* Preload cluster members list */ - get_members(); - - /* Just a sensible default, we work out just how many - responses we expect properly later */ - expected_responses = num_nodes; - - /* Open the Unix socket we listen for commands on */ - local_sock = open_local_sock(); - if (local_sock < 0) - exit(2); - - newfd = malloc(sizeof(struct read_fd)); - if (!newfd) - exit(2); - - newfd->fd = local_sock; - newfd->type = LOCAL_RENDEZVOUS; - newfd->next = NULL; - read_fd_head.next = newfd; - - while (1) - { - fd_set in; - struct read_fd *thisfd; - struct timeval tv = {10,0}; - - read_fd_head.fd = cman_get_fd(ch); - FD_ZERO(&in); - for (thisfd = &read_fd_head; thisfd != NULL; thisfd = thisfd->next) - { - FD_SET(thisfd->fd, &in); - } - - if (select(FD_SETSIZE, &in, NULL, NULL, &tv) > 0) - { - struct read_fd *lastfd = NULL; - - for (thisfd = &read_fd_head; thisfd != NULL; thisfd = thisfd->next) - { - if (FD_ISSET(thisfd->fd, &in)) - { - switch(thisfd->type) - { - /* Request or response from another cluster node */ - case CLUSTER_SOCK: - if (cman_dispatch(ch, CMAN_DISPATCH_ONE) == -1) - goto closedown; - break; - - /* Someone connected to our local socket */ - case LOCAL_RENDEZVOUS: - { - struct sockaddr_un socka; - struct read_fd *rendfd; - socklen_t sl = sizeof(socka); - int client_fd = accept(local_sock, (struct sockaddr *)&socka, &sl); - - if (client_fd >= 0) - { - rendfd = malloc(sizeof(struct read_fd)); - if (!rendfd) - { - close(client_fd); - break; - } - rendfd->fd = client_fd; - rendfd->type = LOCAL_SOCK; - rendfd->next = thisfd->next; - rendfd->nodes_done = 0; - rendfd->start_time = time(NULL); - thisfd->next = rendfd; - } - } - break; - - /* Data on a connected socket */ - case LOCAL_SOCK: - { - int len; - char buffer[PIPE_BUF]; - len = read(thisfd->fd, buffer, sizeof(buffer)); - - /* EOF on socket */ - if (len <= 0) - { - struct read_fd *free_fd; - - close(thisfd->fd); - /* Remove it from the list safely */ - lastfd->next = thisfd->next; - free_fd = thisfd; - thisfd = lastfd; - free(free_fd); - } - else - { - char cman_buffer[PIPE_BUF]; - struct sysman_header *header = (struct sysman_header *)cman_buffer; - - expected_responses = nodes_listening(thisfd->fd); - - header->fd = htonl(thisfd->fd); - header->cmd = SYSMAN_CMD_REQUEST; - memcpy(cman_buffer+sizeof(*header), buffer, len); - - if (!cman_send_data(ch, cman_buffer, sizeof(*header)+len, 0, port, 0)) - { - perror("write"); - goto closedown; - } - } - } - break; - - } /* switch */ - - } - lastfd = thisfd; - } - } - /* Check for timed-out connections */ - for (thisfd = &read_fd_head; thisfd != NULL; thisfd = thisfd->next) - { - if (thisfd->type == LOCAL_SOCK && (thisfd->start_time <= time(NULL)-10)) - { - write(thisfd->fd,"Timed-out\n", 10); - close(thisfd->fd); - remove_sock(thisfd); - - /* Refresh members list in case a node has gone down - or a remote sysmand has crashed */ - get_members(); - } - } - } - closedown: - cman_finish(ch); - close(local_sock); - - return 0; -} - -/* Get a list of members */ -static void get_members() -{ - num_nodes = cman_get_node_count(ch); - if (num_nodes == -1) - { - perror("get nodes"); - } - else - { - if (nodes) free(nodes); - - nodes = malloc(num_nodes * sizeof(cman_node_t)); - - if (cman_get_nodes(ch, num_nodes, &num_nodes, nodes)) - perror("Error getting node list"); - } -} - -/* Convert a nodeid to a node name */ -static int name_from_nodeid(int nodeid, char *name) -{ - int i; - - for (i=0; i<num_nodes; i++) - { - if (nodeid == nodes[i].cn_nodeid) - { - strcpy(name, nodes[i].cn_name); - return 0; - } - } - /* Who?? */ - strcpy(name, "Unknown"); - return -1; -} - -/* Check which nodes are listening on the SYSMAN port */ -static int nodes_listening(int errfd) -{ - int i; - int num_listening = 0; - - for (i=0; i<num_nodes; i++) - { - int listening; - - listening = cman_is_listening(ch, nodes[i].cn_nodeid, CLUSTER_PORT_SYSMAN); - - if (listening > 0) - { - num_listening++; - } - else - { - if (listening == 0) - { - char errstring[1024]; - int len; - len = snprintf(errstring, sizeof(errstring), - "WARNING: node %s is not listening for SYSMAN requests\n", - nodes[i].cn_name); - write(errfd, errstring, len); - } - } - } - return num_listening; -} - -static int open_local_sock() -{ - int local_socket; - struct sockaddr_un sockaddr; - - // Open local socket - unlink(LOCAL_SOCKNAME); - local_socket = socket(PF_UNIX, SOCK_STREAM, 0); - if (local_socket < 0) - { - syslog(LOG_ERR, "Can't create local socket: %m"); - return -1; - } - - strcpy(sockaddr.sun_path, LOCAL_SOCKNAME); - sockaddr.sun_family = AF_UNIX; - if (bind(local_socket, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) - { - syslog(LOG_ERR, "can't bind local socket: %m"); - close(local_socket); - return -1; - } - if (listen(local_socket, 1) != 0) - { - syslog(LOG_ERR, "listen local: %m"); - close(local_socket); - return -1; - } - // Make sure only root can talk to us via the local socket. - // Considering the rest of the security implications of - // this code, this is simply pathetic! - chmod(LOCAL_SOCKNAME, 0600); - - return local_socket; -} - -static struct read_fd *find_by_fd(int fd) -{ - struct read_fd *thisfd; - - for (thisfd = &read_fd_head; thisfd != NULL; thisfd = thisfd->next) - if (fd == thisfd->fd) return thisfd; - - return NULL; -} - -static void remove_sock(struct read_fd *deadfd) -{ - struct read_fd *thisfd; - struct read_fd *lastfd=NULL; - - for (thisfd = &read_fd_head; thisfd != NULL; thisfd = thisfd->next) - { - if (thisfd == deadfd) - { - lastfd->next = deadfd->next; - free(deadfd); - } - lastfd = thisfd; - } -} - -static int exec_command(char *cmd, char *reply, int *len) -{ - FILE *exec_pipe; - int readlen; - int avail = PIPE_BUF-sizeof(struct sysman_header)-1; - char realcmd[strlen(cmd)+25]; - - /* Send stderr back to the caller, and make stdin /dev/null */ - snprintf(realcmd, sizeof(realcmd), "%s </dev/null 2>&1", cmd); - - *len = 0; - exec_pipe = popen(realcmd, "r"); - - /* Fill the buffer as full as possible */ - do - { - readlen = fread(reply + *len, 1, avail, exec_pipe); - if (readlen > 0) - { - *len += readlen; - avail -= readlen; - } - } - while (avail>0 && readlen > 0); - - reply[*len] ='\0'; - - /* Return completion status of command */ - return pclose(exec_pipe); -} diff --git a/cman/tests/user_service.c b/cman/tests/user_service.c deleted file mode 100644 index 039aa72..0000000 --- a/cman/tests/user_service.c +++ /dev/null @@ -1,287 +0,0 @@ -#include "clusterautoconfig.h" - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <signal.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <inttypes.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/socket.h> - -#include "cnxman-socket.h" - -static pthread_t recv_thread; -static int cl_sock; -static int quit = 0; -static int leave_finished = 0; -static pid_t our_pid; - - -/* SIGUSR1 will cause this program to look for a new service event from SM - using the GETEVENT ioctl. - - SIGTERM will cause this program to leave the service group cleanly; it will - do a LEAVE ioctl, get a stop event and then exit. - - SIGKILL will cause the program to exit without first leaving the service - group. In that case the kernel will clean up and leave the service group - (as a part of cl_release on the cluster socket). */ - - -static void sigusr1_handler(int sig) -{ -} - -static void sigterm_handler(int sig) -{ - quit = 1; -} - -/* This thread receives messages on the cluster socket and prints them. */ - -static void *recv_thread_fn(void *arg) -{ - struct iovec iov[2]; - struct msghdr msg; - struct sockaddr_cl saddr; - char buf[256]; - int len; - int nodeid; - - for (;;) { - memset(buf, 0, 256); - - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_iovlen = 1; - msg.msg_iov = iov; - msg.msg_name = &saddr; - msg.msg_flags = 0; - msg.msg_namelen = sizeof(saddr); - iov[0].iov_len = sizeof(buf); - iov[0].iov_base = buf; - - len = recvmsg(cl_sock, &msg, MSG_OOB); - - if (len < 0 && errno == EAGAIN) - continue; - - if (!len || len < 0) - continue; - - nodeid = saddr.scl_nodeid; - - if (buf[0] == CLUSTER_OOB_MSG_PORTCLOSED) - printf("message: oob port-closed from nodeid %d\n", - nodeid); - - else if (buf[0] == CLUSTER_OOB_MSG_SERVICEEVENT) - printf("message: oob service-event\n"); - - else if (!strcmp(buf, "hello")) - printf("message: "%s" from nodeid %d\n", buf, nodeid); - - else - printf("message: unknown len %d byte0 %x nodeid %d\n", - len, buf[0], nodeid); - } -} - -static void send_group_message(void) -{ - struct iovec iov[2]; - struct msghdr msg; - char buf[256]; - int len; - - strcpy(buf, "hello"); - - iov[0].iov_len = strlen(buf); - iov[0].iov_base = buf; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_iovlen = 1; - msg.msg_iov = iov; - msg.msg_name = NULL; - msg.msg_flags = O_NONBLOCK; - msg.msg_namelen = 0; - - len = sendmsg(cl_sock, &msg, 0); -} - -static void print_ev(struct cl_service_event *ev) -{ - switch (ev->type) { - case SERVICE_EVENT_STOP: - printf("stop:\n"); - break; - case SERVICE_EVENT_START: - printf("start:\n"); - break; - case SERVICE_EVENT_FINISH: - printf("finish:\n"); - break; - case SERVICE_EVENT_LEAVEDONE: - printf("leavedone:\n"); - break; - } - printf(" event_id = %u\n", ev->event_id); - printf(" last_stop = %u\n", ev->last_stop); - printf(" last_start = %u\n", ev->last_start); - printf(" last_finish = %u\n", ev->last_finish); - printf(" node_count = %u\n", ev->node_count); -} - -static void print_members(int count, struct cl_cluster_node *nodes) -{ - int i; - - printf("members:\n"); - for (i = 0; i < count; i++) { - printf(" nodeid = %u "%s"\n", nodes->node_id, nodes->name); - nodes++; - } -} - -static int process_event(struct cl_service_event *ev) -{ - struct cl_cluster_node *nodes; - int error = 0; - - print_ev(ev); - - if (ev->type == SERVICE_EVENT_START) { - - nodes = malloc(ev->node_count * sizeof(struct cl_cluster_node)); - if (!nodes) { - perror("process_event: malloc failed"); - return -ENOMEM; - } - - memset(nodes, 0, ev->node_count*sizeof(struct cl_cluster_node)); - - error = ioctl(cl_sock, SIOCCLUSTER_SERVICE_GETMEMBERS, nodes); - if (error < 0) - perror("process_event: service get members failed"); - - print_members(ev->node_count, nodes); - - error = ioctl(cl_sock, SIOCCLUSTER_SERVICE_STARTDONE, - ev->event_id); - if (error < 0) - perror("process_event: start done error"); - - /* send_group_message(); */ - - free(nodes); - } - - if (ev->type == SERVICE_EVENT_LEAVEDONE) - leave_finished = 1; - - return error; -} - -int main(int argc, char **argv) -{ - struct cl_service_event event; - struct sockaddr_cl saddr; - char *name; - int error; - - our_pid = getpid(); - - if (argc > 1) - name = argv[1]; - else - name = "example"; - - - cl_sock = socket(AF_CLUSTER, SOCK_DGRAM, CLPROTO_CLIENT); - if (cl_sock < 0) { - perror("main: can't create cluster socket"); - return -1; - } - - - error = ioctl(cl_sock, SIOCCLUSTER_SERVICE_REGISTER, name); - if (error < 0) { - perror("main: service register failed"); - return -1; - } - - - /* binding to an address is only needed if we want to send/recv - messages to other nodes on the cluster socket. */ - -#if 0 - saddr.scl_family = AF_CLUSTER; - saddr.scl_port = 13; /* CLUSTER_PORT_USER_SERVICE */ - - error = bind(cl_sock, (struct sockaddr *) &saddr, - sizeof(struct sockaddr_cl)); - if (error < 0) { - perror("main: can't bind to cluster socket"); - return -1; - } - pthread_create(&recv_thread, NULL, recv_thread_fn, 0); -#endif - - signal(SIGUSR1, sigusr1_handler); - signal(SIGTERM, sigterm_handler); - - error = ioctl(cl_sock, SIOCCLUSTER_SERVICE_SETSIGNAL, SIGUSR1); - if (error < 0) { - perror("main: service set signal failed"); - return -1; - } - - error = ioctl(cl_sock, SIOCCLUSTER_SERVICE_JOIN, NULL); - if (error < 0) { - perror("main: service join failed"); - return -1; - } - - - for (;;) { - memset(&event, 0, sizeof(struct cl_service_event)); - - error = ioctl(cl_sock, SIOCCLUSTER_SERVICE_GETEVENT, &event); - if (error < 0) { - perror("main: service get event failed"); - return -1; - } - - if (!error) - pause(); - else - process_event(&event); - - - if (quit) { - quit = 0; - leave_finished = 0; - - error = ioctl(cl_sock, SIOCCLUSTER_SERVICE_LEAVE, NULL); - if (error < 0) { - perror("main: service leave failed"); - return -1; - } - } - - if (leave_finished) - break; - } - - error = ioctl(cl_sock, SIOCCLUSTER_SERVICE_UNREGISTER, NULL); - if (error < 0) - perror("main: unregister failed"); - - return 0; -} diff --git a/common/Makefile.am b/common/Makefile.am deleted file mode 100644 index e73a7fb..0000000 --- a/common/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -SUBDIRS = liblogthread diff --git a/common/liblogthread/Makefile.am b/common/liblogthread/Makefile.am deleted file mode 100644 index aad208e..0000000 --- a/common/liblogthread/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -libversion = 3:0:0 - -include_HEADERS = liblogthread.h - -pkgconfigdir = $(libdir)/pkgconfig - -pkgconfig_DATA = liblogthread.pc - -lib_LTLIBRARIES = liblogthread.la - -liblogthread_la_LDFLAGS = -lpthread \ - -version-info $(libversion) diff --git a/common/liblogthread/liblogthread.c b/common/liblogthread/liblogthread.c deleted file mode 100644 index 54c9d38..0000000 --- a/common/liblogthread/liblogthread.c +++ /dev/null @@ -1,336 +0,0 @@ -#include "clusterautoconfig.h" - -#include <stdlib.h> -#include <stdarg.h> -#include <unistd.h> -#include <string.h> -#include <stdio.h> -#include <fcntl.h> -#include <time.h> -#include <syslog.h> -#include <pthread.h> -#include <sys/param.h> - -#include "liblogthread.h" - -#define DEFAULT_ENTRIES 4096 -#define ENTRY_STR_LEN 128 - -struct entry { - int level; - char str[ENTRY_STR_LEN]; - time_t time; -}; - -static struct entry *ents; -static unsigned int num_ents = DEFAULT_ENTRIES; -static unsigned int head_ent, tail_ent; /* add at head, remove from tail */ -static unsigned int dropped; -static unsigned int pending_ents; -static unsigned int init; -static unsigned int done; -static pthread_t thread_handle; -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; - -static int logt_mode; /* LOG_MODE_ */ -static int logt_syslog_facility; -static int logt_syslog_priority; -static int logt_logfile_priority; -static char logt_name[PATH_MAX]; -static char logt_logfile[PATH_MAX]; -static FILE *logt_logfile_fp; - -static char *_time(time_t *t) -{ - static char buf[64]; - - strftime(buf, sizeof(buf), "%b %d %T", localtime(t)); - return buf; -} - -static void write_entry(int level, time_t *t, char *str) -{ - if ((logt_mode & LOG_MODE_OUTPUT_FILE) && - (level <= logt_logfile_priority) && logt_logfile_fp) { - fprintf(logt_logfile_fp, "%s %s %s", _time(t), logt_name, str); - fflush(logt_logfile_fp); - } - if ((logt_mode & LOG_MODE_OUTPUT_SYSLOG) && - (level <= logt_syslog_priority)) - syslog(level, "%s", str); -} - -static void write_dropped(int level, time_t *t, int num) -{ - char str[ENTRY_STR_LEN]; - sprintf(str, "dropped %d entries", num); - write_entry(level, t, str); -} - -static void *thread_fn(void *arg) -{ - char str[ENTRY_STR_LEN]; - struct entry *e; - time_t logtime; - int level, prev_dropped = 0; - - while (1) { - pthread_mutex_lock(&mutex); - while (head_ent == tail_ent) { - if (done) { - pthread_mutex_unlock(&mutex); - goto out; - } - pthread_cond_wait(&cond, &mutex); - } - - e = &ents[tail_ent++]; - tail_ent = tail_ent % num_ents; - pending_ents--; - - memcpy(str, e->str, ENTRY_STR_LEN); - level = e->level; - logtime = e->time; - - prev_dropped = dropped; - dropped = 0; - pthread_mutex_unlock(&mutex); - - if (prev_dropped) { - write_dropped(level, &logtime, prev_dropped); - prev_dropped = 0; - } - - write_entry(level, &logtime, str); - } - out: - pthread_exit(NULL); -} - -static void _logt_print(int level, char *buf) -{ - struct entry *e; - - pthread_mutex_lock(&mutex); - - if (pending_ents == num_ents) { - dropped++; - goto out; - } - - e = &ents[head_ent++]; - head_ent = head_ent % num_ents; - pending_ents++; - - strncpy(e->str, buf, ENTRY_STR_LEN); - e->level = level; - e->time = time(NULL); - out: - pthread_cond_signal(&cond); - pthread_mutex_unlock(&mutex); -} - -void logt_print(int level, const char *fmt, ...) -{ - va_list ap; - char buf[ENTRY_STR_LEN]; - - if (!init) - return; - - buf[sizeof(buf) - 1] = 0; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf) - 1, fmt, ap); - va_end(ap); - - if (level > logt_syslog_priority && level > logt_logfile_priority) - return; - - /* this stderr crap really doesn't belong in this lib, please - feel free to not use it */ - if (logt_mode & LOG_MODE_OUTPUT_STDERR) - fputs(buf, stderr); - - _logt_print(level, buf); -} - -static void _conf(const char *name, int mode, int syslog_facility, - int syslog_priority, int logfile_priority, const char *logfile) -{ - int fd; - - pthread_mutex_lock(&mutex); - logt_mode = mode; - logt_syslog_facility = syslog_facility; - logt_syslog_priority = syslog_priority; - logt_logfile_priority = logfile_priority; - if (name) - strncpy(logt_name, name, PATH_MAX); - if (logfile) - strncpy(logt_logfile, logfile, PATH_MAX); - - if (logt_mode & LOG_MODE_OUTPUT_FILE && logt_logfile[0]) { - if (logt_logfile_fp) { - fclose(logt_logfile_fp); - logt_logfile_fp = NULL; - } - logt_logfile_fp = fopen(logt_logfile, "a+"); - if (logt_logfile_fp != NULL) { - fd = fileno(logt_logfile_fp); - fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); - } - } else { - if (logt_logfile_fp) { - fclose(logt_logfile_fp); - logt_logfile_fp = NULL; - } - } - - if (logt_mode & LOG_MODE_OUTPUT_SYSLOG) { - closelog(); - openlog(logt_name, LOG_CONS | LOG_PID, logt_syslog_facility); - } - pthread_mutex_unlock(&mutex); -} - -void logt_conf(const char *name, int mode, int syslog_facility, int syslog_priority, - int logfile_priority, const char *logfile) -{ - if (!init) - return; - - _conf(name, mode, syslog_facility, syslog_priority, logfile_priority, - logfile); -} - -int logt_init(const char *name, int mode, int syslog_facility, int syslog_priority, - int logfile_priority, const char *logfile) -{ - int rv; - - if (init) - return -1; - - _conf(name, mode, syslog_facility, syslog_priority, logfile_priority, - logfile); - - ents = malloc(num_ents * sizeof(struct entry)); - if (!ents) - return -1; - memset(ents, 0, num_ents * sizeof(struct entry)); - - rv = pthread_create(&thread_handle, NULL, thread_fn, NULL); - if (rv) { - free(ents); - return -1; - } - done = 0; - init = 1; - return 0; -} - - -/* - * Reinitialize logt w/ previous values (e.g. use after - * a call to fork()) - * - * Only works after you call logt_init and logt_exit - */ -int logt_reinit(void) -{ - char name_tmp[PATH_MAX]; - char file_tmp[PATH_MAX]; - - if (!done || init) - return -1; - - /* Use copies on the stack for these */ - memset(name_tmp, 0, sizeof(name_tmp)); - memset(file_tmp, 0, sizeof(file_tmp)); - - strncpy(name_tmp, logt_name, sizeof(name_tmp)); - if (!strlen(name_tmp)) - return -1; - if (strlen(logt_logfile)) - strncpy(file_tmp, logt_logfile, sizeof(file_tmp)); - - return logt_init(name_tmp, logt_mode, logt_syslog_facility, - logt_syslog_priority, logt_logfile_priority, - file_tmp); -} - - -void logt_exit(void) -{ - pthread_mutex_lock(&mutex); - done = 1; - init = 0; - pthread_cond_signal(&cond); - pthread_mutex_unlock(&mutex); - pthread_join(thread_handle, NULL); - - pthread_mutex_lock(&mutex); - /* close syslog + log file */ - closelog(); - if (logt_logfile_fp) { - fclose(logt_logfile_fp); - logt_logfile_fp = NULL; - } - - /* clean up any pending log messages */ - dropped = 0; - pending_ents = 0; - head_ent = tail_ent = 0; - free(ents); - ents = NULL; - - pthread_mutex_unlock(&mutex); -} - -#ifdef TEST -int main(int argc, char **argv) -{ - int pid; - - logt_init("test", LOG_MODE_OUTPUT_FILE|LOG_MODE_OUTPUT_SYSLOG, - LOG_DAEMON, LOG_DEBUG, LOG_DEBUG, "/tmp/logthread"); - logt_print(LOG_DEBUG, "debugging message %d\n", argc); - logt_print(LOG_ERR, "error message %d\n", argc); - sleep(1); - logt_print(LOG_DEBUG, "second debug message\n"); - logt_exit(); - - logt_print(LOG_ERR, "If you see this, it's a bug\n"); - - logt_init("test2", LOG_MODE_OUTPUT_FILE|LOG_MODE_OUTPUT_SYSLOG, - LOG_DAEMON, LOG_DEBUG, LOG_DEBUG, "/tmp/logthread"); - logt_print(LOG_DEBUG, "after 2nd init %d\n", argc); - logt_print(LOG_ERR, "error message %d\n", argc); - logt_print(LOG_DEBUG, "third debug message\n"); - logt_exit(); - - logt_print(LOG_ERR, "If you see this, it's a bug\n"); - - logt_reinit(); - logt_print(LOG_DEBUG, "after reinit\n"); - logt_print(LOG_DEBUG, "<-- should say test2\n"); - - logt_exit(); - - if ((pid = fork()) < 0) - return -1; - - if (pid) - exit(0); - - /* child process */ - logt_reinit(); - logt_print(LOG_DEBUG, "HELLO from child process\n"); - logt_exit(); - - return 0; -} -#endif - diff --git a/common/liblogthread/liblogthread.h b/common/liblogthread/liblogthread.h deleted file mode 100644 index 3c17395..0000000 --- a/common/liblogthread/liblogthread.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef LOGTHREAD_DOT_H -#define LOGTHREAD_DOT_H - -#include <syslog.h> - -#define LOG_MODE_OUTPUT_FILE 1 -#define LOG_MODE_OUTPUT_SYSLOG 2 -#define LOG_MODE_OUTPUT_STDERR 4 - -int logt_init(const char *name, int mode, int syslog_facility, int syslog_priority, - int logfile_priority, const char *logfile); -void logt_conf(const char *name, int mode, int syslog_facility, int syslog_priority, - int logfile_priority, const char *logfile); -void logt_exit(void); -int logt_reinit(void); -void logt_print(int level, const char *fmt, ...) - __attribute__((format(printf, 2, 3)));; - -#endif diff --git a/common/liblogthread/liblogthread.pc.in b/common/liblogthread/liblogthread.pc.in deleted file mode 100644 index 73f87f4..0000000 --- a/common/liblogthread/liblogthread.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=${prefix} -libdir=@libdir@ -includedir=${prefix}/include - -Name: liblogthread -Version: @VERSION@ -Description: Cluster threaded logging library -Requires: -Libs: -L${libdir} -llogthread -Cflags: -I${includedir} diff --git a/config/Makefile.am b/config/Makefile.am deleted file mode 100644 index 4a0b992..0000000 --- a/config/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -SUBDIRS = libs plugins tools man diff --git a/config/libs/Makefile.am b/config/libs/Makefile.am deleted file mode 100644 index f9dbec7..0000000 --- a/config/libs/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -SUBDIRS = libccsconfdb diff --git a/config/libs/libccsconfdb/Makefile.am b/config/libs/libccsconfdb/Makefile.am deleted file mode 100644 index 154c70c..0000000 --- a/config/libs/libccsconfdb/Makefile.am +++ /dev/null @@ -1,24 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -libversion = 3:0:0 - -include_HEADERS = ccs.h - -noinst_HEADERS = ccs_internal.h - -pkgconfigdir = $(libdir)/pkgconfig - -pkgconfig_DATA = libccs.pc - -lib_LTLIBRARIES = libccs.la - -libccs_la_SOURCES = libccs.c xpathlite.c fullxpath.c extras.c - -libccs_la_CPPFLAGS = -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 \ - -I$(top_srcdir)/common/liblogthread/ - -libccs_la_CFLAGS = $(confdb_CFLAGS) \ - $(xml_CFLAGS) - -libccs_la_LDFLAGS = $(xml_LIBS) $(confdb_LIBS) \ - -version-info $(libversion) diff --git a/config/libs/libccsconfdb/ccs.h b/config/libs/libccsconfdb/ccs.h deleted file mode 100644 index 5c67735..0000000 --- a/config/libs/libccsconfdb/ccs.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __CCS_DOT_H__ -#define __CCS_DOT_H__ - -int ccs_connect(void); -int ccs_force_connect(const char *cluster_name, int blocking); -int ccs_disconnect(int desc); -int ccs_get(int desc, const char *query, char **rtn); -int ccs_get_list(int desc, const char *query, char **rtn); -int ccs_set(int desc, const char *path, char *val); -int ccs_lookup_nodename(int desc, const char *nodename, char **rtn); -void ccs_read_logging(int fd, const char *name, int *debug, int *mode, - int *syslog_facility, int *syslog_priority, - int *logfile_priority, char *logfile); -extern int fullxpath; - -#endif /* __CCS_DOT_H__ */ diff --git a/config/libs/libccsconfdb/ccs_internal.h b/config/libs/libccsconfdb/ccs_internal.h deleted file mode 100644 index 617f9e7..0000000 --- a/config/libs/libccsconfdb/ccs_internal.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __CCS_INTERNAL_DOT_H__ -#define __CCS_INTERNAL_DOT_H__ - -/* NOTE: use __attribute__ to hide the internal API */ - -/* from libccs.c */ -void reset_iterator(confdb_handle_t handle, hdb_handle_t connection_handle) - __attribute__ ((visibility("hidden"))); -int get_previous_query(confdb_handle_t handle, hdb_handle_t connection_handle, - char *previous_query, hdb_handle_t *query_handle) - __attribute__ ((visibility("hidden"))); -int set_previous_query(confdb_handle_t handle, hdb_handle_t connection_handle, - const char *previous_query, hdb_handle_t query_handle) - __attribute__ ((visibility("hidden"))); - -/* from xpathlite.c */ -char *_ccs_get_xpathlite(confdb_handle_t handle, hdb_handle_t connection_handle, - const char *query, int list) - __attribute__ ((visibility("hidden"))); - -/* from fullxpath.c */ -char *_ccs_get_fullxpath(confdb_handle_t handle, hdb_handle_t connection_handle, - const char *query, int list) - __attribute__ ((visibility("hidden"))); -int xpathfull_init(confdb_handle_t handle) - __attribute__ ((visibility("hidden"))); -void xpathfull_finish(void) __attribute__ ((visibility("hidden"))); - -#endif /* __CCS_INTERNAL_DOT_H__ */ diff --git a/config/libs/libccsconfdb/extras.c b/config/libs/libccsconfdb/extras.c deleted file mode 100644 index 207faac..0000000 --- a/config/libs/libccsconfdb/extras.c +++ /dev/null @@ -1,449 +0,0 @@ -#include "clusterautoconfig.h" - -#include <ctype.h> -#include <errno.h> -#include <string.h> -#include <netdb.h> -#include <stdlib.h> -#include <stdio.h> -#include <limits.h> - -#define SYSLOG_NAMES -#include <syslog.h> -#include <liblogthread.h> - -#include "ccs.h" - -/** - * ccs_lookup_nodename - * @cd: ccs descriptor - * @nodename: node name string - * @retval: pointer to location to assign the result, if found - * - * This function takes any valid representation (FQDN, non-qualified - * hostname, IP address, IPv6 address) of a node's name and finds its - * canonical name (per cluster.conf). This function will find the primary - * node name if passed a node's "altname" or any valid representation - * of it. - * - * Returns: 0 on success, < 0 on failure - */ -int ccs_lookup_nodename(int cd, const char *nodename, char **retval) -{ - char path[256]; - char host_only[128]; - char *str; - char *p; - int error; - int ret; - unsigned int i; - size_t nodename_len; - struct addrinfo hints; - - if (nodename == NULL) - return (-1); - - nodename_len = strlen(nodename); - ret = snprintf(path, sizeof(path), - "/cluster/clusternodes/clusternode[@name="%s"]/@name", - nodename); - if (ret < 0 || (size_t) ret >= sizeof(path)) { - errno = E2BIG; - return (-E2BIG); - } - - str = NULL; - error = ccs_get(cd, path, &str); - if (!error) { - *retval = str; - return (0); - } - - if (nodename_len >= sizeof(host_only)) { - errno = E2BIG; - return (-E2BIG); - } - - /* Try just the hostname */ - strcpy(host_only, nodename); - p = strchr(host_only, '.'); - if (p != NULL) { - *p = '\0'; - - ret = snprintf(path, sizeof(path), - "/cluster/clusternodes/clusternode[@name="%s"]/@name", - host_only); - if (ret < 0 || (size_t) ret >= sizeof(path)) - return (-E2BIG); - - str = NULL; - error = ccs_get(cd, path, &str); - if (!error) { - *retval = str; - return (0); - } - } - - memset(&hints, 0, sizeof(hints)); - if (strchr(nodename, ':') != NULL) - hints.ai_family = AF_INET6; - else if (isdigit(nodename[nodename_len - 1])) - hints.ai_family = AF_INET; - else - hints.ai_family = AF_UNSPEC; - - /* - ** Try to match against each clusternode in cluster.conf. - */ - for (i = 1;; i++) { - char canonical_name[128]; - unsigned int altcnt; - - ret = snprintf(path, sizeof(path), - "/cluster/clusternodes/clusternode[%u]/@name", - i); - if (ret < 0 || (size_t) ret >= sizeof(path)) - continue; - - for (altcnt = 0;; altcnt++) { - size_t len; - struct addrinfo *ai = NULL; - char cur_node[128]; - - if (altcnt != 0) { - ret = snprintf(path, sizeof(path), - "/cluster/clusternodes/clusternode[%u]/altname[%u]/@name", - i, altcnt); - if (ret < 0 || (size_t) ret >= sizeof(path)) - continue; - } - - str = NULL; - error = ccs_get(cd, path, &str); - if (error || !str) { - if (altcnt == 0) - goto out_fail; - break; - } - - if (altcnt == 0) { - if (strlen(str) >= sizeof(canonical_name)) { - free(str); - errno = E2BIG; - return (-E2BIG); - } - strcpy(canonical_name, str); - } - - if (strlen(str) >= sizeof(cur_node)) { - free(str); - errno = E2BIG; - return (-E2BIG); - } - - strcpy(cur_node, str); - - p = strchr(cur_node, '.'); - if (p != NULL) - len = p - cur_node; - else - len = strlen(cur_node); - - if (strlen(host_only) == len && - !strncasecmp(host_only, cur_node, len)) { - free(str); - *retval = strdup(canonical_name); - if (*retval == NULL) { - errno = ENOMEM; - return (-ENOMEM); - } - return (0); - } - - if (getaddrinfo(str, NULL, &hints, &ai) == 0) { - struct addrinfo *cur; - - for (cur = ai; cur != NULL; cur = cur->ai_next) { - char hostbuf[512]; - if (getnameinfo - (cur->ai_addr, cur->ai_addrlen, - hostbuf, sizeof(hostbuf), NULL, 0, - hints.ai_family != - AF_UNSPEC ? NI_NUMERICHOST : 0)) { - continue; - } - - if (!strcasecmp(hostbuf, nodename)) { - freeaddrinfo(ai); - free(str); - *retval = - strdup(canonical_name); - if (*retval == NULL) { - errno = ENOMEM; - return (-ENOMEM); - } - return (0); - } - } - freeaddrinfo(ai); - } - - free(str); - - /* Now try any altnames */ - } - } - -out_fail: - errno = EINVAL; - *retval = NULL; - return (-1); -} - -static int facility_id_get(char *name) -{ - unsigned int i; - - for (i = 0; facilitynames[i].c_name != NULL; i++) { - if (strcasecmp(name, facilitynames[i].c_name) == 0) { - return (facilitynames[i].c_val); - } - } - return (-1); -} - -static int priority_id_get(char *name) -{ - unsigned int i; - - for (i = 0; prioritynames[i].c_name != NULL; i++) { - if (strcasecmp(name, prioritynames[i].c_name) == 0) { - return (prioritynames[i].c_val); - } - } - return (-1); -} - -/* requires string buffer to be PATH_MAX */ -static void read_string(int fd, const char *path, char *string) -{ - char *str; - int error; - - memset(string, 0, PATH_MAX); - - error = ccs_get(fd, path, &str); - if (error || !str) - return; - - strcpy(string, str); - - free(str); -} - -static void read_yesno(int fd, const char *path, int *yes, int *no) -{ - char *str; - int error; - - *yes = 0; - *no = 0; - - error = ccs_get(fd, path, &str); - if (error || !str) - return; - - if (!strcmp(str, "yes")) - *yes = 1; - else if (!strcmp(str, "no")) - *no = 1; - - free(str); -} - -static void read_onoff(int fd, const char *path, int *on, int *off) -{ - char *str; - int error; - - *on = 0; - *off = 0; - - error = ccs_get(fd, path, &str); - if (error || !str) - return; - - if (!strcmp(str, "on")) - *on = 1; - else if (!strcmp(str, "off")) - *off = 1; - - free(str); -} - -/* requires path buffer to be PATH_MAX */ -static void create_daemon_path(const char *name, const char *field, char *path) -{ - memset(path, 0, PATH_MAX); - snprintf(path, PATH_MAX, - "/cluster/logging/logging_daemon[@name="%s"]/%s", - name, field); -} - -/* Values should be initialized to default values before calling - this function; they are not changed if cluster.conf has nothing - to say about them. If *debug is already set , then *logfile_priority - is set to LOG_DEBUG; all debug and logfile_priority values from - cluster.conf are ignored. */ - -void ccs_read_logging(int fd, const char *name, int *debug, int *mode, - int *syslog_facility, int *syslog_priority, - int *logfile_priority, char *logfile) -{ - char string[PATH_MAX]; - char path[PATH_MAX]; - int val, y, n, on, off; - - /* - * to_syslog - */ - create_daemon_path(name, "to_syslog", path); - - read_yesno(fd, "/cluster/logging/@to_syslog", &y, &n); - if (y) - *mode |= LOG_MODE_OUTPUT_SYSLOG; - if (n) - *mode &= ~LOG_MODE_OUTPUT_SYSLOG; - - read_yesno(fd, path, &y, &n); - if (y) - *mode |= LOG_MODE_OUTPUT_SYSLOG; - if (n) - *mode &= ~LOG_MODE_OUTPUT_SYSLOG; - - /* - * to_logfile - */ - create_daemon_path(name, "to_logfile", path); - - read_yesno(fd, "/cluster/logging/@to_logfile", &y, &n); - if (y) - *mode |= LOG_MODE_OUTPUT_FILE; - if (n) - *mode &= ~LOG_MODE_OUTPUT_FILE; - - read_yesno(fd, path, &y, &n); - if (y) - *mode |= LOG_MODE_OUTPUT_FILE; - if (n) - *mode &= ~LOG_MODE_OUTPUT_FILE; - - /* - * syslog_facility - */ - create_daemon_path(name, "syslog_facility", path); - - read_string(fd, "/cluster/logging/@syslog_facility", string); - - if (string[0]) { - val = facility_id_get(string); - if (val >= 0) - *syslog_facility = val; - } - - read_string(fd, path, string); - - if (string[0]) { - val = facility_id_get(string); - if (val >= 0) - *syslog_facility = val; - } - - /* - * syslog_priority - */ - create_daemon_path(name, "syslog_priority", path); - - read_string(fd, "/cluster/logging/@syslog_priority", string); - - if (string[0]) { - val = priority_id_get(string); - if (val >= 0) - *syslog_priority = val; - } - - read_string(fd, path, string); - - if (string[0]) { - val = priority_id_get(string); - if (val >= 0) - *syslog_priority = val; - } - - /* - * logfile - */ - create_daemon_path(name, "logfile", path); - - read_string(fd, "/cluster/logging/@logfile", string); - - if (string[0]) - strcpy(logfile, string); - - read_string(fd, path, string); - - if (string[0]) - strcpy(logfile, string); - - /* - * debug is only ever turned on, not off, so if it's already on - * (from the daemon), then just skip the debug lookups. - */ - if (*debug) { - *logfile_priority = LOG_DEBUG; - return; - } - - /* - * debug - * debug=on is a shortcut for logfile_priority=LOG_DEBUG - */ - create_daemon_path(name, "debug", path); - - read_onoff(fd, "/cluster/logging/@debug", &on, &off); - if (on) - *debug = 1; - - read_onoff(fd, path, &on, &off); - if (on) - *debug = 1; - else if (off) - *debug = 0; - - if (*debug) { - *logfile_priority = LOG_DEBUG; - return; - } - - /* - * logfile_priority - */ - create_daemon_path(name, "logfile_priority", path); - - read_string(fd, "/cluster/logging/@logfile_priority", string); - - if (string[0]) { - val = priority_id_get(string); - if (val >= 0) - *logfile_priority = val; - } - - read_string(fd, path, string); - - if (string[0]) { - val = priority_id_get(string); - if (val >= 0) - *logfile_priority = val; - } -} - diff --git a/config/libs/libccsconfdb/fullxpath.c b/config/libs/libccsconfdb/fullxpath.c deleted file mode 100644 index 5b4c1af..0000000 --- a/config/libs/libccsconfdb/fullxpath.c +++ /dev/null @@ -1,327 +0,0 @@ -#include "clusterautoconfig.h" - -#include <string.h> -#include <errno.h> -#include <limits.h> -#include <corosync/corotypes.h> -#include <corosync/confdb.h> -#include <libxml/parser.h> -#include <libxml/xpath.h> - -#include "ccs.h" -#include "ccs_internal.h" - -#ifndef XMLBUFSIZE -#define XMLBUFSIZE 64000 -#endif - -int fullxpath = 0; - -static xmlDocPtr doc = NULL; -static xmlXPathContextPtr ctx = NULL; - -static int add_to_buffer(char *data, char **buffer, int *bufsize) -{ - int datalen = 0, bufferlen = 0; - char *newbuf = NULL; - - datalen = strlen(data); - bufferlen = strlen(*buffer); - - if (datalen) { - if ((bufferlen + datalen) >= *bufsize) { - newbuf = malloc((*bufsize * 2)); - if (!newbuf) { - errno = ENOMEM; - return -1; - } - *bufsize = *bufsize * 2; - memset(newbuf, 0, *bufsize); - memcpy(newbuf, *buffer, bufferlen); - free(*buffer); - *buffer = newbuf; - } - strncpy(*buffer + bufferlen, data, datalen); - } - return 0; -} - -static int dump_objdb_buff(confdb_handle_t dump_handle, hdb_handle_t cluster_handle, - hdb_handle_t parent_object_handle, char **buffer, - int *bufsize) -{ - hdb_handle_t object_handle; - char temp[PATH_MAX]; - char object_name[PATH_MAX]; - char key_name[PATH_MAX]; - char key_value[PATH_MAX]; - size_t key_value_len = 0, key_name_len = 0, object_name_len = 0; - int res; - - res = confdb_key_iter_start(dump_handle, parent_object_handle); - if (res != CS_OK) { - errno = ENOMEM; - return -1; - } - - if (!*buffer || ((*buffer) && !strlen(*buffer))) { - snprintf(temp, PATH_MAX - 1, - "<?xml version=\"1.0\"?>\n<cluster"); - if (add_to_buffer(temp, buffer, bufsize)) - return -1; - } - - while ((res = - confdb_key_iter(dump_handle, parent_object_handle, key_name, - &key_name_len, key_value, - &key_value_len)) == CS_OK) { - key_name[key_name_len] = '\0'; - key_value[key_value_len] = '\0'; - - snprintf(temp, PATH_MAX - 1, " %s="%s"", key_name, key_value); - if (add_to_buffer(temp, buffer, bufsize)) - return -1; - } - - if (parent_object_handle > 0) { - snprintf(temp, PATH_MAX - 1, ">\n"); - if (add_to_buffer(temp, buffer, bufsize)) - return -1; - } - - res = confdb_object_iter_start(dump_handle, parent_object_handle); - if (res != CS_OK) { - errno = ENOMEM; - return -1; - } - - while ((res = - confdb_object_iter(dump_handle, parent_object_handle, - &object_handle, object_name, - &object_name_len)) == CS_OK) { - hdb_handle_t parent; - - res = - confdb_object_parent_get(dump_handle, object_handle, - &parent); - if (res != CS_OK) { - errno = EINVAL; - return -1; - } - - object_name[object_name_len] = '\0'; - - snprintf(temp, PATH_MAX - 1, "<%s", object_name); - if (add_to_buffer(temp, buffer, bufsize)) - return -1; - - res = - dump_objdb_buff(dump_handle, cluster_handle, object_handle, buffer, - bufsize); - if (res) { - errno = res; - return res; - } - - if (object_handle != parent_object_handle) { - snprintf(temp, PATH_MAX - 1, "</%s>\n", object_name); - if (add_to_buffer(temp, buffer, bufsize)) - return -1; - } else { - snprintf(temp, PATH_MAX - 1, ">\n"); - if (add_to_buffer(temp, buffer, bufsize)) - return -1; - } - } - - if (parent_object_handle == cluster_handle) { - snprintf(temp, PATH_MAX - 1, "</cluster>\n"); - if (add_to_buffer(temp, buffer, bufsize)) - return -1; - } - - return 0; -} - -int xpathfull_init(confdb_handle_t handle) -{ - int size = XMLBUFSIZE; - char *buffer, *newbuf; - hdb_handle_t cluster_handle; - - newbuf = buffer = malloc(XMLBUFSIZE); - if (!buffer) { - errno = ENOMEM; - goto fail; - } - - memset(buffer, 0, XMLBUFSIZE); - - if (confdb_object_find_start(handle, OBJECT_PARENT_HANDLE) != CS_OK) - goto fail; - - if (confdb_object_find(handle, OBJECT_PARENT_HANDLE, "cluster", strlen("cluster"), &cluster_handle) != CS_OK) - goto fail; - - if (dump_objdb_buff(handle, cluster_handle, cluster_handle, &newbuf, &size)) - goto fail; - - if (newbuf != buffer) { - buffer = newbuf; - newbuf = NULL; - } - - doc = xmlParseMemory(buffer, strlen(buffer)); - if (!doc) - goto fail; - - free(buffer); - - ctx = xmlXPathNewContext(doc); - if (!ctx) { - xmlFreeDoc(doc); - goto fail; - } - - return 0; - -fail: - return -1; -} - -void xpathfull_finish() -{ - if (ctx) { - xmlXPathFreeContext(ctx); - ctx = NULL; - } - if (doc) { - xmlFreeDoc(doc); - doc = NULL; - } - return; -} - -/** - * _ccs_get_fullxpath - * @desc: - * @query: - * @rtn: value returned - * @list: 1 to operate in list fashion - * - * This function will allocate space for the value that is the result - * of the given query. It is the user's responsibility to ensure that - * the data returned is freed. - * - * Returns: char * to result or NULL in case of failure. - */ -char *_ccs_get_fullxpath(confdb_handle_t handle, hdb_handle_t connection_handle, - const char *query, int list) -{ - xmlXPathObjectPtr obj = NULL; - char previous_query[PATH_MAX]; - hdb_handle_t list_handle = 0; - unsigned int xmllistindex = 0; - int prev = 0; - char *rtn = NULL; - - errno = 0; - - if (strncmp(query, "/", 1)) { - errno = EINVAL; - goto fail; - } - - memset(previous_query, 0, PATH_MAX); - - prev = - get_previous_query(handle, connection_handle, previous_query, - &list_handle); - - if (list && !prev && !strcmp(query, previous_query)) { - if (confdb_key_increment - (handle, connection_handle, "iterator_tracker", - strlen("iterator_tracker"), &xmllistindex) != CS_OK) { - xmllistindex = 0; - } else { - xmllistindex--; - } - } else { - reset_iterator(handle, connection_handle); - xmllistindex = 0; - } - - obj = xmlXPathEvalExpression((xmlChar *) query, ctx); - - if (!obj) { - errno = EINVAL; - goto fail; - } - - if (obj->nodesetval && (obj->nodesetval->nodeNr > 0)) { - xmlNodePtr node; - int size = 0, nnv = 0; - - if (xmllistindex >= obj->nodesetval->nodeNr) { - reset_iterator(handle, connection_handle); - errno = ENODATA; - goto fail; - } - - node = obj->nodesetval->nodeTab[xmllistindex]; - - if (!node) { - errno = ENODATA; - goto fail; - } - - if (((node->type == XML_ATTRIBUTE_NODE) && strstr(query, "@*")) - || ((node->type == XML_ELEMENT_NODE) - && strstr(query, "child::*"))) { - if (node->children && node->children->content) - size = strlen((char *)node->children->content) + - strlen((char *)node->name) + 2; - else - size = strlen((char *)node->name) + 2; - - nnv = 1; - } else { - if (node->children && node->children->content) - size = - strlen((char *)node->children->content) + 1; - - else { - errno = ENODATA; - goto fail; - } - } - - rtn = malloc(size); - - if (!rtn) { - errno = ENOMEM; - goto fail; - } - - if (nnv) - sprintf(rtn, "%s=%s", node->name, - node->children ? (char *)node->children-> - content : ""); - else - sprintf(rtn, "%s", - node->children ? node->children-> - content : node->name); - - if (list) - set_previous_query(handle, connection_handle, - (char *)query, OBJECT_PARENT_HANDLE); - - } else - errno = EINVAL; - -fail: - if (obj) - xmlXPathFreeObject(obj); - - return rtn; -} diff --git a/config/libs/libccsconfdb/libccs.c b/config/libs/libccsconfdb/libccs.c deleted file mode 100644 index e068358..0000000 --- a/config/libs/libccsconfdb/libccs.c +++ /dev/null @@ -1,651 +0,0 @@ -#include "clusterautoconfig.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <limits.h> -#include <corosync/corotypes.h> -#include <corosync/confdb.h> - -#include "ccs.h" -#include "ccs_internal.h" - -/* Callbacks are not supported - we will use them to update fullxml doc/ctx */ -static confdb_callbacks_t callbacks = { -}; - -/* helper functions */ - -static confdb_handle_t confdb_connect(void) -{ - confdb_handle_t handle = 0; - - if (confdb_initialize(&handle, &callbacks) != CS_OK) { - errno = ENOMEM; - return -1; - } - - return handle; -} - -static int confdb_disconnect(confdb_handle_t handle) -{ - if (confdb_finalize(handle) != CS_OK) { - errno = EINVAL; - return -1; - } - return 0; -} - -static hdb_handle_t find_libccs_handle(confdb_handle_t handle) -{ - hdb_handle_t libccs_handle = 0; - - if (confdb_object_find_start(handle, OBJECT_PARENT_HANDLE) != CS_OK) { - errno = ENOMEM; - return -1; - } - - if (confdb_object_find - (handle, OBJECT_PARENT_HANDLE, "libccs", strlen("libccs"), - &libccs_handle) != CS_OK) { - errno = ENOENT; - return -1; - } - - confdb_object_find_destroy(handle, OBJECT_PARENT_HANDLE); - - return libccs_handle; -} - -static hdb_handle_t find_ccs_handle(confdb_handle_t handle, int ccs_handle) -{ - int res, found = 0; - hdb_handle_t libccs_handle = 0, connection_handle = 0; - char data[128]; - size_t datalen = 0; - - libccs_handle = find_libccs_handle(handle); - if (libccs_handle == -1) - return -1; - - if (confdb_object_find_start(handle, libccs_handle) != CS_OK) { - errno = ENOMEM; - return -1; - } - - while (confdb_object_find - (handle, libccs_handle, "connection", strlen("connection"), - &connection_handle) == CS_OK) { - memset(data, 0, sizeof(data)); - if (confdb_key_get - (handle, connection_handle, "ccs_handle", - strlen("ccs_handle"), data, &datalen) == CS_OK) { - res = atoi(data); - if (res == ccs_handle) { - found = 1; - break; - } - } - } - - confdb_object_find_destroy(handle, libccs_handle); - - if (found) { - return connection_handle; - } else { - errno = ENOENT; - return -1; - } -} - -static int destroy_ccs_handle(confdb_handle_t handle, - hdb_handle_t connection_handle) -{ - if (confdb_object_destroy(handle, connection_handle) != CS_OK) { - errno = EINVAL; - return -1; - } - - return 0; -} - -static int get_running_config_version(confdb_handle_t handle, int *config_version) -{ - hdb_handle_t cluster_handle; - char data[128]; - size_t datalen = 0; - int ret = -1; - - if (confdb_object_find_start(handle, OBJECT_PARENT_HANDLE) != CS_OK) { - errno = ENOMEM; - return -1; - } - - if (confdb_object_find - (handle, OBJECT_PARENT_HANDLE, "cluster", strlen("cluster"), - &cluster_handle) == CS_OK) { - memset(data, 0, sizeof(data)); - if (confdb_key_get - (handle, cluster_handle, "config_version", - strlen("config_version"), data, &datalen) == CS_OK) { - *config_version = atoi(data); - ret = 0; - } - } - - confdb_object_find_destroy(handle, OBJECT_PARENT_HANDLE); - - if (ret < 0) - errno = ENODATA; - - return ret; -} - -static int get_stored_config_version(confdb_handle_t handle, - hdb_handle_t connection_handle, int *config_version) -{ - char data[128]; - size_t datalen = 0; - int ret = -1; - - if (confdb_key_get - (handle, connection_handle, "config_version", - strlen("config_version"), data, &datalen) == CS_OK) { - *config_version = atoi(data); - ret = 0; - } - - if (ret < 0) - errno = ENODATA; - - return ret; -} - -static int set_stored_config_version(confdb_handle_t handle, - hdb_handle_t connection_handle, int new_version) -{ - char temp[PATH_MAX]; - size_t templen = 0; - char data[128]; - - memset(data, 0, sizeof(data)); - snprintf(data, sizeof(data), "%d", new_version); - - if (confdb_key_get - (handle, connection_handle, "config_version", - strlen("config_version"), temp, &templen) == CS_OK) { - if (confdb_key_replace - (handle, connection_handle, "config_version", - strlen("config_version"), temp, templen, data, - strlen(data) + 1) == CS_OK) { - return 0; - } - } - - return -1; -} - -static int config_reload(confdb_handle_t handle, - hdb_handle_t connection_handle, int fullxpathint) -{ - int running_version; - int stored_version; - - if (get_running_config_version(handle, &running_version) < 0) - return -1; - - if (get_stored_config_version(handle, connection_handle, &stored_version) < 0) - return -1; - - if (running_version == stored_version) - return 0; - - if (fullxpathint) { - xpathfull_finish(); - if (xpathfull_init(handle)) - return -1; - } - - reset_iterator(handle, connection_handle); - - if (set_previous_query(handle, connection_handle, "", 0)) - return -1; - - if (set_stored_config_version(handle, connection_handle, running_version)) - return -1; - - return 0; -} - -static hdb_handle_t create_ccs_handle(confdb_handle_t handle, int ccs_handle, - int xpath) -{ - hdb_handle_t libccs_handle = 0, connection_handle = 0; - char buf[128]; - int config_version = 0; - - libccs_handle = find_libccs_handle(handle); - if (libccs_handle == -1) - return -1; - - if (get_running_config_version(handle, &config_version) < 0) - return -1; - - if (confdb_object_create - (handle, libccs_handle, "connection", strlen("connection"), - &connection_handle) != CS_OK) { - errno = ENOMEM; - return -1; - } - - memset(buf, 0, sizeof(buf)); - snprintf(buf, sizeof(buf), "%d", ccs_handle); - if (confdb_key_create - (handle, connection_handle, "ccs_handle", strlen("ccs_handle"), buf, - strlen(buf) + 1) != CS_OK) { - destroy_ccs_handle(handle, connection_handle); - errno = ENOMEM; - return -1; - } - - memset(buf, 0, sizeof(buf)); - snprintf(buf, sizeof(buf), "%d", config_version); - if (confdb_key_create - (handle, connection_handle, "config_version", - strlen("config_version"), buf, strlen(buf) + 1) != CS_OK) { - destroy_ccs_handle(handle, connection_handle); - errno = ENOMEM; - return -1; - } - - memset(buf, 0, sizeof(buf)); - snprintf(buf, sizeof(buf), "%d", xpath); - if (confdb_key_create - (handle, connection_handle, "fullxpath", strlen("fullxpath"), buf, - strlen(buf) + 1) != CS_OK) { - destroy_ccs_handle(handle, connection_handle); - errno = ENOMEM; - return -1; - } - - return connection_handle; -} - -static hdb_handle_t get_ccs_handle(confdb_handle_t handle, int *ccs_handle, - int xpath) -{ - unsigned int next_handle; - hdb_handle_t libccs_handle = 0; - hdb_handle_t ret = 0; - - libccs_handle = find_libccs_handle(handle); - if (libccs_handle == -1) - return -1; - - if (confdb_key_increment - (handle, libccs_handle, "next_handle", strlen("next_handle"), - &next_handle) == CS_OK) { - ret = create_ccs_handle(handle, (int)next_handle, xpath); - if (ret == -1) { - *ccs_handle = -1; - return ret; - } - - *ccs_handle = (int)next_handle; - return ret; - } - - *ccs_handle = -1; - errno = ENOMEM; - return -1; -} - -int get_previous_query(confdb_handle_t handle, hdb_handle_t connection_handle, - char *previous_query, hdb_handle_t *query_handle) -{ - size_t datalen = 0; - - if (confdb_key_get - (handle, connection_handle, "previous_query", - strlen("previous_query"), previous_query, &datalen) == CS_OK) { - if (confdb_key_get - (handle, connection_handle, "query_handle", - strlen("query_handle"), query_handle, - &datalen) == CS_OK) { - return 0; - } - } - errno = ENOENT; - return -1; -} - -int set_previous_query(confdb_handle_t handle, hdb_handle_t connection_handle, - const char *previous_query, hdb_handle_t query_handle) -{ - char temp[PATH_MAX]; - size_t templen = 0; - hdb_handle_t temphandle; - unsigned int temptracker; - - if (confdb_key_get - (handle, connection_handle, "previous_query", - strlen("previous_query"), temp, &templen) == CS_OK) { - if (strcmp(previous_query, temp)) { - if (confdb_key_replace - (handle, connection_handle, "previous_query", - strlen("previous_query"), temp, templen, - previous_query, - strlen(previous_query) + 1) != CS_OK) { - errno = ENOMEM; - return -1; - } - } - } else { - if (confdb_key_create - (handle, connection_handle, "previous_query", - strlen("previous_query"), previous_query, - strlen(previous_query) + 1) != CS_OK) { - errno = ENOMEM; - return -1; - } - } - - if (confdb_key_get - (handle, connection_handle, "query_handle", strlen("query_handle"), - &temphandle, &templen) == CS_OK) { - if (temphandle != query_handle) { - if (confdb_key_replace - (handle, connection_handle, "query_handle", - strlen("query_handle"), &temphandle, - sizeof(hdb_handle_t), &query_handle, - sizeof(hdb_handle_t)) != CS_OK) { - errno = ENOMEM; - return -1; - } - } - } else { - if (confdb_key_create - (handle, connection_handle, "query_handle", - strlen("query_handle"), &query_handle, - sizeof(hdb_handle_t)) != CS_OK) { - errno = ENOMEM; - return -1; - } - } - - if (confdb_key_get - (handle, connection_handle, "iterator_tracker", - strlen("iterator_tracker"), &temptracker, &templen) != CS_OK) { - temptracker = 1; - if (confdb_key_create - (handle, connection_handle, "iterator_tracker", - strlen("iterator_tracker"), &temptracker, - sizeof(unsigned int)) != CS_OK) { - errno = ENOMEM; - return -1; - } - } - - return 0; -} - -void reset_iterator(confdb_handle_t handle, hdb_handle_t connection_handle) -{ - unsigned int value = 0; - - if (confdb_key_increment - (handle, connection_handle, "iterator_tracker", - strlen("iterator_tracker"), &value) != CS_OK) - return; - - confdb_key_delete(handle, connection_handle, "iterator_tracker", - strlen("iterator_tracker"), &value, - sizeof(unsigned int)); - - return; -} - -static int check_cluster_name(int ccs_handle, const char *cluster_name) -{ - confdb_handle_t handle = 0; - hdb_handle_t cluster_handle; - char data[128]; - int found = 0; - size_t datalen = 0; - - handle = confdb_connect(); - if (handle < 0) - return -1; - - if (confdb_object_find_start(handle, OBJECT_PARENT_HANDLE) != CS_OK) { - errno = ENOMEM; - return -1; - } - - while (confdb_object_find - (handle, OBJECT_PARENT_HANDLE, "cluster", strlen("cluster"), - &cluster_handle) == CS_OK) { - memset(data, 0, sizeof(data)); - if (confdb_key_get - (handle, cluster_handle, "name", strlen("name"), data, - &datalen) == CS_OK) { - if (!strncmp(data, cluster_name, datalen)) { - found = 1; - break; - } - } - } - - confdb_object_find_destroy(handle, OBJECT_PARENT_HANDLE); - - confdb_disconnect(handle); - - if (found) { - return ccs_handle; - } else { - errno = ENOENT; - return -1; - } -} - -/** - * _ccs_get - * @desc: - * @query: - * @rtn: value returned - * @list: 1 to operate in list fashion - * - * This function will allocate space for the value that is the result - * of the given query. It is the user's responsibility to ensure that - * the data returned is freed. - * - * Returns: 0 on success, < 0 on failure - */ -static int _ccs_get(int desc, const char *query, char **rtn, int list) -{ - confdb_handle_t handle = 0; - hdb_handle_t connection_handle = 0; - char data[128]; - size_t datalen = 0; - int fullxpathint = 0; - - *rtn = NULL; - - handle = confdb_connect(); - if (handle < 0) - return -1; - - connection_handle = find_ccs_handle(handle, desc); - if (connection_handle == -1) - goto fail; - - memset(data, 0, sizeof(data)); - if (confdb_key_get - (handle, connection_handle, "fullxpath", strlen("fullxpath"), &data, - &datalen) != CS_OK) { - errno = EINVAL; - goto fail; - } else - fullxpathint = atoi(data); - - if (config_reload(handle, connection_handle, fullxpathint) < 0) - goto fail; - - if (!fullxpathint) - *rtn = - _ccs_get_xpathlite(handle, connection_handle, query, list); - else - *rtn = - _ccs_get_fullxpath(handle, connection_handle, query, list); - -fail: - confdb_disconnect(handle); - - if (!*rtn) - return -1; - - return 0; -} - -/**** PUBLIC API ****/ - -/** - * ccs_connect - * - * Returns: ccs_desc on success, < 0 on failure - */ -int ccs_connect(void) -{ - confdb_handle_t handle = 0; - int ccs_handle = 0; - - handle = confdb_connect(); - if (handle == -1) - return handle; - - get_ccs_handle(handle, &ccs_handle, fullxpath); - if (ccs_handle < 0) - goto fail; - - if (fullxpath) { - if (xpathfull_init(handle)) { - ccs_disconnect(ccs_handle); - return -1; - } - } - -fail: - confdb_disconnect(handle); - - return ccs_handle; -} - -/** - * ccs_force_connect - * - * @cluster_name: verify that we are trying to connect to the requested cluster (tbd) - * @blocking: retry connection forever - * - * Returns: ccs_desc on success, < 0 on failure - */ -int ccs_force_connect(const char *cluster_name, int blocking) -{ - int res = -1; - - if (blocking) { - while (res < 0) { - res = ccs_connect(); - if (res < 0) - sleep(1); - } - } else { - res = ccs_connect(); - if (res < 0) - return res; - } - if (cluster_name) - return check_cluster_name(res, cluster_name); - else - return res; -} - -/** - * ccs_disconnect - * - * @desc: the descriptor returned by ccs_connect - * - * Returns: 0 on success, < 0 on error - */ -int ccs_disconnect(int desc) -{ - confdb_handle_t handle = 0; - hdb_handle_t connection_handle = 0; - int ret; - char data[128]; - size_t datalen = 0; - int fullxpathint = 0; - - handle = confdb_connect(); - if (handle <= 0) - return handle; - - connection_handle = find_ccs_handle(handle, desc); - if (connection_handle == -1) { - ret = -1; - goto fail; - } - - memset(data, 0, sizeof(data)); - if (confdb_key_get - (handle, connection_handle, "fullxpath", strlen("fullxpath"), &data, - &datalen) != CS_OK) { - errno = EINVAL; - ret = -1; - goto fail; - } else - fullxpathint = atoi(data); - - if (fullxpathint) - xpathfull_finish(); - - ret = destroy_ccs_handle(handle, connection_handle); - -fail: - confdb_disconnect(handle); - return ret; -} - -/* see _ccs_get */ -int ccs_get(int desc, const char *query, char **rtn) -{ - return _ccs_get(desc, query, rtn, 0); -} - -/* see _ccs_get */ -int ccs_get_list(int desc, const char *query, char **rtn) -{ - return _ccs_get(desc, query, rtn, 1); -} - -/** - * ccs_set: set an individual element's value in the config file. - * @desc: - * @path: - * @val: - * - * This function is used to update individual elements in a config file. - * It's effects are cluster wide. It only succeeds when the node is part - * of a quorate cluster. - * - * Note currently implemented. - * - * Returns: 0 on success, < 0 on failure - */ -int ccs_set(int desc, const char *path, char *val) -{ - errno = ENOSYS; - return -1; -} diff --git a/config/libs/libccsconfdb/libccs.pc.in b/config/libs/libccsconfdb/libccs.pc.in deleted file mode 100644 index a772ba6..0000000 --- a/config/libs/libccsconfdb/libccs.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=${prefix} -libdir=@libdir@ -includedir=${prefix}/include - -Name: libccs -Version: @VERSION@ -Description: Cluster Config library -Requires: -Libs: -L${libdir} -lccs -Cflags: -I${includedir} diff --git a/config/libs/libccsconfdb/xpathlite.c b/config/libs/libccsconfdb/xpathlite.c deleted file mode 100644 index 0086668..0000000 --- a/config/libs/libccsconfdb/xpathlite.c +++ /dev/null @@ -1,426 +0,0 @@ -#include "clusterautoconfig.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <limits.h> -#include <corosync/corotypes.h> -#include <corosync/confdb.h> - -#include "ccs.h" -#include "ccs_internal.h" - -static int tokenizer(char *current_query) -{ - int tokens = 0; - char *curpos = current_query; - char *next = NULL; - char *end; - - end = current_query + strlen(current_query); - - while (curpos <= end) { - tokens++; - - if (strncmp(curpos, "/", 1)) { - errno = EINVAL; - return -1; - } - - memset(curpos, 0, 1); - curpos = curpos + 1; - - next = strstr(curpos, "/"); - if (next == curpos) { - errno = EINVAL; - return -1; - } - - if (!next) - return tokens; - - if ((strstr(curpos, "[") > next) || !strstr(curpos, "[")) - curpos = next; - else - curpos = strstr(strstr(curpos, "]"), "/"); - - } - errno = EINVAL; - return -1; -} - -/* - * return 0 on success - * return -1 on errors - */ -static int path_dive(confdb_handle_t handle, hdb_handle_t *query_handle, - char *current_query, int tokens) -{ - char *pos = NULL, *next = NULL; - int i; - hdb_handle_t new_obj_handle; - - pos = current_query + 1; - - for (i = 1; i <= tokens; i++) { - if (confdb_object_find_start(handle, *query_handle) != - CS_OK) - goto fail; - - next = pos + strlen(pos) + 1; - - if (!strstr(pos, "[")) { - /* straight path diving */ - if (confdb_object_find - (handle, *query_handle, pos, strlen(pos), - &new_obj_handle) != CS_OK) - goto fail; - else { - confdb_object_find_destroy(handle, - *query_handle); - *query_handle = new_obj_handle; - } - } else { - /* - * /something[int]/ or /something[@foo="bar"]/ - * start and end will identify [] - * middle will point to the inside request - */ - - char *start = NULL, *middle = NULL, *end = NULL; - char data[PATH_MAX]; - size_t datalen = 0; - - /* - * those ones should be always good because - * the tokenizer takes care of them - */ - - start = strstr(pos, "["); - if (!start) - goto fail; - - end = strstr(pos, "]"); - if (!end) - goto fail; - - middle = start + 1; - memset(start, 0, 1); - memset(end, 0, 1); - - if (!strcmp(pos, "child::*")) { - int val, j; - - val = atoi(middle); - - if (val < 1) - goto fail; - - if (confdb_object_iter_start - (handle, *query_handle) != CS_OK) - goto fail; - - for (j = 1; j <= val; j++) { - if (confdb_object_iter - (handle, *query_handle, - &new_obj_handle, data, - &datalen) != CS_OK) - goto fail; - } - confdb_object_iter_destroy(handle, - *query_handle); - confdb_object_find_destroy(handle, - *query_handle); - *query_handle = new_obj_handle; - - } else if (!strstr(middle, "@")) { - /* lookup something with index num = int */ - int val, j; - - val = atoi(middle); - - if (val < 1) - goto fail; - - for (j = 1; j <= val; j++) { - if (confdb_object_find - (handle, *query_handle, pos, - strlen(pos), - &new_obj_handle) != CS_OK) - goto fail; - } - confdb_object_find_destroy(handle, - *query_handle); - *query_handle = new_obj_handle; - - } else { - /* lookup something with obj foo = bar */ - char *equal = NULL, *value = NULL, *tmp = NULL; - int goout = 0; - - equal = strstr(middle, "="); - if (!equal) - goto fail; - - memset(equal, 0, 1); - - value = strstr(equal + 1, """); - if (!value) - goto fail; - - value = value + 1; - - tmp = strstr(value, """); - if (!tmp) - goto fail; - - memset(tmp, 0, 1); - - middle = strstr(middle, "@") + 1; - if (!middle) - goto fail; - - // middle points to foo - // value to bar - - memset(data, 0, PATH_MAX); - while (!goout) { - if (confdb_object_find - (handle, *query_handle, pos, - strlen(pos), - &new_obj_handle) != CS_OK) - goto fail; - else { - if (confdb_key_get - (handle, new_obj_handle, - middle, strlen(middle), - data, - &datalen) == CS_OK) { - if (!strcmp - (data, value)) - goout = 1; - } - } - } - confdb_object_find_destroy(handle, - *query_handle); - *query_handle = new_obj_handle; - } - } - - pos = next; - } - - return 0; - -fail: - errno = EINVAL; - return -1; -} - -static int get_data(confdb_handle_t handle, hdb_handle_t connection_handle, - hdb_handle_t query_handle, hdb_handle_t *list_handle, - char **rtn, char *curpos, int list, int is_oldlist) -{ - int cmp; - char data[PATH_MAX]; - char resval[PATH_MAX]; - char keyval[PATH_MAX]; - hdb_handle_t new_obj_handle; - unsigned int value = 0; - size_t datalen = 0, keyvallen = PATH_MAX; - - memset(data, 0, PATH_MAX); - memset(resval, 0, PATH_MAX); - memset(keyval, 0, PATH_MAX); - - // we need to handle child::*[int value] in non list mode. - cmp = strcmp(curpos, "child::*"); - if (cmp >= 0) { - char *start = NULL, *end = NULL; - - // a pure child::* request should come down as list - if (!cmp && !list) - goto fail; - - if (confdb_object_iter_start(handle, query_handle) != CS_OK) - goto fail; - - if (!is_oldlist) - *list_handle = query_handle; - - if (cmp) { - start = strstr(curpos, "["); - if (!start) - goto fail; - - start = start + 1; - - end = strstr(start, "]"); - if (!end) - goto fail; - - memset(end, 0, 1); - value = atoi(start); - if (value <= 0) - goto fail; - } else { - if (confdb_key_increment - (handle, connection_handle, "iterator_tracker", - strlen("iterator_tracker"), &value) != CS_OK) - value = 1; - } - - while (value != 0) { - memset(data, 0, PATH_MAX); - if (confdb_object_iter - (handle, query_handle, &new_obj_handle, data, - &datalen) != CS_OK) { - reset_iterator(handle, connection_handle); - goto fail; - } - - value--; - } - - snprintf(resval, sizeof(resval), "%s=%s", data, keyval); - *rtn = strndup(resval, datalen + keyvallen + 2); - - } else if (!strncmp(curpos, "@*", strlen("@*"))) { - - // this query makes sense only if we are in list mode - if (!list) - goto fail; - - if (confdb_key_iter_start(handle, query_handle) != CS_OK) - goto fail; - - *list_handle = query_handle; - - if (confdb_key_increment - (handle, connection_handle, "iterator_tracker", - strlen("iterator_tracker"), &value) != CS_OK) - value = 1; - - while (value != 0) { - memset(data, 0, PATH_MAX); - if (confdb_key_iter - (handle, query_handle, data, &datalen, keyval, - &keyvallen) != CS_OK) { - reset_iterator(handle, connection_handle); - goto fail; - } - - value--; - } - - snprintf(resval, sizeof(resval), "%s=%s", data, keyval); - *rtn = strndup(resval, datalen + keyvallen + 2); - - } else { /* pure data request */ - char *query; - - // this query doesn't make sense in list mode - if (list) - goto fail; - - if (confdb_object_find_start(handle, query_handle) != CS_OK) - goto fail; - - query = strstr(curpos, "@"); - if (!query) - goto fail; - - query = query + 1; - - if (confdb_key_get - (handle, query_handle, query, strlen(query), data, - &datalen) != CS_OK) - goto fail; - - *rtn = strndup(data, datalen); - } - - return 0; - -fail: - errno = EINVAL; - return -1; -} - -/** - * _ccs_get_xpathlite - * @handle: - * @connection_handle: - * @query: - * @list: 1 to operate in list fashion - * - * This function will allocate space for the value that is the result - * of the given query. It is the user's responsibility to ensure that - * the data returned is freed. - * - * Returns: char * to result or NULL in case of failure. - */ -char *_ccs_get_xpathlite(confdb_handle_t handle, hdb_handle_t connection_handle, - const char *query, int list) -{ - char current_query[PATH_MAX]; - char *datapos, *rtn = NULL; - char previous_query[PATH_MAX]; - hdb_handle_t list_handle = 0; - hdb_handle_t query_handle = 0; - int prev = 0, is_oldlist = 0; - int tokens, i; - - memset(current_query, 0, PATH_MAX); - strncpy(current_query, query, PATH_MAX - 1); - - memset(previous_query, 0, PATH_MAX); - - datapos = current_query + 1; - - prev = - get_previous_query(handle, connection_handle, previous_query, - &list_handle); - - if (list && !prev && !strcmp(current_query, previous_query)) { - query_handle = list_handle; - is_oldlist = 1; - } else { - reset_iterator(handle, connection_handle); - query_handle = OBJECT_PARENT_HANDLE; - } - - if (confdb_object_find_start(handle, query_handle) != CS_OK) { - errno = ENOENT; - goto fail; - } - - tokens = tokenizer(current_query); - if (tokens < 1) - goto fail; - - for (i = 1; i < tokens; i++) - datapos = datapos + strlen(datapos) + 1; - - if (!is_oldlist) - if (path_dive(handle, &query_handle, current_query, tokens - 1) < 0) /* path dive can mangle tokens */ - goto fail; - - if (get_data - (handle, connection_handle, query_handle, &list_handle, &rtn, - datapos, list, is_oldlist) < 0) - goto fail; - - if (list) - if (set_previous_query - (handle, connection_handle, (char *)query, list_handle)) - goto fail; - - return rtn; - -fail: - return NULL; -} diff --git a/config/man/Makefile.am b/config/man/Makefile.am deleted file mode 100644 index 4c13505..0000000 --- a/config/man/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -dist_man_MANS = cluster.conf.5 diff --git a/config/man/cluster.conf.5 b/config/man/cluster.conf.5 deleted file mode 100644 index d9e50d4..0000000 --- a/config/man/cluster.conf.5 +++ /dev/null @@ -1,208 +0,0 @@ -.TH cluster.conf 5 - -.SH NAME -cluster.conf - configuration file for cman, fence, dlm, gfs, rgmanager - -.SH DESCRIPTION - -The /etc/cluster/cluster.conf file contains configuration for: - -.B cman(5) -for corosync and quorum configuration -.br -.B qdisk(5) -for quorum disk configuration -.br -.B groupd(8) -for daemon configuration -.br -.B fenced(8) -for daemon and fence device configuration -.br -.B dlm_controld(8) -for daemon configuration -.br -.B gfs_controld(8) -for daemon configuration -.br -.B rgmanager(8) -for daemon and resource configuration - -The same cluster.conf file must exist on each cluster node. - -When cman_tool starts corosync, the contents of cluster.conf are loaded into -the corosync in-memory configuration database (confdb). Daemons and programs -listed above use the libccs library to read cluster.conf data from the -corosync confdb. (The libconfdb library can also be used for more general, -non-xml confdb queries.) - -When cman configures corosync using cluster.conf, the corosync.conf file is -not used. - -.SS Cluster Nodes - -cluster.conf is an XML file. It has one top-level \fIcluster\fP section -containing everything else. The cluster section has two mandatory -attributes: \fIname\fP and \fIconfig_version\fP. \fIname\fP can be up to -15 characters long (16 including terminating null) and specifies the name -of the cluster. It is important that this name be unique among clusters -on the same network. \fIconfig_version\fP is a number used to identify -the revision level of the cluster.conf file. - - <cluster name="alpha" config_version="1"> - </cluster> - -The set of nodes that make up the cluster are defined under the -\fIclusternodes\fP section. A \fIclusternode\fP section defines each -node. A clusternode has two mandatory attributes: -.I name -and -.I nodeid - -The name should correspond to the hostname (the fully qualified name is -generally not necessary) on the network interface to be used for cluster -communication. Nodeid's must be greater than zero and unique. - - <cluster name="alpha" config_version="1"> - <clusternodes> - <clusternode name="node-01" nodeid="1"> - </clusternode> - - <clusternode name="node-02" nodeid="2"> - </clusternode> - - <clusternode name="node-03" nodeid="3"> - </clusternode> - </clusternodes> - </cluster> - -.SS Logging -.br -All daemons listed above use the <logging> section to configure loggging. -Global settings apply to all: - - <logging debug="on"/> - -Per-daemon settings override the corresponding global setting. logging_daemon -names that can be configured include: corosync, qdiskd, groupd, fenced, -dlm_controld, gfs_controld, rgmanager. - - <logging> - <logging_daemon name="qdiskd" debug="on"/> - <logging_daemon name="fenced" debug="on"/> - </logging> - -corosync daemon settings apply to all corosync subsystems by default, but -subsystems can also be configured individually. These include CLM, CPG, MAIN, -SERV, CMAN, TOTEM, QUORUM, CONFDB, CKPT, EVT. - - <logging> - <logging_daemon name="corosync" subsys="QUORUM" debug="on"/> - <logging_daemon name="corosync" subsys="CONFDB" debug="on"/> - </logging> - -.B Settings -.br -The settings available at global, daemon and subsystem levels are: - -.B to_syslog -.br -enable/disable messages to syslog (yes/no) -.br -default "yes" - -.B to_logfile -.br -enable/disable messages to log file (yes/no) -.br -default "yes" - -.B syslog_facility -.br -facility used for syslog messages -.br -default "daemon" - -.B syslog_priority -.br -messages at this level and up will be sent to syslog -.br -default "info" - -.B logfile_priority -.br -messages at this level and up will be written to log file -.br -default "info" - -.B logfile -.br -the log file name, default /var/log/cluster/<daemon>.log - -.B debug="on" -.br -is a shortcut for logfile_priority="debug" - -.B Defaults -.br -An explicit configuration for the default settings would be: - -<logging to_syslog="yes" to_logfile="yes" syslog_facility="daemon" - syslog_priority="info" logfile_priority="info"> -.br - <logging_daemon name="qdiskd" - logfile="/var/log/cluster/qdisk.log"/> -.br - <logging_daemon name="groupd" - logfile="/var/log/cluster/groupd.log"/> -.br - <logging_daemon name="fenced" - logfile="/var/log/cluster/fenced.log"/> -.br - <logging_daemon name="dlm_controld" - logfile="/var/log/cluster/dlm_controld.log"/> -.br - <logging_daemon name="gfs_controld" - logfile="/var/log/cluster/gfs_controld.log"/> -.br - <logging_daemon name="rgmanager" - logfile="/var/log/cluster/rgmanager.log"/> -.br - <logging_daemon name="corosync" - logfile="/var/log/cluster/corosync.log"/> -.br -</logging> - -.B Examples -.br -To include debug messages (and above) from all daemons in their default log files, either -.in +7 -<logging debug="on"/> or -<logging logfile_priority="debug"/> -.in -7 - -To exclude all log messages from syslog -.in +7 -<logging to_syslog="no"/> -.in -7 - -To disable logging to all log files -.in +7 -<logging to_file="no"/> -.in -7 - -To include debug messages (and above) from all daemons in syslog -.in +7 -<logging syslog_priority="debug"/> -.in -7 - -To limit syslog messages to error (and above), keeping info (and above) in -log files (this logfile_priority setting is the default so could be omitted) -.in +7 -<logging syslog_priority="error" logfile_priority="info"/> -.in -7 - - -.SH SEE ALSO -cman(5), qdisk(5), groupd(8), fenced(8), dlm_controld(8), gfs_controld(8), rgmanager(8) - diff --git a/config/plugins/Makefile.am b/config/plugins/Makefile.am deleted file mode 100644 index 64cea14..0000000 --- a/config/plugins/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -SUBDIRS = xml ldap diff --git a/config/plugins/ldap/99cluster.ldif b/config/plugins/ldap/99cluster.ldif deleted file mode 100644 index 7b53a12..0000000 --- a/config/plugins/ldap/99cluster.ldif +++ /dev/null @@ -1,138 +0,0 @@ -# Schema for Red Hat cluster suite LDAP configuration -# 2008, Christine Caulfield ccaulfie@redhat.com -# -# This schema is incomplete, and probably always will be -# -# -dn: cn=schema -attributeTypes: ( - 1.3.6.1.4.1.2312.8.1.1.1 NAME 'rhcsConfig-version' - DESC 'An integer describing the configuration version' - EQUALITY integerMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 - SINGLE-VALUE - ) -attributeTypes: ( - 1.3.6.1.4.1.2312.8.1.1.2 NAME 'rhcsNodeid' - DESC 'An integer describing the node ID number' - EQUALITY integerMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 - SINGLE-VALUE - ) -attributeTypes: ( - 1.3.6.1.4.1.2312.8.1.1.3 NAME 'rhcsCluster-id' - DESC 'An integer describing the cluster ID number' - EQUALITY integerMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 - SINGLE-VALUE - ) -attributeTypes: ( - 1.3.6.1.4.1.2312.8.1.1.4 NAME 'rhcsVotes' - DESC 'An integer describing the number of votes a node has' - EQUALITY integerMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 - SINGLE-VALUE - ) -attributeTypes: ( - 1.3.6.1.4.1.2312.8.1.1.5 NAME 'rhcsTwo-node' - DESC 'set to 1 for two_node mode' - EQUALITY integerMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 - SINGLE-VALUE - ) -attributeTypes: ( - 1.3.6.1.4.1.2312.8.1.1.6 NAME 'rhcsExpected-votes' - DESC 'An integer describing the number of votes expected for the whole cluster' - EQUALITY integerMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 - SINGLE-VALUE - ) -attributeTypes: ( - 1.3.6.1.4.1.2312.8.1.1.7 NAME 'rhcsMax-queued' - DESC 'An integer describing the maximum number of outstanding client requests to cman' - EQUALITY integerMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 - SINGLE-VALUE - ) -attributeTypes: ( - 1.3.6.1.4.1.2312.8.1.1.8 NAME 'rhcsToken' - DESC 'An integer describing the totem token timeout' - EQUALITY integerMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 - SINGLE-VALUE - ) -attributeTypes: ( - 1.3.6.1.4.1.2312.8.1.1.9 NAME 'rhcsAgent' - DESC 'The fencing agent to use' - EQUALITY caseIgnoreIA5Match - SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 - SINGLE-VALUE - ) -attributeTypes: ( - 1.3.6.1.4.1.2312.8.1.1.10 NAME 'rhcsUsername' - DESC 'Username to log into the fencing agent' - EQUALITY caseIgnoreIA5Match - SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 - SINGLE-VALUE - ) -attributeTypes: ( - 1.3.6.1.4.1.2312.8.1.1.11 NAME 'rhcsPassword' - DESC 'Password to log into the fencing agent' - EQUALITY caseIgnoreIA5Match - SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 - SINGLE-VALUE - ) -attributeTypes: ( - 1.3.6.1.4.1.2312.8.1.1.12 NAME 'rhcsIpaddr' - DESC 'IP Address the fencing agent' - EQUALITY caseIgnoreIA5Match - SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 - SINGLE-VALUE - ) -attributeTypes: ( - 1.3.6.1.4.1.2312.8.1.1.13 NAME 'rhcsPort' - DESC 'Port number for fence agent or cman' - EQUALITY IntegerMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 - SINGLE-VALUE - ) -objectClasses: ( - 1.3.6.1.4.1.2312.8.1.2.1 NAME 'rhcsCluster' SUP top STRUCTURAL - DESC 'Cluster top-level entry' - MUST ( cn $ name $ rhcsConfig-version ) - ) -objectClasses: ( - 1.3.6.1.4.1.2312.8.1.2.2 NAME 'rhcsNode' SUP top STRUCTURAL - DESC 'Cluster node entry' - MUST ( name $ rhcsNodeid ) - MAY rhcsVotes - ) -objectClasses: ( - 1.3.6.1.4.1.2312.8.1.2.3 NAME 'rhcsCman' SUP top STRUCTURAL - DESC 'Cluster node entry' - MUST ( cn ) - MAY ( rhcsCluster-id $ rhcsTwo-node $ rhcsExpected-votes $ rhcsMax-queued $ rhcsPort ) - ) -objectClasses: ( - 1.3.6.1.4.1.2312.8.1.2.4 NAME 'rhcsTotem' SUP top STRUCTURAL - DESC 'Totem options' - MUST ( cn ) - MAY ( rhcsToken ) - ) -objectClasses: ( - 1.3.6.1.4.1.2312.8.1.2.5 NAME 'rhcsFencedevice' SUP top STRUCTURAL - DESC 'A Fence device' - MUST ( name $ rhcsAgent ) - MAY ( rhcsIpaddr $ rhcsUsername $ rhcsPassword ) - ) -objectClasses: ( - 1.3.6.1.4.1.2312.8.1.2.6 NAME 'rhcsFenceagent' SUP top STRUCTURAL - DESC 'A Fence device' - MUST ( name ) - MAY ( rhcsPort $ rhcsIpaddr ) - ) -objectClasses: ( - 1.3.6.1.4.1.2312.8.1.2.7 NAME 'rhcsFencemethod' SUP top STRUCTURAL - DESC 'A Fence method placeholder' - MUST ( name ) -) diff --git a/config/plugins/ldap/Makefile.am b/config/plugins/ldap/Makefile.am deleted file mode 100644 index 520b093..0000000 --- a/config/plugins/ldap/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -dist_doc_DATA = 99cluster.ldif example.ldif - -AM_CFLAGS = -fPIC $(corosync_CFLAGS) - -AM_LDFLAGS = -lldap - -LCRSO = config_ldap.lcrso - -SOURCES = configldap.c - -EXTRA_DIST = $(SOURCES) - -include $(top_srcdir)/make/lcrso.mk diff --git a/config/plugins/ldap/configldap.c b/config/plugins/ldap/configldap.c deleted file mode 100644 index 557b08f..0000000 --- a/config/plugins/ldap/configldap.c +++ /dev/null @@ -1,288 +0,0 @@ -#include "clusterautoconfig.h" - -#include <sys/types.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <arpa/inet.h> - -// CC: temp until I tame SASL ... is this necessary? -#define LDAP_DEPRECATED 1 -#include <ldap.h> - -/* corosync headers */ -#include <corosync/lcr/lcr_comp.h> -#include <corosync/engine/objdb.h> -#include <corosync/engine/config.h> - -/* These are defaults. they can be overridden with environment variables - * COROSYNC_LDAP_URL & COROSYNC_LDAP_BASEDN - */ -#define DEFAULT_LDAP_URL "ldap:///" -#define DEFAULT_LDAP_BASEDN "dc=chrissie,dc=net" - -static int ldap_readconfig(struct objdb_iface_ver0 *objdb, const char **error_string); -static int ldap_reloadconfig(struct objdb_iface_ver0 *objdb, int flush, const char **error_string); -static int init_config(struct objdb_iface_ver0 *objdb); -static char error_reason[1024]; -static const char *ldap_url = DEFAULT_LDAP_URL; -static const char *ldap_basedn = DEFAULT_LDAP_BASEDN; - -/* - * Exports the interface for the service - */ - -static struct config_iface_ver0 ldapconfig_iface_ver0 = { - .config_readconfig = ldap_readconfig, - .config_reloadconfig = ldap_reloadconfig -}; - -static struct lcr_iface ifaces_ver0[2] = { - { - .name = "ldapconfig", - .version = 0, - .versions_replace = 0, - .versions_replace_count = 0, - .dependencies = 0, - .dependency_count = 0, - .constructor = NULL, - .destructor = NULL, - .interfaces = NULL, - } -}; - -static struct lcr_comp ldap_comp_ver0 = { - .iface_count = 1, - .ifaces = ifaces_ver0, -}; - - - -__attribute__ ((constructor)) static void ldap_comp_register(void) { - lcr_interfaces_set(&ifaces_ver0[0], &ldapconfig_iface_ver0); - lcr_component_register(&ldap_comp_ver0); -}; - -static int ldap_readconfig(struct objdb_iface_ver0 *objdb, const char **error_string) -{ - int ret; - - /* Read config tree from LDAP */ - if (!(ret = init_config(objdb))) - sprintf(error_reason, "%s", "Successfully read config from LDAP\n"); - - *error_string = error_reason; - - return ret; -} - -static int ldap_reloadconfig(struct objdb_iface_ver0 *objdb, int flush, const char **error_string) -{ - return ldap_readconfig(objdb, error_string); -} - -/* - * Convert hyphens to underscores in all attribute names - */ -static void convert_underscores(char *s, int len) -{ - int j; - - for (j=0; j < len; j++) { - if (s[j] == '-') - s[j] = '_'; - } -} - -static void convert_dn_underscores(LDAPDN dn) -{ - int i=0; - - while (dn[i]) { - convert_underscores(dn[i][0][0].la_attr.bv_val, dn[i][0][0].la_attr.bv_len); - i++; - } -} - -/* - * Return the parent object of a DN. - * Actually, this returns the LAST parent with that name. which should (!) be correct. - */ -static hdb_handle_t find_parent(struct objdb_iface_ver0 *objdb, LDAPDN dn, int startdn, const char *parent) -{ - int i=startdn; - int gotstart=0; - int start=0, end=startdn; - hdb_handle_t parent_handle = OBJECT_PARENT_HANDLE; - hdb_handle_t object_handle=0; - hdb_handle_t find_handle; - - /* - * Find the start and end positions first. - * start is where the 'parent' entry is. - * end is the end of the list - */ - do { - if (!gotstart && dn[i][0][0].la_value.bv_len == 7 && - !strncmp(parent, dn[i][0][0].la_value.bv_val, 7)) { - gotstart = 1; - start = i; - } - i++; - } while (dn[i]); - if (start <= 0) - return parent_handle; - - for (i=start; i>=end; i--) { - objdb->object_find_create(parent_handle, - dn[i][0][0].la_value.bv_val, dn[i][0][0].la_value.bv_len, - &find_handle); - while (!objdb->object_find_next(find_handle, &object_handle)) { - parent_handle = object_handle; - } - objdb->object_find_destroy(find_handle); - } - return object_handle; -} - - - -static int read_config_for(LDAP *ld, struct objdb_iface_ver0 *objdb, hdb_handle_t parent, - const char *object, const char *sub_dn, int always_create) -{ - char search_dn[4096]; - int rc; - char *dn; - LDAPMessage *result, *e; - hdb_handle_t parent_handle = OBJECT_PARENT_HANDLE; - hdb_handle_t object_handle; - - sprintf(search_dn, "%s,%s", sub_dn, ldap_basedn); - - /* Search the whole tree from the base DN provided */ - rc = ldap_search_ext_s(ld, search_dn, LDAP_SCOPE_SUBTREE, "(objectClass=*)", NULL, 0, - NULL, NULL, NULL, 0, &result); - if (rc != LDAP_SUCCESS) { - sprintf(error_reason, "ldap_search_ext_s: %s\n", ldap_err2string(rc)); - if (rc == LDAP_NO_SUCH_OBJECT) - return 0; - else - return -1; - } - for (e = ldap_first_entry(ld, result); e != NULL; - e = ldap_next_entry(ld, e)) { - if ((dn = ldap_get_dn(ld, e)) != NULL) { - char *attr; - BerElement *attr_ber; - LDAPDN parsed_dn; - - /* Make it parsable so we can discern the hierarchy */ - if (ldap_str2dn(dn, &parsed_dn, LDAP_DN_PEDANTIC)) { - sprintf(error_reason, "ldap_str2dn failed: %s\n", ldap_err2string(rc)); - return -1; - } - - /* - * LDAP doesn't allow underscores in dn names so we replace hypens with - * underscores so we can have thing like config_version, appear as - * config-version in ldap - */ - convert_dn_underscores(parsed_dn); - - /* Create a new object if the top-level is NOT name= */ - if (strncmp(parsed_dn[0][0][0].la_attr.bv_val, "name", 4)) { - parent_handle = find_parent(objdb, parsed_dn, 0, object); - - objdb->object_create(parent_handle, &object_handle, parsed_dn[0][0][0].la_value.bv_val, - parsed_dn[0][0][0].la_value.bv_len); - } - else { - parent_handle = find_parent(objdb, parsed_dn, 2, object); - /* Create a new object with the same name as the current one */ - objdb->object_create(parent_handle, &object_handle, parsed_dn[1][0][0].la_value.bv_val, - parsed_dn[1][0][0].la_value.bv_len); - } - - /* Finished with the text representation */ - ldap_memfree(dn); - - /* Store the attributes as keys */ - attr = ldap_first_attribute(ld, e, &attr_ber); - while (attr) { - int i; - struct berval **val_ber; - - val_ber = ldap_get_values_len(ld, e, attr); - i=0; - while (val_ber[i]) { - /* - * If the attribute starts "rhcs" then remove that bit - * and make the first letter lower case so it matches the - * cluster.conf entry. - * so, after the above underscore change too: - * eg 'rhcsConfig-version' becomes 'config_version'. magic! - */ - if (strncmp(attr, "rhcs", 4) == 0) { - memmove(attr, attr+4, strlen(attr+4)+1); - attr[0] |= 0x60; - } - convert_underscores(attr, strlen(attr)); - - /* - * Add a key - but ignore "objectClass" & "cn" attributes - * as they don't provide anything we can use - */ - if (strcmp("objectClass", attr) && - strcmp("cn", attr)) { - objdb->object_key_create(object_handle, attr, strlen(attr), - val_ber[i]->bv_val, - val_ber[i]->bv_len+1); - } - i++; - } - ldap_memfree(attr); - attr = ldap_next_attribute(ld, e, attr_ber); - ldap_value_free_len(val_ber); - } - ldap_memfree(attr); - ber_free(attr_ber, 0); - } - } - ldap_msgfree(result); - - return 0; -} - -/* The real work starts here */ -static int init_config(struct objdb_iface_ver0 *objdb) -{ - LDAP *ld; - int version, rc; - - if (getenv("COROSYNC_LDAP_URL")) - ldap_url = getenv("COROSYNC_LDAP_URL"); - if (getenv("COROSYNC_LDAP_BASEDN")) - ldap_basedn = getenv("COROSYNC_LDAP_BASEDN"); - - /* Connect to the LDAP server */ - if (ldap_initialize(&ld, ldap_url)) { - sprintf(error_reason, "ldap_simple_bind failed: %s\n", strerror(errno)); - return -1; - } - version = LDAP_VERSION3; - ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version); - - /* - * CC: Do I need to use sasl ?! - */ - rc = ldap_simple_bind_s(ld, getenv("COROSYNC_LDAP_BINDDN"), getenv("COROSYNC_LDAP_BINDPWD")); - if (rc != LDAP_SUCCESS) { - sprintf(error_reason, "ldap_simple_bind failed: %s\n", ldap_err2string(rc)); - return -1; - } - - rc = read_config_for(ld, objdb, OBJECT_PARENT_HANDLE, "cluster", "name=cluster", 1); - - ldap_unbind(ld); - return 0; -} diff --git a/config/plugins/ldap/example.ldif b/config/plugins/ldap/example.ldif deleted file mode 100644 index 0182dcf..0000000 --- a/config/plugins/ldap/example.ldif +++ /dev/null @@ -1,137 +0,0 @@ -# Example cluster LDIF file -# Christine Caulfield ccaulfie@redhat.com -# -# You WILL need to change this to suit your needs, in particular a search -# and replace of dc=chrissie,dc=net with your own domanin name. -# -# Load with: -# ldapmodify -x -a -D"cn=Directory Manager" -f example.ldif -c -v -W -# -# -# What follows is the LDAP equivalent of the following cluster.conf file: -# -#<totem token="21000"/> -# -#<cluster config_version="1" name="cc_cluster"> -# <cman cluster_id="444"/> -# -# <fencedevices> -# <fencedevice name="myapc" -# password="apc" -# username="apc" -# ipaddr="myapc.chrissie.net" -# agent="fence_apc" -# </fencedevice> -# </fencedevice> -# <clusternodes> -# <clusternode name="ford" -# votes="1" -# nodeid="32"> -# <fence> -# <method name="apc"> -# <device name="myapc" port="4"/> -# </method> -# </fence> -# </clusternode> -# -# <clusternode name="arthur" -# votes="1" -# nodeid="10"> -# </clusternode> -# -# <clusternode name="jeltz" -# votes="2" -# nodeid="1"> -# </clusternode> -# </clusternodes> -#</cluster> -# -# - -dn: cn=cluster,dc=chrissie,dc=net -cn: cluster -objectClass: rhcsCluster -name: cc_cluster -rhcsConfig-version: 1 - -# Some cman parameters -dn: cn=cman,cn=cluster,dc=chrissie,dc=net -cn: cman -objectClass: rhcsCman -rhcsCluster-id: 444 - -# Some totem parameters -dn: cn=totem,cn=cluster,dc=chrissie,dc=net -cn: totem -objectClass: rhcsTotem -rhcsToken: 21000 - -# Define nodes -dn: cn=clusternodes,cn=cluster,dc=chrissie,dc=net -cn: clusternodes -objectClass: nsContainer - - -dn: cn=clusternode,cn=clusternodes,cn=cluster,dc=chrissie,dc=net -cn: clusternode -objectClass: nsContainer - - -dn: name=jeltz,cn=clusternode,cn=clusternodes,cn=cluster,dc=chrissie,dc=net -objectClass: rhcsNode -name: jeltz -rhcsNodeid: 1 -rhcsVotes: 2 - -# Define a fence agent for this node ...! -dn: cn=fence,name=jeltz,cn=clusternode,cn=clusternodes,cn=cluster,dc=chrissie,dc=net -cn: fence -objectclass: nsContainer - -dn: cn=method,cn=fence,name=jeltz,cn=clusternode,cn=clusternodes,cn=cluster,dc=chrissie,dc=net -cn: method -objectclass: nsContainer - -dn: name=apc,cn=method,cn=fence,name=jeltz,cn=clusternode,cn=clusternodes,cn=cluster,dc=chrissie,dc=net -name: apc -objectclass: rhcsFenceMethod - -dn: cn=device,name=apc,cn=method,cn=fence,name=jeltz,cn=clusternode,cn=clusternodes,cn=cluster,dc=chrissie,dc=net -cn: device -objectclass: nsContainer - -dn: name=myapc,cn=device,name=apc,cn=method,cn=fence,name=jeltz,cn=clusternode,cn=clusternodes,cn=cluster,dc=chrissie,dc=net -name: myapc -objectclass: rhcsFenceAgent -rhcsPort: 4 - -dn: name=arthur,cn=clusternode,cn=clusternodes,cn=cluster,dc=chrissie,dc=net -objectClass: rhcsNode -name: arthur -rhcsNodeid: 10 -rhcsVotes: 1 - -dn: name=ford,cn=clusternode,cn=clusternodes,cn=cluster,dc=chrissie,dc=net -objectClass: rhcsNode -name: ford -rhcsNodeid: 32 -rhcsVotes: 1 - -# Fence agent - -dn: cn=fencedevices,cn=cluster,dc=chrissie,dc=net -cn: fencedevices -objectClass: nsContainer - -dn: cn=fencedevice,cn=fencedevices,cn=cluster,dc=chrissie,dc=net -cn: fencedevice -objectClass: nsContainer - - -dn: name=myapc,cn=fencedevice,cn=fencedevices,cn=cluster,dc=chrissie,dc=net -objectClass: rhcsFencedevice -name: myapc -rhcsAgent: fence_apc -rhcsIpaddr: myapc.chrissie.net -rhcsUsername: apc -rhcsPassword: apc diff --git a/config/plugins/xml/Makefile.am b/config/plugins/xml/Makefile.am deleted file mode 100644 index d0b4094..0000000 --- a/config/plugins/xml/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CFLAGS = -fPIC \ - $(xml_CFLAGS) $(corosync_CFLAGS) - -AM_LDFLAGS = $(xml_LIBS) - -LCRSO = config_xml.lcrso - -SOURCES = config.c - -EXTRA_DIST = $(SOURCES) - -include $(top_srcdir)/make/lcrso.mk diff --git a/config/plugins/xml/config.c b/config/plugins/xml/config.c deleted file mode 100644 index 5a53ba8..0000000 --- a/config/plugins/xml/config.c +++ /dev/null @@ -1,150 +0,0 @@ -#include "clusterautoconfig.h" - -#include <string.h> -#include <syslog.h> - -#include <libxml/tree.h> - -#include <corosync/lcr/lcr_comp.h> -#include <corosync/engine/objdb.h> -#include <corosync/engine/config.h> - -static int xml_readconfig(struct objdb_iface_ver0 *objdb, const char **error_string); -static int xml_reloadconfig(struct objdb_iface_ver0 *objdb, int flush, - const char **error_string); -static int init_config(struct objdb_iface_ver0 *objdb, const char *configfile, - const char *error_string); -static char error_reason[1024]; - -#define DEFAULT_CONFIG DEFAULT_CONFIG_DIR "/" DEFAULT_CONFIG_FILE - -/* - * Exports the interface for the service - */ - -static struct config_iface_ver0 xmlconfig_iface_ver0 = { - .config_readconfig = xml_readconfig, - .config_reloadconfig = xml_reloadconfig -}; - -static struct lcr_iface ifaces_ver0[2] = { - { - .name = "xmlconfig", - .version = 0, - .versions_replace = 0, - .versions_replace_count = 0, - .dependencies = 0, - .dependency_count = 0, - .constructor = NULL, - .destructor = NULL, - .interfaces = NULL, - } -}; - -static struct lcr_comp xml_comp_ver0 = { - .iface_count = 1, - .ifaces = ifaces_ver0, -}; - -__attribute__ ((constructor)) -static void xml_comp_register(void) -{ - lcr_interfaces_set(&ifaces_ver0[0], &xmlconfig_iface_ver0); - lcr_component_register(&xml_comp_ver0); -}; - -static void addkeys(xmlAttrPtr tmpattr, struct objdb_iface_ver0 *objdb, - hdb_handle_t object_handle) -{ - for (tmpattr = tmpattr; tmpattr; tmpattr = tmpattr->next) { - if (tmpattr->type == XML_ATTRIBUTE_NODE) - objdb->object_key_create(object_handle, - (char *)tmpattr->name, - strlen((char *)tmpattr->name), - (char *)tmpattr->children-> - content, - strlen((char *)tmpattr-> - children->content) + 1); - } -} - -static void xml2objdb(xmlNodePtr tmpnode, struct objdb_iface_ver0 *objdb, - hdb_handle_t parent) -{ - hdb_handle_t object_handle = 0; - - for (tmpnode = tmpnode; tmpnode; tmpnode = tmpnode->next) { - if (tmpnode->type == XML_ELEMENT_NODE) { - objdb->object_create(parent, &object_handle, - (char *)tmpnode->name, - strlen((char *)tmpnode->name)); - if (tmpnode->properties) - addkeys(tmpnode->properties, objdb, - object_handle); - } - xml2objdb(tmpnode->children, objdb, object_handle); - } -} - -static int xml_reloadconfig(struct objdb_iface_ver0 *objdb, int flush, - const char **error_string) -{ - return xml_readconfig(objdb, error_string); -} - -static int xml_readconfig(struct objdb_iface_ver0 *objdb, const char **error_string) -{ - int ret = 0; - const char *configfile = DEFAULT_CONFIG; - - /* We need to set this up to internal defaults too early */ - openlog("corosync", LOG_CONS | LOG_PID, SYSLOGFACILITY); - - if (getenv("COROSYNC_CLUSTER_CONFIG_FILE")) - configfile = getenv("COROSYNC_CLUSTER_CONFIG_FILE"); - - /* Read low-level totem/aisexec etc config from cluster.conf */ - if (!(ret = init_config(objdb, configfile, error_reason))) - sprintf(error_reason, "Successfully read config from %s\n", - configfile); - else - sprintf(error_reason, "Unable to read config from %s\n", - configfile); - - *error_string = error_reason; - - return ret; -} - -static int init_config(struct objdb_iface_ver0 *objdb, const char *configfile, - const char *error_string) -{ - int err = 0; - xmlDocPtr doc = NULL; - xmlNodePtr root_node = NULL; - - /* openfile */ - - doc = xmlParseFile(configfile); - if (!doc) { - err = -1; - goto fail; - } - - root_node = xmlDocGetRootElement(doc); - if (!root_node) { - err = -1; - goto fail; - } - - /* load it in objdb */ - xml2objdb(root_node, objdb, OBJECT_PARENT_HANDLE); - -fail: - if (doc) - xmlFreeDoc(doc); - - xmlCleanupParser(); - - return err; -} diff --git a/config/tools/Makefile.am b/config/tools/Makefile.am deleted file mode 100644 index 2cebdd3..0000000 --- a/config/tools/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -SUBDIRS = ccs_tool ldap mkconf man diff --git a/config/tools/ccs_tool/Makefile.am b/config/tools/ccs_tool/Makefile.am deleted file mode 100644 index 295950d..0000000 --- a/config/tools/ccs_tool/Makefile.am +++ /dev/null @@ -1,24 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -sbin_PROGRAMS = ccs_tool - -noinst_HEADERS = editconf.h - -ccs_tool_SOURCES = ccs_tool.c editconf.c - -ccs_tool_CPPFLAGS = -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 \ - -I$(top_srcdir)/config/libs/libccsconfdb - -ccs_tool_CFLAGS = $(xml_CFLAGS) - -ccs_tool_LDFLAGS = $(xml_LIBS) - -ccs_tool_LDADD = $(top_builddir)/config/libs/libccsconfdb/libccs.la - -install-exec-hook: - (cd $(DESTDIR)/$(sbindir) && \ - rm -f ccs_test && \ - $(LN_S) ccs_tool ccs_test) - -uninstall-hook: - (cd $(DESTDIR)/$(sbindir) && rm -f ccs_test) diff --git a/config/tools/ccs_tool/ccs_tool.c b/config/tools/ccs_tool/ccs_tool.c deleted file mode 100644 index a00f0dc..0000000 --- a/config/tools/ccs_tool/ccs_tool.c +++ /dev/null @@ -1,309 +0,0 @@ -#include "clusterautoconfig.h" - -#include <stdio.h> -#include <stdlib.h> -#include <getopt.h> -#include <string.h> -#include <errno.h> - -#include "copyright.cf" -#include "editconf.h" -#include "ccs.h" - - -/* - * Old libccs retruned -error (mostly!) but didn't set errno (sigh) - * New libccs sets errno correctly - */ -static char *errstring(int retcode) -{ - return strerror(errno); -} - -static void tool_print_usage(FILE *stream); - -int globalverbose=0; - -static void test_print_usage(FILE *stream); - -static int test_main(int argc, char *argv[], int old_format){ - int desc=0; - int i=0; - int error = 0; - int force = 0, blocking = 0; - char *str=NULL; - char *cluster_name = NULL; - - if(argc <= 1){ - test_print_usage(stderr); - exit(EXIT_FAILURE); - } - - for(i=1; i < argc; i++){ - if(!strcmp(argv[i], "-h")){ - test_print_usage(stdout); - exit(EXIT_SUCCESS); - } - if(!strcmp(argv[i], "-V")){ - printf("%s %s (built %s %s)\n", argv[0], PACKAGE_VERSION, __DATE__, __TIME__); - printf("%s\n", REDHAT_COPYRIGHT); - exit(EXIT_SUCCESS); - } - } - - if(!strcmp(argv[1], "connect")){ - for(i=2; i < argc; i++){ - if(!strcmp(argv[i], "force")){ - printf("Force is set.\n"); - force = 1; - } else if(!strcmp(argv[i], "block")){ - printf("Blocking is set.\n"); - blocking = 1; - } else { - cluster_name = argv[i]; - printf("Setting cluster name to %s\n", cluster_name); - } - } - if(blocking && !force){ - fprintf(stderr, "Blocking can only be used with "force".\n"); - exit(EXIT_FAILURE); - } - if(force){ - desc = ccs_force_connect(cluster_name, blocking); - } else { - if(cluster_name){ - fprintf(stderr, "A cluster name can only be specified when using 'force'.\n"); - exit(EXIT_FAILURE); - } - desc = ccs_connect(); - } - if(desc < 0){ - fprintf(stderr, "ccs_connect failed: %s\n", errstring(-desc)); - exit(EXIT_FAILURE); - } else { - printf("Connect successful.\n"); - printf(" Connection descriptor = %d\n", desc); - ccs_disconnect(desc); - } - } - else if(!strcmp(argv[1], "disconnect")){ - if(argc < 3){ - fprintf(stderr, "Wrong number of arguments.\n"); - exit(EXIT_FAILURE); - } - desc = ccs_connect(); - if((error = ccs_disconnect(desc))){ - fprintf(stderr, "ccs_disconnect failed: %s\n", errstring(-error)); - exit(EXIT_FAILURE); - } else { - printf("Disconnect successful.\n"); - } - } - else if(!strcmp(argv[1], "get")){ - if(argc < 4){ - fprintf(stderr, "Wrong number of arguments.\n"); - exit(EXIT_FAILURE); - } - desc = ccs_connect(); - if((desc < 0) || (error = ccs_get(desc, argv[3], &str))){ - fprintf(stderr, "ccs_get failed: %s\n", errstring(-error)); - exit(EXIT_FAILURE); - } else { - if (old_format) { - printf("Get successful.\n"); - printf(" Value = <%s>\n", str); - } - else { - printf("%s\n", str); - } - if(str)free(str); - ccs_disconnect(desc); - } - } - else { - fprintf(stderr, "Unknown command: %s\n", argv[1]); - exit(EXIT_FAILURE); - } - - exit(EXIT_SUCCESS); -} - -static void test_print_usage(FILE *stream) -{ - fprintf(stream, - "Usage:\n" - "\n" - "ccs_test [Options] <Command>\n" - "\n" - "Options:\n" - " -h Print usage.\n" - " -V Print version information.\n" - "\n" - "Commands:\n" - " connect <force> <block> Connect to CCS and return connection descriptor.\n" - " disconnect <desc> Disconnect from CCS.\n" - " get <desc> <request> Get a value from CCS.\n" - ); -} - -static int xpath_query(int argc, char **argv) -{ - int handle; - char *ret; - int i; - - if (argc < 2) { - fprintf(stderr, - "Usage:\n" - "\n" - "ccs_tool query [-n] <xpath query>\n" - "\n" - "options\n" - " -n disable full XPath parsing\n"); - return 1; - } - - /* Tell the library we want full XPath parsing */ - fullxpath = 1; - - if (strcmp(argv[1], "-n") == 0) { - argv++; - argc--; - - /* Actually ... no we don't */ - fullxpath = 0; - } - - handle = ccs_connect(); - - /* Process all the queries on the command-line */ - for (i=1; i<argc; i++) { - if (!ccs_get(handle, argv[1], &ret)) { - printf("%s\n", ret); - free(ret); - } - else { - fprintf(stderr, "Query failed: %s\n", strerror(errno)); - ccs_disconnect(handle); - return -1; - } - } - ccs_disconnect(handle); - return 0; -} - -static int tool_main(int argc, char *argv[]) -{ - optind = 1; - - if (argc < 2 || !strcmp(argv[optind], "-h")) { - tool_print_usage(stdout); - exit(EXIT_SUCCESS); - } - if (!strcmp(argv[optind], "-V")) { - printf("%s %s (built %s %s)\n", argv[0], PACKAGE_VERSION, - __DATE__, __TIME__); - printf("%s\n", REDHAT_COPYRIGHT); - exit(EXIT_SUCCESS); - } - - if(optind < argc){ - if(!strcmp(argv[optind], "-verbose")){ - optind++; - globalverbose=1; - } - if(!strcmp(argv[optind], "help")){ - tool_print_usage(stdout); - exit(EXIT_SUCCESS); - } - else if(!strcmp(argv[optind], "query")){ - return xpath_query(argc-1, argv+1); - } - else if(!strcmp(argv[optind], "addnode")){ - add_node(argc-1, argv+1); - exit(EXIT_SUCCESS); - } - else if(!strcmp(argv[optind], "delnode")){ - del_node(argc-1, argv+1); - exit(EXIT_SUCCESS); - } - else if(!strcmp(argv[optind], "addfence")){ - add_fence(argc-1, argv+1); - exit(EXIT_SUCCESS); - } - else if(!strcmp(argv[optind], "delfence")){ - del_fence(argc-1, argv+1); - exit(EXIT_SUCCESS); - } - else if(!strcmp(argv[optind], "lsnode")){ - list_nodes(argc-1, argv+1); - exit(EXIT_SUCCESS); - } - else if(!strcmp(argv[optind], "lsfence")){ - list_fences(argc-1, argv+1); - exit(EXIT_SUCCESS); - } - else if(!strcmp(argv[optind], "create")){ - create_skeleton(argc-1, argv+1); - exit(EXIT_SUCCESS); - } - else if(!strcmp(argv[optind], "addnodeids")){ - add_nodeids(argc-1, argv+1); - exit(EXIT_SUCCESS); - } - - else { - fprintf(stderr, "Unknown command, %s.\n" - "Try 'ccs_tool help' for help.\n", argv[optind]); - exit(EXIT_FAILURE); - } - } else { - fprintf(stderr, "Too few arguments.\n" - "Try 'ccs_tool help' for help.\n"); - exit(EXIT_FAILURE); - } - exit(EXIT_SUCCESS); -} - -static void tool_print_usage(FILE *stream){ - fprintf(stream, - "Usage:\n" - " ccs_tool [options] <command>\n" - "\n" - "Options:\n" - " -verbose Make some operations print more details.\n" - " -h Print this usage and exit.\n" - " -V Print version information and exit.\n" - "\n" - "Commands:\n" - " help Print this usage and exit.\n" - " query <xpath query> Query the cluster configuration.\n" - " addnode <node> Add a node\n" - " delnode <node> Delete a node\n" - " lsnode List nodes\n" - " lsfence List fence devices\n" - " addfence <fencedev> Add a new fence device\n" - " delfence <fencedev> Delete a fence device\n" - " create Create a skeleton config file\n" - " addnodeids Assign node ID numbers to all nodes\n" - "\n"); -} - - -int main(int argc, char *argv[]) -{ - char *name = strdup(argv[0]); - - /* - * Don't be anal about the binary name. - * We expect either 'ccs_tool' or 'ccs_test', - * but interpret anything other than 'ccs_test' - * as 'ccs_tool'. - * That's not a bug, it's a feature. - */ - - if (strcmp(basename(name), "ccs_test") == 0) - return test_main(argc, argv, 1); - else - return tool_main(argc, argv); -} diff --git a/config/tools/ccs_tool/editconf.c b/config/tools/ccs_tool/editconf.c deleted file mode 100644 index 5205257..0000000 --- a/config/tools/ccs_tool/editconf.c +++ /dev/null @@ -1,1252 +0,0 @@ -#include "clusterautoconfig.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/stat.h> -#include <getopt.h> -#include <errno.h> -#include <assert.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netdb.h> - -#include <libxml/tree.h> - -#include "editconf.h" - -#define MAX_NODES 256 - -const char *prog_name = "ccs_tool"; - -#define die(fmt, args...) \ -do { \ - fprintf(stderr, "%s: ", prog_name); \ - fprintf(stderr, fmt "\n", ##args); \ - exit(EXIT_FAILURE); \ -} while (0) - - -struct option_info -{ - const char *name; - const char *altname; - const char *votes; - const char *nodeid; - const char *mcast_addr; - const char *fence_type; - const char *configfile; - const char *outputfile; - int do_delete; - int tell_ccsd; - int force_ccsd; -}; - -static void config_usage(int rw) -{ - fprintf(stderr, " -c --configfile Name of configuration file (" DEFAULT_CONFIG_DIR "/" DEFAULT_CONFIG_FILE ")\n"); - if (rw) - { - fprintf(stderr, " -o --outputfile Name of output file (defaults to same as --configfile)\n"); - fprintf(stderr, " -C --no_ccs Don't tell CCSD about this change\n"); - fprintf(stderr, " default: run "ccs_tool update" if file is updated in place)\n"); - fprintf(stderr, " -F --force_ccs Force "ccs_tool upgrade" even if input & output files differ\n"); - } -} - -static void help_usage(void) -{ - fprintf(stderr, " -h --help Display this help text\n"); -} - -static void list_usage(const char *name) -{ - fprintf(stderr, "Usage: %s %s [options]\n", prog_name, name); - fprintf(stderr, " -v --verbose Print all properties of the item\n"); - config_usage(0); - help_usage(); - - exit(0); -} - -static void create_usage(const char *name) -{ - fprintf(stderr, "Usage: %s %s [-2] <clustername>\n", prog_name, name); - fprintf(stderr, " -2 Create a 2-node cman cluster config file\n"); - config_usage(0); - help_usage(); - fprintf(stderr, "\n" - "Note that "create" on its own will not create a valid configuration file.\n" - "Fence agents and nodes will need to be added to it before handing it over\n" - "to ccsd.\n" - "\n" - "eg:\n" - " ccs_tool create MyCluster\n" - " ccs_tool addfence apc fence_apc ipaddr=apc.domain.net user=apc password=apc\n" - " ccs_tool addnode node1 -n 1 -f apc port=1\n" - " ccs_tool addnode node2 -n 2 -f apc port=2\n" - " ccs_tool addnode node3 -n 3 -f apc port=3\n" - " ccs_tool addnode node4 -n 4 -f apc port=4\n" - "\n"); - - exit(0); -} - -static void addfence_usage(const char *name) -{ - fprintf(stderr, "Usage: %s %s [options] <name> <agent> [param=value]\n", prog_name, name); - config_usage(1); - help_usage(); - - exit(0); -} - -static void delfence_usage(const char *name) -{ - fprintf(stderr, "Usage: %s %s [options] <name>\n", prog_name, name); - config_usage(1); - help_usage(); - fprintf(stderr, "\n"); - fprintf(stderr, "%s will allow you to remove a fence device that is in use by nodes.\n", name); - fprintf(stderr, "This is to allow changes to be made, but be aware that it may produce an\n"); - fprintf(stderr, "invalid configuration file if you don't add it back in again.\n"); - - exit(0); -} - -static void delnode_usage(const char *name) -{ - fprintf(stderr, "Usage: %s %s [options] <name>\n", prog_name, name); - config_usage(1); - help_usage(); - - exit(0); -} - -static void addnodeid_usage(const char *name) -{ - fprintf(stderr, "Add node IDs to all nodes in the config file that don't have them.\n"); - fprintf(stderr, "Nodes with IDs will not be afftected, so you can run this as many times\n"); - fprintf(stderr, "as you like without doing any harm.\n"); - fprintf(stderr, "It will optionally add a multicast address to the cluster config too.\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "Usage: %s %s [options] <name>\n", prog_name, name); - fprintf(stderr, " -n --nodeid Nodeid to start with (default 1)\n"); - fprintf(stderr, " -m --multicast Set or change the multicast address\n"); - fprintf(stderr, " -v --verbose Print nodeids that are assigned\n"); - config_usage(1); - help_usage(); - - exit(0); -} - -static void addnode_usage(const char *name) -{ - fprintf(stderr, "Usage: %s %s [options] <nodename> [<fencearg>=<value>]...\n", prog_name, name); - fprintf(stderr, " -n --nodeid Nodeid (required)\n"); - fprintf(stderr, " -v --votes Number of votes for this node (default 1)\n"); - fprintf(stderr, " -a --altname Alternative name/interface for multihomed hosts\n"); - fprintf(stderr, " -f --fence_type Type of fencing to use\n"); - config_usage(1); - help_usage(); - - fprintf(stderr, "\n"); - fprintf(stderr, "Examples:\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "Add a new node to default configuration file:\n"); - fprintf(stderr, " %s %s -n 1 -f manual ipaddr=newnode\n", prog_name, name); - fprintf(stderr, "\n"); - fprintf(stderr, "Add a new node and dump config file to stdout rather than save it\n"); - fprintf(stderr, " %s %s -n 2 -f apc -o- newnode.temp.net port=1\n", prog_name, name); - - exit(0); -} - -/* Is it really ? - * Actually, we don't check that this is a valid multicast address(!), - * merely that it is a valid IP[46] address. - */ -static int valid_mcast_addr(char *mcast) -{ - struct addrinfo *ainfo; - struct addrinfo ahints; - int ret; - - memset(&ahints, 0, sizeof(ahints)); - - ret = getaddrinfo(mcast, NULL, &ahints, &ainfo); - if (ret) { - freeaddrinfo(ainfo); - return 0; - } - return 1; -} - -static void save_file(xmlDoc *doc, struct option_info *ninfo) -{ - char tmpconffile[strlen(ninfo->outputfile)+5]; - char oldconffile[strlen(ninfo->outputfile)+5]; - int using_stdout = 0; - mode_t old_mode; - int ret; - - old_mode = umask(026); - - if (strcmp(ninfo->outputfile, "-") == 0) - using_stdout = 1; - - /* - * Save it to a temp file before moving the old one out of the way - */ - if (!using_stdout) - { - snprintf(tmpconffile, sizeof(tmpconffile), "%s.tmp", ninfo->outputfile); - snprintf(oldconffile, sizeof(oldconffile), "%s.old", ninfo->outputfile); - } - else - { - strcpy(tmpconffile, ninfo->outputfile); - } - - xmlKeepBlanksDefault(0); - ret = xmlSaveFormatFile(tmpconffile, doc, 1); - if (ret == -1) - die("Error writing new config file %s", ninfo->outputfile); - - if (!using_stdout) - { - if (rename(ninfo->outputfile, oldconffile) == -1 && errno != ENOENT) - die("Can't move old config file out of the way\n"); - - if (rename(tmpconffile, ninfo->outputfile)) - { - perror("Error renaming new file to its real filename"); - - /* Drat, that failed, try to put the old one back */ - if (rename(oldconffile, ninfo->outputfile)) - die("Can't move old config fileback in place - clean up after me please\n"); - } - } - - /* free the document */ - xmlFreeDoc(doc); - - umask(old_mode); -} - -static void validate_int_arg(char argopt, char *arg) -{ - char *tmp; - int val; - - val = strtol(arg, &tmp, 10); - if (tmp == arg || tmp != arg + strlen(arg)) - die("argument to %c (%s) is not an integer", argopt, arg); - - if (val < 0) - die("argument to %c cannot be negative", argopt); -} - -/* Get the config_version string from the file */ -static xmlChar *find_version(xmlNode *root) -{ - if (xmlHasProp(root, BAD_CAST "config_version")) - { - xmlChar *ver; - - ver = xmlGetProp(root, BAD_CAST "config_version"); - return ver; - } - return NULL; -} - -/* Get the cluster name string from the file */ -static xmlChar *cluster_name(xmlNode *root) -{ - if (xmlHasProp(root, BAD_CAST "name")) - { - xmlChar *ver; - - ver = xmlGetProp(root, BAD_CAST "name"); - return ver; - } - return NULL; -} - -static void increment_version(xmlNode *root_element) -{ - int ver; - unsigned char *version_string; - char newver[32]; - - /* Increment version */ - version_string = find_version(root_element); - if (!version_string) - die("Can't find "config_version" in config file\n"); - - ver = atoi((char *)version_string); - snprintf(newver, sizeof(newver), "%d", ++ver); - xmlSetProp(root_element, BAD_CAST "config_version", BAD_CAST newver); -} - -static xmlNode *findnode(xmlNode *root, const char *name) -{ - xmlNode *cur_node; - - for (cur_node = root->children; cur_node; cur_node = cur_node->next) - { - if (cur_node->type == XML_ELEMENT_NODE && strcmp((char *)cur_node->name, name)==0) - { - return cur_node; - } - } - return NULL; -} - -/* Return the fence type name (& node) for a cluster node */ -static xmlChar *get_fence_type(xmlNode *clusternode, xmlNode **fencenode) -{ - xmlNode *f; - - f = findnode(clusternode, "fence"); - if (f) - { - f = findnode(f, "method"); - if (f) - { - f = findnode(f, "device"); - *fencenode = f; - return xmlGetProp(f, BAD_CAST "name"); - } - } - return NULL; -} - -/* Check the fence type exists under <fencedevices> */ -static xmlNode *valid_fence_type(xmlNode *root, const char *fencetype) -{ - xmlNode *devs; - xmlNode *cur_node; - - devs = findnode(root, "fencedevices"); - if (!devs) - return NULL; - - for (cur_node = devs->children; cur_node; cur_node = cur_node->next) - { - if (cur_node->type == XML_ELEMENT_NODE && strcmp((char *)cur_node->name, "fencedevice") == 0) - { - xmlChar *name = xmlGetProp(cur_node, BAD_CAST "name"); - if (strcmp((char *)name, fencetype) == 0) - return cur_node; - } - } - return NULL; -} - -/* Check the nodeid is not already in use by another node */ -static xmlNode *get_by_nodeid(xmlNode *root, int nodeid) -{ - xmlNode *cnodes; - xmlNode *cur_node; - - cnodes = findnode(root, "clusternodes"); - if (!cnodes) - return NULL; - - for (cur_node = cnodes->children; cur_node; cur_node = cur_node->next) - { - if (cur_node->type == XML_ELEMENT_NODE && strcmp((char *)cur_node->name, "clusternode") == 0) - { - xmlChar *idstring = xmlGetProp(cur_node, BAD_CAST "nodeid"); - if (idstring && atoi((char *)idstring) == nodeid) - return cur_node; - } - } - return NULL; -} - - -/* Get the multicast address node. - */ -static xmlNode *find_multicast_addr(xmlNode *clusternodes) -{ - xmlNode *clnode = findnode(clusternodes, "cman"); - if (clnode) - { - xmlNode *mcast = findnode(clnode, "multicast"); - return mcast; - } - return NULL; -} - -static xmlNode *find_node(xmlNode *clusternodes, const char *nodename) -{ - xmlNode *cur_node; - - for (cur_node = clusternodes->children; cur_node; cur_node = cur_node->next) - { - if (cur_node->type == XML_ELEMENT_NODE && strcmp((char *)cur_node->name, "clusternode") == 0) - { - xmlChar *name = xmlGetProp(cur_node, BAD_CAST "name"); - if (strcmp((char *)name, nodename) == 0) - return cur_node; - } - } - return NULL; -} - -/* Print name=value pairs for a (n XML) node. - * "ignore" is a string to ignore if present as a property (probably already printed on the main line) - */ -static int print_properties(xmlNode *node, const char *prefix, const char *ignore, const char *ignore2) -{ - xmlAttr *attr; - int done_prefix = 0; - - for (attr = node->properties; attr; attr = attr->next) - { - /* Don't print "name=" */ - if (strcmp((char *)attr->name, "name") && - strcmp((char *)attr->name, ignore) && - strcmp((char *)attr->name, ignore2) - ) - { - if (!done_prefix) - { - done_prefix = 1; - printf("%s", prefix); - } - printf(" %s=%s", attr->name, xmlGetProp(node, attr->name)); - } - } - if (done_prefix) - printf("\n"); - return done_prefix; -} - -/* Add name=value pairs from the commandline as properties to a node */ -static void add_fence_args(xmlNode *fencenode, int argc, char **argv, int optindex) -{ - int i; - - for (i = optindex; i<argc; i++) - { - char *prop; - char *value; - char *equals; - - prop = strdup(argv[i]); - // FIXME: handle failed strdup - equals = strchr(prop, '='); - if (!equals) - die("option '%s' is not opt=value pair\n", prop); - - value = equals+1; - *equals = '\0'; - - /* "name" is used for the fence type itself, so this is just - * to protect the user from their own stupidity - */ - if (strcmp(prop, "name") == 0) - die("Can't use "name" as a fence argument name\n"); - - xmlSetProp(fencenode, BAD_CAST prop, BAD_CAST value); - free(prop); - } -} - -static void add_clusternode(xmlNode *root_element, struct option_info *ninfo, - int argc, char **argv, int optindex) -{ - xmlNode *clusternodes; - xmlNode *newnode; - - xmlNode *newfence; - xmlNode *newfencemethod; - xmlNode *newfencedevice; - - clusternodes = findnode(root_element, "clusternodes"); - if (!clusternodes) - die("Can't find "clusternodes" in %s\n", ninfo->configfile); - - /* Don't allow duplicate node names */ - if (find_node(clusternodes, ninfo->name)) - die("node %s already exists in %s\n", ninfo->name, ninfo->configfile); - - /* Check for duplicate node ID */ - if (!ninfo->nodeid) - die("nodeid not specified\n"); - - if (get_by_nodeid(root_element, atoi((char *)ninfo->nodeid))) - die("nodeid %s already in use\n", ninfo->nodeid); - - /* Don't allow random fence types */ - if (!valid_fence_type(root_element, ninfo->fence_type)) - die("fence type '%s' not known\n", ninfo->fence_type); - - /* Add the new node */ - newnode = xmlNewNode(NULL, BAD_CAST "clusternode"); - xmlSetProp(newnode, BAD_CAST "name", BAD_CAST ninfo->name); - xmlSetProp(newnode, BAD_CAST "votes", BAD_CAST ninfo->votes); - xmlSetProp(newnode, BAD_CAST "nodeid", BAD_CAST ninfo->nodeid); - xmlAddChild(clusternodes, newnode); - - if (ninfo->altname) - { - xmlNode *altnode; - - altnode = xmlNewNode(NULL, BAD_CAST "altname"); - xmlSetProp(altnode, BAD_CAST "name", BAD_CAST ninfo->altname); - xmlAddChild(newnode, altnode); - } - - /* Add the fence attributes */ - newfence = xmlNewNode(NULL, BAD_CAST "fence"); - newfencemethod = xmlNewNode(NULL, BAD_CAST "method"); - xmlSetProp(newfencemethod, BAD_CAST "name", BAD_CAST "single"); - - newfencedevice = xmlNewNode(NULL, BAD_CAST "device"); - xmlSetProp(newfencedevice, BAD_CAST "name", BAD_CAST ninfo->fence_type); - - /* Add name=value options */ - add_fence_args(newfencedevice, argc, argv, optindex+1); - - xmlAddChild(newnode, newfence); - xmlAddChild(newfence, newfencemethod); - xmlAddChild(newfencemethod, newfencedevice); -} - -static xmlDoc *open_configfile(struct option_info *ninfo) -{ - xmlDoc *doc; - - /* Init libxml */ - xmlInitParser(); - LIBXML_TEST_VERSION; - - if (!ninfo->configfile) - ninfo->configfile = DEFAULT_CONFIG_DIR "/" DEFAULT_CONFIG_FILE; - if (!ninfo->outputfile) - ninfo->outputfile = ninfo->configfile; - - /* Load XML document */ - doc = xmlParseFile(ninfo->configfile); - if (doc == NULL) - die("Error: unable to parse requested configuration file\n"); - - return doc; - -} - -static void del_clusternode(xmlNode *root_element, struct option_info *ninfo) -{ - xmlNode *clusternodes; - xmlNode *oldnode; - - clusternodes = findnode(root_element, "clusternodes"); - if (!clusternodes) - { - fprintf(stderr, "Can't find "clusternodes" in %s\n", ninfo->configfile); - exit(1); - } - - oldnode = find_node(clusternodes, ninfo->name); - if (!oldnode) - { - fprintf(stderr, "node %s does not exist in %s\n", ninfo->name, ninfo->configfile); - exit(1); - } - - xmlUnlinkNode(oldnode); -} - -struct option addnode_options[] = -{ - { "votes", required_argument, NULL, 'v'}, - { "nodeid", required_argument, NULL, 'n'}, - { "altname", required_argument, NULL, 'a'}, - { "fence_type", required_argument, NULL, 'f'}, - { "outputfile", required_argument, NULL, 'o'}, - { "configfile", required_argument, NULL, 'c'}, - { "no_ccs", no_argument, NULL, 'C'}, - { "force_ccs", no_argument, NULL, 'F'}, - { NULL, 0, NULL, 0 }, -}; - -struct option delnode_options[] = -{ - { "outputfile", required_argument, NULL, 'o'}, - { "configfile", required_argument, NULL, 'c'}, - { "no_ccs", no_argument, NULL, 'C'}, - { "force_ccs", no_argument, NULL, 'F'}, - { NULL, 0, NULL, 0 }, -}; - -struct option addfence_options[] = -{ - { "outputfile", required_argument, NULL, 'o'}, - { "configfile", required_argument, NULL, 'c'}, - { "no_ccs", no_argument, NULL, 'C'}, - { "force_ccs", no_argument, NULL, 'F'}, - { NULL, 0, NULL, 0 }, -}; - -struct option addnodeid_options[] = -{ - { "outputfile", required_argument, NULL, 'o'}, - { "configfile", required_argument, NULL, 'c'}, - { "multicast", required_argument, NULL, 'm'}, - { "nodeid", no_argument, NULL, 'n'}, - { "verbose", no_argument, NULL, 'v'}, - { NULL, 0, NULL, 0 }, -}; - -struct option list_options[] = -{ - { "configfile", required_argument, NULL, 'c'}, - { "verbose", no_argument, NULL, 'v'}, - { NULL, 0, NULL, 0 }, -}; - - -static int next_nodeid(int startid, int *nodeids, int nodecount) -{ - int i; - int nextid = startid; - -retry: - for (i=0; i<nodecount; i++) - { - if (nodeids[i] == nextid) - { - nextid++; - goto retry; - } - } - - return nextid; -} - -void add_nodeids(int argc, char **argv) -{ - struct option_info ninfo; - unsigned char *nodenames[MAX_NODES]; - xmlDoc *doc; - xmlNode *root_element; - xmlNode *clusternodes; - xmlNode *cur_node; - xmlNode *mcast; - int verbose = 0; - int opt; - int i; - int nodenumbers[MAX_NODES]; - int nodeidx; - int totalnodes; - int nextid; - - memset(nodenames, 0, sizeof(nodenames)); - memset(nodenumbers, 0, sizeof(nodenumbers)); - memset(&ninfo, 0, sizeof(ninfo)); - ninfo.nodeid = "1"; - - while ( (opt = getopt_long(argc, argv, "n:o:c:m:vh?", addnodeid_options, NULL)) != EOF) - { - switch(opt) - { - case 'n': - validate_int_arg(opt, optarg); - ninfo.nodeid = strdup(optarg); - break; - - case 'c': - ninfo.configfile = strdup(optarg); - break; - - case 'o': - ninfo.outputfile = strdup(optarg); - break; - - case 'm': - if (!valid_mcast_addr(optarg)) { - fprintf(stderr, "%s is not a valid multicast address\n", optarg); - return; - } - ninfo.mcast_addr = strdup(optarg); - break; - - case 'v': - verbose++; - break; - - case '?': - default: - addnodeid_usage(argv[0]); - } - } - - doc = open_configfile(&ninfo); - - root_element = xmlDocGetRootElement(doc); - - increment_version(root_element); - - /* Warn if the cluster doesn't have a multicast address */ - mcast = find_multicast_addr(root_element); - if (!mcast & !ninfo.mcast_addr) { - fprintf(stderr, "\nWARNING: The cluster does not have a multicast address.\n"); - fprintf(stderr, "A default will be assigned a run-time which might not suit your installation\n\n"); - } - - if (ninfo.mcast_addr) { - if (!mcast) { - xmlNode *cman = xmlNewNode(NULL, BAD_CAST "cman"); - mcast = xmlNewNode(NULL, BAD_CAST "multicast"); - - xmlAddChild(cman, mcast); - xmlAddChild(root_element, cman); - } - xmlSetProp(mcast, BAD_CAST "addr", BAD_CAST ninfo.mcast_addr); - } - - /* Get a list of nodes that /do/ have nodeids so we don't generate - any duplicates */ - nodeidx=0; - clusternodes = findnode(root_element, "clusternodes"); - if (!clusternodes) - die("Can't find "clusternodes" in %s\n", ninfo.configfile); - - - for (cur_node = clusternodes->children; cur_node; cur_node = cur_node->next) - { - if (cur_node->type == XML_ELEMENT_NODE && strcmp((char *)cur_node->name, "clusternode") == 0) - { - xmlChar *name = xmlGetProp(cur_node, BAD_CAST "name"); - xmlChar *nodeid = xmlGetProp(cur_node, BAD_CAST "nodeid"); - nodenames[nodeidx] = name; - if (nodeid) - nodenumbers[nodeidx] = atoi((char*)nodeid); - nodeidx++; - } - } - totalnodes = nodeidx; - - /* Loop round nodes adding nodeIDs where they don't exist. */ - nextid = next_nodeid(atoi(ninfo.nodeid), nodenumbers, totalnodes); - for (i=0; i<totalnodes; i++) - { - if (nodenumbers[i] == 0) - { - nodenumbers[i] = nextid; - nextid = next_nodeid(nextid, nodenumbers, totalnodes); - if (verbose) - fprintf(stderr, "Node %s now has id %d\n", nodenames[i], nodenumbers[i]); - } - } - - /* Now write them into the tree */ - nodeidx = 0; - for (cur_node = clusternodes->children; cur_node; cur_node = cur_node->next) - { - if (cur_node->type == XML_ELEMENT_NODE && strcmp((char *)cur_node->name, "clusternode") == 0) - { - char tmp[80]; - xmlChar *name = xmlGetProp(cur_node, BAD_CAST "name"); - - assert(strcmp((char*)nodenames[nodeidx], (char*)name) == 0); - - sprintf(tmp, "%d", nodenumbers[nodeidx]); - xmlSetProp(cur_node, BAD_CAST "nodeid", BAD_CAST tmp); - nodeidx++; - } - } - - - /* Write it out */ - save_file(doc, &ninfo); - - /* Shutdown libxml */ - xmlCleanupParser(); -} - -void add_node(int argc, char **argv) -{ - struct option_info ninfo; - int opt; - xmlDoc *doc; - xmlNode *root_element; - - memset(&ninfo, 0, sizeof(ninfo)); - ninfo.tell_ccsd = 1; - ninfo.votes = "1"; - - while ( (opt = getopt_long(argc, argv, "v:n:a:f:o:c:CFh?", addnode_options, NULL)) != EOF) - { - switch(opt) - { - case 'v': - validate_int_arg(opt, optarg); - ninfo.votes = optarg; - break; - - case 'n': - validate_int_arg(opt, optarg); - ninfo.nodeid = optarg; - break; - - case 'a': - ninfo.altname = strdup(optarg); - break; - - case 'f': - ninfo.fence_type = strdup(optarg); - break; - - case 'c': - ninfo.configfile = strdup(optarg); - break; - - case 'o': - ninfo.outputfile = strdup(optarg); - break; - - case 'C': - ninfo.tell_ccsd = 0; - break; - - case 'F': - ninfo.force_ccsd = 1; - break; - - case '?': - default: - addnode_usage(argv[0]); - } - } - - /* Get node name parameter */ - if (optind < argc) - ninfo.name = strdup(argv[optind]); - else - addnode_usage(argv[0]); - - if (!ninfo.fence_type) - addnode_usage(argv[0]); - - - doc = open_configfile(&ninfo); - - root_element = xmlDocGetRootElement(doc); - - increment_version(root_element); - - add_clusternode(root_element, &ninfo, argc, argv, optind); - - /* Write it out */ - save_file(doc, &ninfo); - /* Shutdown libxml */ - xmlCleanupParser(); - -} - -void del_node(int argc, char **argv) -{ - struct option_info ninfo; - int opt; - xmlDoc *doc; - xmlNode *root_element; - - memset(&ninfo, 0, sizeof(ninfo)); - ninfo.tell_ccsd = 1; - - while ( (opt = getopt_long(argc, argv, "o:c:CFh?", delnode_options, NULL)) != EOF) - { - switch(opt) - { - case 'c': - ninfo.configfile = strdup(optarg); - break; - - case 'o': - ninfo.outputfile = strdup(optarg); - break; - - case 'C': - ninfo.tell_ccsd = 0; - break; - - case 'F': - ninfo.force_ccsd = 1; - break; - - case '?': - default: - delnode_usage(argv[0]); - } - } - - /* Get node name parameter */ - if (optind < argc) - ninfo.name = strdup(argv[optind]); - else - delnode_usage(argv[0]); - - doc = open_configfile(&ninfo); - - root_element = xmlDocGetRootElement(doc); - - increment_version(root_element); - - del_clusternode(root_element, &ninfo); - - /* Write it out */ - save_file(doc, &ninfo); -} - -void list_nodes(int argc, char **argv) -{ - xmlNode *cur_node; - xmlNode *root_element; - xmlNode *clusternodes; - xmlNode *fencenode = NULL; - xmlDocPtr doc; - xmlNode *mcast; - struct option_info ninfo; - int opt; - int verbose = 0; - - memset(&ninfo, 0, sizeof(ninfo)); - - while ( (opt = getopt_long(argc, argv, "c:vh?", list_options, NULL)) != EOF) - { - switch(opt) - { - case 'c': - ninfo.configfile = strdup(optarg); - break; - case 'v': - verbose++; - break; - case '?': - default: - list_usage(argv[0]); - } - } - doc = open_configfile(&ninfo); - - root_element = xmlDocGetRootElement(doc); - - - printf("\nCluster name: %s, config_version: %s\n\n", - (char *)cluster_name(root_element), - (char *)find_version(root_element)); - - clusternodes = findnode(root_element, "clusternodes"); - if (!clusternodes) - die("Can't find "clusternodes" in %s\n", ninfo.configfile); - - mcast = find_multicast_addr(root_element); - if (mcast) - printf("Multicast address for cluster: %s\n\n", xmlGetProp(mcast, BAD_CAST "addr")); - - printf("Nodename Votes Nodeid Fencetype\n"); - for (cur_node = clusternodes->children; cur_node; cur_node = cur_node->next) - { - if (cur_node->type == XML_ELEMENT_NODE && strcmp((char *)cur_node->name, "clusternode") == 0) - { - xmlChar *name = xmlGetProp(cur_node, BAD_CAST "name"); - xmlChar *votes = xmlGetProp(cur_node, BAD_CAST "votes"); - xmlChar *nodeid = xmlGetProp(cur_node, BAD_CAST "nodeid"); - xmlChar *ftype = get_fence_type(cur_node, &fencenode); - - if (!nodeid) - nodeid=(unsigned char *)"0"; - if (!votes) - votes = (unsigned char *)"1"; - - printf("%-32s %3d %3d %s\n", name, atoi((char *)votes), - atoi((char *)nodeid), - ftype?ftype:(xmlChar *)""); - if (verbose) - { - xmlNode *a = findnode(cur_node, "altname"); - if (a) - { - printf(" altname %s=%s", "name", xmlGetProp(a, BAD_CAST "name")); - if (!print_properties(a, "","","")) - printf("\n"); - } - print_properties(cur_node, " Node properties: ", "votes", "nodeid"); - print_properties(fencenode, " Fence properties: ", "agent", ""); - } - - } - } -} - -void create_skeleton(int argc, char **argv) -{ - xmlNode *root_element; - xmlNode *fencedevices; - xmlNode *clusternodes; - xmlNode *rm; - xmlNode *rm1; - xmlNode *rm2; - xmlDocPtr doc; - char *clustername; - struct option_info ninfo; - struct stat st; - int twonode = 0; - int opt; - - memset(&ninfo, 0, sizeof(ninfo)); - - while ( (opt = getopt_long(argc, argv, "c:2h?", list_options, NULL)) != EOF) - { - switch(opt) - { - case 'c': - ninfo.outputfile = strdup(optarg); - break; - - case '2': - twonode = 1; - break; - - case '?': - default: - create_usage(argv[0]); - } - } - if (!ninfo.outputfile) - ninfo.outputfile = DEFAULT_CONFIG_DIR "/" DEFAULT_CONFIG_FILE; - ninfo.configfile = "-"; - - if (argc - optind < 1) - create_usage(argv[0]); - - clustername = argv[optind]; - - if (stat(ninfo.outputfile, &st) == 0) - die("%s already exists", ninfo.outputfile); - - /* Init libxml */ - xmlInitParser(); - LIBXML_TEST_VERSION; - - doc = xmlNewDoc(BAD_CAST "1.0"); - root_element = xmlNewNode(NULL, BAD_CAST "cluster"); - xmlDocSetRootElement(doc, root_element); - - xmlSetProp(root_element, BAD_CAST "name", BAD_CAST clustername); - xmlSetProp(root_element, BAD_CAST "config_version", BAD_CAST "1"); - - /* Generate extra bits for a 2node cman cluster */ - if (twonode) { - - xmlNode *cman = xmlNewNode(NULL, BAD_CAST "cman"); - xmlSetProp(cman, BAD_CAST "two_node", BAD_CAST "1"); - xmlSetProp(cman, BAD_CAST "expected_votes", BAD_CAST "1"); - xmlAddChild(root_element, cman); - } - - clusternodes = xmlNewNode(NULL, BAD_CAST "clusternodes"); - fencedevices = xmlNewNode(NULL, BAD_CAST "fencedevices"); - rm = xmlNewNode(NULL, BAD_CAST "rm"); - rm1 = xmlNewNode(NULL, BAD_CAST "failoverdomains"); - - xmlAddChild(root_element, clusternodes); - xmlAddChild(root_element, fencedevices); - xmlAddChild(root_element, rm); - - /* Create empty resource manager sections to keep GUI happy */ - rm2 = xmlNewNode(NULL, BAD_CAST "resources"); - xmlAddChild(rm, rm1); - xmlAddChild(rm, rm2); - - save_file(doc, &ninfo); - -} - -void add_fence(int argc, char **argv) -{ - xmlNode *root_element; - xmlNode *fencedevices; - xmlNode *fencenode = NULL; - xmlDocPtr doc; - char *fencename; - char *agentname; - struct option_info ninfo; - int opt; - - memset(&ninfo, 0, sizeof(ninfo)); - ninfo.tell_ccsd = 1; - - while ( (opt = getopt_long(argc, argv, "c:o:CFh?", list_options, NULL)) != EOF) - { - switch(opt) - { - case 'c': - ninfo.configfile = strdup(optarg); - break; - case 'o': - ninfo.outputfile = strdup(optarg); - break; - - case 'C': - ninfo.tell_ccsd = 0; - break; - - case 'F': - ninfo.force_ccsd = 1; - break; - - case '?': - default: - addfence_usage(argv[0]); - } - } - - if (argc - optind < 2) - addfence_usage(argv[0]); - - doc = open_configfile(&ninfo); - root_element = xmlDocGetRootElement(doc); - - increment_version(root_element); - - fencedevices = findnode(root_element, "fencedevices"); - if (!fencedevices) - die("Can't find "fencedevices" %s\n", ninfo.configfile); - - /* First param is the fence name - check it doesn't already exist */ - fencename = argv[optind++]; - - if (valid_fence_type(root_element, fencename)) - die("fence type %s already exists\n", fencename); - - agentname = argv[optind++]; - - /* Add it */ - fencenode = xmlNewNode(NULL, BAD_CAST "fencedevice"); - xmlSetProp(fencenode, BAD_CAST "name", BAD_CAST fencename); - xmlSetProp(fencenode, BAD_CAST "agent", BAD_CAST agentname); - - /* Add name=value options */ - add_fence_args(fencenode, argc, argv, optind); - - xmlAddChild(fencedevices, fencenode); - - save_file(doc, &ninfo); -} - -void del_fence(int argc, char **argv) -{ - xmlNode *root_element; - xmlNode *fencedevices; - xmlNode *fencenode; - xmlDocPtr doc; - char *fencename; - struct option_info ninfo; - int opt; - - memset(&ninfo, 0, sizeof(ninfo)); - ninfo.tell_ccsd = 1; - - while ( (opt = getopt_long(argc, argv, "c:o:CFhv?", list_options, NULL)) != EOF) - { - switch(opt) - { - case 'c': - ninfo.configfile = strdup(optarg); - break; - case 'o': - ninfo.outputfile = strdup(optarg); - break; - - case 'C': - ninfo.tell_ccsd = 0; - break; - - case 'F': - ninfo.force_ccsd = 1; - break; - - case '?': - default: - delfence_usage(argv[0]); - } - } - - if (argc - optind < 1) - delfence_usage(argv[0]); - - fencename = argv[optind]; - - doc = open_configfile(&ninfo); - root_element = xmlDocGetRootElement(doc); - increment_version(root_element); - - fencedevices = findnode(root_element, "fencedevices"); - if (!fencedevices) - die("Can't find "fencedevices" in %s\n", ninfo.configfile); - - fencenode = valid_fence_type(root_element, fencename); - if (!fencenode) - die("fence type %s does not exist\n", fencename); - - xmlUnlinkNode(fencenode); - - save_file(doc, &ninfo); -} - -void list_fences(int argc, char **argv) -{ - xmlNode *cur_node; - xmlNode *root_element; - xmlNode *fencedevices; - xmlDocPtr doc; - struct option_info ninfo; - int opt; - int verbose=0; - - memset(&ninfo, 0, sizeof(ninfo)); - - while ( (opt = getopt_long(argc, argv, "c:hv?", list_options, NULL)) != EOF) - { - switch(opt) - { - case 'c': - ninfo.configfile = strdup(optarg); - break; - case 'v': - verbose++; - break; - case '?': - default: - list_usage(argv[0]); - } - } - doc = open_configfile(&ninfo); - root_element = xmlDocGetRootElement(doc); - - fencedevices = findnode(root_element, "fencedevices"); - if (!fencedevices) - die("Can't find "fencedevices" in %s\n", ninfo.configfile); - - - printf("Name Agent\n"); - for (cur_node = fencedevices->children; cur_node; cur_node = cur_node->next) - { - if (cur_node->type == XML_ELEMENT_NODE && strcmp((char *)cur_node->name, "fencedevice") == 0) - { - xmlChar *name = xmlGetProp(cur_node, BAD_CAST "name"); - xmlChar *agent = xmlGetProp(cur_node, BAD_CAST "agent"); - - printf("%-16s %s\n", name, agent); - if (verbose) - print_properties(cur_node, " Properties: ", "agent", ""); - } - } -} - diff --git a/config/tools/ccs_tool/editconf.h b/config/tools/ccs_tool/editconf.h deleted file mode 100644 index 1847e2c..0000000 --- a/config/tools/ccs_tool/editconf.h +++ /dev/null @@ -1,8 +0,0 @@ -void add_node(int argc, char **argv); -void add_nodeids(int argc, char **argv); -void add_fence(int argc, char **argv); -void del_node(int argc, char **argv); -void del_fence(int argc, char **argv); -void list_nodes(int argc, char **argv); -void list_fences(int argc, char **argv); -void create_skeleton(int argc, char **argv); diff --git a/config/tools/ldap/Makefile.am b/config/tools/ldap/Makefile.am deleted file mode 100644 index 1c5c4a8..0000000 --- a/config/tools/ldap/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -sbin_PROGRAMS = confdb2ldif - -confdb2ldif_CPPFLAGS = -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 - -confdb2ldif_CFLAGS = $(confdb_CFLAGS) - -confdb2ldif_LDFLAGS = $(confdb_LIBS) diff --git a/config/tools/ldap/confdb2ldif.c b/config/tools/ldap/confdb2ldif.c deleted file mode 100644 index 607d87d..0000000 --- a/config/tools/ldap/confdb2ldif.c +++ /dev/null @@ -1,203 +0,0 @@ -#include "clusterautoconfig.h" - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <signal.h> -#include <unistd.h> -#include <string.h> -#include <sys/types.h> -#include <sys/un.h> - -#include <corosync/corotypes.h> -#include <corosync/confdb.h> - -confdb_callbacks_t callbacks = { -}; - -/* This structure maps object parent names to object classes */ -struct objectclasses -{ - const char *name; - const char *class; -} objectclasses[] = -{ - { "cluster", "rhcsCluster" }, - { "cman", "rhcsCman" }, - { "totem", "rhcsTotem" }, - { "clusternode", "rhcsNode" }, - { "device", "rhcsFenceagent" }, - { "fencedevice", "rhcsFencedevice" }, - { "method", "rhcsFencemethod" }, - { "logging", "rhcsLoggersubsys" }, -}; -/* TODO: Add more here as the schema gets filled in */ - - -static char *ldap_attr_name(char *attrname) -{ - static char newname[1024]; - int i; - - if (strcmp(attrname, "name") == 0) - return attrname; - - sprintf(newname, "rhcs"); - for (i=0; i<strlen(attrname)+1; i++) { - if (i == 0) - newname[4+i] = attrname[i] & 0x5F; - else - if (attrname[i] == '_') - newname[4+i] = '-'; - else - newname[4+i] = attrname[i]; - } - return newname; -} - - -/* Recursively dump the object tree */ -static void print_config_tree(confdb_handle_t handle, hdb_handle_t parent_object_handle, const char *dn, char *fulldn) -{ - hdb_handle_t object_handle; - char object_name[1024]; - size_t object_name_len; - char key_name[1024]; - size_t key_name_len; - char key_value[1024]; - size_t key_value_len; - char cumulative_dn[4096]; - int res; - int i; - int keycount=0; - - printf("\ndn: %s\n", fulldn); - - /* Show the keys */ - res = confdb_key_iter_start(handle, parent_object_handle); - if (res != CS_OK) { - printf( "error resetting key iterator for object "HDB_X_FORMAT": %d\n", parent_object_handle, res); - return; - } - - while ( (res = confdb_key_iter(handle, parent_object_handle, key_name, &key_name_len, - key_value, &key_value_len)) == CS_OK) { - key_name[key_name_len] = '\0'; - key_value[key_value_len] = '\0'; - - printf("%s: %s\n", ldap_attr_name(key_name), key_value); - keycount++; - } - if (strncmp(fulldn, "cn=", 3) == 0) { - printf("cn: %s\n", dn); - } - - - /* Determine objectclass... */ - if (keycount == 0) { - printf("objectclass: nsContainer\n"); - } - else { - for (i = 0; i < sizeof(objectclasses)/sizeof(struct objectclasses); i++) { - if (strcmp(objectclasses[i].name, dn) == 0) - printf("objectclass: %s\n", objectclasses[i].class); - } - } - - /* Show sub-objects */ - res = confdb_object_iter_start(handle, parent_object_handle); - if (res != CS_OK) { - printf( "error resetting object iterator for object "HDB_X_FORMAT": %d\n", parent_object_handle, res); - return; - } - - while ( (res = confdb_object_iter(handle, parent_object_handle, &object_handle, object_name, &object_name_len)) == CS_OK) { - hdb_handle_t parent; - - res = confdb_object_parent_get(handle, object_handle, &parent); - if (res != CS_OK) { - printf( "error getting parent for object "HDB_X_FORMAT": %d\n", object_handle, res); - return; - } - - object_name[object_name_len] = '\0'; - - /* Check for "name", and create dummy parent object */ - res = confdb_key_get(handle, object_handle, "name", strlen("name"), key_value, &key_value_len); - if (res == CS_OK) { - sprintf(cumulative_dn, "cn=%s,%s", object_name, fulldn); - printf("\n"); - printf("dn: %s\n", cumulative_dn); - printf("cn: %s\n", object_name); - printf("objectclass: %s\n", "nsContainer"); - - sprintf(cumulative_dn, "name=%s,cn=%s,%s", key_value, object_name, fulldn); - } - else { - sprintf(cumulative_dn, "cn=%s,%s", object_name, fulldn); - } - - /* Down we go ... */ - print_config_tree(handle, object_handle, object_name, cumulative_dn); - } -} - - -int main(int argc, char *argv[]) -{ - confdb_handle_t handle; - int result; - hdb_handle_t cluster_handle; - const char *clusterroot = "cluster"; - char basedn[1024]; - - if (argc == 1) { - fprintf(stderr, "usage: \n"); - fprintf(stderr, " %s <dn> [<objdb root>]\n", argv[0]); - fprintf(stderr, "\n"); - fprintf(stderr, " eg: \n"); - fprintf(stderr, " %s dc=mycompany,dc=com\n", argv[0]); - fprintf(stderr, " %s dc=mycompany,dc=com rhcluster\n", argv[0]); - fprintf(stderr, "\n"); - fprintf(stderr, "objdb root defaults to 'cluster'\n"); - fprintf(stderr, "\n"); - return 0; - } - - if (argc > 2) { - clusterroot = argv[2]; - } - - result = confdb_initialize (&handle, &callbacks); - if (result != CS_OK) { - printf ("Could not initialize Cluster Configuration Database API instance error %d\n", result); - exit (1); - } - - /* Find the starting object ... this should be a param */ - - result = confdb_object_find_start(handle, OBJECT_PARENT_HANDLE); - if (result != CS_OK) { - printf ("Could not start object_find %d\n", result); - exit (1); - } - - result = confdb_object_find(handle, OBJECT_PARENT_HANDLE, clusterroot, strlen(clusterroot), &cluster_handle); - if (result != CS_OK) { - printf ("Could not object_find "cluster": %d\n", result); - exit (1); - } - - sprintf(basedn, "name=%s,%s", clusterroot, argv[1]); - - /* Print a header */ - printf("# This file was generated by confdb2ldif, from an existing cluster configuration\n"); - printf("#\n"); - - /* Print the configuration */ - print_config_tree(handle, cluster_handle, clusterroot, basedn); - - - result = confdb_finalize (handle); - return (0); -} diff --git a/config/tools/man/Makefile.am b/config/tools/man/Makefile.am deleted file mode 100644 index 4eb4002..0000000 --- a/config/tools/man/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -dist_man_MANS = ccs_tool.8 \ - confdb2ldif.8 diff --git a/config/tools/man/ccs_tool.8 b/config/tools/man/ccs_tool.8 deleted file mode 100644 index ef13406..0000000 --- a/config/tools/man/ccs_tool.8 +++ /dev/null @@ -1,185 +0,0 @@ -.TH "ccs_tool" "8" "" "" "" -.SH "NAME" -ccs_tool - The tool used to make online updates of CCS config files. - -.SH "SYNOPSIS" -.B ccs_tool -[\fIOPTION\fR].. <\fBcommand\fP> - -.SH "DESCRIPTION" - -\fBccs_tool\fP is part of the Cluster Configuration System (CCS). It is -used to make online updates to cluster.conf. It can also be used to -upgrade old style (GFS <= 6.0) CCS archives to the new xml cluster.conf -format. - -.SH "OPTIONS" -.TP -\fB-h\fP -Help. Print out the usage. -.TP -\fB-V\fP -Print the version information. - -sub-commands have their own options, see below for more detail -.SH "COMMANDS" -.TP -\fBupdate\fP \fI<xml file>\fP -This command is used to update the config file that ccsd is working with -while the cman cluster is operational (i.e. online). Run this on a single -machine to update cluster.conf on all current cluster members. This also -notifies cman of the new config version. - -.TP -\fBupgrade\fP \fI<location>\fP -This command is used to upgrade an old CCS format archive to the new -xml format. \fI<location>\fP is the location of the old archive, -which can be either a block device archive or a file archive. The -converted configuration will be printed to stdout. - -.TP -\fBaddnode\fP [options] \fI<node> [<fenceoption=value>]...\fP -Adds a new node to the cluster configuration file. Fencing device options -are specified as key=value pairs (as many as required) and are entered into the -configuration file as is. See the documentation for your fencing agent for more -details (eg a powerswitch fence device may need to know which port the node is -connected to). -.br -\fIOptions:\fP -.br --v <votes> Number of votes for this node (mandatory) -.br --n <nodeid> Node id for this node (optional) -.br --i <interface> Network interface to use for this node. Mandatory if the cluster -is using multicast as transport. Forbidden if not. -.br --m <multicast> Multicast address for cluster. Only allowed on the first node to -be added to the file. Subsequent nodes will use either multicast or broadcast -depending on the properties of the first node. -.br --f <fencedevice> Name of fence device to use for this node. The fence device -section must already have been added to the file, probably using the addfence command. -.br --c <file> Config file to use. Defaults to /etc/cluster/cluster.conf -.br --o <file> Output file. Defaults to the same as -c -.br --C Don't run "ccs_tool update" after changing file. This will -happen by default if the input file is the same as the output file. -.br --F Force a "ccs_tool update" even if the input and output files -are different. - - - -.TP -\fBdelnode\fP [options] \fI<node>\fP -Delete a node from the cluster configuration file. Note: there is no -"edit" command so to change the properties of a node you must delete it -and add it back in with the new properties. -.br -\fIOptions:\fP -.br --c <file> Config file to use. Defaults to /etc/cluster/cluster.conf -.br --o <file> Output file. Defaults to the same as -c -.br --C Don't run "ccs_tool update" after changing file. This will -happen by default if the input file is the same as the output file. -.br --F Force a "ccs_tool update" even if the input and output files -are different. - - - -.TP -\fBaddfence\fP [options] \fI<name> <agent> [<option>=<value>]...\fP -Adds a new fence device section to the cluster configuration file. <agent> is the -name of the fence agent that controls the device. the options following are entered -as key-value pairs. See the fence agent documentation for details about these. eg: -you may need to enter the IP address and username/password for a powerswitch fencing -device. -.br -\fIOptions:\fP -.br --c <file> Config file to use. Defaults to /etc/cluster/cluster.conf -.br --o <file> Output file. Defaults to the same as -c -.br --C Don't run "ccs_tool update" after changing file. This will -happen by default if the input file is the same as the output file. -.br --F Force a "ccs_tool update" even if the input and output files -are different. - -.TP -\fBdelfence\fP [options] \fI<node>\fP -Deletes a fencing device from the cluster configuration file. -delfence will allow you to remove a fence device that is in use by nodes. -This is to allow changes to be made, but be aware that it may produce an -invalid configuration file if you don't add it back in again. -.br -\fIOptions:\fP -.br --c <file> Config file to use. Defaults to /etc/cluster/cluster.conf -.br --o <file> Output file. Defaults to the same as -c -.br --C Don't run "ccs_tool update" after changing file. This will -happen by default if the input file is the same as the output file. -.br --F Force a "ccs_tool update" even if the input and output files -are different. - - -.TP -\fBlsnode [options] \fP -List the nodes in the configuration file. This is (hopefully obviously) not -necessarily the same as the nodes currently in the cluster, but it should -be a superset. -.br -\fIOptions:\fP -.br --v Verbose. Lists all the properties of the node, and the -node-specific properties of the fence device too. -.br --c <file> Config file to use. Defaults to /etc/cluster/cluster.conf - - -.TP -\fBlsfence [options] \fP -List all the fence devices in the cluster configuration file. -.br -\fIOptions:\fP -.br --v Verbose. Lists all the properties of the fence device rather -than just the names and agents. -.br --c <file> Config file to use. Defaults to /etc/cluster/cluster.conf - - -.TP -\fBcreate [options] \fP \fI<clustername>\fP -Create a new, skeleton, configuration file. Note that "create" on its own will -not create a valid configuration file. Fence agents and nodes will need to be -added to it before handing it over to ccsd. The new configuration file will -have a version number of 1. Subsequent addnode/delnode/addfence/delfence operations -will increment the version number by 1 each time. -.br -\fIOptions:\fP -.br -.br --c <file> Config file to create. Defaults to /etc/cluster/cluster.conf - -.TP -\fBaddnodeids\fP -Adds node ID numbers to all the nodes in cluster.conf. In RHEL4, node IDs were optional -and assigned by cman when a node joined the cluster. In RHEL5 they must be pre-assigned -in cluster.conf. This command will not change any node IDs that are already set in -cluster.conf, it will simply add unique node ID numbers to nodes that do not already -have them. - - -.SH "SEE ALSO" -ccs(7), ccsd(8), cluster.conf(5) diff --git a/config/tools/man/confdb2ldif.8 b/config/tools/man/confdb2ldif.8 deleted file mode 100644 index 2964eec..0000000 --- a/config/tools/man/confdb2ldif.8 +++ /dev/null @@ -1,64 +0,0 @@ -.TH confdb2ldif 8 - -.SH NAME -confdb2ldif - Create an LDIF file from a cluster configuration - -.SH SYNOPSIS -.B confdb2ldap <basedn> [<config object base>] - -.SH DESCRIPTION -\fBconfdb2ldif\fP reads the cluster configuration from the openais object database -and generates an LDIF file suitable for importing into an LDAP database. The LDIF -file is written to standard output. - -.SH OPTIONS -.TP -\fB<basedn>\fP -This is the base DN of the LDAP server into which the configuration will be imported. -confdb2ldif will create a "cn=cluster" object below this to contain the cluster configuration. -The base DN is usually derived from the host's domain name. So if the host is ldapsrv.mycorp.com -then the base DN could be dc=mycorp,dc=com. -.TP -\fB[<config object base>]\fP -Configuration object in the objdb to start from. This defaults to "cluster" and -there should rarely be any need to change it. - -.SH COMMENTS -\fBconfdb2ldif\fP uses the openais libconfdb to read the configuration. The default way to -do this is run against a running aisexec to read the live configuration. -It is possible to generate an LDIF file from a non-running system by using the standalone feature of openais's libconfdb. -.br -eg to read the configuration from /etc/cluster/cluster.conf, use the following command: - -.nf -OPENAIS_DEFAULT_CONFIG_IFACE=xmlconfig:cmanpreconfig confdb2ldif dc=mycompany,dc=com -.fi - -or to do it from CCS - -.nf -OPENAIS_DEFAULT_CONFIG_IFACE=ccsconfig:cmanpreconfig confdb2ldif dc=mycompany,dc=com -.fi - -The LDIF file is written to stdout and so can be saved or piped straight into ldapmodify if required. -.br -.br -It's important that the 99cluster.ldif schema file has been loaded into the LDAP server -before adding the contents of this generated LDIF file. - -.SH EXAMPLE - -.nf -confdb2ldif dc=mycorp,dc=com | ldapmodify -x -a -D"cn=Directory Manager" -c -v -W -.fi - -.SH BUGS -\fBconfdb2ldif\fP parses the cluster configuration without checking it against the loaded -schema. So if there are attributes in the config file that are not known to the schema, -parts of the load will fail. It is important to check the results of feeding the -output into ldapmodify. In particular aisexec logging operations will not convert -into LDIF because they rely on duplicate keys. - - -.SH SEE ALSO -libconfdb(3), openais(8), cluster.conf(5) diff --git a/config/tools/mkconf/Makefile.am b/config/tools/mkconf/Makefile.am deleted file mode 100644 index a380bea..0000000 --- a/config/tools/mkconf/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -sbin_PROGRAMS = cman-mkconf - -cman_mkconf_SOURCES = mkconf.c - -cman_mkconf_CPPFLAGS = -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 \ - -I$(top_srcdir)/config/libs/libccsconfdb/ - -cman_mkconf_CFLAGS = $(confdb_CFLAGS) $(quorum_CFLAGS) $(cfg_CFLAGS) - -cman_mkconf_LDFLAGS = $(confdb_LIBS) $(quorum_LIBS) $(cfg_LIBS) - -cman_mkconf_LDADD = $(top_builddir)/config/libs/libccsconfdb/libccs.la diff --git a/config/tools/mkconf/mkconf.c b/config/tools/mkconf/mkconf.c deleted file mode 100644 index 0845202..0000000 --- a/config/tools/mkconf/mkconf.c +++ /dev/null @@ -1,248 +0,0 @@ -#include "clusterautoconfig.h" - -#include <sys/types.h> -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <netdb.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <errno.h> - -#include <corosync/corotypes.h> -#include <corosync/quorum.h> -#include <corosync/confdb.h> -#include <corosync/cfg.h> -#include <ccs.h> - -struct node_info { - uint32_t nodeid; - char name[256]; -}; - -static uint32_t node_list_size; -static struct node_info *node_list; - - -static char *node_name(corosync_cfg_node_address_t *addr) -{ - static char name[256]; - - if (getnameinfo((struct sockaddr *)addr->address, addr->address_length, name, sizeof(name), - NULL, 0, NI_NAMEREQD)) - return NULL; - else - return name; -} - -static char *ip_address(corosync_cfg_node_address_t *addr) -{ - static char name[256]; - struct sockaddr *sa = (struct sockaddr *)addr->address; - char *addrpart; - - if (sa->sa_family == AF_INET) { - struct sockaddr_in *sin = (struct sockaddr_in *)sa; - addrpart = (char *)&sin->sin_addr; - } - else { - struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa; - addrpart = (char *)&sin->sin6_addr; - } - - if (inet_ntop(sa->sa_family, addrpart, name, sizeof(name))) - return name; - else - return NULL; -} - -static void quorum_notification_callback( - quorum_handle_t handle, - uint32_t quorate, - uint64_t ring_seq, - uint32_t view_list_entries, - uint32_t *view_list) -{ - int i; - - node_list = malloc(sizeof(struct node_info) * view_list_entries); - if (node_list) { - for (i=0; i<view_list_entries; i++) { - node_list[i].nodeid = view_list[i]; - } - node_list_size = view_list_entries; - } -} - - -static int refresh_node_list(int use_ip_addrs) -{ - int error; - int i; - quorum_handle_t quorum_handle; - corosync_cfg_handle_t cfg_handle; - quorum_callbacks_t quorum_callbacks = {.quorum_notify_fn = quorum_notification_callback}; - int max_addrs = 4; - corosync_cfg_node_address_t addrs[max_addrs]; - int num_addrs; - char *name = NULL; - - if (quorum_initialize(&quorum_handle, &quorum_callbacks) != CS_OK) { - errno = ENOMEM; - return -1; - } - if (corosync_cfg_initialize(&cfg_handle, NULL) != CS_OK) { - quorum_finalize(quorum_handle); - errno = ENOMEM; - return -1; - } - - quorum_trackstart(quorum_handle, CS_TRACK_CURRENT); - - error = quorum_dispatch(quorum_handle, CS_DISPATCH_ONE); - if (error != CS_OK) - return -1; - - quorum_finalize(quorum_handle); - - for (i=0; i < node_list_size; i++) { - - error = corosync_cfg_get_node_addrs(cfg_handle, node_list[i].nodeid, max_addrs, &num_addrs, addrs); - if (error == CS_OK) { - if (use_ip_addrs) - name = ip_address(&addrs[0]); - else - name = node_name(&addrs[0]); - } - if (name) { - sprintf(node_list[i].name, "%s", name); - } - else { - sprintf(node_list[i].name, "Node-%x", node_list[i].nodeid); - } - - } - corosync_cfg_finalize(cfg_handle); - return 0; -} - -static void usage(char *prog) -{ - printf("Usage:\n\n"); - printf(" %s [options]\n", prog); - printf("\n"); - - printf(" -N Generate sequential nodeids\n"); - printf(" -n <name> Use this cluster name\n"); - printf(" -i Use IP Addresses rather than resolved node names\n"); - printf(" -f <name> Fence agent name (default: 'default')\n"); - printf(" -F <name> Fence agent parameter name (default: 'ipaddr'\n"); - printf(" -v <num> Config version number (default: 0)\n"); - - printf("\n"); - - printf("NOTE: It is stringly recommended that the existing cluster is shut down\n"); - printf(" completely before restarting any nodes using the generated file\n"); - - printf("\n"); -} - -int main(int argc, char *argv[]) -{ - unsigned int ccs_handle; - char *value; - int optchar; - int nodeid = 0; - int i; - - int seq_nodeids=0; - int use_ip_addrs=0; - int config_version = 0; - char *cluster_name = NULL; - const char *fence_type = "default"; - const char *fence_param = "ipaddr"; - const char *fence_agent = "fence_manual"; - - /* Parse options... */ - do { - optchar = getopt(argc, argv, "?hNn:if:F:v:a:"); - switch (optchar) { - case 'N': - seq_nodeids=1; - break; - case 'n': - cluster_name = strdup(optarg); - break; - case 'i': - use_ip_addrs=1; - break; - case 'f': - fence_type = strdup(optarg); - break; - case 'a': - fence_agent = strdup(optarg); - break; - case 'F': - fence_param = strdup(optarg); - break; - case 'v': - config_version = atoi(optarg); - break; - case '?': - case 'h': - usage(argv[0]); - exit(0); - case EOF: - break; - - } - } while (optchar != EOF); - - - /* Get the list of nodes and names */ - if (refresh_node_list(use_ip_addrs)){ - fprintf(stderr, "Unable to get node information from corosync\n"); - return 1; - } - - ccs_handle = ccs_connect(); - - if (!cluster_name) { - if (!ccs_get(ccs_handle, "/cluster/@name", &value)) { - cluster_name = strdup(value); - free(value); - } - } - - /* Print config file header */ - printf("<?xml version=\"1.0\" ?>\n"); - printf("<cluster name="%s" config_version="0">\n", cluster_name); - printf(" <clusternodes>\n\n"); - for (i=0; i<node_list_size; i++) { - printf(" <clusternode name="%s" nodeid="%u">\n", node_list[i].name, - seq_nodeids?++nodeid:node_list[i].nodeid); - printf(" <fence>\n"); - printf(" <method name="single">\n"); - printf(" <device name="%s" %s="%s"/>\n", fence_type, fence_param,node_list[i].name); - printf(" </method>\n"); - printf(" </fence>\n"); - printf(" </clusternode>\n"); - printf("\n"); - } - printf(" </clusternodes>\n"); - - /* Make up something for fence devices */ - printf("<fencedevices>\n"); - - printf(" <fencedevice name="%s"> agent="%s"/>\n", fence_type, fence_agent); - - printf("</fencedevices>\n"); - - - printf("</cluster>\n"); - - ccs_disconnect(ccs_handle); - return 0; -} diff --git a/configure.ac b/configure.ac deleted file mode 100644 index c0996a3..0000000 --- a/configure.ac +++ /dev/null @@ -1,308 +0,0 @@ - -# Process this file with autoconf to produce a configure script. - -AC_PREREQ([2.63]) -AC_INIT([cluster], [master], [linux-cluster@redhat.com]) -AM_INIT_AUTOMAKE([-Wno-portability]) -LT_PREREQ([2.2.6]) -LT_INIT - -AC_CONFIG_MACRO_DIR([m4]) -AC_CONFIG_SRCDIR([config/plugins/xml/config.c]) -AC_CONFIG_HEADERS([make/clusterautoconfig.h]) - -AC_CANONICAL_HOST -AC_PROG_LIBTOOL - -AC_LANG([C]) - -# Sanitize path - -if test "$prefix" = "NONE"; then - prefix="/usr" - if test "$localstatedir" = "${prefix}/var"; then - localstatedir="/var" - fi - if test "$sysconfdir" = "${prefix}/etc"; then - sysconfdir="/etc" - fi - if test "$libdir" = "${exec_prefix}/lib"; then - if test -e /usr/lib64; then - libdir="/usr/lib64" - else - libdir="/usr/lib" - fi - fi -fi - -case $exec_prefix in - NONE) exec_prefix=$prefix;; - prefix) exec_prefix=$prefix;; -esac - -# Checks for programs. - -# check stolen from gnulib/m4/gnu-make.m4 -if ! ${MAKE-make} --version /cannot/make/this >/dev/null 2>&1; then - AC_MSG_ERROR([you don't seem to have GNU make; it is required]) -fi - -AC_PROG_CC -AM_PROG_CC_C_O -AC_PROG_LN_S -AC_PROG_INSTALL -AC_PROG_MAKE_SET - -## local helper functions - -# this function checks if CC support options passed as -# args. Global CFLAGS are ignored during this test. -cc_supports_flag() { - local CFLAGS="$@" - AC_MSG_CHECKING([whether $CC supports "$@"]) - AC_COMPILE_IFELSE([int main(){return 0;}] , - [RC=0; AC_MSG_RESULT([yes])], - [RC=1; AC_MSG_RESULT([no])]) - return $RC -} - -# this function tests if a library has a certain function -# by using AC_CHECK_LIB but restores the original LIBS global -# envvar. This is required to avoid libtool to link everything -# with everything. -check_lib_no_libs() { - AC_CHECK_LIB([$1], [$2],, - [AC_MSG_ERROR([Unable to find $1 library])]) - LIBS=$ac_check_lib_save_LIBS -} - -# corosync libs -PKG_CHECK_MODULES([corosync],[corosync]) -PKG_CHECK_MODULES([cfg],[libcfg]) -PKG_CHECK_MODULES([confdb],[libconfdb]) -PKG_CHECK_MODULES([coroipcc],[libcoroipcc]) -PKG_CHECK_MODULES([quorum],[libquorum]) -PKG_CHECK_MODULES([votequorum],[libvotequorum]) - -# external libs -PKG_CHECK_MODULES([xml],[libxml-2.0]) - -# external libs (no pkgconfig) -check_lib_no_libs pthread pthread_mutex_lock -check_lib_no_libs ldap ldap_initialize -check_lib_no_libs rt clock_gettime -check_lib_no_libs z crc32 - -# Checks for header files. -AC_FUNC_ALLOCA -AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h syslog.h unistd.h]) - -# Checks for typedefs, structures, and compiler characteristics. -AC_C_INLINE -AC_TYPE_MODE_T -AC_TYPE_OFF_T -AC_TYPE_PID_T -AC_TYPE_SIZE_T -AC_TYPE_SSIZE_T -AC_CHECK_MEMBERS([struct stat.st_rdev]) -AC_TYPE_UID_T -AC_TYPE_UINT16_T -AC_TYPE_UINT32_T -AC_TYPE_UINT64_T -AC_TYPE_UINT8_T - -# Checks for library functions. -AC_FUNC_FORK -AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK -AC_HEADER_MAJOR -AC_FUNC_MALLOC -AC_CHECK_FUNCS([alarm atexit clock_gettime dup2 ftruncate gethostname gettimeofday memmove memset select socket strcasecmp strchr strdup strerror strncasecmp strndup strstr strtol uname]) - -# local options -AC_ARG_ENABLE([debug], - [ --enable-debug enable debug build. ], - [ default="no" ]) - -AC_ARG_WITH([lcrso-dir], - [ --with-lcrso-dir=DIR corosync lcrso files. ], - [ LCRSODIR="$withval" ], - [ LCRSODIR="$libexecdir/lcrso" ]) - -AC_ARG_WITH([default-config-dir], - [ --default-config-dir=DIR - cluster config directory. ], - [ DEFAULT_CONFIG_DIR="$withval" ], - [ DEFAULT_CONFIG_DIR="$sysconfdir/cluster" ]) - -AC_ARG_WITH([default-config-file], - [ --default-config-file=FILE - cluster config file. ], - [ DEFAULT_CONFIG_FILE="$withval" ], - [ DEFAULT_CONFIG_FILE="cluster.conf" ]) - -AC_ARG_WITH([syslogfacility], - [ --syslogfacility=FACILITY - cluster default syslog facility. ], - [ SYSLOGFACILITY="$withval" ], - [ SYSLOGFACILITY="LOG_LOCAL4" ]) - -AC_ARG_WITH([sysloglevel], - [ --sysloglevel=LEVEL - cluster default syslog level. ], - [ SYSLOGLEVEL="$withval" ], - [ SYSLOGLEVEL="LOG_INFO" ]) - -AC_ARG_ENABLE([bindings], - [ --enable-bindings enable bindings build. ], - [ default="no" ]) - -## random vars - -NOTIFYDDIR=${DEFAULT_CONFIG_DIR}/cman-notify.d -LOGDIR=${localstatedir}/log/cluster -LOGROTATEDIR=${sysconfdir}/logrotate.d -CLUSTERVARRUN=${localstatedir}/run/cluster -CLUSTERVARLIB=${localstatedir}/lib/cluster - -## do subst - -AC_SUBST([LCRSODIR]) -AC_DEFINE_UNQUOTED([LCRSODIR], "$(eval echo ${LCRSODIR})", [LCRSO directory]) - -AC_SUBST([DEFAULT_CONFIG_DIR]) -AC_DEFINE_UNQUOTED([DEFAULT_CONFIG_DIR], "$(eval echo ${DEFAULT_CONFIG_DIR})", - [Default config directory]) - -AC_SUBST([DEFAULT_CONFIG_FILE]) -AC_DEFINE_UNQUOTED([DEFAULT_CONFIG_FILE], "$(eval echo ${DEFAULT_CONFIG_FILE})", - [Default config file]) - -AC_SUBST([LOGDIR]) -AC_DEFINE_UNQUOTED([LOGDIR], "$(eval echo ${LOGDIR})", - [Default logging directory]) - -AC_SUBST([NOTIFYDDIR]) - -AC_SUBST([LOGROTATEDIR]) - -AC_SUBST([CLUSTERVARRUN]) -AC_DEFINE_UNQUOTED([CLUSTERVARRUN], "$(eval echo ${CLUSTERVARRUN})", - [Default cluster var/run directory]) - -AC_SUBST([CLUSTERVARLIB]) - -AC_DEFINE_UNQUOTED([SBINDIR], "$(eval echo ${sbindir})", - [/sbin path]) - -AC_DEFINE_UNQUOTED([COROSYNCBIN], "$(eval echo ${sbindir}/corosync)", - [corosync executable file]) - -AC_DEFINE_UNQUOTED([SYSLOGFACILITY], $(eval echo ${SYSLOGFACILITY}), - [Default syslog facility]) - -AC_DEFINE_UNQUOTED([SYSLOGLEVEL], $(eval echo ${SYSLOGLEVEL}), - [Default syslog level]) - -AM_CONDITIONAL(BUILD_BINDINGS, test "x${enable_bindings}" = xyes) - -## *FLAGS handling - -ENV_CFLAGS="$CFLAGS" -ENV_CPPFLAGS="$CPPFLAGS" -ENV_LDFLAGS="$LDFLAGS" - -# debug build stuff -if test "x${enable_debug}" = xyes; then - AC_DEFINE_UNQUOTED([DEBUG], [1], [Compiling Debugging code]) - OPT_CFLAGS="-O0" -else - OPT_CFLAGS="-O2" -fi - -# gdb flags -if test "x${GCC}" = xyes; then - GDB_FLAGS="-ggdb3" -else - GDB_FLAGS="-g" -fi - -# extra warnings -EXTRA_WARNINGS="" - -WARNLIST=" - all - shadow - missing-prototypes - missing-declarations - strict-prototypes - declaration-after-statement - pointer-arith - write-strings - cast-align - bad-function-cast - missing-format-attribute - format=2 - format-security - format-nonliteral - no-long-long - unsigned-char - gnu89-inline - no-strict-aliasing - " - -for j in $WARNLIST; do - if cc_supports_flag -W$j; then - EXTRA_WARNINGS="$EXTRA_WARNINGS -W$j"; - fi -done - -CFLAGS="$ENV_CFLAGS $OPT_CFLAGS $GDB_FLAGS \ - $EXTRA_WARNINGS $WERROR_CFLAGS" -CPPFLAGS="-I$(top_builddir)/make -I$(top_srcdir)/make -I. $ENV_CPPFLAGS" -LDFLAGS="$ENV_LDFLAGS" - -# -# missing: -# cman/init.d/Makefile -# bindings/perl/ccs/Makefile - -AC_CONFIG_FILES([Makefile - common/Makefile - common/liblogthread/Makefile - common/liblogthread/liblogthread.pc - config/Makefile - config/libs/Makefile - config/libs/libccsconfdb/Makefile - config/libs/libccsconfdb/libccs.pc - config/plugins/Makefile - config/plugins/ldap/Makefile - config/plugins/xml/Makefile - config/tools/Makefile - config/tools/ccs_tool/Makefile - config/tools/ldap/Makefile - config/tools/mkconf/Makefile - config/tools/man/Makefile - config/man/Makefile - cman/Makefile - cman/services/Makefile - cman/services/cman/Makefile - cman/services/cman/include/Makefile - cman/services/cman/services/Makefile - cman/services/cman/lib/Makefile - cman/services/cman/lib/libcman.pc - cman/cman_tool/Makefile - cman/config/Makefile - cman/qdisk/Makefile - cman/notifyd/Makefile - cman/man/Makefile - cman/tests/Makefile - group/Makefile - group/man/Makefile - group/tool/Makefile - doc/Makefile - bindings/Makefile - bindings/perl/Makefile - bindings/perl/ccs/Makefile - ]) - -AC_OUTPUT diff --git a/doc/COPYING.applications b/doc/COPYING.applications deleted file mode 100644 index d511905..0000000 --- a/doc/COPYING.applications +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/doc/COPYING.libraries b/doc/COPYING.libraries deleted file mode 100644 index 2d2d780..0000000 --- a/doc/COPYING.libraries +++ /dev/null @@ -1,510 +0,0 @@ - - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations -below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it -becomes a de-facto standard. To achieve this, non-free programs must -be allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control -compilation and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at least - three years, to give the same user the materials specified in - Subsection 6a, above, for a charge no more than the cost of - performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply, and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License -may add an explicit geographical distribution limitation excluding those -countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms -of the ordinary General Public License). - - To apply these terms, attach the following notices to the library. -It is safest to attach them to the start of each source file to most -effectively convey the exclusion of warranty; and each file should -have at least the "copyright" line and a pointer to where the full -notice is found. - - - <one line to give the library's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or -your school, if any, to sign a "copyright disclaimer" for the library, -if necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James - Random Hacker. - - <signature of Ty Coon>, 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/doc/COPYRIGHT b/doc/COPYRIGHT deleted file mode 100644 index 71fa6a9..0000000 --- a/doc/COPYRIGHT +++ /dev/null @@ -1,58 +0,0 @@ -Unless specified otherwise in the "exceptions section" below: - -Copyright (C) 1997-2003 Sistina Software, Inc. All rights reserved. -Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved. - -Exceptions: - -cman/qdisk/crc32.c: - Copyright (C) 2000 Bryan Call <bc at fodder.org> - Modified by Lon H. Hohberger <lhh at redhat.com> - Copyright (C) 2003-2010 Red Hat, Inc. All rights reserved. - -cman/qdisk/daemon_init.c: - Copyright (C) 2000 Mission Critical Linux - Copyright (C) 2002-2010 Red Hat, Inc. All rights reserved. - Author: Jeff Moyer <jmoyer at redhat.com> - -cman/qdisk/disk.c: - Copyright (C) 2000 Mission Critical Linux - Copyright (C) 2002-2010 Red Hat, Inc. All rights reserved. - Author: Tim Burke <tburke at redhat.com> - -cman/qdisk/scandisk.{c,h}: - Original design by: Joel Becker <Joel.Becker at oracle.com> and - Fabio M. Di Nitto <fdinitto at redhat.com> - -Authors as known by current RCS as of the time of writing: - -Abhijith Das <adas at redhat.com> -Adam Manthei <amanthei at redhat.com> -A. J. Lewis <alewis at redhat.com> -Alasdair G. Kergon <agk at redhat.com> -Andrew Price <andy at andrewprice.me.uk> -Benjamin Marzinski <bmarzins at redhat.com> -Bob Peterson <rpeterso at redhat.com> -Chris Feist <cfeist at redhat.com> -Christine Caulfield <ccaulfie at redhat.com> -Daniel Phillips <phillips at redhat.com> -David Teigland <teigland at redhat.com> -Fabio M. Di Nitto <fdinitto at redhat.com> -James Parsons <jparsons at redhat.com> -Joel Becker <joel.becker at oracle.com> -Jonathan Brassow <jbrassow at redhat.com> -jparsons <jparsons at redhat.com> -Ken Preslan <kpreslan at redhat.com> -Lon Hohberger <lhh at redhat.com> -Marc - A. Dahlhaus <mad at wol.de> -Marek 'marx' Grac <mgrac at redhat.com> -Mark Hlawatschek <hlawatschek at atix.de> -Michael Conrad Tadpol Tilstra <mtilstra at redhat.com> -Patrick Caulfield <pcaulfie at redhat.com> -Robert Peterson <rpeterso at redhat.com> -Ross Vandegrift <ross at kallisti.us> -Ryan McCabe <rmccabe at redhat.com> -Ryan O'Hara <rohara at redhat.com> -Stanko Kupcevic <kupcevic at redhat.com> -Steven Whitehouse <swhiteho at redhat.com> -Wendy Cheng <wcheng at redhat.com> diff --git a/doc/Makefile.am b/doc/Makefile.am deleted file mode 100644 index a9332de..0000000 --- a/doc/Makefile.am +++ /dev/null @@ -1,34 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -dist_doc_DATA = gfs2.txt \ - journaling.txt \ - min-gfs.txt \ - usage.txt \ - COPYING.applications \ - COPYING.libraries \ - COPYRIGHT \ - README.licence - -EXTRA_DIST = cman_notify_template.sh \ - cluster.logrotate.in - -logrotate_TARGET = cluster - -$(logrotate_TARGET): $(logrotate_TARGET).logrotate.in - cat $(srcdir)/$^ | sed \ - -e 's#_LOGDIR_#${LOGDIR}#g' \ - > $@ - -all-local: $(logrotate_TARGET) - -clean-local: - rm -f $(logrotate_TARGET) - -install-exec-local: - $(INSTALL) -d $(DESTDIR)/$(LOGROTATEDIR) - $(INSTALL) -m 644 cluster $(DESTDIR)/$(LOGROTATEDIR) - -uninstall-local: - cd $(DESTDIR)/$(LOGROTATEDIR) && \ - rm -f $(logrotate_TARGET) - rmdir $(DESTDIR)/$(LOGROTATEDIR) || :; diff --git a/doc/README.licence b/doc/README.licence deleted file mode 100644 index 075aa77..0000000 --- a/doc/README.licence +++ /dev/null @@ -1,33 +0,0 @@ -The Red Hat Cluster is a collection of free software built on top of different -libraries and applications. - -For a detailed list of authors and copyright holders, please check the -included COPYRIGHT file. - -Libraries: - -You can redistribute them and/or modify them under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -The libraries are distributed in the hope that they will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. - -Applications: - -You can redistribute them and/or modify them under the terms of the GNU General -Public License as published by the Free Software Foundation; either version -2 of the License, or (at your option) any later version. - -The applications are distributed in the hope that they will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -details. - -A copy of each license is included for your convenience in COPYING.applications -and COPYING.libraries. - -If missing, write to the Free Software Foundation, Inc., 51 Franklin St, -Fifth Floor, Boston, MA 02110-1301 USA. diff --git a/doc/cluster.logrotate.in b/doc/cluster.logrotate.in deleted file mode 100644 index 44451a6..0000000 --- a/doc/cluster.logrotate.in +++ /dev/null @@ -1,8 +0,0 @@ -_LOGDIR_/*log { - missingok - compress - notifempty - daily - rotate 7 - create 0600 root root -} diff --git a/doc/cman_notify_template.sh b/doc/cman_notify_template.sh deleted file mode 100644 index ef43860..0000000 --- a/doc/cman_notify_template.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash - -# This is a simple template that can be used as reference -# for notification scripts. Note: notification scripts need -# to be executable in order for cman_notify to run them. - -# Set the path for the commands you expect to execute! -# cmannotifyd does not set any for you. - -PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin - -# define a simple wrapper to echo that will log to file only if -# debugging is enable. -my_echo() { - [ -n "$OUT" ] && echo $@ >> $OUT -} - -LOGFILE="/var/log/cluster/file.log" - -# verify if you are running in debugging mode -if [ "$CMAN_NOTIFICATION_DEBUG" = "1" ]; then - # in debuggin mode, we want to see the whole output somewhere - OUT="$LOGFILE" - my_echo "debugging is enabled" -fi - -# parse the notification we received. -case "$CMAN_NOTIFICATION" in - CMAN_REASON_CONFIG_UPDATE) - # we received a configuration change - my_echo "replace me with something to do" - ;; - CMAN_REASON_STATECHANGE) - # we received a status change. A node might have left or joined - # the cluster - my_echo "replace me with something to do" - - # STATECHANGE contains information about the quorum status of - # the node. - # 1 = the node is part of a quorate cluster - # 0 = there is no quorum - if [ "$CMAN_NOTIFICATION_QUORUM" = "1" ]; then - my_echo "we still have quorum" - fi - ;; - CMAN_REASON_TRY_SHUTDOWN) - # we received a shutdown request. It means that cman might go - # offline very soon. - my_echo "replace me with something to do" - ;; - *) - # we received an unknown notification. - my_echo "no clue of what to do with this" - ;; -esac - -exit 0 diff --git a/doc/gfs2.txt b/doc/gfs2.txt deleted file mode 100644 index 88f0143..0000000 --- a/doc/gfs2.txt +++ /dev/null @@ -1,45 +0,0 @@ -Global File System ------------------- - -http://sources.redhat.com/cluster/ - -GFS is a cluster file system. It allows a cluster of computers to -simultaneously use a block device that is shared between them (with FC, -iSCSI, NBD, etc). GFS reads and writes to the block device like a local -file system, but also uses a lock module to allow the computers coordinate -their I/O so file system consistency is maintained. One of the nifty -features of GFS is perfect consistency -- changes made to the file system -on one machine show up immediately on all other machines in the cluster. - -GFS uses interchangable inter-node locking mechanisms. Different lock -modules can plug into GFS and each file system selects the appropriate -lock module at mount time. Lock modules include: - - lock_nolock -- does no real locking and allows gfs to be used as a - local file system - - lock_dlm -- uses a distributed lock manager (dlm) for inter-node locking - The dlm is found at linux/fs/dlm/ - -In addition to interfacing with an external locking manager, a gfs lock -module is responsible for interacting with external cluster management -systems. Lock_dlm depends on user space cluster management systems found -at the URL above. - -To use gfs as a local file system, no external clustering systems are -needed, simply: - - $ gfs2_mkfs -p lock_nolock -j 1 /dev/block_device - $ mount -t gfs2 /dev/block_device /dir - -GFS2 is not on-disk compatible with previous versions of GFS. - -The following man pages can be found at the URL above: - gfs2_mkfs to make a filesystem - gfs2_fsck to repair a filesystem - gfs2_grow to expand a filesystem online - gfs2_jadd to add journals to a filesystem online - gfs2_tool to manipulate, examine and tune a filesystem - gfs2_quota to examine and change quota values in a filesystem - mount.gfs2 to find mount options - diff --git a/doc/journaling.txt b/doc/journaling.txt deleted file mode 100644 index e89eefa..0000000 --- a/doc/journaling.txt +++ /dev/null @@ -1,155 +0,0 @@ -o Journaling & Replay - -The fundamental problem with a journaled cluster filesystem is -handling journal replay with multiple journals. A single block of -metadata can be modified sequentially by many different nodes in the -cluster. As the block is modified by each node, it gets logged in the -journal for each node. If care is not taken, it's possible to get -into a situation where a journal replay can actually corrupt a -filesystem. The error scenario is: - -1) Node A modifies a metadata block by putting a updated copy into its - incore log. -2) Node B wants to read and modify the block so it requests the lock - and a blocking callback is sent to Node A. -3) Node A flushes its incore log to disk, and then syncs out the - metadata block to its inplace location. -4) Node A then releases the lock. -5) Node B reads in the block and puts a modified copy into its ondisk - log and then the inplace block location. -6) Node A crashes. - -At this point, Node A's journal needs to be replayed. Since there is -a newer version of block inplace, if that block is replayed, the -filesystem will be corrupted. There are a few different ways of -avoiding this problem. - -1) Generation Numbers (GFS1) - - Each metadata block has header in it that contains a 64-bit - generation number. As each block is logged into a journal, the - generation number is incremented. This provides a strict ordering - of the different versions of the block a they are logged in the FS' - different journals. When journal replay happens, each block in the - journal is not replayed if generation number in the journal is less - than the generation number in place. This ensures that a newer - version of a block is never replaced with an older version. So, - this solution basically allows multiple copies of the same block in - different journals, but it allows you to always know which is the - correct one. - - Pros: - - A) This method allows the fastest callbacks. To release a lock, - the incore log for the lock must be flushed and then the inplace - data and metadata must be synced. That's it. The sync - operations involved are: start the log body and wait for it to - become stable on the disk, synchronously write the commit block, - start the inplace metadata and wait for it to become stable on - the disk. - - Cons: - - A) Maintaining the generation numbers is expensive. All newly - allocated metadata block must be read off the disk in order to - figure out what the previous value of the generation number was. - When deallocating metadata, extra work and care must be taken to - make sure dirty data isn't thrown away in such a way that the - generation numbers stop doing their thing. - B) You can't continue to modify the filesystem during journal - replay. Basically, replay of a block is a read-modify-write - operation: the block is read from disk, the generation number is - compared, and (maybe) the new version is written out. Replay - requires that the R-M-W operation is atomic with respect to - other R-M-W operations that might be happening (say by a normal - I/O process). Since journal replay doesn't (and can't) play by - the normal metadata locking rules, you can't count on them to - protect replay. Hence GFS1, quieces all writes on a filesystem - before starting replay. This provides the mutual exclusion - required, but it's slow and unnecessarily interrupts service on - the whole cluster. - -2) Total Metadata Sync (OCFS2) - - This method is really simple in that it uses exactly the same - infrastructure that a local journaled filesystem uses. Every time - a node receives a callback, it stops all metadata modification, - syncs out the whole incore journal, syncs out any dirty data, marks - the journal as being clean (unmounted), and then releases the lock. - Because journal is marked as clean and recovery won't look at any - of the journaled blocks in it, a valid copy of any particular block - only exists in one journal at a time and that journal always the - journal who modified it last. - - Pros: - - A) Very simple to implement. - B) You can reuse journaling code from other places (such as JBD). - C) No quiece necessary for replay. - D) No need for generation numbers sprinkled throughout the metadata. - - Cons: - - A) This method has the slowest possible callbacks. The sync - operations are: stop all metadata operations, start and wait for - the log body, write the log commit block, start and wait for all - the FS' dirty metadata, write an unmount block. Writing the - metadata for the whole filesystem can be particularly expensive - because it can be scattered all over the disk and there can be a - whole journal's worth of it. - -3) Revocation of a lock's buffers (GFS2) - - This method prevents a block from appearing in more than one - journal by canceling out the metadata blocks in the journal that - belong to the lock being released. Journaling works very similarly - to a local filesystem or to #2 above. - - The biggest difference is you have to keep track of buffers in the - active region of the ondisk journal, even after the inplace blocks - have been written back. This is done in GFS2 by adding a second - part to the Active Items List. The first part (in GFS2 called - AIL1) contains a list of all the blocks which have been logged to - the journal, but not written back to their inplace location. Once - an item in AIL1 has been written back to its inplace location, it - is moved to AIL2. Once the tail of the log moves past the block's - transaction in the log, it can be removed from AIL2. - - When a callback occurs, the log is flushed to the disk and the - metadata for the lock is synced to disk. At this point, any - metadata blocks for the lock that are in the current active region - of the log will be in the AIL2 list. We then build a transaction - that contains revoke tags for each buffer in the AIL2 list that - belongs to that lock. - - Pros: - - A) No quiece necessary for Replay - B) No need for generation numbers sprinkled throughout the - metadata. - C) The sync operations are: stop all metadata operations, start and - wait for the log body, write the log commit block, start and - wait for all the FS' dirty metadata, start and wait for the log - body of a transaction that revokes any of the lock's metadata - buffers in the journal's active region, and write the commit - block for that transaction. - - Cons: - - A) Recovery takes two passes, one to find all the revoke tags in - the log and one to replay the metadata blocks using the revoke - tags as a filter. This is necessary for a local filesystem and - the total sync method, too. It's just that there will probably - be more tags. - -Comparing #2 and #3, both do extra I/O during a lock callback to make -sure that any metadata blocks in the log for that lock will be -removed. I believe #2 will be slower because syncing out all the -dirty metadata for entire filesystem requires lots of little, -scattered I/O across the whole disk. The extra I/O done by #3 is a -log write to the disk. So, not only should it be less I/O, but it -should also be better suited to get good performance out of the disk -subsystem. - -KWP 07/06/05 - diff --git a/doc/min-gfs.txt b/doc/min-gfs.txt deleted file mode 100644 index af1399c..0000000 --- a/doc/min-gfs.txt +++ /dev/null @@ -1,159 +0,0 @@ - -Minimum GFS HowTo ------------------ - -The following gfs configuration requires a minimum amount of hardware and -no expensive storage system. It's the cheapest and quickest way to "play" -with gfs. - - - ---------- ---------- - | GNBD | | GNBD | - | client | | client | <-- these nodes use gfs - | node2 | | node3 | - ---------- ---------- - | | - ------------------ IP network - | - ---------- - | GNBD | - | server | <-- this node doesn't use gfs - | node1 | - ---------- - -- There are three machines to use with hostnames: node1, node2, node3 - -- node1 has an extra disk /dev/sda1 to use for gfs - (this could be hda1 or an lvm LV or an md device) - -- node1 will use gnbd to export this disk to node2 and node3 - -- Node1 cannot use gfs, it only acts as a gnbd server. - (Node1 will /not/ actually be part of the cluster since it is only - running the gnbd server.) - -- Only node2 and node3 will be in the cluster and use gfs. - (A two-node cluster is a special case for cman, noted in the config below.) - -- There's not much point to using clvm in this setup so it's left out. - -- Download the "cluster" source tree. - -- Build and install from the cluster source tree. (The kernel components - are not required on node1 which will only need the gnbd_serv program.) - - cd cluster - ./configure --kernel_src=/path/to/kernel - make; make install - -- Create /etc/cluster/cluster.conf on node2 with the following contents: - -<?xml version="1.0"?> -<cluster name="gamma" config_version="1"> - -<cman two_node="1" expected_votes="1"> -</cman> - -<clusternodes> -<clusternode name="node2"> - <fence> - <method name="single"> - <device name="gnbd" ipaddr="node2"/> - </method> - </fence> -</clusternode> - -<clusternode name="node3"> - <fence> - <method name="single"> - <device name="gnbd" ipaddr="node3"/> - </method> - </fence> -</clusternode> -</clusternodes> - -<fencedevices> - <fencedevice name="gnbd" agent="fence_gnbd" servers="node1"/> -</fencedevices> - -</cluster> - - -- load kernel modules on nodes - -node2 and node3> modprobe gnbd -node2 and node3> modprobe gfs -node2 and node3> modprobe lock_dlm - -- run the following commands - -node1> gnbd_serv -n -node1> gnbd_export -c -d /dev/sda1 -e global_disk - -node2 and node3> gnbd_import -n -i node1 -node2 and node3> ccsd -node2 and node3> cman_tool join -node2 and node3> fence_tool join - -node2> gfs_mkfs -p lock_dlm -t gamma:gfs1 -j 2 /dev/gnbd/global_disk - -node2 and node3> mount -t gfs /dev/gnbd/global_disk /mnt - -- the end, you now have a gfs file system mounted on node2 and node3 - - -Appendix A ----------- - -To use manual fencing instead of gnbd fencing, the cluster.conf file -would look like this: - -<?xml version="1.0"?> -<cluster name="gamma" config_version="1"> - -<cman two_node="1" expected_votes="1"> -</cman> - -<clusternodes> -<clusternode name="node2"> - <fence> - <method name="single"> - <device name="manual" ipaddr="node2"/> - </method> - </fence> -</clusternode> - -<clusternode name="node3"> - <fence> - <method name="single"> - <device name="manual" ipaddr="node3"/> - </method> - </fence> -</clusternode> -</clusternodes> - -<fencedevices> - <fencedevice name="manual" agent="fence_manual"/> -</fencedevices> - -</cluster> - - -FAQ ---- - -- Why can't node3 use gfs, too? - -You might be able to make it work, but we recommend that you not try. -This software was not intended or designed to allow that kind of usage. - -- Isn't node3 a single point of failure? how do I avoid that? - -Yes it is. For the time being, there's no way to avoid that, apart from -not using gnbd, of course. Eventually, there will be a way to avoid this -using cluster mirroring. - -- More info from - http://sources.redhat.com/cluster/gnbd/gnbd_usage.txt - http://sources.redhat.com/cluster/doc/usage.txt - diff --git a/doc/usage.txt b/doc/usage.txt deleted file mode 100644 index f9e2866..0000000 --- a/doc/usage.txt +++ /dev/null @@ -1,177 +0,0 @@ -How to install and run GFS. - -Refer to the cluster project page for the latest information. -http://sources.redhat.com/cluster/ - - -Install -------- - -Install a Linux kernel with GFS2, DLM, configfs, IPV6 and SCTP, - 2.6.23-rc1 or later - - If you want to use gfs1 (from cluster/gfs-kernel), then you need to - export three additional symbols from gfs2 by adding the following lines - to the end of linux/fs/gfs2/locking.c: - EXPORT_SYMBOL_GPL(gfs2_unmount_lockproto); - EXPORT_SYMBOL_GPL(gfs2_mount_lockproto); - EXPORT_SYMBOL_GPL(gfs2_withdraw_lockproto); - -Install openais - get the latest "whitetank" (stable) release from - http://openais.org/ - or - svn checkout http://svn.osdl.org/openais - cd openais/branches/whitetank - make; make install DESTDIR=/ - -Install gfs/dlm/fencing/etc components - get the latest cluster-2.xx.yy tarball from - ftp://sources.redhat.com/pub/cluster/ - or - cvs -d :pserver:cvs@sources.redhat.com:/cvs/cluster login cvs - cvs -d :pserver:cvs@sources.redhat.com:/cvs/cluster checkout cluster - the password is "cvs" - cd cluster - ./configure --kernel_src=/path/to/kernel - make install - - NOTE: On 64-bit systems, you will usually need to add '--libdir=/usr/lib64' - to the configure line. - -Install LVM2/CLVM (optional) - cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 login cvs - cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 checkout LVM2 - cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 - the password is "cvs" - cd LVM2 - ./configure --with-clvmd=cman --with-cluster=shared - make; make install - - NOTE: On 64-bit systems, you will usually need to add '--libdir=/usr/lib64' - to the configure line. - -Load kernel modules -------------------- - -modprobe gfs2 -modprobe gfs -modprobe lock_dlm -modprobe lock_nolock -modprobe dlm - - -Configuration -------------- - -Create /etc/cluster/cluster.conf and copy it to all nodes. - - The format and content of cluster.conf has changed little since the - last generation of the software. See old example here: - http://sources.redhat.com/cluster/doc/usage.txt - The one change you will need to make is to add nodeids for all nodes - in the cluster. These are now mandatory. eg: - - <clusternode name="node12.mycluster.mycompany.com" votes="1" nodeid="12"> - - If you already have a cluster.conf file with no nodeids in it, then you can - use the 'ccs_tool addnodeids' command to add them. - - -Example cluster.conf --------------------- - -This is a basic cluster.conf file that requires manual fencing. The node -names should resolve to the address on the network interface you want to -use for openais/cman/dlm communication. - -<?xml version="1.0"?> -<cluster name="alpha" config_version="1"> - -<clusternodes> -<clusternode name="node01" nodeid="1"> - <fence> - </fence> -</clusternode> - -<clusternode name="node02" nodeid="2"> - <fence> - </fence> -</clusternode> - -<clusternode name="node03" nodeid="3"> - <fence> - </fence> -</clusternode> -</clusternodes> - -<fencedevices> -</fencedevices> - -</cluster> - - -Startup procedure ------------------ - -Run these commands on each cluster node: - -> mount -t configfs none /sys/kernel/config -> ccsd -> cman_tool join -> groupd -> fenced -> fence_tool join -> dlm_controld -> gfs_controld -> clvmd (optional) -> mkfs -t gfs2 -p lock_dlm -t <clustername>:<fsname> -j <#journals> <blockdev> -> mount -t gfs2 [-v] <blockdev> <mountpoint> - -Notes: -- replace "gfs2" with "gfs" above to use gfs1 instead of gfs2 -- <clustername> in mkfs should match the one in cluster.conf. -- <fsname> in mkfs is any name you pick, each fs must have a different name. -- <#journals> in mkfs should be greater than or equal to the number of nodes - that you want to mount this fs, each node uses a separate journal. -- To avoid unnecessary fencing when starting the cluster, it's best for - all nodes to join the cluster (complete cman_tool join) before any - of them do fence_tool join. -- The cman_tool "status" and "nodes" options show the status and members - of the cluster. -- The group_tool command shows the status of fencing, dlm and gfs groups - that the local node is part of. -- The "cman" init script can be used for starting everything up through - gfs_controld in the list above. - - -Shutdown procedure ------------------- - -Run these commands on each cluster node: - -> umount [-v] <mountpoint> -> fence_tool leave -> cman_tool leave - - -Converting from GFS1 to GFS2 ----------------------------- - -If you have GFS1 filesystems that you need to convert to GFS2, follow -this procedure: - -1. Back up your entire filesystem first. - e.g. cp /dev/your_vg/lvol0 /your_gfs_backup - -2. Run fsck to ensure filesystem integrity. - e.g. gfs2_fsck /dev/your_vg/lvol0 - -3. Make sure the filesystem is not mounted from any node. - e.g. for i in `grep "<clusternode name" /etc/cluster/cluster.conf | cut -d '"' -f2` ; do ssh $i "mount | grep gfs" ; done - -4. Make sure you have the latest software versions. - -5. Run gfs2_convert <blockdev> from one of the nodes. - e.g. gfs2_convert /dev/your_vg/lvol0 - diff --git a/group/Makefile.am b/group/Makefile.am deleted file mode 100644 index 9345392..0000000 --- a/group/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -SUBDIRS = tool man diff --git a/group/man/Makefile.am b/group/man/Makefile.am deleted file mode 100644 index fcc1510..0000000 --- a/group/man/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -dist_man_MANS = group_tool.8 diff --git a/group/man/group_tool.8 b/group/man/group_tool.8 deleted file mode 100644 index 6cf5e7f..0000000 --- a/group/man/group_tool.8 +++ /dev/null @@ -1,61 +0,0 @@ -.TH group_tool 8 - -.SH NAME -group_tool - display/dump information about fence, dlm and gfs groups - -.SH SYNOPSIS -.B -group_tool -[\fISUBCOMMAND\fR] [\fIOPTION\fR]... - -.SH DESCRIPTION - -The group_tool program displays the status of fence, dlm and gfs groups. -The information is read from the groupd daemon which controls the fenced, -dlm_controld and gfs_controld daemons. group_tool will also dump debug -logs from various daemons. - -.SH SUBCOMMANDS - -.TP -\fBls\fP -displays the list of groups and their membership. It is the default -subcommand if none is specified. - -.TP -\fBdump\fP -dumps the debug log from groupd. - -.TP -\fBdump fence\fP -dumps the debug log from fenced. - -.TP -\fBdump gfs\fP -dumps the debug log from gfs_controld. - -.TP -\fBdump plocks\fP <fsname> -prints the posix locks on the named gfs fs from gfs_controld. - -.SH OPTIONS -.TP -\fB-v\fP -Verbose output, used with the 'ls' subcommand. -.TP -\fB-D\fP -Run the daemon in the foreground and print debug statements to stdout. -.TP -\fB-V\fP -Print the version information and exit. -.TP -\fB-h\fP -Print out a help message describing available options, then exit. - -.SH DEBUGGING -The groupd daemon keeps a circular buffer of debug messages that can be -dumped with the 'group_tool dump' command. - -.SH SEE ALSO -groupd(8) - diff --git a/group/tool/Makefile.am b/group/tool/Makefile.am deleted file mode 100644 index 5c36907..0000000 --- a/group/tool/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -sbin_PROGRAMS = group_tool - -group_tool_SOURCES = main.c diff --git a/group/tool/main.c b/group/tool/main.c deleted file mode 100644 index aed540f..0000000 --- a/group/tool/main.c +++ /dev/null @@ -1,147 +0,0 @@ -#include "clusterautoconfig.h" - -#include <sys/types.h> -#include <sys/un.h> -#include <inttypes.h> -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <stddef.h> -#include <fcntl.h> -#include <string.h> -#include <errno.h> -#include <limits.h> -#include <netinet/in.h> - -#include "copyright.cf" - -#define OP_LIST 1 -#define OP_DUMP 2 - -static char *prog_name; -static int operation; -static int opt_ind; -static int verbose; -static int ls_all_nodes; - -static void print_usage(void) -{ - printf("Usage:\n"); - printf("\n"); - printf("%s [options] [ls|dump]\n", prog_name); - printf("\n"); - printf("Options:\n"); - printf(" -v Verbose output, extra information\n"); - printf(" -n Show all node information\n"); - printf(" -h Print this help, then exit\n"); - printf(" -V Print program version information, then exit\n"); - printf("\n"); - printf("Display debugging information\n"); - printf("dump fence Show debug log from fenced\n"); - printf("dump dlm Show debug log from dlm_controld\n"); - printf("dump gfs Show debug log from gfs_controld\n"); - printf("\n"); -} - -#define OPTION_STRING "hVvn" - -static void decode_arguments(int argc, char **argv) -{ - int cont = 1; - int optchar; - - while (cont) { - optchar = getopt(argc, argv, OPTION_STRING); - - switch (optchar) { - case 'n': - ls_all_nodes = 1; - break; - - case 'v': - verbose = 1; - break; - - case 'h': - print_usage(); - exit(EXIT_SUCCESS); - break; - - case 'V': - printf("%s %s (built %s %s)\n", - prog_name, PACKAGE_VERSION, __DATE__, __TIME__); - printf("%s\n", REDHAT_COPYRIGHT); - exit(EXIT_SUCCESS); - break; - - case ':': - case '?': - fprintf(stderr, "Please use '-h' for usage.\n"); - exit(EXIT_FAILURE); - break; - - case EOF: - cont = 0; - break; - - default: - fprintf(stderr, "unknown option: %c\n", optchar); - exit(EXIT_FAILURE); - break; - }; - } - - while (optind < argc) { - if (strcmp(argv[optind], "dump") == 0) { - operation = OP_DUMP; - opt_ind = optind + 1; - break; - } else if (strcmp(argv[optind], "ls") == 0 || - strcmp(argv[optind], "list") == 0) { - operation = OP_LIST; - opt_ind = optind + 1; - break; - } - optind++; - } - - if (!operation) - operation = OP_LIST; -} - -int main(int argc, char **argv) -{ - prog_name = argv[0]; - decode_arguments(argc, argv); - - switch (operation) { - case OP_LIST: - if (verbose || ls_all_nodes) { - system("fence_tool ls -n"); - system("dlm_tool ls -n"); - system("gfs_control ls -n"); - } else { - system("fence_tool ls"); - system("dlm_tool ls"); - system("gfs_control ls"); - } - break; - - case OP_DUMP: - if (opt_ind && opt_ind < argc) { - if (!strncmp(argv[opt_ind], "gfs", 3)) - system("gfs_control dump"); - - if (!strncmp(argv[opt_ind], "dlm", 3)) - system("dlm_tool dump"); - - if (!strncmp(argv[opt_ind], "fence", 5)) - system("fence_tool dump"); - } - break; - } - - return 0; -} - diff --git a/make/copyright.cf b/make/copyright.cf deleted file mode 100644 index 3801aa9..0000000 --- a/make/copyright.cf +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __COPYRIGHT_DOT_CF__ -#define __COPYRIGHT_DOT_CF__ - -#define REDHAT_COPYRIGHT "Copyright (C) Red Hat, Inc. 2004-2010 All rights reserved." - -#endif /* __COPYRIGHT_DOT_CF__ */ diff --git a/make/lcrso.mk b/make/lcrso.mk deleted file mode 100644 index a2ab978..0000000 --- a/make/lcrso.mk +++ /dev/null @@ -1,23 +0,0 @@ -LCRSO_OBJS = $(SOURCES:%.c=%.o) - -$(LCRSO): $(LCRSO_OBJS) - $(CC) $(AM_LDFLAGS) $(LDFLAGS) -shared -Wl,-soname=$@ $^ -o $@ - -%.o: %.c - $(CC) $(AM_CPPFLAGS) $(AM_CFLAGS) \ - $(CFLAGS) $(CPPFLAGS) \ - $(INCLUDES) \ - -c -o $@ $< - -all-local: $(LCRSO_OBJS) $(LCRSO) - -install-exec-local: - $(INSTALL) -d $(DESTDIR)/$(LCRSODIR) - $(INSTALL) -m 755 $(LCRSO) $(DESTDIR)/$(LCRSODIR) - -uninstall-local: - cd $(DESTDIR)/$(LCRSODIR) && \ - rm -f $(LCRSO) - -clean-local: - rm -f *.o *.a *.lcrso
cluster-commits@lists.stg.fedorahosted.org