📄 vacm.c
字号:
/* $Id: vacm.c,v 1.10 2005/01/31 09:45:31 sunjd Exp $ *//******************************************************************************** Copyright 2000 Sistina Software, Inc.* Tiny bits Copyright 2000 Alan Robertson <alanr@unix.sh>* Tiny bits Copyright 2000 Zac Sprackett, VA Linux Systems* Tiny bits Copyright 2005 International Business Machines* Significantly Mangled by Sun Jiang Dong <sunjd@cn.ibm.com>, IBM, 2005 ** This is free software released under the GNU General Public License.* There is no warranty for this software. See the file COPYING for* details.** See the file CONTRIBUTORS for a list of contributors.** This file is maintained by:* Michael C Tilstra <conrad@sistina.com>** Becasue I have no device to test, now I just make it pass the compiling* with vacm-2.0.5a. Please review before using.* Sun Jiang Dong <sunjd@cn.ibm.com>, IBM, 2005** This module provides a driver for the VA Linux Cluster Manager.* For more information on VACM, see http://vacm.sourceforge.net/** This module is rather poorly commented. But if you've read the* VACM Manual, and looked at the code example they have, this* should make pretty clean sense. (You obiviously should have* looked at the other stonith source too)* */#include "stonith_plugin_common.h"#include "vacmclient_api.h"#define PIL_PLUGIN vacm#define PIL_PLUGIN_S "vacm"#define PIL_PLUGINLICENSE LICENSE_LGPL#define PIL_PLUGINLICENSEURL URL_LGPL#include <pils/plugin.h>static StonithPlugin * vacm_new(void);static void vacm_destroy(StonithPlugin *);static const char ** vacm_get_confignames(StonithPlugin *);static int vacm_set_config(StonithPlugin *, StonithNVpair *);static const char * vacm_getinfo(StonithPlugin * s, int InfoType);static int vacm_status(StonithPlugin * );static int vacm_reset_req(StonithPlugin * s, int request, const char * host);static char ** vacm_hostlist(StonithPlugin *);static struct stonith_ops vacmOps ={ vacm_new, /* Create new STONITH object */ vacm_destroy, /* Destroy STONITH object */ vacm_getinfo, /* Return STONITH info string */ vacm_get_confignames, /* Return configuration parameters */ vacm_set_config, /* Set configuration */ vacm_status, /* Return STONITH device status */ vacm_reset_req, /* Request a reset */ vacm_hostlist, /* Return list of supported hosts */};PIL_PLUGIN_BOILERPLATE2("1.0", Debug);static const PILPluginImports* PluginImports;static PILPlugin* OurPlugin;static PILInterface* OurInterface;static StonithImports* OurImports;static void* interfprivate;PIL_rcPIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports);PIL_rcPIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports){ /* Force the compiler to do a little type checking */ (void)(PILPluginInitFun)PIL_PLUGIN_INIT; PluginImports = imports; OurPlugin = us; /* Register ourself as a plugin */ imports->register_plugin(us, &OurPIExports); /* Register our interface implementation */ return imports->register_interface(us, PIL_PLUGINTYPE_S , PIL_PLUGIN_S , &vacmOps , NULL /*close */ , &OurInterface , (void*)&OurImports , &interfprivate); }/*structs*/struct pluginDevice { StonithPlugin sp; const char * pluginid; void *h; /* a handle to the nexxus. */ char * nexxus; char * user; char * passwd;};#define ST_NEXXUS "nexxus"static const char * pluginid = "VACMDevice-Stonith";static const char * NOTpluginid = "VACM device has been destroyed";/*funcs*/intvacm_status(StonithPlugin *s){ struct pluginDevice *sd; char snd[] = "NEXXUS:VERSION"; char *rcv, *tk; int rcvlen; ERRIFWRONGDEV(s,S_OOPS); sd = (struct pluginDevice*)s; /* If grabbing the nexxus version works, then the stauts must be ok. * right? */ api_nexxus_send_ipc(sd->h, snd, strlen(snd)+1); while(1) { if (api_nexxus_wait_for_data(sd->h, &rcv, &rcvlen, 20)<0) { break; } if (!(tk = strtok(rcv,":"))) { /*NEXXUS*/ break; }else if (!(tk=strtok(NULL,":"))) { /* Job ID */ break; }else if (!(tk=strtok(NULL,":"))) { /* one of the below */ break; } else if ( !strcmp(tk, "JOB_COMPLETED")) { free(rcv); return S_OK; /* YEAH!! */ }else if(!strcmp(tk, "JOB_STARTED")) { free(rcv); continue; }else if(!strcmp(tk, "JOB_ERROR")) { free(rcv); break; }else if(!strcmp(tk, "VERSION")) { free(rcv); continue; } else { LOG(PIL_CRIT, "Unexpected token \"%s\" in line \"%s\"\n" , tk, rcv); break; } } return S_OOPS;}/* Better make sure the current group is correct. * Can't think of a good way to do this. */char **vacm_hostlist(StonithPlugin *s){ struct pluginDevice *sd; char snd[] = "NEXXUS:NODE_LIST"; char *rcv,*tk; int rcvlen; char ** hlst=NULL; int hacnt=0, hrcnt=0;#define MSTEP 20 ERRIFWRONGDEV(s, NULL); sd = (struct pluginDevice*)s; hlst = (char **)malloc(MSTEP * sizeof(char*)); hacnt=MSTEP; api_nexxus_send_ipc(sd->h, snd, strlen(snd)+1); while(1) { if(api_nexxus_wait_for_data(sd->h, &rcv, &rcvlen, 20)<0) { goto HL_cleanup; } if(!(tk=strtok(rcv, ":"))) { /* NEXXUS */ goto HL_cleanup; }else if(!(tk=strtok(NULL,":"))) { /* Job ID */ goto HL_cleanup; }else if(!(tk=strtok(NULL,":"))) { /* JOB_* or NODELIST */ goto HL_cleanup; }else if( !strcmp(tk, "JOB_STARTED")) { free(rcv); continue; }else if( !strcmp(tk, "JOB_COMPLETED")) { free(rcv); return hlst; }else if( !strcmp(tk, "JOB_ERROR")) { free(rcv); break; }else if( !strcmp(tk, "NODELIST")) { if(!(tk = strtok(NULL,":"))) { /* group */ goto HL_cleanup; }else if((tk = strtok(NULL," \t\n\r"))) { /*Finally, a machine name.*/ if( hrcnt >= (hacnt-1)) { /* grow array. */ hlst = (char **)realloc(hlst, (hacnt +MSTEP)*sizeof(char*)); if( !hlst ) return NULL; /* yeah, i know. possible leak */ hacnt += MSTEP; } hlst[hrcnt++] = strdup(tk); /* stuff the name. */ hlst[hrcnt] = NULL; /* set next to NULL for looping */ } }else { /* WTF?! */ LOG(PIL_CRIT, "Unexpected token \"%s\" in line \"%s\"\n",tk,rcv); break; } }HL_cleanup: stonith_free_hostlist(hlst); /* give the mem back */ return NULL;}#define SND_SIZE 256intvacm_reset_req(StonithPlugin *s, int request, const char *host){ struct pluginDevice *sd; char snd[SND_SIZE]; /* god forbid its bigger than this */ char *rcv, *tk; int rcvlen; ERRIFWRONGDEV(s,S_OOPS); sd = (struct pluginDevice*)s; switch(request) {#ifdef ST_POWERON case ST_POWERON: snprintf(snd, SND_SIZE, "EMP:POWER_ON:%s", host); break;#endif /*ST_POWERON*/#ifdef ST_POWEROFF case ST_POWEROFF: snprintf(snd, SND_SIZE, "EMP:POWER_OFF:%s", host); break;#endif /*ST_POWEROFF*/ case ST_GENERIC_RESET: snprintf(snd, SND_SIZE, "EMP:POWER_CYCLE:%s", host); break; default: return S_INVAL; } api_nexxus_send_ipc(sd->h, snd, strlen(snd)+1); while(1) { if (api_nexxus_wait_for_data(sd->h, &rcv, &rcvlen, 20)<0) { return S_RESETFAIL; } if (!(tk = strtok(rcv,":"))) { /*EMP*/ break; }else if (!(tk=strtok(NULL,":"))) { /* Job ID */ break; }else if (!(tk=strtok(NULL,":"))) { /* one of teh below */ break; } else if ( !strcmp(tk, "JOB_COMPLETED")) { free(rcv); return S_OK; } else if(!strcmp(tk, "JOB_STARTED")) { free(rcv); continue; } else if(!strcmp(tk, "JOB_ERROR")) { free(rcv); return S_RESETFAIL; } else { /* WTF?! */ LOG(PIL_CRIT, "Unexpected token \"%s\" in line \"%s\"\n" , tk, rcv); break; } } return S_RESETFAIL;}/* list => "nexxus:username:password" */static const char **vacm_get_confignames(StonithPlugin * s){ static const char * ret[] = {ST_NEXXUS, ST_LOGIN, ST_PASSWD, NULL}; return ret;}static intvacm_set_config(StonithPlugin *s, StonithNVpair * list){ struct pluginDevice* sd = (struct pluginDevice *)s; int rc; StonithNamesToGet namestoget [] = { {ST_NEXXUS, NULL} , {ST_LOGIN, NULL} , {ST_PASSWD, NULL} , {NULL, NULL} }; ERRIFWRONGDEV(s, S_OOPS); if (sd->sp.isconfigured) { return S_OOPS; } if ((rc=OurImports->GetAllValues(namestoget, list)) != S_OK) { return rc; } sd->nexxus = namestoget[0].s_value; sd->user = namestoget[1].s_value; sd->passwd = namestoget[2].s_value; /* When to initialize the sd->h */ return(S_OK);}/* * The "vacmconf:" is in the conffile so that one file could be used for * multiple device configs. This module will only look at the first line * that starts with this token. All other line are ignored. (and thus * could contain configs for other modules.) * * I don't think any other stonith modules do this currently. */const char *vacm_getinfo(StonithPlugin *s, int reqtype){ const char * ret; ERRIFWRONGDEV(s, NULL); switch (reqtype) { case ST_DEVICEID: /* What type of device? */ ret = dgettext(ST_TEXTDOMAIN, "VACM"); break; case ST_DEVICENAME: /* Which particular device? */ ret = dgettext(ST_TEXTDOMAIN, "VACM"); break; case ST_DEVICEDESCR: /* Description of dev type */ ret = "A driver for the VA Linux Cluster Manager."; break; case ST_DEVICEURL: /* VACM's web site */ ret = "http://vacm.sourceforge.net/"; break; default: ret = NULL; break; } return ret;}voidvacm_destroy(StonithPlugin *s){ struct pluginDevice *sd; VOIDERRIFWRONGDEV(s); sd = (struct pluginDevice*)s; if( sd->h ) { api_nexxus_disconnect(sd->h); } sd->pluginid = NOTpluginid; if (sd->nexxus != NULL) { FREE(sd->nexxus); sd->nexxus = NULL; } if (sd->user != NULL) { FREE(sd->user); sd->user = NULL; } if (sd->passwd != NULL) { FREE(sd->passwd); sd->passwd = NULL; } free(sd); sd = NULL;}static StonithPlugin *vacm_new(void){ struct pluginDevice *sd; sd = malloc(sizeof(struct pluginDevice)); if (sd == NULL) { LOG(PIL_CRIT, "%s", "out of memory"); return(NULL); } memset(sd, 0, sizeof(*sd)); sd->h = NULL; sd->pluginid = pluginid; sd->nexxus = NULL; sd->user = NULL; sd->passwd = NULL; sd->sp.s_ops = &vacmOps; return &(sd->sp); /* same as "sd" */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -