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

« back to all changes in this revision

Viewing changes to lib/plugins/stonith/ipmilan.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
 
 * Stonith module for ipmi lan Stonith device
3
 
 *
4
 
 * Copyright (c) 2003 Intel Corp. 
5
 
 *      Yixiong Zou <yixiong.zou@intel.com>
6
 
 *
7
 
 * Mangled by Sun Jiang Dong <sunjd@cn.ibm.com>, IBM, 2005.
8
 
 * And passed the compiling with OpenIPMI-1.4.8.
9
 
 *
10
 
 * This library is free software; you can redistribute it and/or
11
 
 * modify it under the terms of the GNU Lesser General Public
12
 
 * License as published by the Free Software Foundation; either
13
 
 * version 2.1 of the License, or (at your option) any later version.
14
 
 * 
15
 
 * This library is distributed in the hope that it will be useful,
16
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 
 * Lesser General Public License for more details.
19
 
 * 
20
 
 * You should have received a copy of the GNU Lesser General Public
21
 
 * License along with this library; if not, write to the Free Software
22
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 
 *
24
 
 */
25
 
 
26
 
 
27
 
/*
28
 
 * See README.ipmi for information regarding this plugin.
29
 
 *
30
 
 */
31
 
 
32
 
#define DEVICE  "IPMI Over LAN"
33
 
 
34
 
#include "stonith_plugin_common.h"
35
 
 
36
 
#define PIL_PLUGIN              ipmilan
37
 
#define PIL_PLUGIN_S            "ipmilan"
38
 
#define PIL_PLUGINLICENSE       LICENSE_LGPL
39
 
#define PIL_PLUGINLICENSEURL    URL_LGPL
40
 
#include <pils/plugin.h>
41
 
 
42
 
#include <OpenIPMI/ipmi_types.h>
43
 
#include <OpenIPMI/ipmi_auth.h>
44
 
 
45
 
#include "ipmilan.h"
46
 
 
47
 
static StonithPlugin *  ipmilan_new(const char *);
48
 
static void             ipmilan_destroy(StonithPlugin *);
49
 
static const char **    ipmilan_get_confignames(StonithPlugin *);
50
 
static int              ipmilan_set_config(StonithPlugin *, StonithNVpair *);
51
 
static const char *     ipmilan_getinfo(StonithPlugin * s, int InfoType);
52
 
static int              ipmilan_status(StonithPlugin * );
53
 
static int              ipmilan_reset_req(StonithPlugin * s, int request, const char * host);
54
 
static char **          ipmilan_hostlist(StonithPlugin  *);
55
 
 
56
 
static struct stonith_ops ipmilanOps ={
57
 
        ipmilan_new,            /* Create new STONITH object    */
58
 
        ipmilan_destroy,        /* Destroy STONITH object       */
59
 
        ipmilan_getinfo,        /* Return STONITH info string   */
60
 
        ipmilan_get_confignames,/* Get configuration parameter names */
61
 
        ipmilan_set_config,     /* Set configuration */
62
 
        ipmilan_status,         /* Return STONITH device status */
63
 
        ipmilan_reset_req,      /* Request a reset */
64
 
        ipmilan_hostlist,       /* Return list of supported hosts */
65
 
};
66
 
 
67
 
PIL_PLUGIN_BOILERPLATE2("1.0", Debug);
68
 
const PILPluginImports*  PluginImports;
69
 
static PILPlugin*               OurPlugin;
70
 
static PILInterface*            OurInterface;
71
 
static StonithImports*          OurImports;
72
 
static void*                    interfprivate;
73
 
 
74
 
PIL_rc
75
 
PIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports);
76
 
 
77
 
PIL_rc
78
 
PIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports)
79
 
{
80
 
        /* Force the compiler to do a little type checking */
81
 
        (void)(PILPluginInitFun)PIL_PLUGIN_INIT;
82
 
 
83
 
        PluginImports = imports;
84
 
        OurPlugin = us;
85
 
 
86
 
        /* Register ourself as a plugin */
87
 
        imports->register_plugin(us, &OurPIExports);  
88
 
 
89
 
        /*  Register our interface implementation */
90
 
        return imports->register_interface(us, PIL_PLUGINTYPE_S
91
 
        ,       PIL_PLUGIN_S
92
 
        ,       &ipmilanOps
93
 
        ,       NULL            /*close */
94
 
        ,       &OurInterface
95
 
        ,       (void*)&OurImports
96
 
        ,       &interfprivate); 
97
 
}
98
 
 
99
 
/*
100
 
 *      ipmilan STONITH device.  
101
 
 * 
102
 
 *      ipmilanHostInfo is a double linked list. Where the prev of the head always
103
 
 *      points to the tail.  This is a little wierd.  But it saves me from looping
104
 
 *      around to find the tail when destroying the list.
105
 
 */
106
 
 
107
 
struct pluginDevice {
108
 
        StonithPlugin   sp;
109
 
        const char *    pluginid;
110
 
        const char *    idinfo;
111
 
        int             hostcount;
112
 
        struct ipmilanHostInfo *        hostlist;
113
 
};
114
 
 
115
 
static const char * pluginid = "IPMI-LANDevice-Stonith";
116
 
static const char * NOTpluginid = "IPMI-LAN device has been destroyed";
117
 
 
118
 
#define ST_HOSTNAME     "hostname"
119
 
#define ST_PORT         "port"
120
 
#define ST_AUTH         "auth"
121
 
#define ST_PRIV         "priv"
122
 
#define ST_RESET_METHOD         "reset_method"
123
 
 
124
 
#include "stonith_config_xml.h"
125
 
 
126
 
#define XML_HOSTNAME_SHORTDESC \
127
 
        XML_PARM_SHORTDESC_BEGIN("en") \
128
 
        ST_HOSTNAME \
129
 
        XML_PARM_SHORTDESC_END
130
 
 
131
 
#define XML_HOSTNAME_LONGDESC \
132
 
        XML_PARM_LONGDESC_BEGIN("en") \
133
 
        "The hostname of the STONITH device" \
134
 
        XML_PARM_LONGDESC_END
135
 
 
136
 
#define XML_HOSTNAME_PARM \
137
 
        XML_PARAMETER_BEGIN(ST_HOSTNAME, "string", "1") \
138
 
          XML_HOSTNAME_SHORTDESC \
139
 
          XML_HOSTNAME_LONGDESC \
140
 
        XML_PARAMETER_END
141
 
 
142
 
#define XML_PORT_SHORTDESC \
143
 
        XML_PARM_SHORTDESC_BEGIN("en") \
144
 
        ST_PORT \
145
 
        XML_PARM_SHORTDESC_END
146
 
 
147
 
#define XML_PORT_LONGDESC \
148
 
        XML_PARM_LONGDESC_BEGIN("en") \
149
 
        "The port number to where the IPMI message is sent" \
150
 
        XML_PARM_LONGDESC_END
151
 
 
152
 
#define XML_PORT_PARM \
153
 
        XML_PARAMETER_BEGIN(ST_PORT, "string", "1") \
154
 
          XML_PORT_SHORTDESC \
155
 
          XML_PORT_LONGDESC \
156
 
        XML_PARAMETER_END
157
 
 
158
 
#define XML_AUTH_SHORTDESC \
159
 
        XML_PARM_SHORTDESC_BEGIN("en") \
160
 
        ST_AUTH \
161
 
        XML_PARM_SHORTDESC_END
162
 
 
163
 
#define XML_AUTH_LONGDESC \
164
 
        XML_PARM_LONGDESC_BEGIN("en") \
165
 
        "The authorization type of the IPMI session (\"none\", \"straight\", \"md2\", or \"md5\")" \
166
 
        XML_PARM_LONGDESC_END
167
 
 
168
 
#define XML_AUTH_PARM \
169
 
        XML_PARAMETER_BEGIN(ST_AUTH, "string", "1") \
170
 
          XML_AUTH_SHORTDESC \
171
 
          XML_AUTH_LONGDESC \
172
 
        XML_PARAMETER_END
173
 
 
174
 
#define XML_PRIV_SHORTDESC \
175
 
        XML_PARM_SHORTDESC_BEGIN("en") \
176
 
        ST_PRIV \
177
 
        XML_PARM_SHORTDESC_END
178
 
 
179
 
#define XML_PRIV_LONGDESC \
180
 
        XML_PARM_LONGDESC_BEGIN("en") \
181
 
        "The privilege level of the user (\"operator\" or \"admin\")" \
182
 
        XML_PARM_LONGDESC_END
183
 
 
184
 
#define XML_PRIV_PARM \
185
 
        XML_PARAMETER_BEGIN(ST_PRIV, "string", "1") \
186
 
          XML_PRIV_SHORTDESC \
187
 
          XML_PRIV_LONGDESC \
188
 
        XML_PARAMETER_END
189
 
 
190
 
#define XML_RESET_METHOD_SHORTDESC \
191
 
        XML_PARM_SHORTDESC_BEGIN("en") \
192
 
        ST_RESET_METHOD \
193
 
        XML_PARM_SHORTDESC_END
194
 
 
195
 
#define XML_RESET_METHOD_LONGDESC \
196
 
        XML_PARM_LONGDESC_BEGIN("en") \
197
 
        "How to reset the host (\"power_cycle\" or \"hard_reset\")" \
198
 
        XML_PARM_LONGDESC_END
199
 
 
200
 
#define XML_RESET_METHOD_PARM \
201
 
        XML_PARAMETER_BEGIN(ST_RESET_METHOD, "string", "0") \
202
 
          XML_RESET_METHOD_SHORTDESC \
203
 
          XML_RESET_METHOD_LONGDESC \
204
 
        XML_PARAMETER_END
205
 
 
206
 
static const char *ipmilanXML = 
207
 
  XML_PARAMETERS_BEGIN
208
 
    XML_HOSTNAME_PARM
209
 
    XML_IPADDR_PARM
210
 
    XML_PORT_PARM
211
 
    XML_AUTH_PARM
212
 
    XML_PRIV_PARM
213
 
    XML_LOGIN_PARM
214
 
    XML_PASSWD_PARM
215
 
  XML_PARAMETERS_END;
216
 
 
217
 
/*
218
 
 * Check the status of the IPMI Lan STONITH device. 
219
 
 * 
220
 
 * NOTE: not sure what we should do here since each host is configured
221
 
 * seperately.
222
 
 *     
223
 
 * Two options: 
224
 
 *   1) always return S_OK. 
225
 
 *   2) using IPMI ping to confirm the status for every host that's
226
 
 *      configured. 
227
 
 * 
228
 
 * For now I choose the option 1 hoping that I can get by. Maybe we should
229
 
 * change it to option 2 later. 
230
 
 */
231
 
 
232
 
static int
233
 
ipmilan_status(StonithPlugin  *s)
234
 
{
235
 
        struct pluginDevice * nd;
236
 
        struct ipmilanHostInfo * node;
237
 
        int ret, rv;
238
 
        int i;
239
 
 
240
 
        ERRIFWRONGDEV(s,S_OOPS);
241
 
 
242
 
        ret = S_OK;
243
 
 
244
 
        nd = (struct pluginDevice *)s;
245
 
        for( i=0, node = nd->hostlist;
246
 
                        i < nd->hostcount; i++, node = node->next ) {
247
 
                rv = do_ipmi_cmd(node, ST_IPMI_STATUS);
248
 
                if (rv) {
249
 
                        LOG(PIL_INFO, "Host %s ipmilan status failure."
250
 
                        ,       node->hostname);
251
 
                        ret = S_ACCESS;
252
 
                } else {
253
 
                        LOG(PIL_INFO, "Host %s ipmilan status OK."
254
 
                        ,       node->hostname);
255
 
                }
256
 
 
257
 
        }
258
 
 
259
 
        return ret;
260
 
}
261
 
 
262
 
/*
263
 
 * This function returns the list of hosts that's configured. 
264
 
 *
265
 
 * The detailed configuration is disabled because the STONITH command can be
266
 
 * run by anyone so there is a security risk if that to be exposed.
267
 
 */
268
 
 
269
 
static char *
270
 
get_config_string(struct pluginDevice * nd, int index)
271
 
{
272
 
        struct ipmilanHostInfo * host;
273
 
        int i;
274
 
 
275
 
        if (index >= nd->hostcount || index < 0) {
276
 
                return (NULL);
277
 
        }
278
 
 
279
 
        host = nd->hostlist;
280
 
        for (i = 0; i < index; i++) {
281
 
                host = host->next;
282
 
        }
283
 
 
284
 
        return STRDUP(host->hostname);
285
 
}
286
 
 
287
 
 
288
 
/*
289
 
 *      Return the list of hosts configured for this ipmilan device
290
 
 *      
291
 
 */
292
 
 
293
 
static char **
294
 
ipmilan_hostlist(StonithPlugin  *s)
295
 
{
296
 
        int             numnames = 0;
297
 
        char **         ret = NULL;
298
 
        struct pluginDevice*    nd;
299
 
        int             j;
300
 
 
301
 
        ERRIFWRONGDEV(s,NULL);
302
 
        
303
 
        nd = (struct pluginDevice*) s;
304
 
        if (nd->hostcount < 0) {
305
 
                LOG(PIL_CRIT
306
 
                ,       "unconfigured stonith object in ipmi_hostlist");
307
 
                return(NULL);
308
 
        }
309
 
        numnames = nd->hostcount;
310
 
 
311
 
        ret = (char **)MALLOC((numnames + 1)*sizeof(char*));
312
 
        if (ret == NULL) {
313
 
                LOG(PIL_CRIT, "out of memory");
314
 
                return (ret);
315
 
        }
316
 
 
317
 
        memset(ret, 0, (numnames + 1)*sizeof(char*));
318
 
 
319
 
        for (j = 0; j < numnames; ++j) {
320
 
                ret[j] = get_config_string(nd, j);
321
 
                if (!ret[j]) {
322
 
                        stonith_free_hostlist(ret);
323
 
                        ret = NULL;
324
 
                        break;
325
 
                }
326
 
                g_strdown(ret[j]);
327
 
        }
328
 
 
329
 
        return(ret);
330
 
}
331
 
 
332
 
/*
333
 
 *      Parse the config information, and stash it away...
334
 
 *
335
 
 *      The buffer for each string is MAX_IPMI_STRING_LEN bytes long.
336
 
 *      Right now it is set to 64. Hope this is enough.
337
 
 *      
338
 
 */
339
 
 
340
 
#define MAX_IPMI_STRING_LEN 64
341
 
 
342
 
/*
343
 
 *      Reset the given host on this StonithPlugin device.
344
 
 */
345
 
static int
346
 
ipmilan_reset_req(StonithPlugin * s, int request, const char * host)
347
 
{
348
 
        int rc = 0;
349
 
        struct pluginDevice * nd;
350
 
        struct ipmilanHostInfo * node;
351
 
        int i;
352
 
 
353
 
        ERRIFWRONGDEV(s,S_OOPS);
354
 
        
355
 
        nd = (struct pluginDevice *)s;
356
 
        for( i=0, node = nd->hostlist;
357
 
                        i < nd->hostcount; i++, node = node->next ) {
358
 
                if (strcasecmp(node->hostname, host) == 0) {
359
 
                        break;
360
 
                }
361
 
        }
362
 
 
363
 
        if (i >= nd->hostcount) {
364
 
                LOG(PIL_CRIT, "Host %s is not configured in this STONITH "
365
 
                " module. Please check your configuration file.", host);
366
 
                return (S_OOPS);
367
 
        }
368
 
 
369
 
        rc = do_ipmi_cmd(node, request);
370
 
        if (!rc) {
371
 
                LOG(PIL_INFO, "Host %s ipmilan-reset.", host);
372
 
        } else {
373
 
                LOG(PIL_INFO, "Host %s ipmilan-reset error. Error = %d."
374
 
                ,       host, rc);
375
 
        }
376
 
        return rc;
377
 
}
378
 
 
379
 
/*
380
 
 *      Get configuration parameter names
381
 
 */
382
 
static const char **
383
 
ipmilan_get_confignames(StonithPlugin * s)
384
 
{
385
 
        static const char * ret[] = 
386
 
                { ST_HOSTNAME, ST_IPADDR, ST_PORT, ST_AUTH,
387
 
                  ST_PRIV, ST_LOGIN, ST_PASSWD, ST_RESET_METHOD, NULL};
388
 
        return ret;
389
 
}
390
 
 
391
 
/*
392
 
 *      Set the configuration parameters
393
 
 */
394
 
static int
395
 
ipmilan_set_config(StonithPlugin* s, StonithNVpair * list)
396
 
{
397
 
        struct pluginDevice* nd;
398
 
        int             rc;
399
 
        struct ipmilanHostInfo *  tmp;
400
 
        const char *reset_opt;
401
 
 
402
 
        StonithNamesToGet       namestocopy [] =
403
 
        {       {ST_HOSTNAME,   NULL}
404
 
        ,       {ST_IPADDR,     NULL}
405
 
        ,       {ST_PORT,       NULL}
406
 
        ,       {ST_AUTH,       NULL}
407
 
        ,       {ST_PRIV,       NULL}
408
 
        ,       {ST_LOGIN,      NULL}
409
 
        ,       {ST_PASSWD,     NULL}
410
 
        ,       {NULL,          NULL}
411
 
        };
412
 
 
413
 
        ERRIFWRONGDEV(s,S_OOPS);
414
 
        nd = (struct pluginDevice *)s;
415
 
 
416
 
        ERRIFWRONGDEV(s, S_OOPS);
417
 
        if (nd->sp.isconfigured) {
418
 
                return S_OOPS;
419
 
        }
420
 
 
421
 
        if ((rc=OurImports->CopyAllValues(namestocopy, list)) != S_OK) {
422
 
                return rc;
423
 
        }
424
 
 
425
 
        tmp = ST_MALLOCT(struct ipmilanHostInfo);
426
 
        tmp->hostname = namestocopy[0].s_value;
427
 
        tmp->ipaddr   = namestocopy[1].s_value;
428
 
        tmp->portnumber = atoi(namestocopy[2].s_value);
429
 
        FREE(namestocopy[2].s_value);
430
 
        if (namestocopy[3].s_value == NULL) {
431
 
                LOG(PIL_CRIT, "ipmilan auth type is NULL.  See "
432
 
                "README.ipmilan for allowed values");
433
 
                return S_OOPS;
434
 
        } else if (strcmp(namestocopy[3].s_value, "none") == 0) {
435
 
                tmp->authtype = 0;
436
 
        } else if (strcmp(namestocopy[3].s_value, "md2") == 0) {
437
 
                tmp->authtype = 1;
438
 
        } else if (strcmp(namestocopy[3].s_value, "md5") == 0) {
439
 
                tmp->authtype = 2;
440
 
        } else if (strcmp(namestocopy[3].s_value, "key") == 0 ||
441
 
                        strcmp(namestocopy[3].s_value, "password") == 0 ||
442
 
                        strcmp(namestocopy[3].s_value, "straight") == 0) {
443
 
                tmp->authtype = 4;
444
 
        } else {
445
 
                LOG(PIL_CRIT, "ipmilan auth type '%s' invalid.  See "
446
 
                "README.ipmilan for allowed values", namestocopy[3].s_value);
447
 
                return S_OOPS;
448
 
        }
449
 
        FREE(namestocopy[3].s_value);
450
 
        if (namestocopy[4].s_value == NULL) {
451
 
                LOG(PIL_CRIT, "ipmilan priv value is NULL.  See "
452
 
                "README.ipmilan for allowed values");
453
 
                return S_OOPS;
454
 
        } else if (strcmp(namestocopy[4].s_value, "operator") == 0) {
455
 
                tmp->privilege = 3;
456
 
        } else if (strcmp(namestocopy[4].s_value, "admin") == 0) {
457
 
                tmp->privilege = 4;
458
 
        } else {
459
 
                LOG(PIL_CRIT, "ipmilan priv value '%s' invalid.  See "
460
 
                "README.ipmilan for allowed values", namestocopy[4].s_value);
461
 
                return(S_OOPS);
462
 
        }
463
 
        FREE(namestocopy[4].s_value);
464
 
        tmp->username = namestocopy[5].s_value;
465
 
        tmp->password = namestocopy[6].s_value;
466
 
        reset_opt = OurImports->GetValue(list, ST_RESET_METHOD);
467
 
        if (!reset_opt || !strcmp(reset_opt, "power_cycle")) {
468
 
                tmp->reset_method = 0;
469
 
        } else if (!strcmp(reset_opt, "hard_reset")) {
470
 
                tmp->reset_method = 1;
471
 
        } else {
472
 
                LOG(PIL_CRIT, "ipmilan reset_method '%s' invalid", reset_opt);
473
 
                return S_OOPS;
474
 
        }
475
 
 
476
 
        if (nd->hostlist == NULL ) {
477
 
                nd->hostlist = tmp;
478
 
                nd->hostlist->prev = tmp;
479
 
                nd->hostlist->next = tmp;
480
 
        } else {
481
 
                tmp->prev = nd->hostlist->prev;
482
 
                tmp->next = nd->hostlist;
483
 
                nd->hostlist->prev->next = tmp;
484
 
                nd->hostlist->prev = tmp;
485
 
        }
486
 
        nd->hostcount++;
487
 
 
488
 
        return(S_OK);
489
 
}
490
 
 
491
 
static const char *
492
 
ipmilan_getinfo(StonithPlugin * s, int reqtype)
493
 
{
494
 
        struct pluginDevice *   nd;
495
 
        const char *            ret;
496
 
 
497
 
        ERRIFWRONGDEV(s,NULL);
498
 
        /*
499
 
         *      We look in the ST_TEXTDOMAIN catalog for our messages
500
 
         */
501
 
        nd = (struct pluginDevice *)s;
502
 
 
503
 
        switch (reqtype) {
504
 
                case ST_DEVICEID:
505
 
                        ret = nd->idinfo;
506
 
                        break;
507
 
 
508
 
                case ST_DEVICENAME:
509
 
                        ret = nd->hostlist ? nd->hostlist->hostname : NULL;
510
 
                        break;
511
 
 
512
 
                case ST_DEVICEDESCR:
513
 
                        ret = "IPMI LAN STONITH device\n";
514
 
                        break;
515
 
 
516
 
                case ST_DEVICEURL:
517
 
                        ret = "http://www.intel.com/design/servers/ipmi/";
518
 
                        break;
519
 
 
520
 
                case ST_CONF_XML:               /* XML metadata */
521
 
                        ret = ipmilanXML;
522
 
                        break;
523
 
 
524
 
                default:
525
 
                        ret = NULL;
526
 
                        break;
527
 
        }
528
 
        return ret;
529
 
}
530
 
 
531
 
/*
532
 
 *      ipmilan StonithPlugin destructor...
533
 
 *
534
 
 *      The hostlist is a link list.  So have to iterate through.
535
 
 */
536
 
static void
537
 
ipmilan_destroy(StonithPlugin *s)
538
 
{
539
 
        struct pluginDevice* nd;
540
 
        struct ipmilanHostInfo * host;
541
 
        int i;
542
 
 
543
 
        VOIDERRIFWRONGDEV(s);
544
 
 
545
 
        nd = (struct pluginDevice *)s;
546
 
 
547
 
        nd->pluginid = NOTpluginid;
548
 
 
549
 
        if (nd->hostlist) {
550
 
                host = nd->hostlist->prev;
551
 
                for (i = 0; i < nd->hostcount; i++) {
552
 
                        struct ipmilanHostInfo * host_prev = host->prev;
553
 
 
554
 
                        FREE(host->hostname);
555
 
                        FREE(host->ipaddr);
556
 
                        FREE(host->username);
557
 
                        FREE(host->password);
558
 
 
559
 
                        FREE(host);
560
 
                        host = host_prev;
561
 
                }
562
 
        }
563
 
 
564
 
        nd->hostcount = -1;
565
 
        FREE(nd);
566
 
        ipmi_leave();
567
 
}
568
 
 
569
 
/* Create a new ipmilan StonithPlugin device.  Too bad this function can't be static */
570
 
static StonithPlugin *
571
 
ipmilan_new(const char *subplugin)
572
 
{
573
 
        struct pluginDevice*    nd = ST_MALLOCT(struct pluginDevice);
574
 
 
575
 
        if (nd == NULL) {
576
 
                LOG(PIL_CRIT, "out of memory");
577
 
                return(NULL);
578
 
        }
579
 
        memset(nd, 0, sizeof(*nd));
580
 
        nd->pluginid = pluginid;
581
 
        nd->hostlist = NULL;
582
 
        nd->hostcount = 0; 
583
 
        nd->idinfo = DEVICE;
584
 
        nd->sp.s_ops = &ipmilanOps;
585
 
        return(&(nd->sp));
586
 
}