summaryrefslogtreecommitdiffstats
path: root/agents/zvm/fence_zvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'agents/zvm/fence_zvm.c')
-rw-r--r--agents/zvm/fence_zvm.c1056
1 files changed, 1056 insertions, 0 deletions
diff --git a/agents/zvm/fence_zvm.c b/agents/zvm/fence_zvm.c
new file mode 100644
index 0000000..6f1469e
--- /dev/null
+++ b/agents/zvm/fence_zvm.c
@@ -0,0 +1,1056 @@
+/*
+ * fence_zvm.c: SMAPI interface for managing zVM Guests
+ *
+ * Copyright (C) 2012 Sine Nomine Associates
+ *
+ * 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, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Neale Ferguson <neale@sinenomine.net>
+ *
+ */
+
+#ifdef __s390__
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netiucv/iucv.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <getopt.h>
+#include <ctype.h>
+#include <syslog.h>
+#include "fence_zvm.h"
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define DEFAULT_TIMEOUT 300
+#define DEFAULT_DELAY 0
+
+#define ACT_OFFON 0
+#define ACT_OFF 1
+#define ACT_ON 2
+#define ACT_METADATA 3
+#define ACT_STATUS 4
+#define ACT_MONITOR 5
+#define ACT_LIST 6
+#define ACT_HELP 7
+
+static int zvm_smapi_reportError (void *, void *);
+
+static struct option longopts[] = {
+ {"action", required_argument, NULL, 'o'},
+ {"delay", required_argument, NULL, 'h'},
+ {"help", no_argument, NULL, 'h'},
+ {"ip", required_argument, NULL, 'a'},
+ {"plug", required_argument, NULL, 'n'},
+ {"timeout", required_argument, NULL, 'T'},
+ {"zvmsys", required_argument, NULL, 'z'},
+ {NULL, 0, NULL, 0}
+};
+
+static const char *optString = "a:ho:n:T:";
+
+static int zvm_metadata (void);
+static int usage (void);
+
+/**
+ * zvm_smapi_open:
+ * @zvm: z/VM driver information
+ *
+ * Opens a connection with the z/VM SMAPI server
+ */
+int
+zvm_smapi_open (zvm_driver_t * zvm)
+{
+ int rc = -1, sockaddrlen;
+ static char iucvprog[9] = "DMSRSRQU\0";
+ struct sockaddr_iucv siucv_addr;
+ const struct sockaddr *siucv_ptr = (void *) &siucv_addr;
+
+ if ((zvm->sd = socket (AF_IUCV, SOCK_STREAM, IPPROTO_IP)) != -1) {
+ memset (&siucv_addr, 0, sizeof (siucv_addr));
+ siucv_addr.siucv_family = AF_IUCV;
+ siucv_addr.siucv_port = 0;
+ siucv_addr.siucv_addr = 0;
+ memset (&siucv_addr.siucv_nodeid, ' ', 8);
+ memset (&siucv_addr.siucv_user_id, ' ', 8);
+ memset (&siucv_addr.siucv_name, ' ', 8);
+ sockaddrlen = sizeof (siucv_addr);
+ if ((rc = bind (zvm->sd, siucv_ptr, sockaddrlen)) != -1) {
+ memcpy (&siucv_addr.siucv_user_id, zvm->smapiSrv,
+ strlen (zvm->smapiSrv));
+ memcpy (&siucv_addr.siucv_name, &iucvprog, 8);
+ memcpy (&siucv_addr.siucv_nodeid, zvm->node,
+ strlen (zvm->node));
+ rc = connect (zvm->sd,
+ (__CONST_SOCKADDR_ARG) siucv_ptr,
+ sockaddrlen);
+ }
+ if (rc == -1) {
+ syslog (LOG_ERR, "Error connecting to %s - %m",
+ zvm->smapiSrv);
+ close (zvm->sd);
+ }
+ }
+ return (rc);
+}
+
+/**
+ * zvm_smapi_imageRecycle
+ * @zvm: z/VM driver information
+ *
+ * Deactivates a virtual image
+ */
+int
+zvm_smapi_imageRecycle (zvm_driver_t * zvm)
+{
+ struct _inPlist
+ {
+ int32_t lPlist;
+ int32_t lFName;
+ char fName[13];
+ int32_t lUser;
+ int32_t lPass;
+ int32_t lTarget;
+ char target[0];
+ } __attribute__((__packed__)) * inPlist;
+ int32_t lInPlist;
+ struct _outPlist
+ {
+ smapiOutHeader_t hdr;
+ int32_t nActive;
+ int32_t nInActive;
+ int32_t lFail;
+ char failArray[0];
+ } *outPlist = NULL;
+ void *pOut = NULL;
+ int32_t lRsp;
+ uint32_t reqId;
+ int rc;
+
+ /*
+ * Implement any delay
+ */
+ if (zvm->delay > 0)
+ sleep (zvm->delay);
+
+ lInPlist = sizeof (*inPlist) + strlen (zvm->target);
+ inPlist = malloc (lInPlist);
+ if (inPlist != NULL) {
+ inPlist->lPlist = lInPlist - sizeof (inPlist->lPlist);
+ inPlist->lFName = sizeof (inPlist->fName);
+ memcpy (inPlist->fName, Image_Recycle,
+ sizeof (inPlist->fName));
+ inPlist->lUser = inPlist->lPass = 0;
+ inPlist->lTarget = strlen (zvm->target);
+ memcpy (inPlist->target, zvm->target, inPlist->lTarget);
+ if ((rc =
+ zvm_smapi_send (zvm, inPlist, &reqId, lInPlist)) != -1) {
+ if ((rc = zvm_smapi_recv (zvm, &pOut, &lRsp)) != -1) {
+ outPlist = pOut;
+ if (outPlist->hdr.rc == 0) {
+ syslog (LOG_INFO,
+ "Recycling of %s successful",
+ zvm->target);
+ rc = 0;
+ }
+ else {
+ if ((outPlist->hdr.rc ==
+ RCERR_IMAGEOP) & ((outPlist->hdr.
+ reason ==
+ RS_NOT_ACTIVE)
+ | (outPlist->
+ hdr.
+ reason ==
+ RS_BEING_DEACT)))
+ {
+ syslog (LOG_INFO,
+ "Recycling of %s successful",
+ zvm->target);
+ rc = 0;
+ }
+ else {
+ rc = outPlist->hdr.rc;
+ zvm->reason =
+ outPlist->hdr.reason;
+ (void) zvm_smapi_reportError
+ (inPlist, outPlist);
+ }
+ }
+ }
+ }
+ free (inPlist);
+ free (outPlist);
+ }
+ else {
+ syslog (LOG_ERR, "%s - cannot allocate parameter list",
+ __func__);
+ rc = -1;
+ }
+ return (rc);
+}
+
+/**
+ * zvm_smapi_imageDeactivate
+ * @zvm: z/VM driver information
+ *
+ * Deactivates a virtual image
+ */
+int
+zvm_smapi_imageDeactivate (zvm_driver_t * zvm)
+{
+ struct _inPlist
+ {
+ int32_t lPlist;
+ int32_t lFName;
+ char fName[16];
+ int32_t lUser;
+ int32_t lPass;
+ int32_t lTarget;
+ char target[0];
+ } __attribute__((__packed__)) * inPlist;
+ struct _deactTime
+ {
+ int32_t lForceTime;
+ char forceTime[5];
+ } __attribute__((__packed__)) * deactTime;
+ int32_t lInPlist;
+ struct _outPlist
+ {
+ smapiOutHeader_t hdr;
+ int32_t nActive;
+ int32_t nInActive;
+ int32_t lFail;
+ char failArray[0];
+ } *outPlist = NULL;
+ void *pOut = NULL;
+ int32_t lRsp;
+ uint32_t reqId;
+ int rc;
+
+ /*
+ * Implement any delay
+ */
+ if (zvm->delay > 0)
+ sleep (zvm->delay);
+
+ lInPlist =
+ sizeof (*inPlist) + strlen (zvm->target) +
+ sizeof (*deactTime);
+ inPlist = malloc (lInPlist);
+ if (inPlist != NULL) {
+ inPlist->lPlist = lInPlist - sizeof (inPlist->lPlist);
+ inPlist->lFName = sizeof (inPlist->fName);
+ memcpy (inPlist->fName, Image_Deactivate,
+ sizeof (inPlist->fName));
+ deactTime =
+ (void *) ((intptr_t) inPlist + sizeof (*inPlist) +
+ strlen (zvm->target));
+ deactTime->lForceTime = sizeof (deactTime->forceTime);
+ memcpy (deactTime->forceTime, "IMMED",
+ sizeof (deactTime->forceTime));
+ inPlist->lUser = inPlist->lPass = 0;
+ inPlist->lTarget = strlen (zvm->target);
+ memcpy (inPlist->target, zvm->target, inPlist->lTarget);
+ if ((rc =
+ zvm_smapi_send (zvm, inPlist, &reqId, lInPlist)) != -1) {
+ if ((rc = zvm_smapi_recv (zvm, &pOut, &lRsp)) != -1) {
+ outPlist = pOut;
+ if (outPlist->hdr.rc == 0) {
+ syslog (LOG_INFO,
+ "Deactivation of %s successful",
+ zvm->target);
+ rc = 0;
+ }
+ else {
+ if ((outPlist->hdr.rc ==
+ RCERR_IMAGEOP) & ((outPlist->hdr.
+ reason ==
+ RS_NOT_ACTIVE)
+ | (outPlist->
+ hdr.
+ reason ==
+ RS_BEING_DEACT)))
+ {
+ syslog (LOG_INFO,
+ "Deactivation of %s successful",
+ zvm->target);
+ rc = 0;
+ }
+ else {
+ rc = outPlist->hdr.rc;
+ zvm->reason =
+ outPlist->hdr.reason;
+ (void) zvm_smapi_reportError
+ (inPlist, outPlist);
+ }
+ }
+ }
+ }
+ free (inPlist);
+ free (outPlist);
+ }
+ else {
+ syslog (LOG_ERR, "%s - cannot allocate parameter list",
+ __func__);
+ rc = -1;
+ }
+ return (rc);
+}
+
+/**
+ * zvm_smapi_imageActivate
+ * @zvm: z/VM driver information
+ *
+ * Deactivates a virtual image
+ */
+int
+zvm_smapi_imageActivate (zvm_driver_t * zvm)
+{
+ struct _inPlist
+ {
+ int32_t lPlist;
+ int32_t lFName;
+ char fName[14];
+ int32_t lUser;
+ int32_t lPass;
+ int32_t lTarget;
+ char target[0];
+ } __attribute__((__packed__)) * inPlist;
+ int32_t lInPlist;
+ struct _outPlist
+ {
+ smapiOutHeader_t hdr;
+ int32_t nActive;
+ int32_t nInActive;
+ int32_t lFail;
+ char failArray[0];
+ } *outPlist = NULL;
+ void *pOut = NULL;
+ int32_t lRsp;
+ uint32_t reqId;
+ int rc;
+
+ /*
+ * Implement any delay
+ */
+ if (zvm->delay > 0)
+ sleep (zvm->delay);
+
+ lInPlist = sizeof (*inPlist) + strlen (zvm->target);
+ inPlist = malloc (lInPlist);
+ if (inPlist != NULL) {
+ inPlist->lPlist = lInPlist - sizeof (inPlist->lPlist);
+ inPlist->lFName = sizeof (inPlist->fName);
+ memcpy (inPlist->fName, Image_Activate,
+ sizeof (inPlist->fName));
+ inPlist->lUser = inPlist->lPass = 0;
+ inPlist->lTarget = strlen (zvm->target);
+ memcpy (inPlist->target, zvm->target, inPlist->lTarget);
+ if ((rc =
+ zvm_smapi_send (zvm, inPlist, &reqId, lInPlist)) != -1) {
+ if ((rc = zvm_smapi_recv (zvm, &pOut, &lRsp)) != -1) {
+ outPlist = pOut;
+ if (outPlist->hdr.rc == 0) {
+ syslog (LOG_INFO,
+ "Activation of %s successful",
+ zvm->target);
+ rc = 0;
+ }
+ else {
+ if ((outPlist->hdr.rc ==
+ RCERR_IMAGEOP) & (outPlist->hdr.
+ reason ==
+ RS_ALREADY_ACTIVE))
+ {
+ syslog (LOG_INFO,
+ "Activation of %s successful",
+ zvm->target);
+ rc = 0;
+ }
+ else {
+ rc = outPlist->hdr.rc;
+ zvm->reason =
+ outPlist->hdr.reason;
+ (void) zvm_smapi_reportError
+ (inPlist, outPlist);
+ }
+ }
+ }
+ }
+ free (inPlist);
+ free (outPlist);
+ }
+ else {
+ syslog (LOG_ERR, "%s - cannot allocate parameter list",
+ __func__);
+ rc = -1;
+ }
+ return (rc);
+}
+
+/**
+ * zvm_smapi_imageQuery
+ * @zvm: z/VM driver information
+ *
+ * Queries the state of a virtual image
+ */
+int
+zvm_smapi_imageQuery (zvm_driver_t * zvm)
+{
+ struct _inPlist
+ {
+ int32_t lPlist;
+ int32_t lFName;
+ char fName[18];
+ int32_t lUser;
+ int32_t lPass;
+ int32_t lTarget;
+ char target[0];
+ } __attribute__((__packed__)) * inPlist;
+ int32_t lInPlist;
+ struct _outPlist
+ {
+ smapiOutHeader_t hdr;
+ int32_t lNames;
+ char nameArray[0];
+ } *outPlist = NULL;
+ void *pOut = NULL;
+ int32_t lRsp;
+ uint32_t reqId;
+ int rc;
+
+ /*
+ * Implement any delay
+ */
+ if (zvm->delay > 0)
+ sleep (zvm->delay);
+
+ lInPlist = sizeof (*inPlist) + strlen (zvm->target);
+ inPlist = malloc (lInPlist);
+ if (inPlist != NULL) {
+ inPlist->lPlist = lInPlist - sizeof (inPlist->lPlist);
+ inPlist->lFName = sizeof (inPlist->fName);
+ memcpy (inPlist->fName, Image_Status_Query,
+ sizeof (inPlist->fName));
+ inPlist->lUser = inPlist->lPass = 0;
+ inPlist->lTarget = strlen (zvm->target);
+ memcpy (inPlist->target, zvm->target, inPlist->lTarget);
+ if ((rc =
+ zvm_smapi_send (zvm, inPlist, &reqId, lInPlist)) != -1) {
+ if ((rc = zvm_smapi_recv (zvm, &pOut, &lRsp)) != -1) {
+ outPlist = pOut;
+ if (outPlist->hdr.rc == 0) {
+ if (outPlist->hdr.reason == 0) {
+ syslog (LOG_INFO,
+ "Node %s is active",
+ zvm->target);
+ rc = 0;
+ }
+ else {
+ syslog (LOG_INFO,
+ "Node %s is inactive",
+ zvm->target);
+ rc = 2;
+ }
+ }
+ else {
+ rc = 1;
+ zvm->reason = outPlist->hdr.reason;
+ (void) zvm_smapi_reportError (inPlist,
+ outPlist);
+ }
+ }
+ }
+ free (inPlist);
+ free (outPlist);
+ }
+ else {
+ syslog (LOG_ERR, "%s - cannot allocate parameter list",
+ __func__);
+ rc = -1;
+ }
+ return (rc);
+}
+
+/**
+ * zvm_smapi_send:
+ * @zvm: z/VM driver information
+ * @reqid: Returned request id
+ * @req: Request parameter list
+ * @lSend: Length of request
+ *
+ * Send a request to the SMAPI server and retrieve the request id
+ */
+int
+zvm_smapi_send (zvm_driver_t * zvm, void *req, uint32_t * reqId,
+ int32_t lSend)
+{
+ int rc, nFds;
+ fd_set readFds;
+ struct timeval timeout;
+
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+ zvm->reason = -1;
+ if ((rc = zvm_smapi_open (zvm)) == 0) {
+ rc = send (zvm->sd, req, lSend, 0);
+ if (rc != -1) {
+ FD_ZERO (&readFds);
+ FD_SET (zvm->sd, &readFds);
+ nFds = zvm->sd + 1;
+
+ if ((rc =
+ select (nFds, &readFds, NULL, NULL,
+ &timeout)) != -1) {
+ /*
+ * Get request ID
+ */
+ rc = recv (zvm->sd, reqId, sizeof (*reqId),
+ 0);
+ if (rc == -1)
+ syslog (LOG_ERR,
+ "Error receiving from SMAPI - %m");
+ }
+ }
+ else
+ syslog (LOG_ERR, "Error sending to SMAPI - %m");
+ }
+ return (rc);
+}
+
+/**
+ * zvm_smapi_recv:
+ * @zvm: z/VM driver information
+ * @req: Returned response parameter list
+ * @lRsp: Length of response
+ *
+ * Receive a response from the SMAPI server
+ */
+int
+zvm_smapi_recv (zvm_driver_t * zvm, void **rsp, int32_t * lRsp)
+{
+ int rc, lRem = 0, nFds;
+ void *pRecv = rsp;
+ fd_set readFds;
+ smapiOutHeader_t *out;
+ struct timeval timeout;
+
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+ FD_ZERO (&readFds);
+ FD_SET (zvm->sd, &readFds);
+ nFds = zvm->sd + 1;
+
+ zvm->reason = -1;
+ if ((rc = select (nFds, &readFds, NULL, NULL, &timeout)) != -1) {
+ /*
+ * Get response length
+ */
+ if ((rc = recv (zvm->sd, lRsp, sizeof (*lRsp), 0)) != -1) {
+ lRem = *lRsp;
+ if (*rsp == NULL)
+ *rsp = malloc (*lRsp + sizeof (out->outLen));
+ out = *rsp;
+ out->outLen = *lRsp;
+ pRecv = &out->reqId;
+ while (lRem > 0) {
+ if ((rc =
+ recv (zvm->sd, pRecv, lRem, 0)) != -1) {
+ lRem -= rc;
+ pRecv = (void *) ((uintptr_t) pRecv +
+ rc);
+ }
+ else
+ syslog (LOG_ERR,
+ "Error receiving from SMAPI - %m");
+ (void) zvm_smapi_close (zvm);
+ return (rc);
+ }
+ zvm->reason = out->reason;
+ }
+ }
+ else
+ syslog (LOG_ERR, "Error receiving from SMAPI - %m");
+
+ (void) zvm_smapi_close (zvm);
+
+ return (rc);
+}
+
+/**
+ * zvm_smapi_close:
+ * @zvm: z/VM driver information
+ *
+ * Close a connection with the z/VM SMAPI server
+ */
+int
+zvm_smapi_close (zvm_driver_t * zvm)
+{
+ close (zvm->sd);
+ return (0);
+}
+
+/**
+ * zvm_smapi_reportError
+ * @inHdr - Input parameter list header
+ * @outHdr - Output parameter list header
+ *
+ * Report an error from the SMAPI server
+ */
+static int
+zvm_smapi_reportError (void *inHdr, void *oHdr)
+{
+ struct _inParm
+ {
+ int32_t lPlist;
+ int32_t lFName;
+ char fName[0];
+ } *inParm = inHdr;
+ smapiOutHeader_t *outHdr = oHdr;
+ char fName[64];
+
+ memset (fName, 0, sizeof (fName));
+ memcpy (fName, inParm->fName, inParm->lFName);
+ syslog (LOG_ERR, "%s - returned (%d,%d)",
+ fName, outHdr->rc, outHdr->reason);
+ return (-1);
+}
+
+
+/**
+ * trim - Trim spaces from string
+ * @str - Pointer to string
+ *
+ */
+static int
+trim (char *str)
+{
+ char *p;
+ int len;
+
+ if (!str)
+ return (0);
+
+ len = strlen (str);
+
+ while (len--) {
+ if (isspace (str[len])) {
+ str[len] = 0;
+ }
+ else {
+ break;
+ }
+ }
+
+ for (p = str; *p && isspace (*p); p++);
+
+ memmove (str, p, strlen (p) + 1);
+
+ return (strlen (str));
+}
+
+/**
+ * zvm_metadata - Show fence metadata
+ * @self - Path to this executable
+ *
+ */
+static int
+zvm_metadata ()
+{
+ fprintf (stdout, "<?xml version=\"1.0\" ?>\n");
+ fprintf (stdout, "<resource-agent name=\"fence_zvm\"");
+ fprintf (stdout,
+ " shortdesc=\"Fence agent for use with z/VM Virtual Machines\">\n");
+ fprintf (stdout, "<longdesc>");
+ fprintf (stdout,
+ "The fence_zvm agent is intended to be used with with z/VM SMAPI service.");
+ fprintf (stdout, "</longdesc>\n");
+ fprintf (stdout, "<vendor-url>http://www.ibm.com</vendor-url>\n");
+
+ fprintf (stdout, "<parameters>\n");
+
+ fprintf (stdout,
+ "\t<parameter name=\"port\" unique=\"1\" required=\"1\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-n, --plug\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Name of the Virtual Machine to be fenced");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout,
+ "\t<parameter name=\"ipaddr\" unique=\"1\" required=\"1\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-a, --ip\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Name of the SMAPI IUCV Server Virtual Machine");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout,
+ "\t<parameter name=\"zvmsys\" unique=\"1\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"--zvmsys\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Node of the SMAPI IUCV Server Virtual Machine");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout,
+ "\t<parameter name=\"action\" unique=\"1\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-o, --action\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" default=\"off\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Fencing action");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout,
+ "\t<parameter name=\"delay\" unique=\"1\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"--delay\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" default=\"0\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Time to delay fencing action in seconds");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout,
+ "\t<parameter name=\"usage\" unique=\"1\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-h, --help\" />\n");
+ fprintf (stdout, "\t\t<content type=\"boolean\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Print usage");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "</parameters>\n");
+
+ fprintf (stdout, "<actions>\n");
+ fprintf (stdout, "\t<action name=\"off\" />\n");
+ fprintf (stdout, "\t<action name=\"on\" automatic=\"0\" />\n");
+ fprintf (stdout, "\t<action name=\"list\" />\n");
+ fprintf (stdout, "\t<action name=\"metadata\" />\n");
+ fprintf (stdout, "\t<action name=\"monitor\" />\n");
+ fprintf (stdout, "\t<action name=\"reboot\" />\n");
+ fprintf (stdout, "\t<action name=\"status\" />\n");
+ fprintf (stdout, "</actions>\n");
+
+ fprintf (stdout, "</resource-agent>\n");
+
+ return (0);
+
+}
+
+/**
+ * get_options_stdin - get options from stdin
+ * @zvm - Pointer to driver information
+ *
+ */
+static int
+get_options_stdin (zvm_driver_t * zvm)
+{
+ char buf[1024], *endPtr, *opt, *arg;
+ int32_t lSrvName, lSrvNode, lTarget;
+ int fence = ACT_OFFON;
+
+ while (fgets (buf, sizeof (buf), stdin) != 0) {
+ if (trim (buf) == 0) {
+ continue;
+ }
+ if (buf[0] == '#') {
+ continue;
+ }
+
+ opt = buf;
+
+ if ((arg = strchr (opt, '=')) != 0) {
+ *arg = 0;
+ arg++;
+ }
+ else {
+ continue;
+ }
+
+ if (trim (arg) == 0)
+ continue;
+
+ if (!strcasecmp (opt, "action")) {
+ if (strcasecmp (arg, "reboot") == 0) {
+ fence = ACT_OFFON;
+ }
+ else if (strcasecmp (arg, "off") == 0) {
+ fence = ACT_OFF;
+ }
+ else if (strcasecmp (arg, "on") == 0) {
+ fence = ACT_ON;
+ }
+ else if (strcasecmp (arg, "metadata") == 0) {
+ fence = ACT_METADATA;
+ }
+ else if (strcasecmp (arg, "status") == 0) {
+ fence = ACT_STATUS;
+ }
+ else if (strcasecmp (arg, "monitor") == 0) {
+ fence = ACT_MONITOR;
+ }
+ else if (strcasecmp (arg, "list") == 0) {
+ fence = ACT_LIST;
+ }
+ else {
+ fence = ACT_HELP;
+ }
+ }
+ else if (!strcasecmp (opt, "ipaddr")) {
+ lSrvName = MIN (strlen (arg), sizeof (zvm->smapiSrv));
+ memcpy (zvm->smapiSrv, arg, lSrvName);
+ continue;
+ }
+ else if (!strcasecmp (opt, "port")) {
+ lTarget =
+ MIN (strlen (arg), sizeof (zvm->target) - 1);
+ strncpy (zvm->target, arg, lTarget);
+ continue;
+ }
+ else if (!strcasecmp (opt, "timeout")) {
+ zvm->timeOut = strtoul (arg, &endPtr, 10);
+ if (*endPtr != 0) {
+ syslog (LOG_WARNING,
+ "Invalid timeout value specified %s "
+ "defaulting to %d", arg,
+ DEFAULT_DELAY);
+ zvm->timeOut = DEFAULT_DELAY;
+ }
+ }
+ else if (!strcasecmp (opt, "zvmsys")) {
+ lSrvNode = MIN (strlen (arg), sizeof (zvm->node));
+ memcpy (zvm->node, arg, lSrvNode);
+ continue;
+ }
+ else if (!strcasecmp (opt, "delay")) {
+ zvm->delay = strtoul (arg, &endPtr, 10);
+ if (*endPtr != 0) {
+ syslog (LOG_WARNING,
+ "Invalid delay value specified %s "
+ "defaulting to %d", arg,
+ DEFAULT_DELAY);
+ zvm->delay = DEFAULT_DELAY;
+ }
+ }
+ else if (!strcasecmp (opt, "help")) {
+ fence = ACT_HELP;
+ }
+ }
+ return (fence);
+}
+
+/**
+ * get_options - get options from the command line
+ * @argc - Count of arguments
+ * @argv - Array of character strings
+ * @zvm - Pointer to driver information
+ *
+ */
+static int
+get_options (int argc, char **argv, zvm_driver_t * zvm)
+{
+ int c, fence = ACT_OFFON;
+ int32_t lSrvName, lSrvNode, lTarget;
+ char *endPtr;
+
+ while ((c =
+ getopt_long (argc, argv, optString, longopts, NULL)) != -1) {
+ switch (c) {
+ case 'n':
+ lTarget = MIN (strlen (optarg), sizeof (zvm->target));
+ memcpy (zvm->target, optarg, lTarget);
+ break;
+ case 'o':
+ if (strcasecmp (optarg, "reboot") == 0) {
+ fence = ACT_OFFON;
+ }
+ else if (strcasecmp (optarg, "off") == 0) {
+ fence = ACT_OFF;
+ }
+ else if (strcasecmp (optarg, "on") == 0) {
+ fence = ACT_ON;
+ }
+ else if (strcasecmp (optarg, "metadata") == 0) {
+ fence = ACT_METADATA;
+ }
+ else if (strcasecmp (optarg, "status") == 0) {
+ fence = ACT_STATUS;
+ }
+ else if (strcasecmp (optarg, "monitor") == 0) {
+ fence = ACT_MONITOR;
+ }
+ else if (strcasecmp (optarg, "list") == 0) {
+ fence = ACT_LIST;
+ }
+ else {
+ fence = ACT_HELP;
+ }
+ break;
+ case 'a':
+ lSrvName =
+ MIN (strlen (optarg), sizeof (zvm->smapiSrv));
+ memcpy (zvm->smapiSrv, optarg, lSrvName);
+ break;
+ case 'T':
+ zvm->timeOut = strtoul (optarg, &endPtr, 10);
+ if (*endPtr != 0) {
+ syslog (LOG_WARNING,
+ "Invalid timeout value specified: %s - "
+ "defaulting to %d", optarg,
+ DEFAULT_TIMEOUT);
+ zvm->timeOut = DEFAULT_TIMEOUT;
+ }
+ break;
+ case 'd':
+ zvm->delay = strtoul (optarg, &endPtr, 10);
+ if (*endPtr != 0) {
+ syslog (LOG_WARNING,
+ "Invalid delay value specified: %s - "
+ "defaulting to %d", optarg,
+ DEFAULT_DELAY);
+ zvm->delay = DEFAULT_DELAY;
+ }
+ break;
+ case 'z':
+ lSrvNode = MIN (strlen (optarg), sizeof (zvm->node));
+ memcpy (zvm->node, optarg, lSrvNode);
+ break;
+ default:
+ fence = ACT_HELP;
+ }
+ }
+ return (fence);
+}
+
+/**
+ * usage - display command syntax and parameters
+ *
+ */
+static int
+usage ()
+{
+ printf ("Usage: fence_zvm [options]\n\n"
+ "\tWhere [options] =\n"
+ "\t-o --action [action] - \"off\", \"on\", \"list\", \"metadata\", "
+ "\"monitor\", \"reboot\", \"status\"\n"
+ "\t--delay [seconds] - Time to delay fencing action in seconds\n"
+ "\t-n --plug [target] - Name of virtual machine to fence\n"
+ "\t-a --ip [server] - Name of SMAPI IUCV Request server\n"
+ "\t-T --timeout [secs] - Time to wait for fence in seconds - currently ignored\n"
+ "\t--zvmsys [node] - z/VM Node on which SMAPI server lives\n"
+ "\t-h --help - Display this usage information\n");
+ return (0);
+}
+
+/**
+ * check_param - Check that mandatory parameters have been specified
+ * @zvm - Pointer to driver information
+ *
+ */
+static int
+check_parm (zvm_driver_t * zvm)
+{
+ int rc;
+
+ if (zvm->smapiSrv[0] != 0) {
+ if (zvm->target[0] != 0) {
+ rc = 0;
+ }
+ else {
+ syslog (LOG_ERR, "Missing fence target name");
+ rc = 2;
+ }
+ }
+ else {
+ syslog (LOG_ERR, "Missing SMAPI server name");
+ rc = 1;
+ }
+ return (rc);
+}
+
+int
+main (int argc, char **argv)
+{
+ zvm_driver_t zvm;
+ int fence, rc = 0;
+
+ openlog ("fence_zvm", LOG_CONS | LOG_PID, LOG_DAEMON);
+ memset (&zvm, 0, sizeof (zvm));
+ zvm.timeOut = DEFAULT_TIMEOUT;
+ zvm.delay = DEFAULT_DELAY;
+
+ if (argc > 1)
+ fence = get_options (argc, argv, &zvm);
+ else
+ fence = get_options_stdin (&zvm);
+
+ switch (fence) {
+ case ACT_OFFON: // OFFON
+ if ((rc = check_parm (&zvm)) == 0)
+ rc = zvm_smapi_imageRecycle (&zvm);
+ break;
+ case ACT_OFF: // OFF
+ if ((rc = check_parm (&zvm)) == 0)
+ rc = zvm_smapi_imageDeactivate (&zvm);
+ break;
+ case ACT_ON: // ON
+ if ((rc = check_parm (&zvm)) == 0)
+ rc = zvm_smapi_imageActivate (&zvm);
+ break;
+ case ACT_METADATA: // METADATA
+ rc = zvm_metadata ();
+ break;
+ case ACT_STATUS: // STATUS
+ if ((rc = check_parm (&zvm)) == 0)
+ rc = zvm_smapi_imageQuery (&zvm);
+ break;
+ case ACT_MONITOR: // MONITOR
+ rc = 0;
+ break;
+ case ACT_LIST: // LIST
+ printf ("N/A");
+ rc = 0;
+ break;
+ case ACT_HELP:
+ rc = usage ();
+ }
+ closelog ();
+ return (rc);
+}
+#else
+#include <syslog.h>
+int
+main (int argc, char **argv)
+{
+ openlog ("fence_zvm", LOG_CONS | LOG_PID, LOG_DAEMON);
+ syslog (LOG_ERR,
+ "Fencing of a z/VM agent is not possible on this platform\n");
+ closelog ();
+ return (-1);
+}
+#endif