Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4833052
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/fence/agents/powerman/Makefile.am b/fence/agents/powerman/Makefile.am
new file mode 100644
index 00000000..99fe199d
--- /dev/null
+++ b/fence/agents/powerman/Makefile.am
@@ -0,0 +1,17 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+TARGET = fence_powerman
+
+SRC = $(TARGET).py
+
+EXTRA_DIST = $(SRC)
+
+sbin_SCRIPTS = $(TARGET)
+
+man_MANS = $(TARGET).8
+
+FENCE_TEST_ARGS = -l test -p test -a test -n 1
+
+include $(top_srcdir)/make/fencebuild.mk
+include $(top_srcdir)/make/fenceman.mk
+include $(top_srcdir)/make/agentpycheck.mk
diff --git a/fence/agents/powerman/fence_powerman.8 b/fence/agents/powerman/fence_powerman.8
new file mode 100644
index 00000000..2923cdee
--- /dev/null
+++ b/fence/agents/powerman/fence_powerman.8
@@ -0,0 +1,221 @@
+
+.TH FENCE_AGENT 8 2009-10-20 "fence_powerman (Fence Agent)"
+.SH NAME
+fence_powerman - Fence Agent for Powerman
+.SH DESCRIPTION
+.P
+This is a Pacemaker Fence Agent for the Powerman management utility that was designed for LLNL systems.
+.P
+fence_powerman accepts options on the command line as well
+as from stdin. Fenced sends parameters through stdin when it execs the
+agent. fence_powerman can be run by itself with command
+line options. This is useful for testing and for turning outlets on or off
+from scripts.
+
+Vendor URL: https://github.com/chaos/powerman
+.SH PARAMETERS
+
+
+.TP
+.B -o, --action=[action]
+.
+Fencing action (Default Value: reboot)
+
+.TP
+.B -4, --inet4-only
+.
+Forces agent to use IPv4 addresses only
+
+.TP
+.B -6, --inet6-only
+.
+Forces agent to use IPv6 addresses only
+
+.TP
+.B -a, --ip=[ip]
+.
+IP address or hostname of fencing device
+
+.TP
+.B -u, --ipport=[port]
+.
+TCP/UDP port to use for connection with device (Default Value: 10101)
+
+.TP
+.B -n, --plug=[ip]
+.
+IP address or hostname of fencing device (together with --port-as-ip)
+
+.TP
+.B -v, --verbose
+.
+Verbose mode
+
+.TP
+.B -D, --debug-file=[debugfile]
+.
+Write debug information to given file
+
+.TP
+.B -V, --version
+.
+Display version information and exit
+
+.TP
+.B -h, --help
+.
+Display help and exit
+
+.TP
+.B --delay=[seconds]
+.
+Wait X seconds before fencing is started (Default Value: 3)
+
+.TP
+.B --login-timeout=[seconds]
+.
+Wait X seconds for cmd prompt after login (Default Value: 5)
+
+.TP
+.B --port-as-ip
+.
+Make "port/plug" to be an alias to IP address
+
+.TP
+.B --power-timeout=[seconds]
+.
+Test X seconds for status change after ON/OFF (Default Value: 20)
+
+.TP
+.B --power-wait=[seconds]
+.
+Wait X seconds after issuing ON/OFF (Default Value: 3)
+
+.TP
+.B --shell-timeout=[seconds]
+.
+Wait X seconds for cmd prompt after issuing command (Default Value: 3)
+
+.TP
+.B --retry-on=[attempts]
+.
+Count of attempts to retry power on (Default Value: 1)
+
+.SH ACTIONS
+
+
+.TP
+\fBon \fP
+Power on machine.
+
+.TP
+\fBoff \fP
+Power off machine.
+
+.TP
+\fBreboot \fP
+Reboot machine.
+
+.TP
+\fBstatus \fP
+This returns the status of the plug/virtual machine.
+
+.TP
+\fBmonitor \fP
+Check the health of fence device
+
+.TP
+\fBmetadata \fP
+Display the XML metadata describing this resource.
+
+.TP
+\fBvalidate-all \fP
+Validate if all required parameters are entered.
+
+.SH STDIN PARAMETERS
+
+
+.TP
+.B action
+.
+Fencing action (Default Value: reboot)
+
+.TP
+.B inet4_only
+.
+Forces agent to use IPv4 addresses only
+
+.TP
+.B inet6_only
+.
+Forces agent to use IPv6 addresses only
+
+.TP
+.B ipaddr
+.
+IP address or hostname of fencing device
+
+.TP
+.B ipport
+.
+TCP/UDP port to use for connection with device (Default Value: 10101)
+
+.TP
+.B port
+.
+IP address or hostname of fencing device (together with --port-as-ip)
+
+.TP
+.B verbose
+.
+Verbose mode
+
+.TP
+.B debug
+.
+Write debug information to given file
+
+.TP
+.B version
+.
+Display version information and exit
+
+.TP
+.B help
+.
+Display help and exit
+
+.TP
+.B delay
+.
+Wait X seconds before fencing is started (Default Value: 3)
+
+.TP
+.B login_timeout
+.
+Wait X seconds for cmd prompt after login (Default Value: 5)
+
+.TP
+.B port_as_ip
+.
+Make "port/plug" to be an alias to IP address
+
+.TP
+.B power_timeout
+.
+Test X seconds for status change after ON/OFF (Default Value: 20)
+
+.TP
+.B power_wait
+.
+Wait X seconds after issuing ON/OFF (Default Value: 3)
+
+.TP
+.B shell_timeout
+.
+Wait X seconds for cmd prompt after issuing command (Default Value: 3)
+
+.TP
+.B retry_on
+.
+Count of attempts to retry power on (Default Value: 1)
diff --git a/fence/agents/powerman/fence_powerman.py b/fence/agents/powerman/fence_powerman.py
new file mode 100755
index 00000000..f168e28d
--- /dev/null
+++ b/fence/agents/powerman/fence_powerman.py
@@ -0,0 +1,238 @@
+#!/usr/bin/env python
+import os
+import time
+from datetime import datetime
+import sys
+import subprocess
+import re
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import run_delay
+import logging
+
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION="Powerman Fencing Agent"
+REDHAT_COPYRIGHT=""
+BUILD_DATE=""
+#END_VERSION_GENERATION
+
+
+#### important!!! #######
+class PowerMan:
+ """Python wrapper for calling powerman commands
+
+ This class makes calls to a powerman deamon for a cluster of computers.
+ The make-up of such a call looks something like:
+ $ pm -h elssd1:10101 <option> <node>
+ where option is something like --off, --on, --cycle and where node is
+ elssd8, or whatever values are setup in powerman.conf (***this is key,
+ because otherwise this code will not work!)
+ """
+ program_name = "powerman"
+
+ def __init__(self, server_name, port="10101"):
+ """
+ Args:
+ server_name: (string) host or ip of powerman server
+ port: (str) port number that the powerman server is listening on
+ """
+ self.server_name = server_name
+ self.port = port
+ self.server_and_port = server_name + ":" + str(port)
+ # this is a list of the command and its options. For example:
+ # ['powerman', '--server-host', 'elssd1:10101']
+ self.base_cmd = [
+ self.program_name,
+ "--server-host",
+ self.server_and_port
+ ]
+
+ def _run(self, cmd):
+ # Args:
+ # cmd: (list) commands and arguments to pass to the program_name
+
+ # add the 2 command lists together to get whole command to run
+ run_this = self.base_cmd + cmd
+ try:
+ popen = subprocess.Popen(run_this, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ out = popen.communicate()
+ except OSError as e:
+ logging.debug("_run command error: %s\n", e)
+ sys.exit(1)
+
+ result = out[0].decode().strip()
+ return (result, popen.returncode)
+
+ def is_running(self):
+ """simple query to see if powerman server is responding. Returns boolean"""
+ cmd = ["-q"] # just check if we get a response from the server
+ result, ret_code = self._run(cmd)
+ if ret_code != 0:
+ return False
+ return True
+
+ def on(self, host):
+ logging.debug("PowerMan on: %s\n", host)
+ cmd = ["--on", host]
+ try:
+ result, ret_code = self._run(cmd)
+ except OSError as e:
+ logging.debug("PowerMan Error: The command '--on' failed: %s\n", e)
+ return -1
+ except ValueError as e:
+ logging.debug("PowerMan Error: Popen: invalid arguments: %s\n", e)
+ return -1
+ logging.debug("result: %s ret_code: %s\n", result, ret_code)
+ return ret_code
+
+ def off(self, host):
+ logging.debug("PowerMan off: %s\n", host)
+ cmd = ["--off", host]
+ try:
+ result, ret_code = self._run(cmd)
+ except OSError as e:
+ logging.debug("PowerMan Error: The command '%s' failed: %s\n", cmd, e)
+ return -1
+ except ValueError as e:
+ logging.debug("PowerMan Error: Popen: invalid arguments: %s\n", e)
+ return -1
+ logging.debug("%s\n", result)
+ return ret_code
+
+ def query(self, host):
+ cmd = ["--query", host]
+ try:
+ result, ret_code = self._run(cmd)
+ except OSError as e:
+ logging.debug("PowerMan Error: The command '%s' failed: %s\n", cmd, e)
+ return -1
+ except ValueError as e:
+ logging.debug("PowerMan Error: Popen: invalid arguments: %s\n", e)
+ return -1
+ if ret_code < 0:
+ # there was an error with the command
+ return ret_code
+ else:
+ res = result.split('\n')
+ res = [r.split() for r in res]
+ # find the host in command's returned output
+ for lst in res:
+ if lst[0] == 'No' and lst[1] == 'such' and lst[2] == 'nodes:':
+ return -1
+ if host in lst:
+ return lst[0][:-1] # lst[0] would be 'off:'-- this removes the colon
+ # host isn't in the output
+ return -1
+
+
+def get_power_status(conn, options):
+ logging.debug("get_power_status function:\noptions: %s\n", str(options))
+ pm = PowerMan(options['--ip'], options['--ipport'])
+ # if Pacemaker is checking the status of the Powerman server...
+ if options['--action'] == 'monitor':
+ if pm.is_running():
+ logging.debug("Powerman is running\n")
+ return "on"
+ logging.debug("Powerman is NOT running\n")
+ return "off"
+ else:
+ status = pm.query(options['--plug'])
+ if isinstance(int, type(status)):
+ # query only returns ints on error
+ logging.debug("get_power_status: query returned %s\n", str(status))
+ fail(EC_STATUS)
+ return status
+
+
+def set_power_status(conn, options):
+ logging.debug("set_power_status function:\noptions: %s", str(options))
+ pm = PowerMan(options['--ip'], options['--ipport'])
+
+ action = options["--action"]
+ if action == "on":
+ pm.on(options['--plug'])
+ elif action == "off":
+ pm.off(options['--plug'])
+
+ return
+
+
+def reboot(conn, options):
+ logging.debug("reboot function:\noptions: %s", str(options))
+ pm = PowerMan(options['--ip'], options['--ipport'])
+ res = pm.off(options['--plug'])
+ if res < 0:
+ logging.debug("reboot: power off failed!\n")
+ return False
+ time.sleep(2)
+ res = pm.on(options['--plug'])
+ if res < 0:
+ logging.debug("reboot: power on failed!\n")
+ return False
+ return True
+
+
+def get_list(conn, options):
+ # TODO: make this function return a dictionary of hosts and their statuses
+ # by iterating over options['--plugs'] (I think???) and querying powerman
+ logging.debug("get_list function:\noptions: %s", str(options))
+ outlets = {'elssd8': 'on', 'elssd9': 'on'}
+ return outlets
+
+
+def define_new_opts():
+ """add elements to all_opt dict if you need to define new options"""
+ pass
+
+
+def main():
+ device_opt = [
+ 'ipaddr',
+ 'no_password',
+ 'no_login',
+ ]
+
+ atexit.register(atexit_handler)
+
+ define_new_opts()
+
+ # redefine default values for the options given by fencing.py
+ # these 3 different values are derived from the lssd test cluster and may
+ # need to adjusted depending on how other systems fare
+ all_opt['ipport']['default'] = '10101'
+ all_opt['delay']['default'] = '3'
+ all_opt['power_wait']['default'] = '3'
+
+ options = check_input(device_opt, process_input(device_opt))
+ logging.debug("fence_powerman.main: options: %s", str(options))
+ docs = {}
+ docs["shortdesc"] = "Fence Agent for Powerman"
+ docs["longdesc"] = "This is a Pacemaker Fence Agent for the \
+Powerman management utility that was designed for LLNL systems."
+ docs["vendorurl"] = "https://github.com/chaos/powerman"
+ show_docs(options, docs)
+
+ ## Do the delay of the fence device
+ run_delay(options)
+
+ if options["--action"] in ["off", "reboot"]:
+ # add extra delay if rebooting
+ time.sleep(int(options["--delay"]))
+
+ # call the fencing.fence_action function, passing in my various fence functions
+ result = fence_action(
+ None,
+ options,
+ set_power_status,
+ get_power_status,
+ None,
+ reboot
+ )
+
+ sys.exit(result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/data/metadata/fence_powerman.xml b/tests/data/metadata/fence_powerman.xml
new file mode 100644
index 00000000..df77e015
--- /dev/null
+++ b/tests/data/metadata/fence_powerman.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_powerman" shortdesc="Fence Agent for Powerman" >
+<longdesc>This is a Pacemaker Fence Agent for the Powerman management utility that was designed for LLNL systems.</longdesc>
+<vendor-url>https://github.com/chaos/powerman</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="10101" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jul 20, 8:38 PM (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2081433
Default Alt Text
(15 KB)
Attached To
Mode
rF Fence Agents
Attached
Detach File
Event Timeline
Log In to Comment