~ampelbein/ubuntu/oneiric/heartbeat/lp-770743

« back to all changes in this revision

Viewing changes to lib/plugins/lrm/raexechb.c

  • Committer: Bazaar Package Importer
  • Author(s): Ante Karamatic
  • Date: 2010-02-17 21:59:18 UTC
  • mfrom: (1.1.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20100217215918-06paxph5do4saw8v
Tags: 3.0.2-0ubuntu1
* New upstream release
* Drop hard dep on pacemaker for heartbet; moved to Recommends
* debian/heartbeat.install:
  - follow upstream changes
* debian/control:
  - added docbook-xsl and xsltproc to build depends

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
 * This program is free software; you can redistribute it and/or
3
 
 * modify it under the terms of the GNU General Public
4
 
 * License as published by the Free Software Foundation; either
5
 
 * version 2.1 of the License, or (at your option) any later version.
6
 
 * 
7
 
 * This software is distributed in the hope that it will be useful,
8
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10
 
 * General Public License for more details.
11
 
 * 
12
 
 * You should have received a copy of the GNU General Public
13
 
 * License along with this library; if not, write to the Free Software
14
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15
 
 *
16
 
 * File: raexechb.c
17
 
 * Author: Sun Jiang Dong <sunjd@cn.ibm.com>
18
 
 * Copyright (c) 2004 International Business Machines
19
 
 *
20
 
 * This code implements the Resource Agent Plugin Module for LSB style.
21
 
 * It's a part of Local Resource Manager. Currently it's used by lrmd only.
22
 
 */
23
 
 
24
 
#include <lha_internal.h>
25
 
#include <stdio.h>
26
 
#include <string.h>
27
 
#include <unistd.h>
28
 
#include <stdlib.h>
29
 
#include <sys/types.h>
30
 
#include <sys/wait.h>
31
 
#include <sys/stat.h>
32
 
#include <errno.h>
33
 
#include <dirent.h>
34
 
#include <libgen.h>
35
 
#include <glib.h>
36
 
#include <clplumbing/cl_log.h>
37
 
#include <pils/plugin.h>
38
 
#include <lrm/raexec.h>
39
 
 
40
 
#define PIL_PLUGINTYPE          RA_EXEC_TYPE
41
 
#define PIL_PLUGIN              heartbeat
42
 
#define PIL_PLUGINTYPE_S        "RAExec"
43
 
#define PIL_PLUGIN_S            "heartbeat"
44
 
#define PIL_PLUGINLICENSE       LICENSE_PUBDOM
45
 
#define PIL_PLUGINLICENSEURL    URL_PUBDOM
46
 
 
47
 
static const char * RA_PATH = HB_RA_DIR;
48
 
 
49
 
static const char meta_data_template[] =
50
 
"<?xml version=\"1.0\"?>\n"
51
 
"<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n"
52
 
"<resource-agent name=\"%s\">\n"
53
 
"<version>1.0</version>\n"
54
 
"<longdesc lang=\"en\">\n"
55
 
"%s"
56
 
"</longdesc>\n"
57
 
"<shortdesc lang=\"en\">%s</shortdesc>\n"
58
 
"<parameters>\n"
59
 
"<parameter name=\"1\" unique=\"1\" required=\"0\">\n"
60
 
"<longdesc lang=\"en\">\n"
61
 
"This argument will be passed as the first argument to the "
62
 
"heartbeat resource agent (assuming it supports one)\n"
63
 
"</longdesc>\n"
64
 
"<shortdesc lang=\"en\">argv[1]</shortdesc>\n"
65
 
"<content type=\"string\" default=\" \" />\n"
66
 
"</parameter>\n"
67
 
"<parameter name=\"2\" unique=\"1\" required=\"0\">\n"
68
 
"<longdesc lang=\"en\">\n"
69
 
"This argument will be passed as the second argument to the "
70
 
"heartbeat resource agent (assuming it supports one)\n"
71
 
"</longdesc>\n"
72
 
"<shortdesc lang=\"en\">argv[2]</shortdesc>\n"
73
 
"<content type=\"string\" default=\" \" />\n"
74
 
"</parameter>\n"
75
 
"<parameter name=\"3\" unique=\"1\" required=\"0\">\n"
76
 
"<longdesc lang=\"en\">\n"
77
 
"This argument will be passed as the third argument to the "
78
 
"heartbeat resource agent (assuming it supports one)\n"
79
 
"</longdesc>\n"
80
 
"<shortdesc lang=\"en\">argv[3]</shortdesc>\n"
81
 
"<content type=\"string\" default=\" \" />\n"
82
 
"</parameter>\n"
83
 
"<parameter name=\"4\" unique=\"1\" required=\"0\">\n"
84
 
"<longdesc lang=\"en\">\n"
85
 
"This argument will be passed as the fourth argument to the "
86
 
"heartbeat resource agent (assuming it supports one)\n"
87
 
"</longdesc>\n"
88
 
"<shortdesc lang=\"en\">argv[4]</shortdesc>\n"
89
 
"<content type=\"string\" default=\" \" />\n"
90
 
"</parameter>\n"
91
 
"<parameter name=\"5\" unique=\"1\" required=\"0\">\n"
92
 
"<longdesc lang=\"en\">\n"
93
 
"This argument will be passed as the fifth argument to the "
94
 
"heartbeat resource agent (assuming it supports one)\n"
95
 
"</longdesc>\n"
96
 
"<shortdesc lang=\"en\">argv[5]</shortdesc>\n"
97
 
"<content type=\"string\" default=\" \" />\n"
98
 
"</parameter>\n"
99
 
"</parameters>\n"
100
 
"<actions>\n"
101
 
"<action name=\"start\"   timeout=\"15\" />\n"
102
 
"<action name=\"stop\"    timeout=\"15\" />\n"
103
 
"<action name=\"status\"  timeout=\"15\" />\n"
104
 
"<action name=\"monitor\" timeout=\"15\" interval=\"15\" start-delay=\"15\" />\n"
105
 
"<action name=\"meta-data\"  timeout=\"5\" />\n"
106
 
"</actions>\n"
107
 
"<special tag=\"heartbeart\">\n"
108
 
"</special>\n"
109
 
"</resource-agent>\n";
110
 
 
111
 
/* The begin of exported function list */
112
 
static int execra(const char * rsc_id,
113
 
                  const char * rsc_type,
114
 
                  const char * provider,
115
 
                  const char * op_type,
116
 
                  const int    timeout,
117
 
                  GHashTable * params);
118
 
 
119
 
static uniform_ret_execra_t map_ra_retvalue(int ret_execra
120
 
        , const char * op_type, const char * std_output);
121
 
static int get_resource_list(GList ** rsc_info);
122
 
static char* get_resource_meta(const char* rsc_type,  const char* provider);
123
 
static int get_provider_list(const char* ra_type, GList ** providers);
124
 
 
125
 
/* The end of exported function list */
126
 
 
127
 
/* The begin of internal used function & data list */
128
 
#define HADEBUGVAL      "HA_debug"
129
 
#define MAX_PARAMETER_NUM 40
130
 
typedef char * RA_ARGV[MAX_PARAMETER_NUM];
131
 
 
132
 
static const int MAX_LENGTH_OF_RSCNAME = 40,
133
 
                 MAX_LENGTH_OF_OPNAME = 40;
134
 
 
135
 
static int prepare_cmd_parameters(const char * rsc_type, const char * op_type,
136
 
                GHashTable * params, RA_ARGV params_argv);
137
 
/* The end of internal function & data list */
138
 
 
139
 
/* Rource agent execution plugin operations */
140
 
static struct RAExecOps raops =
141
 
{       execra,
142
 
        map_ra_retvalue,
143
 
        get_resource_list,
144
 
        get_provider_list,
145
 
        get_resource_meta
146
 
};
147
 
 
148
 
PIL_PLUGIN_BOILERPLATE2("1.0", Debug)
149
 
 
150
 
static const PILPluginImports*  PluginImports;
151
 
static PILPlugin*               OurPlugin;
152
 
static PILInterface*            OurInterface;
153
 
static void*                    OurImports;
154
 
static void*                    interfprivate;
155
 
static int                      idebuglevel = 0;
156
 
 
157
 
/*
158
 
 * Our plugin initialization and registration function
159
 
 * It gets called when the plugin gets loaded.
160
 
 */
161
 
PIL_rc
162
 
PIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports* imports);
163
 
 
164
 
PIL_rc
165
 
PIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports* imports)
166
 
{
167
 
        /* Force the compiler to do a little type checking */
168
 
        (void)(PILPluginInitFun)PIL_PLUGIN_INIT;
169
 
 
170
 
        PluginImports = imports;
171
 
        OurPlugin = us;
172
 
 
173
 
        /* Register ourself as a plugin */
174
 
        imports->register_plugin(us, &OurPIExports);  
175
 
 
176
 
        if (getenv(HADEBUGVAL) != NULL && atoi(getenv(HADEBUGVAL)) > 0 ) {
177
 
                idebuglevel = atoi(getenv(HADEBUGVAL));
178
 
                cl_log(LOG_DEBUG, "LRM debug level set to %d", idebuglevel);
179
 
        }
180
 
 
181
 
        /*  Register our interfaces */
182
 
        return imports->register_interface(us, PIL_PLUGINTYPE_S,  PIL_PLUGIN_S,
183
 
                &raops, NULL, &OurInterface, &OurImports,
184
 
                interfprivate); 
185
 
}
186
 
 
187
 
/*
188
 
 *      Real work starts here ;-)
189
 
 */
190
 
 
191
 
static int 
192
 
execra( const char * rsc_id, const char * rsc_type, const char * provider,
193
 
        const char * op_type, const int timeout, GHashTable * params)
194
 
{
195
 
        RA_ARGV params_argv;
196
 
        char ra_pathname[RA_MAX_NAME_LENGTH];
197
 
        uniform_ret_execra_t exit_value;
198
 
        GString * debug_info;
199
 
        char * optype_tmp = NULL;
200
 
        int index_tmp = 0;
201
 
 
202
 
        /* How to generate the meta-data? There is nearly no value
203
 
         * information in meta-data build up in current way. 
204
 
         * Should directly add meta-data to the script itself?
205
 
         */
206
 
        if ( 0 == STRNCMP_CONST(op_type, "meta-data") ) {
207
 
                printf("%s", get_resource_meta(rsc_type, provider));
208
 
                exit(0);
209
 
        }
210
 
 
211
 
        /* To simulate the 'monitor' operation with 'status'.
212
 
         * Now suppose there is no 'monitor' operation for heartbeat scripts.
213
 
         */
214
 
        if ( 0 == STRNCMP_CONST(op_type, "monitor") ) {
215
 
                optype_tmp = g_strdup("status");
216
 
        } else {
217
 
                optype_tmp = g_strdup(op_type);
218
 
        }
219
 
 
220
 
        /* Prepare the call parameter */
221
 
        if (0 > prepare_cmd_parameters(rsc_type, optype_tmp, params, params_argv)) {
222
 
                cl_log(LOG_ERR, "HB RA: Error of preparing parameters");
223
 
                g_free(optype_tmp);
224
 
                return -1;
225
 
        }
226
 
        g_free(optype_tmp);
227
 
 
228
 
        get_ra_pathname(RA_PATH, rsc_type, NULL, ra_pathname);
229
 
 
230
 
        /* let this log show only high loglevel. */
231
 
        if (idebuglevel  > 1) {
232
 
                debug_info = g_string_new("");
233
 
                do {
234
 
                        g_string_append(debug_info, params_argv[index_tmp]);
235
 
                        g_string_append(debug_info, " ");
236
 
                } while (params_argv[++index_tmp] != NULL);
237
 
                debug_info->str[debug_info->len-1] = '\0';
238
 
 
239
 
                cl_log(LOG_DEBUG, "RA instance %s executing: heartbeat::%s"
240
 
                        , rsc_id, debug_info->str);
241
 
 
242
 
                g_string_free(debug_info, TRUE);
243
 
        } 
244
 
 
245
 
        closefiles(); /* don't leak open files */
246
 
        execv(ra_pathname, params_argv);
247
 
        cl_perror("(%s:%s:%d) execv failed for %s"
248
 
                  , __FILE__, __FUNCTION__, __LINE__, ra_pathname);
249
 
 
250
 
        switch (errno) {
251
 
                case ENOENT:   /* No such file or directory */
252
 
                case EISDIR:   /* Is a directory */
253
 
                        exit_value = EXECRA_NOT_INSTALLED;
254
 
                        break;
255
 
                default:
256
 
                        exit_value = EXECRA_EXEC_UNKNOWN_ERROR;
257
 
        }
258
 
        exit(exit_value);
259
 
}
260
 
 
261
 
static int 
262
 
prepare_cmd_parameters(const char * rsc_type, const char * op_type,
263
 
        GHashTable * params_ht, RA_ARGV params_argv)
264
 
{
265
 
        int tmp_len, index;
266
 
        int ht_size = 0;
267
 
        int param_num = 0;
268
 
        char buf_tmp[20];
269
 
        void * value_tmp;
270
 
 
271
 
        if (params_ht) {
272
 
                ht_size = g_hash_table_size(params_ht);
273
 
        }
274
 
        if ( ht_size+3 > MAX_PARAMETER_NUM ) {
275
 
                cl_log(LOG_ERR, "Too many parameters");
276
 
                return -1;
277
 
        }
278
 
                                                                                        
279
 
        /* Now suppose the parameter format stored in Hashtabe is as like as
280
 
         * key="1", value="-Wl,soname=test"
281
 
         * Moreover, the key is supposed as a string transfered from an integer.
282
 
         * It may be changed in the future.
283
 
         */
284
 
        /* Notice: if ht_size==0, no actual arguments except op_type */
285
 
        for (index = 1; index <= ht_size; index++ ) {
286
 
                snprintf(buf_tmp, sizeof(buf_tmp), "%d", index);
287
 
                value_tmp = g_hash_table_lookup(params_ht, buf_tmp);
288
 
                /* suppose the key is consecutive */
289
 
                if ( value_tmp == NULL ) {
290
 
/*                      cl_log(LOG_WARNING, "Parameter ordering error in"\
291
 
                                "prepare_cmd_parameters, raexeclsb.c");
292
 
                        cl_log(LOG_WARNING, "search key=%s.", buf_tmp);
293
 
*/                      continue;
294
 
                }
295
 
                param_num ++;
296
 
                params_argv[param_num] = g_strdup((char *)value_tmp);
297
 
        }
298
 
 
299
 
        tmp_len = strnlen(rsc_type, MAX_LENGTH_OF_RSCNAME);
300
 
        params_argv[0] = g_strndup(rsc_type, tmp_len);
301
 
        /* Add operation code as the last argument */
302
 
        tmp_len = strnlen(op_type, MAX_LENGTH_OF_OPNAME);
303
 
        params_argv[param_num+1] = g_strndup(op_type, tmp_len);
304
 
        /* Add the teminating NULL pointer */
305
 
        params_argv[param_num+2] = NULL;
306
 
        return 0;
307
 
}
308
 
 
309
 
static uniform_ret_execra_t 
310
 
map_ra_retvalue(int ret_execra, const char * op_type, const char * std_output)
311
 
{
312
 
 
313
 
        /* Now there is no formal related specification for Heartbeat RA 
314
 
         * scripts. Temporarily deal as LSB init script.
315
 
         */
316
 
        /* Except op_type equals 'status', the UNIFORM_RET_EXECRA is compatible
317
 
           with LSB standard.
318
 
        */
319
 
        const char * stop_pattern1 = "*stopped*",
320
 
                   * stop_pattern2 = "*not*running*",
321
 
                   * running_pattern1 = "*running*",
322
 
                   * running_pattern2 = "*OK*";
323
 
        char * lower_std_output = NULL;
324
 
 
325
 
        if(ret_execra == EXECRA_NOT_INSTALLED) {
326
 
                return ret_execra;
327
 
        }
328
 
        
329
 
        if (    0 == STRNCMP_CONST(op_type, "status")
330
 
        ||      0 == STRNCMP_CONST(op_type, "monitor")) {
331
 
                if (std_output == NULL ) {
332
 
                        cl_log(LOG_WARNING, "No status output from the (hb) resource agent.");
333
 
                        return EXECRA_NOT_RUNNING;
334
 
                }
335
 
 
336
 
                if (idebuglevel) {
337
 
                        cl_log(LOG_DEBUG, "RA output was: [%s]", std_output);
338
 
                }
339
 
 
340
 
                lower_std_output = g_ascii_strdown(std_output, -1);
341
 
 
342
 
                if ( TRUE == g_pattern_match_simple(stop_pattern1
343
 
                        , lower_std_output) || TRUE ==
344
 
                        g_pattern_match_simple(stop_pattern2
345
 
                        , lower_std_output) ) {
346
 
                        if (idebuglevel) {
347
 
                                cl_log(LOG_DEBUG
348
 
                                ,       "RA output [%s] matched stopped pattern"
349
 
                                " [%s] or [%s]"
350
 
                                ,       std_output
351
 
                                ,       stop_pattern1
352
 
                                ,       stop_pattern2);
353
 
                        }
354
 
                        ret_execra = EXECRA_NOT_RUNNING; /* stopped */
355
 
                } else if ( TRUE == g_pattern_match_simple(running_pattern1
356
 
                        , lower_std_output) || TRUE ==
357
 
                        g_pattern_match_simple(running_pattern2
358
 
                        , std_output) ) {
359
 
                        if (idebuglevel) {
360
 
                                cl_log(LOG_DEBUG
361
 
                                ,       "RA output [%s] matched running"
362
 
                                " pattern [%s] or [%s]"
363
 
                                ,       std_output, running_pattern1
364
 
                                ,       running_pattern2);
365
 
                        }
366
 
                        ret_execra = EXECRA_OK; /* running */
367
 
                } else {
368
 
                        /* It didn't say it was running - must be stopped */
369
 
                        cl_log(LOG_DEBUG, "RA output [%s] didn't match any pattern"
370
 
                        ,       std_output);
371
 
                        ret_execra = EXECRA_NOT_RUNNING; /* stopped */
372
 
                }
373
 
                g_free(lower_std_output);
374
 
        }
375
 
        /* For non-status operation return code */
376
 
        if (ret_execra < 0) {
377
 
                ret_execra = EXECRA_UNKNOWN_ERROR;
378
 
        }
379
 
        return ret_execra;
380
 
}
381
 
 
382
 
static int 
383
 
get_resource_list(GList ** rsc_info)
384
 
{
385
 
        return get_runnable_list(RA_PATH, rsc_info);
386
 
}
387
 
 
388
 
static char*
389
 
get_resource_meta(const char* rsc_type,  const char* provider)
390
 
{
391
 
        GString * meta_data;
392
 
 
393
 
        meta_data = g_string_new("");
394
 
        g_string_sprintf( meta_data, meta_data_template, rsc_type
395
 
                        , rsc_type, rsc_type);
396
 
        return meta_data->str;
397
 
}
398
 
static int
399
 
get_provider_list(const char* ra_type, GList ** providers)
400
 
{
401
 
        if ( providers == NULL ) {
402
 
                cl_log(LOG_ERR, "%s:%d: Parameter error: providers==NULL"
403
 
                        , __FUNCTION__, __LINE__);
404
 
                return -2;
405
 
        }
406
 
 
407
 
        if ( *providers != NULL ) {
408
 
                cl_log(LOG_ERR, "%s:%d: Parameter error: *providers==NULL."
409
 
                        "This will cause memory leak."
410
 
                        , __FUNCTION__, __LINE__);
411
 
        }
412
 
 
413
 
        /* Now temporarily make it fixed */
414
 
        *providers = g_list_append(*providers, g_strdup("heartbeat"));
415
 
 
416
 
        return g_list_length(*providers);
417
 
}