diff options
Diffstat (limited to '')
-rw-r--r-- | lrm/admin/Makefile.am | 40 | ||||
-rwxr-xr-x | lrm/admin/cibsecret.in | 350 | ||||
-rw-r--r-- | lrm/admin/lrmadmin.c | 1129 | ||||
-rw-r--r-- | lrm/admin/lrmadmin.txt | 60 |
4 files changed, 1579 insertions, 0 deletions
diff --git a/lrm/admin/Makefile.am b/lrm/admin/Makefile.am new file mode 100644 index 0000000..a92cd72 --- /dev/null +++ b/lrm/admin/Makefile.am @@ -0,0 +1,40 @@ +# +# Author: Sun Jiang Dong <sunjd@cn.ibm.com> +# Copyright (c) 2004 International Business Machines +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ + -I$(top_builddir)/libltdl -I$(top_srcdir)/libltdl + +halibdir = $(libdir)/@HB_PKG@ +COMMONLIBS = $(top_builddir)/lib/clplumbing/libplumb.la $(GLIBLIB) +LRM_DIR = lrm +sbin_PROGRAMS = lrmadmin +sbin_SCRIPTS = cibsecret +lrmadmin_SOURCES = lrmadmin.c +lrmadmin_LDFLAGS = $(COMMONLIBS) +lrmadmin_LDADD = $(top_builddir)/lib/$(LRM_DIR)/liblrm.la +lrmadmin_DEPENDENCIES = $(top_builddir)/lib/$(LRM_DIR)/liblrm.la + +if BUILD_HELP +man8_MANS = $(sbin_PROGRAMS:%=%.8) +%.8: % + echo Creating $@ + chmod a+x $< + help2man --output $@ --no-info --section 8 --name "Part of the Linux-HA project" $(top_builddir)/lrm/admin/$< +endif diff --git a/lrm/admin/cibsecret.in b/lrm/admin/cibsecret.in new file mode 100755 index 0000000..5255cdd --- /dev/null +++ b/lrm/admin/cibsecret.in @@ -0,0 +1,350 @@ +#!/bin/sh + +# Copyright (C) 2011 Dejan Muhamedagic <dmuhamedagic@suse.de> +# +# 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.1 of the License, or (at your option) any later version. +# +# This software 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 library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# WARNING: +# +# The CIB secrets interface and implementation is still being +# discussed, it may change + +# +# cibsecret: manage the secrets directory /var/lib/heartbeat/lrm/secrets +# +# secrets are ascii files, holding just one value per file: +# /var/lib/heartbeat/lrm/secrets/<rsc>/<param> +# +# NB: this program depends on utillib.sh +# + +. @OCF_ROOT_DIR@/lib/heartbeat/ocf-shellfuncs + +HA_NOARCHBIN=@datadir@/@PACKAGE_NAME@ + +. $HA_NOARCHBIN/utillib.sh + +LRM_CIBSECRETS=$HA_VARLIB/lrm/secrets + +PROG=`basename $0` +SSH_OPTS="-o StrictHostKeyChecking=no" + +usage() { + cat<<EOF +usage: $PROG [-C] <command> <parameters> + +-C: don't read/write the CIB + +command: set | delete | stash | unstash | get | check | sync + + set <rsc> <param> <value> + get <rsc> <param> + check <rsc> <param> + stash <rsc> <param> (if not -C) + unstash <rsc> <param> (if not -C) + delete <rsc> <param> + sync + +stash/unstash: move the parameter from/to the CIB (if you already + have the parameter set in the CIB). + +set/delete: add/remove a parameter from the local file. + +get: display the parameter from the local file. + +check: verify MD5 hash of the parameter from the local file and the CIB. + +sync: copy $LRM_CIBSECRETS to other nodes. + +Examples: + + $PROG set ipmi_node1 passwd SecreT_PASS + $PROG stash ipmi_node1 passwd + $PROG get ipmi_node1 passwd + $PROG check ipmi_node1 passwd + $PROG sync +EOF + exit $1 +} +fatal() { + echo "ERROR: $*" + exit 1 +} +warn() { + echo "WARNING: $*" +} +info() { + echo "INFO: $*" +} + +check_env() { + which md5sum >/dev/null 2>&1 || + fatal "please install md5sum to run $PROG" + if which pssh >/dev/null 2>&1; then + rsh=pssh_fun + rcp=pscp_fun + elif which pdsh >/dev/null 2>&1; then + rsh=pdsh_fun + rcp=pdcp_fun + elif which ssh >/dev/null 2>&1; then + rsh=ssh_fun + rcp=scp_fun + else + fatal "please install pssh, pdsh, or ssh to run $PROG" + fi + ps -ef | grep '[c]rmd' >/dev/null || + fatal "pacemaker not running? $PROG needs pacemaker" +} + +get_other_nodes() { + crm_node -l | awk '{print $2}' | grep -v `uname -n` +} +check_down_nodes() { + local n down_nodes + down_nodes=`(for n; do echo $n; done) | sort | uniq -u` + if [ -n "$down_nodes" ]; then + if [ `echo $down_nodes | wc -w` = 1 ]; then + warn "node $down_nodes is down" + warn "you'll need to update it using $PROG sync later" + else + warn "nodes `echo $down_nodes` are down" + warn "you'll need to update them using $PROG sync later" + fi + fi +} + +pssh_fun() { + pssh -qi -H "$nodes" -x "$SSH_OPTS" $* +} +pscp_fun() { + pscp -q -H "$nodes" -x "-pr" -x "$SSH_OPTS" $* +} +pdsh_fun() { + local pdsh_nodes=`echo $nodes | tr ' ' ','` + export PDSH_SSH_ARGS_APPEND="$SSH_OPTS" + pdsh -w $pdsh_nodes $* +} +pdcp_fun() { + local pdsh_nodes=`echo $nodes | tr ' ' ','` + export PDSH_SSH_ARGS_APPEND="$SSH_OPTS" + pdcp -pr -w $pdsh_nodes $* +} +ssh_fun() { + local h + for h in $nodes; do + ssh $SSH_OPTS $h $* || return + done +} +scp_fun() { + local h src="$1" dest=$2 + for h in $nodes; do + scp -pr -q $SSH_OPTS $src $h:$dest || return + done +} +# TODO: this procedure should be replaced with csync2 +# provided that csync2 has already been configured +sync_files() { + local crm_nodes=`get_other_nodes` + local nodes=`get_live_nodes $crm_nodes` + check_down_nodes $nodes $crm_nodes + [ "$nodes" = "" ] && { + info "no other nodes live" + return + } + info "syncing $LRM_CIBSECRETS to `echo $nodes` ..." + $rsh rm -rf $LRM_CIBSECRETS && + $rsh mkdir -p `dirname $LRM_CIBSECRETS` && + $rcp $LRM_CIBSECRETS `dirname $LRM_CIBSECRETS` +} +sync_one() { + local f=$1 f_all="$1 $1.sign" + local crm_nodes=`get_other_nodes` + local nodes=`get_live_nodes $crm_nodes` + check_down_nodes $nodes $crm_nodes + [ "$nodes" = "" ] && { + info "no other nodes live" + return + } + info "syncing $f to `echo $nodes` ..." + $rsh mkdir -p `dirname $f` && + if [ -f "$f" ]; then + $rcp "$f_all" `dirname $f` + else + $rsh rm -f $f_all + fi +} + +is_secret() { + # assume that the secret is in the CIB if we cannot talk to + # cib + [ "$NO_CRM" ] || + test "$1" = "$MAGIC" +} +check_cib_rsc() { + local rsc=$1 output + output=`$NO_CRM crm_resource -r $rsc -W >/dev/null 2>&1` || + fatal "resource $rsc doesn't exist: $output" +} +get_cib_param() { + local rsc=$1 param=$2 + check_cib_rsc $rsc + $NO_CRM crm_resource -r $rsc -g $param 2>/dev/null +} +set_cib_param() { + local rsc=$1 param=$2 value=$3 + check_cib_rsc $rsc + $NO_CRM crm_resource -r $rsc -p $param -v "$value" 2>/dev/null +} +remove_cib_param() { + local rsc=$1 param=$2 + check_cib_rsc $rsc + $NO_CRM crm_resource -r $rsc -d $param 2>/dev/null +} + +localfiles() { + local cmd=$1 + local rsc=$2 param=$3 value=$4 + local local_file=$LRM_CIBSECRETS/$rsc/$param + case $cmd in + "get") + cat $local_file 2>/dev/null + true + ;; + "getsum") + cat $local_file.sign 2>/dev/null + true + ;; + "set") + local md5sum + md5sum=`printf $value | md5sum` || + fatal "md5sum failed to produce hash for resource $rsc parameter $param" + md5sum=`echo $md5sum | awk '{print $1}'` + mkdir -p `dirname $local_file` && + echo $value > $local_file && + echo $md5sum > $local_file.sign && + sync_one $local_file + ;; + "remove") + rm -f $local_file + sync_one $local_file + ;; + *) + # not reached, this is local interface + ;; + esac +} +get_local_param() { + local rsc=$1 param=$2 + localfiles get $rsc $param +} +set_local_param() { + local rsc=$1 param=$2 value=$3 + localfiles set $rsc $param $value +} +remove_local_param() { + local rsc=$1 param=$2 + localfiles remove $rsc $param +} + +cibsecret_set() { + local value=$1 + + if [ -z "$NO_CRM" ]; then + [ "$current" -a "$current" != "$MAGIC" -a "$current" != "$value" ] && + fatal "CIB value <$current> different for $rsc parameter $param; please delete it first" + fi + set_local_param $rsc $param $value && + set_cib_param $rsc $param "$MAGIC" +} + +cibsecret_check() { + local md5sum local_md5sum + is_secret "$current" || + fatal "resource $rsc parameter $param not set as secret, nothing to check" + local_md5sum=`localfiles getsum $rsc $param` + [ "$local_md5sum" ] || + fatal "no MD5 hash for resource $rsc parameter $param" + md5sum=`printf "$current_local" | md5sum | awk '{print $1}'` + [ "$md5sum" = "$local_md5sum" ] || + fatal "MD5 hash mismatch for resource $rsc parameter $param" +} + +cibsecret_get() { + cibsecret_check + echo "$current_local" +} + +cibsecret_delete() { + remove_local_param $rsc $param && + remove_cib_param $rsc $param +} + +cibsecret_stash() { + [ "$NO_CRM" ] && + fatal "no access to Pacemaker, stash not supported" + [ "$current" = "" ] && + fatal "nothing to stash for resource $rsc parameter $param" + is_secret "$current" && + fatal "resource $rsc parameter $param already set as secret, nothing to stash" + cibsecret_set "$current" +} + +cibsecret_unstash() { + [ "$NO_CRM" ] && + fatal "no access to Pacemaker, unstash not supported" + [ "$current_local" = "" ] && + fatal "nothing to unstash for resource $rsc parameter $param" + is_secret "$current" || + warn "resource $rsc parameter $param not set as secret, but we have local value so proceeding anyway" + remove_local_param $rsc $param && + set_cib_param $rsc $param $current_local +} + +cibsecret_sync() { + sync_files +} + +check_env + +MAGIC="lrm://" +umask 0077 + +if [ "$1" = "-C" ]; then + NO_CRM=':' + shift 1 +fi + +cmd=$1 +rsc=$2 +param=$3 +value=$4 + +case "$cmd" in + set) [ $# -ne 4 ] && usage 1;; + get) [ $# -ne 3 ] && usage 1;; + check) [ $# -ne 3 ] && usage 1;; + stash) [ $# -ne 3 ] && usage 1;; + unstash) [ $# -ne 3 ] && usage 1;; + delete) [ $# -ne 3 ] && usage 1;; + sync) [ $# -ne 1 ] && usage 1;; + *) usage 1; +esac + +# we'll need these two often +current=`get_cib_param $rsc $param` +current_local=`get_local_param $rsc $param` + +cibsecret_$cmd $value diff --git a/lrm/admin/lrmadmin.c b/lrm/admin/lrmadmin.c new file mode 100644 index 0000000..27f37bf --- /dev/null +++ b/lrm/admin/lrmadmin.c @@ -0,0 +1,1129 @@ +/* File: lrmadmin.c + * Description: A adminstration tool for Local Resource Manager + * + * Author: Sun Jiang Dong <sunjd@cn.ibm.com> + * Copyright (c) 2004 International Business Machines + * + * Todo: security verification + * + * 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.1 of the License, or (at your option) any later version. + * + * This software 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <lha_internal.h> + +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <time.h> +#ifndef __USE_GNU +#define __USE_GNU +/* For strnlen protype */ +#include <string.h> +#undef __USE_GNU +#else +#include <string.h> +#endif +#include <errno.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#endif /* HAVE_GETOPT_H */ +#include <clplumbing/cl_log.h> +#include <lrm/lrm_api.h> +#include <lrm/lrm_msg.h> +#include <lrm/raexec.h> +#include <clplumbing/lsb_exitcodes.h> +#include <clplumbing/GSource.h> +#include <clplumbing/Gmain_timeout.h> + +static const char *optstring = "A:D:X:dE:F:dg:p:M:O:P:c:S:LI:CT:n:hv"; + +#ifdef HAVE_GETOPT_H +static struct option long_options[] = { + {"daemon", 0, NULL, 'd'}, + {"executera", 1, NULL, 'E'}, + {"flush", 1, NULL, 'F'}, + {"state", 1, NULL, 'S'}, + {"listall", 0, NULL, 'L'}, + {"information", 1, NULL, 'I'}, + {"add", 1, NULL, 'A'}, + {"delete", 1, NULL, 'D'}, + {"fail", 1, NULL, 'X'}, + {"raclass_supported", 1, NULL, 'C'}, + {"ratype_supported", 1, NULL, 'T'}, + {"all_type_metadata", 1, NULL, 'O'}, + {"metadata", 1, NULL, 'M'}, + {"provider", 1, NULL, 'P'}, + {"set_lrmd_param", 1, NULL, 'p'}, + {"get_lrmd_param", 1, NULL, 'g'}, + {"help", 0, NULL, 'h'}, + {"version", 0, NULL, 'v'}, + {NULL, 0, NULL, 0} +}; +#endif /* HAVE_GETOPT_H */ + +static GMainLoop *mainloop; +static const char *lrmadmin_name = "lrmadmin"; +static const char *fake_name; +/* 20 is the length limit for a argv[x] */ +static const int ARGVI_MAX_LEN = 48; + +typedef enum { + ERROR_OPTION = -1, + NULL_OP, + DAEMON_OP, + EXECUTE_RA, + FLUSH, + RSC_STATE, + LIST_ALLRSC, + INF_RSC, + SET_PARAM, + GET_PARAM, + ADD_RSC, + DEL_RSC, + FAIL_RSC, + RACLASS_SUPPORTED, + RATYPE_SUPPORTED, + RA_METADATA, + RA_PROVIDER, + ALL_RA_METADATA, + HELP +} lrmadmin_cmd_t; + +#define nullcheck(p) ((p) ? (p) : "<null>") +static const char * status_msg[6] = { + "pending", /* LRM_OP_PENDING */ + "succeed", /* LRM_OP_DONE */ + "cancelled", /* LRM_OP_CANCELLED */ + "timeout", /* LRM_OP_TIMEOUT */ + "not Supported", /* LRM_OP_NOTSUPPORTED */ + "failed due to an error" /* LRM_OP_ERROR */ +}; + +static const char * rc_msg[] = { + "unknown error", + "no ra", + "ok", + "unknown error", + "invalid parameter", + "unimplement feature", + "insufficient priority", + "not installed", + "not configured", + "not running", + "running master", + "failed master", + "invalid rc", + /* For status command only */ + "daemon dead1", + "daemon dead2", + "daemon stopped", + "status unknow" +}; + + +static gboolean QUIT_GETOPT = FALSE; +static lrmadmin_cmd_t lrmadmin_cmd = NULL_OP; +static gboolean ASYN_OPS = FALSE; +static int call_id = 0; +static int TIMEOUT = -1; /* the unit is ms */ + +static const char *simple_help_screen = +"lrmadmin -d,--daemon\n" +" -A,--add <rscid> <raclass> <ratype> <provider|NULL> [<rsc_params_list>]\n" +" -D,--delete <rscid>\n" +" -F,--flush <rscid>\n" +" -X,--fail <rscid> [<fail_rc> [<fail_reason>]]\n" +" -E,--execute <rscid> <operator> <timeout> <interval> <target_rc|EVERYTIME|CHANGED> [<operator_parameters_list>]\n" +" -S,--state <rscid> [-n <fake_name>]\n" +" -L,--listall\n" +" -I,--information <rsc_id>\n" +" -C,--raclass_supported\n" +" -T,--ratype_supported <raclass>\n" +" -O,--all metadata of this class <raclass>\n" +" -M,--metadata <raclass> <ratype> <provider|NULL>\n" +" -P,--provider <raclass> <ratype>\n" +" -p,--set_lrmd_param <name> <value>\n" +" -g,--get_lrmd_param <name>\n" +" -v,--version\n" +" -h,--help\n"; + +#define OPTION_OBSCURE_CHECK \ + if ( lrmadmin_cmd != NULL_OP ) { \ + cl_log(LOG_ERR,"Obscure options."); \ + return -1; \ + } + +/* the begin of the internal used function list */ +static int resource_operation(ll_lrm_t * lrmd, char *rsc_id, + int argc, int optind, char * argv[]); +static int add_resource(ll_lrm_t * lrmd, char *rsc_id, + int argc, int optind, char * argv[]); +static int fail_resource(ll_lrm_t * lrmd, char *rsc_id, int optc, char *opts[]); +static int get_param(ll_lrm_t * lrmd, int argc, int optind, char * argv[]); +static int set_param(ll_lrm_t * lrmd, int argc, int optind, char * argv[]); +static int transfer_cmd_params(int amount, int start, char * argv[], + const char * class, GHashTable ** params_ht); +static void g_print_stringitem_and_free(gpointer data, gpointer user_data); +static void g_print_rainfo_item_and_free(gpointer data, gpointer user_data); +static void g_print_ops(gpointer data, gpointer user_data); +static void g_get_rsc_description(gpointer data, gpointer user_data); +static void g_print_meta(gpointer key, gpointer value, gpointer user_data); + +static void print_rsc_inf(lrm_rsc_t * lrmrsc); +static char * params_hashtable_to_str(const char * class, GHashTable * ht); +static void free_stritem_of_hashtable(gpointer key, gpointer value, + gpointer user_data); +static void ocf_params_hash_to_str(gpointer key, gpointer value, + gpointer user_data); +static void normal_params_hash_to_str(gpointer key, gpointer value, + gpointer user_data); +static lrm_rsc_t * get_lrm_rsc(ll_lrm_t * lrmd, char * rscid); + +static int ra_metadata(ll_lrm_t * lrmd, int argc, int optind, char * argv[]); +static int ra_provider(ll_lrm_t * lrmd, int argc, int optind, char * argv[]); +static gboolean lrmd_output_dispatch(IPC_Channel* notused, gpointer user_data); +static gboolean lrm_op_timeout(gpointer data); + +/* the end of the internal used function list */ + +static void lrm_op_done_callback(lrm_op_t* op); + +static int ret_value; +int main(int argc, char **argv) +{ + int option_char; + char rscid_arg_tmp[RID_LEN]; + ll_lrm_t* lrmd; + lrm_rsc_t * lrm_rsc; + GList *raclass_list = NULL, + *ratype_list = NULL, + *rscid_list; + GHashTable *all_meta = NULL; + char raclass[20]; + const char * login_name = lrmadmin_name; + + /* Prevent getopt_long to print error message on stderr itself */ + /*opterr = 0; */ + + if (argc == 1) { + printf("%s",simple_help_screen); + return 0; + } + + cl_log_set_entity(lrmadmin_name); + cl_log_enable_stderr(TRUE); + cl_log_set_facility(LOG_USER); + + memset(rscid_arg_tmp, '\0', RID_LEN); + memset(raclass, '\0', 20); + do { +#ifdef HAVE_GETOPT_H + option_char = getopt_long (argc, argv, optstring, + long_options, NULL); +#else + option_char = getopt (argc, argv, optstring); +#endif + + if (option_char == -1) { + break; + } + + switch (option_char) { + case 'd': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = DAEMON_OP; + QUIT_GETOPT = TRUE; + break; + + case 'A': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = ADD_RSC; + strncpy(rscid_arg_tmp, optarg, RID_LEN-1); + break; + + case 'D': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = DEL_RSC; + strncpy(rscid_arg_tmp, optarg, RID_LEN-1); + break; + + case 'X': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = FAIL_RSC; + strncpy(rscid_arg_tmp, optarg, RID_LEN-1); + break; + + case 'C': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = RACLASS_SUPPORTED; + break; + + case 'T': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = RATYPE_SUPPORTED; + if (optarg) { + strncpy(raclass, optarg, 19); + } + break; + + case 'O': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = ALL_RA_METADATA; + if (optarg) { + strncpy(raclass, optarg, 19); + } + break; + + case 'F': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = FLUSH; + strncpy(rscid_arg_tmp, optarg, RID_LEN-1); + break; + + case 'E': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = EXECUTE_RA; + strncpy(rscid_arg_tmp, optarg, RID_LEN-1); + break; + + case 'M': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = RA_METADATA; + break; + + case 'P': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = RA_PROVIDER; + break; + + case 'S': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = RSC_STATE; + strncpy(rscid_arg_tmp, optarg, RID_LEN-1); + break; + + case 'L': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = LIST_ALLRSC; + break; + + case 'I': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = INF_RSC; + strncpy(rscid_arg_tmp, optarg, RID_LEN-1); + break; + + case 'p': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = SET_PARAM; + break; + + case 'g': + OPTION_OBSCURE_CHECK + lrmadmin_cmd = GET_PARAM; + break; + + case 'n': + if (optarg) { + fake_name = optarg; + } + break; + + case 'v': + printf("%s\n",GLUE_VERSION); + return 0; + case 'h': + OPTION_OBSCURE_CHECK + printf("%s",simple_help_screen); + return 0; + + case '?': + /* cl_log(LOG_ERR,"There is a unrecognized + option %s", optarg); + */ + printf("%s", simple_help_screen); + return -1; + + default: + cl_log(LOG_ERR,"getopt returned character" + " code %c.", option_char); + return -1; + } + } while (!QUIT_GETOPT); + + lrmd = ll_lrm_new("lrm"); + + if (NULL == lrmd) { + cl_log(LOG_ERR,"ll_lrm_new returned NULL."); + return -2; + } + + lrmd->lrm_ops->set_lrm_callback(lrmd, lrm_op_done_callback); + + if (fake_name != NULL) { + login_name = fake_name; + } + if (lrmd->lrm_ops->signon(lrmd, login_name) != 1) { /* != HA_OK */ + printf("lrmd is not running.\n"); + if (lrmadmin_cmd == DAEMON_OP) { + return LSB_STATUS_STOPPED; + } else { + cl_log(LOG_WARNING,"Can't connect to lrmd!"); + return -2; + } + } + + if (lrmadmin_cmd == DAEMON_OP) { + printf("lrmd is stopped.\n"); + lrmd->lrm_ops->signoff(lrmd); + return 0; + } + + switch (lrmadmin_cmd) { + case EXECUTE_RA: + call_id = resource_operation(lrmd, rscid_arg_tmp, argc, optind, argv); + if (call_id < 0) { + if ( call_id == -2 ) { + cl_log(LOG_ERR, "Failed to operate " + "resource %s due to parameter error." + , argv[optind]); + ret_value = -3; + } + if ( call_id == -1 ) { + cl_log(LOG_WARNING, "Failed! No such " + "resource %s.", argv[optind]); + ret_value = -2; + } + else { + cl_log(LOG_ERR, "Failed to operate " + "resource %s due to unknown error." + , argv[optind]); + ret_value = -3; + } + ASYN_OPS = FALSE; + } else { + /* Return value: HA_OK = 1 Or HA_FAIL = 0 */ + if ( call_id == 0 ) { + cl_log(LOG_ERR, "Resource operation " + "failed." ); + ret_value = -3; + ASYN_OPS = FALSE; + } else { + ASYN_OPS = TRUE; + } + } + break; + + case RA_METADATA: + ra_metadata(lrmd, argc, optind, argv); + ASYN_OPS = FALSE; + break; + case RA_PROVIDER: + ra_provider(lrmd, argc, optind, argv); + ASYN_OPS = FALSE; + break; + + case SET_PARAM: + set_param(lrmd, argc, optind, argv); + ASYN_OPS = FALSE; + break; + + case GET_PARAM: + get_param(lrmd, argc, optind, argv); + ASYN_OPS = FALSE; + break; + + case ADD_RSC: + if (add_resource(lrmd, rscid_arg_tmp, argc, optind, argv) == 0) { + printf("Succeeded in adding this resource.\n"); + } else { + printf("Failed to add this resource.\n"); + ret_value = -3; + } + ASYN_OPS = FALSE; + break; + + case DEL_RSC: + /* Return value: HA_OK = 1 Or HA_FAIL = 0 */ + if (lrmd->lrm_ops->delete_rsc(lrmd, rscid_arg_tmp)==1) { + printf("Succeeded in deleting this resource.\n"); + } else { + printf("Failed to delete this resource.\n"); + ret_value = -3; + } + ASYN_OPS = FALSE; + break; + + case FAIL_RSC: + /* Return value: HA_OK = 1 Or HA_FAIL = 0 */ + if (fail_resource(lrmd, rscid_arg_tmp, + argc-optind, argv+optind) == 1) + { + printf("Succeeded in failing the resource.\n"); + } else { + printf("Failed to fail the resource.\n"); + ret_value = -3; + } + ASYN_OPS = FALSE; + break; + + case FLUSH: + lrm_rsc = get_lrm_rsc(lrmd, rscid_arg_tmp); + if (!(lrm_rsc)) { + ret_value = -3; + } else { + /* Return value: HA_OK = 1 Or HA_FAIL = 0 */ + if (lrm_rsc->ops->flush_ops(lrm_rsc) == 1 ) { + printf("Succeeded in flushing.\n"); + } else { + printf("Failed to flush.\n"); + ret_value = -3; + } + lrm_free_rsc(lrm_rsc); + } + + ASYN_OPS = FALSE; + break; + + case RACLASS_SUPPORTED: + raclass_list = lrmd->lrm_ops-> + get_rsc_class_supported(lrmd); + printf("There are %d RA classes supported:\n", + g_list_length(raclass_list)); + if (raclass_list) { + g_list_foreach(raclass_list, g_print_stringitem_and_free, + NULL); + g_list_free(raclass_list); + ret_value = LSB_EXIT_OK; + } else { + printf("No RA classes found!\n"); + ret_value = -3; + } + + ASYN_OPS = FALSE; + break; + + case RATYPE_SUPPORTED: + ratype_list = lrmd->lrm_ops-> + get_rsc_type_supported(lrmd, raclass); + printf("There are %d RAs:\n", g_list_length(ratype_list)); + if (ratype_list) { + g_list_foreach(ratype_list, g_print_rainfo_item_and_free, + NULL); + g_list_free(ratype_list); + } + + ASYN_OPS = FALSE; + break; + case ALL_RA_METADATA: + all_meta = lrmd->lrm_ops->get_all_type_metadata(lrmd, raclass); + if (all_meta) { + g_hash_table_foreach(all_meta, g_print_meta, NULL); + g_hash_table_destroy(all_meta); + } + ASYN_OPS = FALSE; + break; + case LIST_ALLRSC: + rscid_list = lrmd->lrm_ops->get_all_rscs(lrmd); + if (rscid_list) { + g_list_foreach(rscid_list, g_get_rsc_description + , lrmd); + g_list_free(rscid_list); + } else + printf("Currently no resources are managed by " + "LRM.\n"); + + ASYN_OPS = FALSE; + break; + + case INF_RSC: + lrm_rsc = get_lrm_rsc(lrmd, rscid_arg_tmp); + if (!(lrm_rsc)) { + ret_value = -3; + } else { + print_rsc_inf(lrm_rsc); + lrm_free_rsc(lrm_rsc); + } + + ASYN_OPS = FALSE; + break; + + case RSC_STATE: + lrm_rsc = get_lrm_rsc(lrmd, rscid_arg_tmp); + if (!(lrm_rsc)) { + ret_value = -3; + } else { + state_flag_t cur_state = LRM_RSC_IDLE; + GList * ops_queue; + ops_queue = lrm_rsc->ops->get_cur_state(lrm_rsc, + &cur_state); + printf("resource state:%s\n", + cur_state==LRM_RSC_IDLE? + "LRM_RSC_IDLE":"LRM_RSC_BUSY"); + + printf("The resource %d operations' " + "information:\n" + , g_list_length(ops_queue)); + if (ops_queue) { + g_list_foreach(ops_queue, + g_print_ops, + NULL); + lrm_free_op_list(ops_queue); + } + lrm_free_rsc(lrm_rsc); + } + + ASYN_OPS = FALSE; + break; + + + default: + fprintf(stderr, "Option %c is not supported yet.\n", + option_char); + ret_value = -1; + ASYN_OPS = FALSE; + break; + } + + if (ASYN_OPS) { + G_main_add_IPC_Channel(G_PRIORITY_LOW, lrmd->lrm_ops->ipcchan(lrmd), + FALSE, lrmd_output_dispatch, lrmd, NULL); + if (TIMEOUT > 0) { + Gmain_timeout_add(TIMEOUT, lrm_op_timeout, &ret_value); + } + + mainloop = g_main_new(FALSE); + printf( "Waiting for lrmd to callback...\n"); + g_main_run(mainloop); + } + + lrmd->lrm_ops->signoff(lrmd); + return ret_value; +} + +static gboolean +lrm_op_timeout(gpointer data) +{ + int * idata = data; + + printf("ERROR: This operation has timed out - no result from lrmd.\n"); + + *idata = -5; + g_main_quit(mainloop); + return FALSE; +} + +static gboolean +lrmd_output_dispatch(IPC_Channel* notused, gpointer user_data) +{ + ll_lrm_t *lrm = (ll_lrm_t*)user_data; + lrm->lrm_ops->rcvmsg(lrm, FALSE); + + g_main_quit(mainloop); + return TRUE; +} + +static void +lrm_op_done_callback(lrm_op_t* op) +{ + if (!op) { + cl_log(LOG_ERR, "In callback function, op is NULL pointer."); + ret_value = -3; + return; + } + + printf("----------------operation--------------\n"); + printf("type:%s\n", op->op_type); + if ( (0 == STRNCMP_CONST(op->op_type, "status") + || 0 == STRNCMP_CONST(op->op_type, "monitor")) && (op->rc == 7) ) { + printf("operation status:%s\n", status_msg[LRM_OP_DONE-LRM_OP_PENDING]); + printf("op_status: %d\n", LRM_OP_DONE); + } else { + printf("operation status:%s\n", status_msg[(op->op_status + - LRM_OP_PENDING) % DIMOF(status_msg)]); + printf("op_status: %d\n", op->op_status); + } + printf("return code: %d\n", op->rc); + printf("output data: \n%s\n", (op->output ? op->output : "[null]")); + printf("---------------------------------------\n\n"); + ret_value = op->rc; +} + +static int +resource_operation(ll_lrm_t * lrmd, char *rsc_id, int argc, int optind, char * argv[]) +{ + GHashTable * params_ht = NULL; + lrm_op_t op = lrm_zero_op; + lrm_rsc_t * lrm_rsc; + int call_id; + + if ((argc - optind) < 3) { + cl_log(LOG_ERR,"Not enough parameters."); + return -2; + } + + lrm_rsc = lrmd->lrm_ops->get_rsc(lrmd, rsc_id); + if (!lrm_rsc) { + return -1; + } + + op.op_type = argv[optind]; + op.timeout = atoi(argv[optind+1]); + + /* When op.timeout!=0, plus additional 1s. Or lrmadmin may time out before + the normal operation result returned from lrmd. This may be redudant, + but harmless. */ + if (0 < op.timeout ) { + TIMEOUT = op.timeout + 1000; + } + op.interval = atoi(argv[optind+2]); + op.user_data = NULL; + op.user_data_len = 0; + if (0 == strcmp(argv[optind+3], "EVERYTIME")) { + op.target_rc = EVERYTIME; + } + else + if (0 == strcmp(argv[optind+3], "CHANGED")) { + op.target_rc = CHANGED; + } + else { + op.target_rc = atoi(argv[optind+3]); + } + + if ((argc - optind) > 3) { + if (0 > transfer_cmd_params(argc, optind+4, argv, + lrm_rsc->class, ¶ms_ht) ) { + return -2; + } + } + op.params = params_ht; + + call_id = lrm_rsc->ops->perform_op(lrm_rsc, &op); + lrm_free_rsc(lrm_rsc); + if (params_ht) { + g_hash_table_foreach(params_ht, free_stritem_of_hashtable, NULL); + g_hash_table_destroy(params_ht); + } + return call_id; +} +static int +ra_metadata(ll_lrm_t * lrmd, int argc, int optind, char * argv[]) +{ + const char * class = argv[optind-1]; + const char * type = argv[optind]; + const char * provider = argv[optind+1]; + char* metadata; + + if(argc < 5) { + cl_log(LOG_ERR,"Not enough parameters."); + return -2; + } + + if (0 == strncmp(provider,"NULL",strlen("NULL"))) { + provider=NULL; + } + + metadata = lrmd->lrm_ops->get_rsc_type_metadata(lrmd, class, type, provider); + if (NULL!=metadata) { + printf ("%s\n", metadata); + g_free (metadata); + } + return 0; +} + +static int +ra_provider(ll_lrm_t * lrmd, int argc, int optind, char * argv[]) +{ + const char * class = argv[optind-1]; + const char * type = argv[optind]; + GList* providers = NULL; + GList* provider = NULL; + + if(argc < 4) { + cl_log(LOG_ERR,"Not enough parameters."); + return -2; + } + + providers = lrmd->lrm_ops->get_rsc_provider_supported(lrmd,class,type); + + while (NULL != (provider = g_list_first(providers))) { + printf("%s\n",(char*)provider->data); + g_free(provider->data); + providers = g_list_remove(providers, provider->data); + } + g_list_free(providers); + return 0; +} + +static int +add_resource(ll_lrm_t * lrmd, char *rsc_id, int argc, int optind, char * argv[]) +{ + const char * class = argv[optind]; + const char * type = argv[optind+1]; + const char * provider = argv[optind+2]; + GHashTable * params_ht = NULL; + int tmp_ret; + + if ((argc - optind) < 3) { + cl_log(LOG_ERR,"Not enough parameters."); + return -2; + } + + if (0 == strncmp(provider, "NULL", strlen("NULL"))) { + provider=NULL; + } + + /* delete Hashtable */ + if ((argc - optind) > 3) { + if ( 0 > transfer_cmd_params(argc, optind+3, argv, class, + ¶ms_ht) ) { + return -1; + } + } + + tmp_ret = lrmd->lrm_ops->add_rsc(lrmd, rsc_id, class, + type, provider, params_ht); + + /*delete params_ht*/ + if (params_ht) { + g_hash_table_foreach(params_ht, free_stritem_of_hashtable, NULL); + g_hash_table_destroy(params_ht); + } + + return (tmp_ret ? 0 : -1); /* tmp_ret is HA_OK=1 or HA_FAIL=0 */ +} + +static int +fail_resource(ll_lrm_t * lrmd, char *rsc_id, int optc, char *opts[]) +{ + int fail_rc = 0; + const char * reason = NULL; + + if (optc > 2) { + cl_log(LOG_ERR,"Bad usage."); + return -2; + } + + if (optc >= 1) + fail_rc = atoi(opts[0]); + if (optc == 2) + reason = opts[1]; + + return lrmd->lrm_ops->fail_rsc(lrmd, rsc_id, fail_rc, reason); +} + +static int +get_param(ll_lrm_t * lrmd, int argc, int optind, char * argv[]) +{ + const char *name = argv[optind-1]; + char *value; + + if ((argc - optind) != 0) { + cl_log(LOG_ERR,"Bad usage."); + return -2; + } + value = lrmd->lrm_ops->get_lrmd_param(lrmd, name); + printf("%s: %s\n", name, value); + return 0; +} + +static int +set_param(ll_lrm_t * lrmd, int argc, int optind, char * argv[]) +{ + const char *name = argv[optind-1]; + const char *value = argv[optind]; + + if ((argc - optind) != 1) { + cl_log(LOG_ERR,"Bad usage."); + return -2; + } + return lrmd->lrm_ops->set_lrmd_param(lrmd, name, value); +} + +static int +transfer_cmd_params(int amount, int start, char * argv[], const char * class, +GHashTable ** params_ht) +{ + int i, len_tmp; + char * delimit, * key, * value; + char buffer[21]; + + if (amount < start) { + return -1; + } + + if ( strncmp("ocf", class, strlen("ocf"))==0 + || strncmp("stonith", class, strlen("stonith"))==0) { + *params_ht = g_hash_table_new(g_str_hash, g_str_equal); + + for (i=start; i<amount; i++) { + delimit = strchr(argv[i], '='); + if (!delimit) { + cl_log(LOG_ERR, "Parameter %s is invalid for " + "the OCF standard.", argv[i]); + goto error_return; /* Have to */ + } + + len_tmp = strnlen(delimit+1, MAX_PARAM_LEN) + 1; + value = g_new(gchar, len_tmp); + strncpy(value, delimit+1, len_tmp); + + len_tmp = strnlen(argv[i], MAX_PARAM_LEN) - strnlen(delimit, MAX_PARAM_LEN); + key = g_new(gchar, len_tmp+1); + key[len_tmp] = '\0'; + strncpy(key, argv[i], len_tmp); + + g_hash_table_insert(*params_ht, key, value); + } + } else if ( strncmp("lsb", class, strlen("lsb")) == 0 + || strncmp("heartbeat", class, strlen("heartbeat")) == 0 ) { + + /* Pay attention: for parameter ordring issue */ + *params_ht = g_hash_table_new(g_str_hash, g_str_equal); + + memset(buffer, '0', 21); + for (i=start; i<amount; i++) { + snprintf(buffer, 20, "%d", i-start+1); + g_hash_table_insert( *params_ht, g_strdup(buffer), + g_strdup(argv[i])); + /* printf("index: %d value: %s \n", i-start+1, argv[i]); */ + } + } else { + fprintf(stderr, "Not supported resource agent class.\n"); + return -1; + } + + return 0; + +error_return: + if (*params_ht) { + g_hash_table_foreach(*params_ht, free_stritem_of_hashtable, NULL); + g_hash_table_destroy(*params_ht); + *params_ht = NULL; + } + return -1; +} + +static char * +params_hashtable_to_str(const char * class, GHashTable * ht) +{ + int i,ht_size; + gchar * params_str = NULL; + GString * gstr_tmp; + gchar * tmp_str; + + if (!ht) { + return NULL; + } + + if ( strncmp("ocf", class, strlen("ocf")) == 0 + || strncmp("stonith", class, strlen("stonith")) == 0) { + gstr_tmp = g_string_new(""); + g_hash_table_foreach(ht, ocf_params_hash_to_str, &gstr_tmp); + params_str = g_new(gchar, gstr_tmp->len+1); + strncpy(params_str, gstr_tmp->str, gstr_tmp->len+1); + g_string_free(gstr_tmp, TRUE); + } else if ( strncmp("lsb", class, strlen("lsb")) == 0 + || strncmp("heartbeat", class, strlen("heartbeat")) == 0 ) { + ht_size = g_hash_table_size(ht); + if (ht_size == 0) { + return NULL; + } + tmp_str = g_new(gchar, ht_size*ARGVI_MAX_LEN); + memset(tmp_str, ' ', ht_size*ARGVI_MAX_LEN); + tmp_str[ht_size*ARGVI_MAX_LEN-1] = '\0'; + g_hash_table_foreach(ht, normal_params_hash_to_str, &tmp_str); + gstr_tmp = g_string_new(""); + for (i=0; i< ht_size; i++) { + gstr_tmp = g_string_append(gstr_tmp + , tmp_str + i*ARGVI_MAX_LEN ); + gstr_tmp = g_string_append(gstr_tmp, " "); + } + params_str = g_new(gchar, gstr_tmp->len+1); + strncpy(params_str, gstr_tmp->str, gstr_tmp->len+1); + g_string_free(gstr_tmp, TRUE); + } else { + fprintf(stderr, "Not supported resource agent class.\n"); + } + + return params_str; +} + +static void +g_print_stringitem_and_free(gpointer data, gpointer user_data) +{ + printf("%s\n", (char*)data); + g_free(data); +} + +static void +g_print_rainfo_item_and_free(gpointer data, gpointer user_data) +{ + printf("%s\n", (char *)data); + g_free(data); +} + + +static void +g_print_ops(gpointer data, gpointer user_data) +{ + lrm_op_t* op = (lrm_op_t*)data; + GString * param_gstr; + time_t run_at=0, rcchange_at=0; + + if (NULL == op) { + cl_log(LOG_ERR, "%s:%d: op==NULL" + , __FUNCTION__, __LINE__); + return; + } + + param_gstr = g_string_new(""); + g_hash_table_foreach(op->params, ocf_params_hash_to_str, ¶m_gstr); + + if( op->t_run ) + run_at=(time_t)op->t_run; + if( op->t_rcchange ) + rcchange_at=(time_t)op->t_rcchange; + printf(" operation '%s' [call_id=%d]:\n" + " start_delay=%d, interval=%d, timeout=%d, app_name=%s\n" + " rc=%d (%s), op_status=%d (%s)\n" + , nullcheck(op->op_type), op->call_id + , op->start_delay, op->interval, op->timeout + , nullcheck(op->app_name), op->rc + , rc_msg[(op->rc-EXECRA_EXEC_UNKNOWN_ERROR) % DIMOF(rc_msg)] + , op->op_status + , status_msg[(op->op_status-LRM_OP_PENDING) % DIMOF(status_msg)] + ); + if( op->t_run || op->t_rcchange ) + printf(" run at: %s" + " last rc change at: %s" + " queue time: %lums, exec time: %lums\n" + , op->t_run ? ctime(&run_at) : "N/A\n" + , op->t_rcchange ? ctime(&rcchange_at) : "N/A\n" + , op->queue_time, op->exec_time + ); + printf(" parameters: %s\n", param_gstr->str); + g_string_free(param_gstr, TRUE); +} + +static void +g_get_rsc_description(gpointer data, gpointer user_data) +{ + ll_lrm_t* lrmd = (ll_lrm_t *)user_data; + lrm_rsc_t * lrm_rsc; + char rsc_id_tmp[RID_LEN]; + + if (!(user_data)) { + return; + } + + memset(rsc_id_tmp, '\0', RID_LEN); + strncpy(rsc_id_tmp, data, RID_LEN-1); + + lrm_rsc = lrmd->lrm_ops->get_rsc(lrmd, rsc_id_tmp); + if (lrm_rsc) { + print_rsc_inf(lrm_rsc); + lrm_free_rsc(lrm_rsc); + } else + cl_log(LOG_ERR, "Invalid resource id: %s.", + rsc_id_tmp); + + g_free(data); +} +static void +g_print_meta(gpointer key, gpointer value, gpointer user_data) +{ + printf("%s\n", (const char*)key); + printf("%s\n", (const char*)value); +} +static void +print_rsc_inf(lrm_rsc_t * lrm_rsc) +{ + char rscid_str_tmp[RID_LEN]; + char * tmp = NULL; + + if (!lrm_rsc) { + return; + } + + rscid_str_tmp[RID_LEN-1] = '\0'; + strncpy(rscid_str_tmp, lrm_rsc->id, RID_LEN-1); + printf("\nResource ID:%s\n", rscid_str_tmp); + printf("Resource agent class:%s\n", lrm_rsc->class); + printf("Resource agent type:%s\n", lrm_rsc->type); + printf("Resource agent provider:%s\n" + , lrm_rsc->provider?lrm_rsc->provider:"default"); + + if (lrm_rsc->params) { + tmp = params_hashtable_to_str(lrm_rsc->class, + lrm_rsc->params); + printf("Resource agent parameters:%s\n" + , (tmp == NULL) ? "No parameter" : tmp); + if (tmp != NULL) { + g_free(tmp); + } + } +} + +static void +free_stritem_of_hashtable(gpointer key, gpointer value, gpointer user_data) +{ + /*printf("key=%s value=%s\n", (char *)key, (char *)value);*/ + g_free(key); + g_free(value); +} + +static void +ocf_params_hash_to_str(gpointer key, gpointer value, gpointer user_data) +{ + GString * gstr_tmp = *(GString **)user_data; + gstr_tmp = g_string_append(gstr_tmp, (char*)key); + gstr_tmp = g_string_append(gstr_tmp, "="); + gstr_tmp = g_string_append(gstr_tmp, (char *)value); + gstr_tmp = g_string_append(gstr_tmp, " "); +} + +static void +normal_params_hash_to_str(gpointer key, gpointer value, gpointer user_data) +{ + gint key_int; + + gchar * str_tmp = *(gchar **) user_data; + if (str_tmp == NULL ) { + return; + } + + key_int = atoi((char *)key) - 1; + if( key_int < 0 ) { + return; + } + strncpy(str_tmp + key_int * ARGVI_MAX_LEN, (char*)value, + ARGVI_MAX_LEN - 1); +} + +static lrm_rsc_t * +get_lrm_rsc(ll_lrm_t * lrmd, char * rscid) +{ + char uuid_str_tmp[RID_LEN]; + lrm_rsc_t * lrm_rsc; + lrm_rsc = lrmd->lrm_ops->get_rsc(lrmd, rscid); + if (!(lrm_rsc)) { + uuid_str_tmp[RID_LEN-1] = '\0'; + strncpy(uuid_str_tmp, rscid, RID_LEN-1); + cl_log(LOG_ERR,"Resource %s does not exist.", uuid_str_tmp); + } + return lrm_rsc; +} + diff --git a/lrm/admin/lrmadmin.txt b/lrm/admin/lrmadmin.txt new file mode 100644 index 0000000..739aa70 --- /dev/null +++ b/lrm/admin/lrmadmin.txt @@ -0,0 +1,60 @@ +# LRM Admin Command-line Interface +# It's a draft +NAME + lrmadmin - Local Resource Manager Commander-line Daministrator Tools + +SYNOPSIS +lrmadmin {-d|--daemon} + {-A|--add} <rscid> <rsc_class> <rsc_type> [<rsc_params_list>] + {-D|--delete} <rscid> + {-F|--flush} <rscid> + {-E|--execute} <rscid> <operator> <timeout> [<operator_parameters_list>] + {-M|--monitor} -s <rscid> <operator> <timeout> <interval> + [<operator_parameters_list>] + {-M|--monitor} {-g|-c} <rscid> + {-S|--status} <rscid> + {-L|--listall} + {-I|--information} <rsc_id> + {-R|--rasupported} + {-h|--help} + +Detailed Explanation for Options + +Lrmd daemon options + {-d|--daemon} +# -s The status of lrmd: running or not running +# -r Reset lrmd (?) + +Resource options + {-A|--add} <rscid> <rsc_class> <rsc_type> [<rsc_params_list>] + Add a resource. + + {-D|--delete} <rscid> + Delete a resource + + {-E|--execute} <rscid> <operator> <timeout> [<operator_parameters_list>] + Let resource agent to performance the operation + + {-F|--flush} <rscid> + Clear all pending operation on the resource agnency + + {-M|--monitor} {-s|-g} <rscid> <interval> + -s rscname Set a monitors on the resource agent + -g Get the information about the monitors on the + resource agent + + {-S|--status} <rscid> + Get the status of current resource agent + + {-L|--listall} + List all available resource agent + + {-I|--information} <rsc_id> + List the information about a resource + + {-R|--rasupported} + List the support types of resource agent such as OCF and etc. + +Other options + {-h|--help} + Display the help screen |