[Cluster-devel] [PATCH] fencing: fix parsing issue with options which don't have short opt

2014-06-26 Thread Ondrej Mular
There was problem with options which have value, but we don't want short opt 
for them. In this case we can now use getopt = :.

---
 fence/agents/lib/fencing.py.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py
index 5084f24..2cfa046 100644
--- a/fence/agents/lib/fencing.py.py
+++ b/fence/agents/lib/fencing.py.py
@@ -559,7 +559,8 @@ def process_input(avail_opt):
getopt_string = 
longopt_list = []
for k in avail_opt:
-   if all_opt.has_key(k):
+   if all_opt.has_key(k) and all_opt[k][getopt] != ::
+   # getopt == : means that opt is without short getopt, 
but has value
getopt_string += all_opt[k][getopt]
else:
fail_usage(Parse error: unknown option '+k+')
-- 
1.8.3.1



Re: [Cluster-devel] [PATCH] fence_docker: new fence agent for Docker containers

2014-06-26 Thread Ondrej Mular
With support for TLS authentication.

---
 .gitignore   |   1 +
 configure.ac |   1 +
 fence/agents/docker/Makefile.am  |  20 +
 fence/agents/docker/fence_docker.py  | 152 +++
 tests/data/metadata/fence_docker.xml | 129 +
 5 files changed, 303 insertions(+)
 create mode 100644 fence/agents/docker/Makefile.am
 create mode 100644 fence/agents/docker/fence_docker.py
 create mode 100644 tests/data/metadata/fence_docker.xml

diff --git a/.gitignore b/.gitignore
index 75b9aa7..8bcae2b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,6 +39,7 @@ fence/agents/bullpap/fence_bullpap
 fence/agents/cisco_mds/fence_cisco_mds
 fence/agents/cisco_ucs/fence_cisco_ucs
 fence/agents/cpint/fence_cpint
+fence/agents/docker/fence_docker
 fence/agents/drac/fence_drac
 fence/agents/drac5/fence_drac5
 fence/agents/eaton_snmp/fence_eaton_snmp
diff --git a/configure.ac b/configure.ac
index 4d0aa6a..bc9785b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -264,6 +264,7 @@ AC_CONFIG_FILES([Makefile
 fence/agents/brocade/Makefile
 fence/agents/cisco_mds/Makefile
 fence/agents/cisco_ucs/Makefile
+fence/agents/docker/Makefile
 fence/agents/drac/Makefile
 fence/agents/drac5/Makefile
 fence/agents/dummy/Makefile
diff --git a/fence/agents/docker/Makefile.am b/fence/agents/docker/Makefile.am
new file mode 100644
index 000..a232902
--- /dev/null
+++ b/fence/agents/docker/Makefile.am
@@ -0,0 +1,20 @@
+MAINTAINERCLEANFILES   = Makefile.in
+
+TARGET = fence_docker
+
+SRC= $(TARGET).py
+
+EXTRA_DIST = $(SRC)
+
+sbin_SCRIPTS   = $(TARGET)
+
+man_MANS   = $(TARGET).8
+
+FENCE_TEST_ARGS= -a test -n 1
+
+include $(top_srcdir)/make/fencebuild.mk
+include $(top_srcdir)/make/fenceman.mk
+include $(top_srcdir)/make/agentpycheck.mk
+
+clean-local: clean-man
+   rm -f $(TARGET)
diff --git a/fence/agents/docker/fence_docker.py 
b/fence/agents/docker/fence_docker.py
new file mode 100644
index 000..7363611
--- /dev/null
+++ b/fence/agents/docker/fence_docker.py
@@ -0,0 +1,152 @@
+#!/usr/bin/python -tt
+
+import atexit
+import sys
+import StringIO
+import logging
+import pycurl
+import json
+
+sys.path.append(@FENCEAGENTSLIBDIR@)
+from fencing import fail_usage, all_opt, fence_action, atexit_handler, 
check_input, process_input, show_docs, run_delay
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION = 
+REDHAT_COPYRIGHT = 
+BUILD_DATE = 
+#END_VERSION_GENERATION
+
+def get_power_status(conn, options):
+   del conn
+   status = send_cmd(options, containers/%s/json % options[--plug])
+   if status is None:
+   return None
+   return on if status[State][Running] else off
+
+
+def set_power_status(conn, options):
+   del conn
+   if options[--action] == on:
+   send_cmd(options, containers/%s/start % options[--plug], 
True)
+   else:
+   send_cmd(options, containers/%s/kill % options[--plug], 
True)
+   return
+
+
+def reboot_cycle(conn, options):
+   del conn
+   send_cmd(options, containers/%s/restart % options[--plug], True)
+   return get_power_status(conn, options)
+
+
+def get_list(conn, options):
+   del conn
+   output = send_cmd(options, containers/json?all=1)
+   containers = {}
+   for container in output:
+   containers[container[Id]] = (container[Names][0], 
{True:off, False: on}[container[Status][:4].lower() == exit])
+   return containers
+
+
+def send_cmd(options, cmd, post = False):
+   url = http%s://%s:%s/v1.11/%s % (s if --ssl in options else , 
options[--ip], options[--ipport], cmd)
+   conn = pycurl.Curl()
+   output_buffer = StringIO.StringIO()
+   if logging.getLogger().getEffectiveLevel()  logging.WARNING:
+   conn.setopt(pycurl.VERBOSE, True)
+   conn.setopt(pycurl.HTTPGET, 1)
+   conn.setopt(pycurl.URL, str(url))
+   if post:
+   conn.setopt(pycurl.POST, 1)
+   conn.setopt(pycurl.POSTFIELDSIZE, 0)
+   conn.setopt(pycurl.WRITEFUNCTION, output_buffer.write)
+   conn.setopt(pycurl.TIMEOUT, int(options[--shell-timeout]))
+   if --ssl in options:
+   if not (set((--tlscert, --tlskey, --tlscacert)) = 
set(options)):
+   fail_usage(Failed. If --ssl option is used, You have 
to also \
+specify: --tlscert, --tlskey and --tlscacert)
+   conn.setopt(pycurl.SSL_VERIFYPEER, 1)
+   conn.setopt(pycurl.SSLCERT, options[--tlscert])
+   conn.setopt(pycurl.SSLKEY, options[--tlskey])
+   conn.setopt(pycurl.CAINFO, options[--tlscacert])
+   else:
+   conn.setopt(pycurl.SSL_VERIFYPEER, 0)
+   conn.setopt(pycurl.SSL_VERIFYHOST, 0)
+
+   

[Cluster-devel] [PATCH] fence_docker: new fence agent for Docker containers

2014-06-09 Thread Ondrej Mular
---
 .gitignore   |   1 +
 configure.ac |   1 +
 fence/agents/docker/Makefile.am  |  18 ++
 fence/agents/docker/fence_docker.py  |  72 +++
 tests/data/metadata/fence_docker.xml | 109 +++
 5 files changed, 201 insertions(+)
 create mode 100644 fence/agents/docker/Makefile.am
 create mode 100644 fence/agents/docker/fence_docker.py
 create mode 100644 tests/data/metadata/fence_docker.xml

diff --git a/.gitignore b/.gitignore
index 75b9aa7..8bcae2b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,6 +39,7 @@ fence/agents/bullpap/fence_bullpap
 fence/agents/cisco_mds/fence_cisco_mds
 fence/agents/cisco_ucs/fence_cisco_ucs
 fence/agents/cpint/fence_cpint
+fence/agents/docker/fence_docker
 fence/agents/drac/fence_drac
 fence/agents/drac5/fence_drac5
 fence/agents/eaton_snmp/fence_eaton_snmp
diff --git a/configure.ac b/configure.ac
index 4d0aa6a..bc9785b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -264,6 +264,7 @@ AC_CONFIG_FILES([Makefile
 fence/agents/brocade/Makefile
 fence/agents/cisco_mds/Makefile
 fence/agents/cisco_ucs/Makefile
+fence/agents/docker/Makefile
 fence/agents/drac/Makefile
 fence/agents/drac5/Makefile
 fence/agents/dummy/Makefile
diff --git a/fence/agents/docker/Makefile.am b/fence/agents/docker/Makefile.am
new file mode 100644
index 000..f3d53be
--- /dev/null
+++ b/fence/agents/docker/Makefile.am
@@ -0,0 +1,18 @@
+MAINTAINERCLEANFILES   = Makefile.in
+
+TARGET = fence_docker
+
+SRC= $(TARGET).py
+
+EXTRA_DIST = $(SRC)
+
+sbin_SCRIPTS   = $(TARGET)
+
+man_MANS   = $(TARGET).8
+
+include $(top_srcdir)/make/fencebuild.mk
+include $(top_srcdir)/make/fenceman.mk
+include $(top_srcdir)/make/agentpycheck.mk
+
+clean-local: clean-man
+   rm -f $(TARGET)
diff --git a/fence/agents/docker/fence_docker.py 
b/fence/agents/docker/fence_docker.py
new file mode 100644
index 000..63ce6b8
--- /dev/null
+++ b/fence/agents/docker/fence_docker.py
@@ -0,0 +1,72 @@
+#!/usr/bin/python -tt
+
+import atexit
+import sys
+import docker
+import logging
+
+sys.path.append(@FENCEAGENTSLIBDIR@)
+from fencing import fail_usage, all_opt, fence_action, atexit_handler, 
check_input, process_input, show_docs, run_delay, fail, EC_LOGIN_DENIED
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION = 
+REDHAT_COPYRIGHT = 
+BUILD_DATE = 
+#END_VERSION_GENERATION
+
+def get_power_status(conn, options):
+   try:
+   status = conn.inspect_container(container=options[--plug])
+   return on if status[State][Running] else off
+   except Exception:
+   return None
+
+
+def set_power_status(conn, options):
+   if options[--action] == on:
+   conn.start(container=options[--plug])
+   else:
+   conn.kill(container=options[--plug])
+   return
+
+
+def reboot_cycle(conn, options):
+   conn.restart(container=options[--plug], 
timeout=float(options[--power-timeout]))
+   return get_power_status(conn, options)
+
+
+def get_list(conn, options):
+   output = conn.containers(all=True)
+   containers = {}
+   for container in output:
+   containers[container[Id]] = (; .join(container[Names]), 
{True:off, False: on}[container[Status][:4].lower() == exit])
+   return containers
+
+
+def main():
+   atexit.register(atexit_handler)
+
+   device_opt = [ipaddr, no_password, port, method]
+
+   options = check_input(device_opt, process_input(device_opt))
+
+   docs = { }
+   docs[shortdesc] = Fence agent for Docker
+   docs[longdesc] = fence_docker is I/O fencing agent which can be used 
with the Docker Engine containers.
+   docs[vendorurl] = www.docker.io
+   show_docs(options, docs)
+
+   run_delay(options)
+
+   conn = docker.Client(base_url = http://; + options[--ip] + : + 
str(options[--ipport]), version = 1.9, timeout = 
float(options[--shell-timeout]))
+
+   try:
+   result = fence_action(conn, options, set_power_status, 
get_power_status, get_list, reboot_cycle)
+   except IOError as ex:
+   logging.debug(ex.message)
+   fail(EC_LOGIN_DENIED)
+
+   sys.exit(result)
+
+if __name__ == __main__:
+   main()
diff --git a/tests/data/metadata/fence_docker.xml 
b/tests/data/metadata/fence_docker.xml
new file mode 100644
index 000..19cdd0a
--- /dev/null
+++ b/tests/data/metadata/fence_docker.xml
@@ -0,0 +1,109 @@
+?xml version=1.0 ?
+resource-agent name=fence_docker shortdesc=Fence agent for Docker 
+longdescfence_docker is I/O fencing agent which can be used with the Docker 
Engine containers./longdesc
+vendor-urlwww.docker.io/vendor-url
+parameters
+   parameter name=ipport unique=0 required=0
+   getopt mixed=-u, --ipport=[port] /
+  

Re: [Cluster-devel] [PATCH 2/3] fence_scsi: port to fencing library

2014-05-12 Thread Ondrej Mular
I did few small changes and fix a problem in function register_dev.

---
 configure.ac  |   8 +
 fence/agents/scsi/Makefile.am |  20 +-
 fence/agents/scsi/fence_scsi.8| 119 -
 fence/agents/scsi/fence_scsi.pl   | 875 --
 fence/agents/scsi/fence_scsi.py   | 452 ++
 fence/agents/scsi/fence_scsi_check.pl | 170 ---
 make/fencebuild.mk|   4 +
 7 files changed, 475 insertions(+), 1173 deletions(-)
 delete mode 100644 fence/agents/scsi/fence_scsi.8
 delete mode 100644 fence/agents/scsi/fence_scsi.pl
 create mode 100644 fence/agents/scsi/fence_scsi.py
 delete mode 100644 fence/agents/scsi/fence_scsi_check.pl

diff --git a/configure.ac b/configure.ac
index 5e37ee5..f208bef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -163,6 +163,10 @@ CLUSTERDATA=${datadir}/cluster
 AC_PATH_PROG([IPMITOOL_PATH], [ipmitool], [/usr/bin/ipmitool])
 AC_PATH_PROG([AMTTOOL_PATH], [amttool], [/usr/bin/amttool])
 AC_PATH_PROG([GNUTLSCLI_PATH], [gnutlscli], [/usr/bin/gnutls-cli])
+AC_PATH_PROG([COROSYNC_CMAPCTL_PATH], [corosync-cmapctl], 
[/usr/sbin/corosync-cmapctl])
+AC_PATH_PROG([SG_PERSIST_PATH], [sg_persist], [/usr/bin/sg_persist])
+AC_PATH_PROG([SG_TURS_PATH], [sg_turs], [/usr/bin/sg_turs])
+AC_PATH_PROG([VGS_PATH], [vgs], [/usr/sbin/vgs])
 ## do subst
 
 AC_SUBST([DEFAULT_CONFIG_DIR])
@@ -189,6 +193,10 @@ AM_CONDITIONAL(BUILD_XENAPILIB, test $XENAPILIB -eq 1)
 
 AC_SUBST([IPMITOOL_PATH])
 AC_SUBST([AMTTOOL_PATH])
+AC_SUBST([COROSYNC_CMAPCTL_PATH])
+AC_SUBST([SG_PERSIST_PATH])
+AC_SUBST([SG_TURS_PATH])
+AC_SUBST([VGS_PATH])
 
 ## *FLAGS handling
 
diff --git a/fence/agents/scsi/Makefile.am b/fence/agents/scsi/Makefile.am
index 5652bda..896406a 100644
--- a/fence/agents/scsi/Makefile.am
+++ b/fence/agents/scsi/Makefile.am
@@ -2,20 +2,22 @@ MAINTAINERCLEANFILES  = Makefile.in
 
 TARGET = fence_scsi
 
-SRC= $(TARGET).pl
+SYMTARGET  = fence_scsi_check
 
-EXTRA_DIST = $(SRC) \
- $(TARGET)_check.pl 
+SRC= $(TARGET).py
 
-scsidatadir= $(CLUSTERDATA)
+EXTRA_DIST = $(SRC)
 
-scsidata_SCRIPTS   = $(TARGET)_check.pl
+sbin_SCRIPTS   = $(TARGET) $(SYMTARGET)
 
-sbin_SCRIPTS   = $(TARGET)
+man_MANS   = $(TARGET).8
 
-dist_man_MANS  = $(TARGET).8
+$(SYMTARGET): $(TARGET)
+   ln -s $^ $@
 
 include $(top_srcdir)/make/fencebuild.mk
+include $(top_srcdir)/make/fenceman.mk
+include $(top_srcdir)/make/agentpycheck.mk
 
-clean-local:
-   rm -f $(TARGET)
+clean-local: clean-man
+   rm -f $(TARGET) $(SYMTARGET)
diff --git a/fence/agents/scsi/fence_scsi.8 b/fence/agents/scsi/fence_scsi.8
deleted file mode 100644
index 180de4f..000
--- a/fence/agents/scsi/fence_scsi.8
+++ /dev/null
@@ -1,119 +0,0 @@
-.TH fence_scsi 8
-
-.SH NAME
-fence_scsi - I/O fencing agent for SCSI persistent reservations
-
-.SH SYNOPSIS
-.B
-fence_scsi
-[\fIOPTION\fR]...
-
-.SH DESCRIPTION
-fence_scsi is an I/O fencing agent that uses SCSI-3 persistent
-reservations to control access to shared storage devices. These
-devices must support SCSI-3 persistent reservations (SPC-3 or greater)
-as well as the preempt-and-abort subcommand.
-
-The fence_scsi agent works by having each node in the cluster register
-a unique key with the SCSI devive(s). Once registered, a single node
-will become the reservation holder by creating a write exclusive,
-registrants only reservation on the device(s). The result is that
-only registered nodes may write to the device(s). When a node failure
-occurs, the fence_scsi agent will remove the key belonging to the
-failed node from the device(s). The failed node will no longer be able
-to write to the device(s). A manual reboot is required. In the cluster
-environment unfence action should be configured also.
-
-Keys are either be specified manually (see -k option) or generated
-automatically (see -n option). Automatic key generation requires that
-cman be running. Keys will then be generated using the cluster ID and
-node ID such that each node has a unique key that can be determined by
-any other node in the cluster.
-
-Devices can either be specified manually (see -d option) or discovered
-automatically. Multiple devices can be specified manually by using a
-comma-separated list. If no devices are specified, the fence_scsi
-agent will attempt to discover devices by looking for cluster volumes
-and extracting the underlying devices. Devices may be device-mapper
-multipath devices or raw devices. If using a device-mapper multipath
-device, the fence_scsi agent will find the underlying devices (paths)
-and created registrations for each path.
-
-.SH OPTIONS
-.TP
-\fB-o\fP \fIaction\fR
-Fencing action. This value can be on, off, status, or
-metadata. The on, off, and status actions require either a key
-(see -k option) or node name (see -n option). For on, 

[Cluster-devel] [PATCH 3/3] fence_pve: new fence-agent for Proxmox VE

2014-05-02 Thread Ondrej Mular
Thanks to Frank Brendel (author of original perl fence_pve) for help with 
writing and testing this agent.

---
 .gitignore|   1 +
 configure.ac  |   1 +
 fence/agents/pve/Makefile.am  |  18 
 fence/agents/pve/fence_pve.py | 178 ++
 tests/data/metadata/fence_pve.xml | 121 ++
 5 files changed, 319 insertions(+)
 create mode 100644 fence/agents/pve/Makefile.am
 create mode 100644 fence/agents/pve/fence_pve.py
 create mode 100644 tests/data/metadata/fence_pve.xml

diff --git a/.gitignore b/.gitignore
index 74198b2..75b9aa7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -65,6 +65,7 @@ fence/agents/node_assassin/fence_na.conf
 fence/agents/node_assassin/fence_na.lib
 fence/agents/node_assassin/fence_na.pod
 fence/agents/nss_wrapper/fence_nss_wrapper
+fence/agents/pve/fence_pve
 fence/agents/rackswitch/fence_rackswitch
 fence/agents/rhevm/fence_rhevm
 fence/agents/raritan/fence_raritan
diff --git a/configure.ac b/configure.ac
index c24198c..5e37ee5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -283,6 +283,7 @@ AC_CONFIG_FILES([Makefile
 fence/agents/netio/Makefile
 fence/agents/rackswitch/Makefile
 fence/agents/ovh/Makefile
+fence/agents/pve/Makefile
 fence/agents/raritan/Makefile
 fence/agents/rhevm/Makefile
 fence/agents/rsa/Makefile
diff --git a/fence/agents/pve/Makefile.am b/fence/agents/pve/Makefile.am
new file mode 100644
index 000..9ac184e
--- /dev/null
+++ b/fence/agents/pve/Makefile.am
@@ -0,0 +1,18 @@
+MAINTAINERCLEANFILES   = Makefile.in
+
+TARGET = fence_pve
+
+SRC= $(TARGET).py
+
+EXTRA_DIST = $(SRC)
+
+sbin_SCRIPTS   = $(TARGET)
+
+man_MANS   = $(TARGET).8
+
+include $(top_srcdir)/make/fencebuild.mk
+include $(top_srcdir)/make/fenceman.mk
+include $(top_srcdir)/make/agentpycheck.mk
+
+clean-local: clean-man
+   rm -f $(TARGET)
diff --git a/fence/agents/pve/fence_pve.py b/fence/agents/pve/fence_pve.py
new file mode 100644
index 000..132234e
--- /dev/null
+++ b/fence/agents/pve/fence_pve.py
@@ -0,0 +1,178 @@
+#!/usr/bin/python -tt
+
+# This agent uses Proxmox VE API
+# Thanks to Frank Brendel (author of original perl fence_pve)
+# for help with writing and testing this agent.
+
+import sys
+import json
+import pycurl
+import StringIO
+import urllib
+import atexit
+import logging
+sys.path.append(@FENCEAGENTSLIBDIR@)
+from fencing import fail, EC_LOGIN_DENIED, atexit_handler, all_opt, 
check_input, process_input, show_docs, fence_action, run_delay
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION=
+BUILD_DATE=
+REDHAT_COPYRIGHT=
+#END_VERSION_GENERATION
+
+
+def get_power_status(conn, options):
+   del conn
+   state = {running : on, stopped : off}
+   if options[--nodename] is None:
+   nodes = send_cmd(options, nodes)
+   if type(nodes) is not dict or data not in nodes or 
type(nodes[data]) is not list:
+   return None
+   for node in nodes[data]: # lookup the node holding the vm
+   if type(node) is not dict or node not in node:
+   return None
+   options[--nodename] = node[node]
+   status = get_power_status(None, options)
+   if status is not None:
+   logging.info(vm found on node:  + 
options[--nodename])
+   break
+   else:
+   options[--nodename] = None
+   return status
+   else:
+   cmd = nodes/ + options[--nodename] + /qemu/ + 
options[--plug] + /status/current
+   result = send_cmd(options, cmd)
+   if type(result) is dict and data in result:
+   if type(result[data]) is dict and status in 
result[data]:
+   if result[data][status] in state:
+   return state[result[data][status]]
+   return None
+
+
+def set_power_status(conn, options):
+   del conn
+   action = {
+   'on' : start,
+   'off': stop
+   }[options[--action]]
+   cmd = nodes/ + options[--nodename] + /qemu/ + options[--plug] + 
/status/ + action
+   send_cmd(options, cmd, post={skiplock:1})
+
+
+def get_outlet_list(conn, options):
+   del conn
+   nodes = send_cmd(options, nodes)
+   outlets = dict()
+   if type(nodes) is not dict or data not in nodes or 
type(nodes[data]) is not list:
+   return None
+   for node in nodes[data]:
+   if type(node) is not dict or node not in node:
+   return None
+   vms = send_cmd(options, nodes/ + node[node] + /qemu)
+   if type(vms) is not 

[Cluster-devel] [PATCH 1/3] fencing: added timeout and env parameters to run_command function

2014-04-11 Thread Ondrej Mular
Now, we can set enviromant variables and maximum execution time for subprocess.

---
 fence/agents/lib/fencing.py.py | 21 +
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py
index 32040db..31155ac 100644
--- a/fence/agents/lib/fencing.py.py
+++ b/fence/agents/lib/fencing.py.py
@@ -4,6 +4,7 @@ import sys, getopt, time, os, uuid, pycurl, stat
 import pexpect, re, atexit, syslog
 import logging
 import subprocess
+import threading
 import shlex
 import __main__
 
@@ -1094,20 +1095,32 @@ def is_executable(path):
return True
return False
 
-def run_command(options, command):
-   # @todo: Use timeouts from options[]
+def run_command(options, command, timeout = None, env = None):
+   if timeout is None and --power-timeout in options:
+   timeout = options[--power-timeout]
+   if timeout is not None:
+   timeout = float(timeout)
+
logging.info(Executing: %s\n % command)
 
try:
-   process = subprocess.Popen(shlex.split(command), 
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+   process = subprocess.Popen(shlex.split(command), 
stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
except OSError, ex:
fail_usage(Unable to run %s\n % command)
 
+   thread = threading.Thread(target = process.wait)
+   thread.start()
+   thread.join(timeout)
+   if (thread.is_alive()):
+   process.kill()
+   fail(EC_TIMED_OUT)
+
status = process.wait()
+
(pipe_stdout, pipe_stderr) = process.communicate()
process.stdout.close()
process.stderr.close()
 
-   logging.debug(%s %s %s\n % str(status), str(pipe_stdout), 
str(pipe_stderr))
+   logging.debug(%s %s %s\n % (str(status), str(pipe_stdout), 
str(pipe_stderr)))
 
return (status, pipe_stdout, pipe_stderr)
-- 
1.8.3.1



[Cluster-devel] [PATCH] fencing: fixed pexpect TypeError exception, when using identity file for login via ssh

2014-03-07 Thread Ondrej Mular
Previously, fence-agent failed to log in (ssh) using identity file. This caused 
fence-agent failure because of uncaught exception.

Resolves: rhbz#1073947

---
 fence/agents/lib/fencing.py.py | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py
index 2006f0d..76855e1 100644
--- a/fence/agents/lib/fencing.py.py
+++ b/fence/agents/lib/fencing.py.py
@@ -1022,13 +1022,12 @@ def fence_login(options, re_login_string = (login\s*: 
)|(Login Name:  )|(userna
are not in the spec file and must be installed 
separately. + \n)
sys.exit(EC_GENERIC_ERROR)
 
-   result = conn.log_expect(options, [ 
options[--command-prompt], \
-   Are you sure you want to continue connecting 
(yes/no)?, \
-   Enter passphrase for key ' + 
options[--identity-file] + ': ], int(options[--login-timeout]))
+   result = conn.log_expect(options, [ Enter passphrase 
for key ' + options[--identity-file] + ':,\
+   Are you sure you want to continue connecting 
(yes/no)? ] + options[--command-prompt], int(options[--login-timeout]))
if result == 1:
conn.sendline(yes)
-   conn.log_expect(options, [ 
options[--command-prompt], Enter passphrase for key 
'+options[--identity-file]+':] , int(options[--login-timeout]))
-   if result != 0:
+   result = conn.log_expect(options, [ Enter 
passphrase for key '+options[--identity-file]+':] + 
options[--command-prompt], int(options[--login-timeout]))
+   if result == 0:
if options.has_key(--password):
conn.sendline(options[--password])
conn.log_expect(options, 
options[--command-prompt], int(options[--login-timeout]))
-- 
1.8.3.1



[Cluster-devel] [PATCH 2/2] fence_scsi: port to fencing lib

2014-02-21 Thread Ondrej Mular
Port of fence_scsi to fencing library

---
 fence/agents/scsi/fence_scsi.py | 328 
 1 file changed, 328 insertions(+)
 create mode 100644 fence/agents/scsi/fence_scsi.py

diff --git a/fence/agents/scsi/fence_scsi.py b/fence/agents/scsi/fence_scsi.py
new file mode 100644
index 000..18b5e60
--- /dev/null
+++ b/fence/agents/scsi/fence_scsi.py
@@ -0,0 +1,328 @@
+#!/usr/bin/python
+
+import sys, stat, shlex, subprocess, re, os
+sys.path.append(@FENCEAGENTSLIBDIR@)
+from fencing import *
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION=
+REDHAT_COPYRIGHT=
+BUILD_DATE=
+#END_VERSION_GENERATION
+
+def get_status(_, options):
+   status = off
+   for dev in options[devices]:
+   is_block_device(dev)
+   reset_dev(dev)
+   if options[--key] in get_registration_keys(dev):
+   status = on
+   elif options[log] = LOG_MODE_VERBOSE:
+   options[debug_fh].write(No registration for key \
+   + options[--key] +  on device  + dev + \n)
+   return status
+
+def set_status(_, options):
+   count = 0
+   if options[--action] == on:
+   set_key(options)
+   for dev in options[devices]:
+   is_block_device(dev)
+
+   register_dev(options[--key], dev, 
options.has_key(--atptl))
+   if options[--key] not in get_registration_keys(dev):
+   count += 1
+   if options[log] = LOG_MODE_VERBOSE:
+   options[debug_fh].write(Failed to 
register key \
+   + options[--key] + on device  + dev 
+ \n)
+   continue
+   dev_write(dev, options)
+
+   if get_reservation_key(dev) is None \
+   and not reserve_dev(options[--key], dev) \
+   and get_reservation_key(dev) is None:
+   count += 1
+   if options[log] = LOG_MODE_VERBOSE:
+   options[debug_fh].write(Failed to 
create reservation (key=\
+   + options[--key] + , device= + dev 
+ )\n)
+
+   else:
+   host_key = get_key(options)
+   if host_key == options[--key].lower():
+   fail_usage(Failed: keys cannot be same)
+   for dev in options[devices]:
+   is_block_device(dev)
+
+   if get_reservation_key(dev) == options[--key]:
+   release_dev(options[--key], dev)
+
+   if options[--key] in get_registration_keys(dev):
+   preempt(host_key, options[--key], dev)
+
+   if get_reservation_key(dev) == options[--key]:
+   count += 1
+   if options[log] = LOG_MODE_VERBOSE:
+   options[debug_fh].write(Failed to 
release device \
+   + dev +  from key + options[--key] 
+ \n)
+
+   if options[--key] in get_registration_keys(dev):
+   count += 1
+   if options[log] = LOG_MODE_VERBOSE:
+   options[debug_fh].write(Failed to 
remove key \
+   + options[--key] +  on device  + 
dev + \n)
+   if count:
+   fail_usage(Failed to verify  + count +  device(s))
+
+#run command, returns dict, ret[err] = exit code; ret[out] = output
+def run_cmd(cmd):
+   cmd = shlex.split(cmd)
+   cmd[0] = find_binary(cmd[0])
+   ret = {}
+   null = open(/dev/null, w)
+   try:
+   process = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
stderr=null)
+   except OSError:
+   null.close()
+   fail_usage(Failed: Cannot run ' + cmd + ')
+
+   ret[err] = process.wait()
+   ret[out] = .join([i for i in process.communicate() if i is not 
None])
+
+   process.stdout.close()
+   null.close()
+   return ret
+
+# check if device exist and is block device
+def is_block_device(dev):
+   if not os.path.exists(dev):
+   fail_usage(Failed: device \ + dev + \ does not exist)
+   if not stat.S_ISBLK(os.stat(dev).st_mode):
+   fail_usage(Failed: device \ + dev + \ is not a block 
device)
+
+# cancel registration
+def preempt(host, node, dev):
+   cmd = sg_persist -n -o -A -T 5 -K  + host +  -S  + node +  -d  + 
dev
+   return not bool(run_cmd(cmd)[err])
+
+def reset_dev(dev):
+   return run_cmd(sg_turs  + dev)[err]
+
+def register_dev(node_key, dev, atptl):
+   dev = os.path.realpath(dev)
+   if re.search(^dm, dev[5:]):
+   

[Cluster-devel] [PATCH] fencing: correct default values in manual pages for symlinks

2014-01-30 Thread Ondrej Mular
---
 make/fenceman.mk | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/make/fenceman.mk b/make/fenceman.mk
index d4f0377..163fe88 100644
--- a/make/fenceman.mk
+++ b/make/fenceman.mk
@@ -1,7 +1,7 @@
 %.8: $(TARGET) $(top_srcdir)/fence/agents/lib/fence2man.xsl
set -e  \
PYTHONPATH=$(abs_srcdir)/../lib:$(abs_builddir)/../lib \
-   python $^ -o metadata  .$@.tmp  \
+   python $(@:%.8=%) -o metadata  .$@.tmp  \
xmllint --noout --relaxng $(abs_srcdir)/../lib/metadata.rng .$@.tmp  \
xsltproc $(top_srcdir)/fence/agents/lib/fence2man.xsl .$@.tmp  $@
 
-- 
1.8.3.1



[Cluster-devel] [PATCH 2/4] fencing: add function is_executale

2013-12-30 Thread Ondrej Mular
New function is_executable added to fencing library.
Function checks if path is reachable and executable.
Used for example in fence_amt to check path to amttool.

---
 fence/agents/lib/fencing.py.py | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py
index ab14cb7..f4150ff 100644
--- a/fence/agents/lib/fencing.py.py
+++ b/fence/agents/lib/fencing.py.py
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-import sys, getopt, time, os, uuid, pycurl
+import sys, getopt, time, os, uuid, pycurl, stat
 import pexpect, re, atexit, syslog
 import __main__
 
@@ -1065,3 +1065,10 @@ def fence_login(options, re_login_string = (login\s*: 
)|(Login Name:  )|(userna
except pexpect.TIMEOUT:
fail(EC_LOGIN_DENIED)
return conn
+
+def is_executable(path):
+   if os.path.exists(path):
+   stats = os.stat(path)
+   if stat.S_ISREG(stats.st_mode) and os.access(path, os.X_OK):
+   return True
+   return False
-- 
1.8.3.1




[Cluster-devel] [PATCH 1/4] fencing: new option --method

2013-12-30 Thread Ondrej Mular
Add new option method --method for cycle reboot

Checks input for invalid usage of cycle (method cycle and plug)

---
 fence/agents/lib/fencing.py.py | 62 --
 1 file changed, 42 insertions(+), 20 deletions(-)

diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py
index 2b914f2..ab14cb7 100644
--- a/fence/agents/lib/fencing.py.py
+++ b/fence/agents/lib/fencing.py.py
@@ -342,7 +342,16 @@ all_opt = {
help : --use-sudo Use sudo (without 
password) when calling 3rd party software,
required : 0,
shortdesc : Use sudo (without password) when calling 3rd 
party sotfware.,
-   order : 205}
+   order : 205},
+   method : {
+   getopt : m:,
+   longopt : method,
+   help : -m, --method=[method]  Method to fence 
(offon|cycle) (Default: offon),
+   required : 0,
+   shortdesc : Method to fence (offon|cycle) (Default: offon),
+   default : offon,
+   choices : [ offon, cycle ],
+   order : 1}
 }
 
 # options which are added automatically if 'key' is encountered (default is 
always added)
@@ -723,6 +732,9 @@ def check_input(device_opt, opt):
else:
options[--ipport] = 23
 
+   if options.has_key(--plug) and options.has_key(--method) and 
options[--method] == cycle:
+   fail_usage(Failed: Cannot use --method cycle and --plug 
together)
+
for opt in device_opt:
if all_opt[opt].has_key(choices):
long = -- + all_opt[opt][longopt]
@@ -804,7 +816,7 @@ def show_docs(options, docs = None):
print __main__.REDHAT_COPYRIGHT
sys.exit(0)
 
-def fence_action(tn, options, set_power_fn, get_power_fn, get_outlet_list = 
None):
+def fence_action(tn, options, set_power_fn, get_power_fn, get_outlet_list = 
None, reboot_cycle_fn = None):
result = 0
 
try:
@@ -863,28 +875,38 @@ def fence_action(tn, options, set_power_fn, get_power_fn, 
get_outlet_list = None
else:
fail(EC_WAITING_OFF)
elif options[--action] == reboot:
-   if status != off:
-   options[--action] = off
-   set_multi_power_fn(tn, options, set_power_fn)
-   time.sleep(int(options[--power-wait]))
-   if wait_power_status(tn, options, get_power_fn) 
== 0:
-   fail(EC_WAITING_OFF)
-   options[--action] = on
-
power_on = False
-   try:
+   if options.has_key(--method) and 
options[--method].lower() == cycle and reboot_cycle_fn is not None:
for _ in range(1, 1 + 
int(options[--retry-on])):
-   set_multi_power_fn(tn, options, 
set_power_fn)
-   time.sleep(int(options[--power-wait]))
-   if wait_power_status(tn, options, 
get_power_fn) == 1:
+   if reboot_cycle_fn(tn, options):
power_on = True
break
-   except Exception, ex:
-   # an error occured during power ON phase in 
reboot
-   # fence action was completed succesfully even 
in that case
-   sys.stderr.write(str(ex))
-   syslog.syslog(syslog.LOG_NOTICE, str(ex))
-   pass
+
+   if not power_on:
+   fail(EC_TIMED_OUT)
+
+   else:
+   if status != off:
+   options[--action] = off
+   set_multi_power_fn(tn, options, 
set_power_fn)
+   time.sleep(int(options[--power-wait]))
+   if wait_power_status(tn, options, 
get_power_fn) == 0:
+   fail(EC_WAITING_OFF)
+   options[--action] = on
+
+   try:
+   for _ in range(1, 1 + 
int(options[--retry-on])):
+   set_multi_power_fn(tn, options, 
set_power_fn)
+   
time.sleep(int(options[--power-wait]))
+   if wait_power_status(tn, 
options, get_power_fn) == 1:
+   

[Cluster-devel] [PATCH 1/2] fence_ipmilan: port to fencing library

2013-12-03 Thread Ondrej Mular
Port of fence_ipmilan to fencing library. 

---
 fence/agents/ipmilan/fence_ipmilan.py | 207 ++
 1 file changed, 207 insertions(+)
 create mode 100644 fence/agents/ipmilan/fence_ipmilan.py

diff --git a/fence/agents/ipmilan/fence_ipmilan.py 
b/fence/agents/ipmilan/fence_ipmilan.py
new file mode 100644
index 000..1cb26d0
--- /dev/null
+++ b/fence/agents/ipmilan/fence_ipmilan.py
@@ -0,0 +1,207 @@
+#!/usr/bin/python
+
+import sys, shlex, stat, subprocess, re, os
+from pipes import quote
+sys.path.append(@FENCEAGENTSLIBDIR@)
+from fencing import *
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION=
+REDHAT_COPYRIGHT=
+BUILD_DATE=
+#END_VERSION_GENERATION
+
+def get_power_status(_, options):
+
+cmd = create_command(options, status)
+
+if options[log] = LOG_MODE_VERBOSE:
+options[debug_fh].write(executing:  + cmd + \n)
+
+try:
+process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, 
stderr=subprocess.PIPE)
+except OSError:
+fail_usage(Ipmitool not found or not accessible)
+
+process.wait()
+
+out = process.communicate()
+process.stdout.close()
+
+match = re.search('[Cc]hassis [Pp]ower is [\\s]*([a-zA-Z]{2,3})', str(out))
+status = match.group(1) if match else None
+
+return status
+
+def set_power_status(_, options):
+
+cmd = create_command(options, options[--action])
+
+if options[log] = LOG_MODE_VERBOSE:
+options[debug_fh].write(executing:  + cmd + \n)
+
+null = open('/dev/null', 'w')
+try:
+process = subprocess.Popen(shlex.split(cmd), stdout=null, stderr=null)
+except OSError:
+null.close()
+fail_usage(Ipmitool not found or not accessible)
+
+process.wait()
+null.close()
+
+return
+
+def reboot_cycle(_, options):
+cmd = create_command(options, cycle)
+
+if options[log] = LOG_MODE_VERBOSE:
+options[debug_fh].write(executing:  + cmd + \n)
+
+try:
+process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, 
stderr=subprocess.PIPE)
+except OSError:
+fail_usage(Ipmitool not found or not accessible)
+
+process.wait()
+
+out = process.communicate()
+process.stdout.close()
+
+return bool(re.search('chassis power control: cycle', str(out).lower()))
+
+def is_executable(path):
+   if os.path.exists(path):
+   stats = os.stat(path)
+   if stat.S_ISREG(stats.st_mode) and os.access(path, os.X_OK):
+   return True
+   return False
+
+def create_command(options, action):
+cmd = options[--ipmitool-path]
+
+# --lanplus / -L
+if options.has_key(--lanplus) and options[--lanplus] in [, 1]:
+cmd +=  -I lanplus
+else:
+cmd +=  -I lan
+# --ip / -a
+cmd +=  -H  + options[--ip]
+
+# --username / -l
+if options.has_key(--username) and len(options[--username]) != 0:
+cmd +=  -U  + quote(options[--username])
+
+# --auth / -A
+if options.has_key(--auth):
+cmd +=  -A  + options[--auth]
+
+# --password / -p
+if options.has_key(--password):
+cmd +=  -P  + quote(options[--password])
+
+# --cipher / -C
+cmd +=  -C  + options[--cipher]
+
+# --port / -n
+if options.has_key(--ipport):
+cmd +=  -p  + options[--ipport]
+
+if options.has_key(--privlvl):
+cmd +=  -L  + options[--privlvl]
+
+# --action / -o
+cmd +=  chassis power  + action
+
+ # --use-sudo / -d
+if options.has_key(--use-sudo):
+cmd = SUDO_PATH +   + cmd
+
+return cmd
+
+def define_new_opts():
+all_opt[lanplus] = {
+getopt : L,
+longopt : lanplus,
+help : -L, --lanplus  Use Lanplus to improve 
security of connection,
+required : 0,
+default : 0,
+shortdesc : Use Lanplus to improve security of connection,
+order: 1
+}
+all_opt[auth] = {
+getopt : A:,
+longopt : auth,
+help : -A, --auth=[auth]  IPMI Lan Auth type 
(md5|password|none),
+required : 0,
+shortdesc : IPMI Lan Auth type.,
+default : none,
+choices : [md5, password, none],
+order: 1
+}
+all_opt[cipher] = {
+getopt : C:,
+longopt : cipher,
+help : -C, --cipher=[cipher]  Ciphersuite to use (same as 
ipmitool -C parameter),
+required : 0,
+shortdesc : Ciphersuite to use (same as ipmitool -C parameter),
+default : 0,
+order: 1
+}
+all_opt[privlvl] = {
+getopt : P:,
+longopt : privlvl,
+help : -P, --privlvl=[level]  Privilege level on IPMI 
device (callback|user|operator|administrator),
+required : 0,
+shortdesc : Privilege level on IPMI device,
+default : administrator,
+choices : [callback, user, operator, administrator],
+order: 1
+}
+all_opt[ipmitool_path] = {
+  

[Cluster-devel] [PATCH 2/2] fence_amt: new fence agent for Intel AMT

2013-12-03 Thread Ondrej Mular
New fence agent for Intel AMT.

---
 fence/agents/amt/fence_amt.py | 161 ++
 1 file changed, 161 insertions(+)
 create mode 100755 fence/agents/amt/fence_amt.py

diff --git a/fence/agents/amt/fence_amt.py b/fence/agents/amt/fence_amt.py
new file mode 100755
index 000..6f00727
--- /dev/null
+++ b/fence/agents/amt/fence_amt.py
@@ -0,0 +1,161 @@
+#!/usr/bin/python
+
+import sys, subprocess, re, os, stat
+from pipes import quote
+sys.path.append(@FENCEAGENTSLIBDIR@)
+from fencing import *
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION=Fence agent for Intel AMT
+REDHAT_COPYRIGHT=
+BUILD_DATE=
+#END_VERSION_GENERATION
+
+def get_power_status(_, options):
+
+cmd = create_command(options, status)
+
+if options[log] = LOG_MODE_VERBOSE:
+options[debug_fh].write(executing:  + cmd + \n)
+
+try:
+process = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
stderr=subprocess.PIPE, shell=True)
+except OSError:
+fail_usage(Amttool not found or not accessible)
+
+process.wait()
+
+output = process.communicate()
+process.stdout.close()
+
+match = re.search('Powerstate:[\\s]*(..)', str(output))
+status = match.group(1) if match else None
+
+if (status == None):
+return fail
+elif (status == S0): # SO = on; S3 = sleep; S5 = off
+return on
+else:
+return off
+
+def set_power_status(_, options):
+
+cmd = create_command(options, options[--action])
+
+if options[log] = LOG_MODE_VERBOSE:
+options[debug_fh].write(executing:  + cmd + \n)
+
+null = open('/dev/null', 'w')
+try:
+process = subprocess.Popen(cmd, stdout=null, stderr=null, shell=True)
+except OSError:
+null.close()
+fail_usage(Amttool not found or not accessible)
+
+process.wait()
+null.close()
+
+return
+
+def reboot_cycle(_, options):
+cmd = create_command(options, cycle)
+
+if options[log] = LOG_MODE_VERBOSE:
+options[debug_fh].write(executing:  + cmd + \n)
+
+null = open('/dev/null', 'w')
+try:
+process = subprocess.Popen(cmd, stdout=null, stderr=null, shell=True)
+except OSError:
+null.close()
+fail_usage(Amttool not found or not accessible)
+
+status = process.wait()
+null.close()
+
+return not bool(status)
+
+def is_executable(path):
+if os.path.exists(path):
+stats = os.stat(path)
+if stat.S_ISREG(stats.st_mode) and os.access(path, os.X_OK):
+return True
+return False
+
+def create_command(options, action):
+
+# --password / -p
+cmd = AMT_PASSWORD= + quote(options[--password])
+
+cmd +=   + options[--amttool-path]
+
+# --ip / -a
+cmd +=   + options[--ip]
+
+# --action / -o
+if action == status:
+cmd +=  info
+elif action == on:
+cmd = echo \y\| + cmd
+cmd +=  powerup
+elif action == off:
+cmd = echo \y\| + cmd
+cmd +=  powerdown
+elif action == cycle:
+cmd = echo \y\| + cmd
+cmd +=  powercycle
+if action in [on, off, cycle] and options.has_key(--boot-option):
+cmd += options[--boot-option]
+
+# --use-sudo / -d
+if options.has_key(--use-sudo):
+cmd = SUDO_PATH +   + cmd
+
+return cmd
+
+def define_new_opts():
+all_opt[boot_option] = {
+getopt : b:,
+longopt : boot-option,
+help : -b, --boot-option=[option] Change the default boot 
behavior of the machine. (pxe|hd|hdsafe|cd|diag),
+required : 0,
+shortdesc : Change the default boot behavior of the machine.,
+choices : [pxe, hd, hdsafe, cd, diag],
+order : 1
+}
+all_opt[amttool_path] = {
+getopt : i:,
+longopt : amttool-path,
+help : --amttool-path=[path]  Path to amttool binary,
+required : 0,
+shortdesc : Path to amttool binary,
+default : @AMTTOOL_PATH@,
+order: 200
+}
+
+def main():
+
+atexit.register(atexit_handler)
+
+device_opt = [ ipaddr, no_login, passwd, boot_option, no_port,
+ sudo, amttool_path, method ]
+
+define_new_opts()
+
+options = check_input(device_opt, process_input(device_opt))
+
+docs = { }
+docs[shortdesc] = Fence agent for AMT
+docs[longdesc] = Fence agent for AMT
+docs[vendorurl] = http://www.intel.com/;
+show_docs(options, docs)
+
+if not is_executable(options[--amttool-path]):
+fail_usage(Amttool not found or not accessible)
+
+result = fence_action(None, options, set_power_status, get_power_status, 
None, reboot_cycle)
+
+sys.exit(result)
+
+if __name__ == __main__:
+main()
-- 
1.8.3.1



[Cluster-devel] [PATCH 1/3] fencing: new option --method

2013-11-29 Thread Ondrej Mular
Add new option method --method for cycle reboot

---
 fence/agents/lib/fencing.py.py | 80 ++
 1 file changed, 57 insertions(+), 23 deletions(-)

diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py
index b4abfb2..59ab91b 100644
--- a/fence/agents/lib/fencing.py.py
+++ b/fence/agents/lib/fencing.py.py
@@ -25,7 +25,6 @@ EC_STATUS  = 8
 EC_STATUS_HMC  = 9
 EC_PASSWORD_MISSING = 10
 EC_INVALID_PRIVILEGES = 11
-EC_TOOL_FAIL = 12
 
 TELNET_PATH = /usr/bin/telnet
 SSH_PATH= /usr/bin/ssh
@@ -343,7 +342,16 @@ all_opt = {
help : --use-sudo Use sudo (without 
password) when calling 3rd party software,
required : 0,
shortdesc : Use sudo (without password) when calling 3rd 
party sotfware.,
-   order : 205}
+   order : 205},
+   method : {
+   getopt : m:,
+   longopt : method,
+   help : -m, --method=[method]  Method to fence 
(onoff|cycle) (Default: onoff),
+   required : 0,
+   shortdesc : Method to fence (onoff|cycle) (Default: onoff),
+   default : onoff,
+   choices : [ onoff, cycle ],
+   order : 1}
 }
 
 # options which are added automatically if 'key' is encountered (default is 
always added)
@@ -413,8 +421,7 @@ def fail(error_code):
EC_STATUS_HMC :
Failed: Either unable to obtain correct plug status, 
partition is not available or incorrect HMC version used,
EC_PASSWORD_MISSING : Failed: You have to set login password,
-   EC_INVALID_PRIVILEGES : Failed: The user does not have the 
correct privileges to do the requested action.,
-   EC_TOOL_FAIL: Failed: Required tool not found or not 
accessible.
+   EC_INVALID_PRIVILEGES : Failed: The user does not have the 
correct privileges to do the requested action.
}[error_code] + \n
sys.stderr.write(message)
syslog.syslog(syslog.LOG_ERR, message)
@@ -782,6 +789,23 @@ def set_multi_power_fn(tn, options, set_power_fn):
else:
set_power_fn(tn, options)
 
+def multi_reboot_cycle_fn(tn, options, reboot_cycle_fn):
+   success = False;
+   if options.has_key(--plugs):
+   for plug in options[--plugs]:
+   try:
+   options[--uuid] = str(uuid.UUID(plug))
+   except ValueError:
+   pass
+   except KeyError:
+   pass
+   options[--plug] = plug
+   plug_status = reboot_cycle_fn(tn, options)
+   if plug_status:
+   success = plug_status
+   else:
+   success = reboot_cycle_fn(tn, options)
+   return success
 
 def show_docs(options, docs = None):
device_opt = options[device_opt]
@@ -806,7 +830,7 @@ def show_docs(options, docs = None):
print __main__.REDHAT_COPYRIGHT
sys.exit(0)
 
-def fence_action(tn, options, set_power_fn, get_power_fn, get_outlet_list = 
None):
+def fence_action(tn, options, set_power_fn, get_power_fn, get_outlet_list = 
None, reboot_cycle_fn = None):
result = 0
 
try:
@@ -865,28 +889,38 @@ def fence_action(tn, options, set_power_fn, get_power_fn, 
get_outlet_list = None
else:
fail(EC_WAITING_OFF)
elif options[--action] == reboot:
-   if status != off:
-   options[--action] = off
-   set_multi_power_fn(tn, options, set_power_fn)
-   time.sleep(int(options[--power-wait]))
-   if wait_power_status(tn, options, get_power_fn) 
== 0:
-   fail(EC_WAITING_OFF)
-   options[--action] = on
-
power_on = False
-   try:
+   if options.has_key(--method) and 
options[--method].lower() == cycle:
for _ in range(1, 1 + 
int(options[--retry-on])):
-   set_multi_power_fn(tn, options, 
set_power_fn)
-   time.sleep(int(options[--power-wait]))
-   if wait_power_status(tn, options, 
get_power_fn) == 1:
+   if multi_reboot_cycle_fn(tn, options, 
reboot_cycle_fn):
power_on = True
break
-   except Exception, ex:
-   # an error occured during power ON phase in 
reboot
-   # 

[Cluster-devel] [PATCH 3/3] fence_amt: option --method and new option --amttool-path

2013-11-29 Thread Ondrej Mular
Add support for option --method and new option --amttool-path

---
 fence/agents/amt/fence_amt.py | 72 ++-
 1 file changed, 57 insertions(+), 15 deletions(-)

diff --git a/fence/agents/amt/fence_amt.py b/fence/agents/amt/fence_amt.py
index 8fe2dbc..7077828 100755
--- a/fence/agents/amt/fence_amt.py
+++ b/fence/agents/amt/fence_amt.py
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-import sys, subprocess, re
+import sys, subprocess, re, os, stat
 from pipes import quote
 sys.path.append(@FENCEAGENTSLIBDIR@)
 from fencing import *
@@ -21,12 +21,11 @@ def get_power_status(_, options):
 try:
 process = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
stderr=subprocess.PIPE, shell=True)
 except OSError:
-fail(EC_TOOL_FAIL)
+fail_usage(Amttool not found or not accessible)
 
 process.wait()
 
 output = process.communicate()
-
 process.stdout.close()
 
 match = re.search('Powerstate:[\\s]*(..)', str(output))
@@ -51,19 +50,44 @@ def set_power_status(_, options):
 process = subprocess.Popen(cmd, stdout=null, stderr=null, shell=True)
 except OSError:
 null.close()
-fail(EC_TOOL_FAIL)
+fail_usage(Amttool not found or not accessible)
 
 process.wait()
 null.close()
 
 return
 
+def reboot_cycle(_, options):
+cmd = create_command(options, cycle)
+
+if options[log] = LOG_MODE_VERBOSE:
+options[debug_fh].write(executing:  + cmd + \n)
+
+null = open('/dev/null', 'w')
+try:
+process = subprocess.Popen(cmd, stdout=null, stderr=null, shell=True)
+except OSError:
+null.close()
+fail_usage(Amttool not found or not accessible)
+
+status = process.wait()
+null.close()
+
+return not bool(status)
+
+def is_executable(path):
+if os.path.exists(path):
+stats = os.stat(path)
+if stat.S_ISREG(stats.st_mode) and os.access(path, os.X_OK):
+return True
+return False
+
 def create_command(options, action):
 
 # --password / -p
 cmd = AMT_PASSWORD= + quote(options[--password])
 
-cmd +=   + options[amttool_path]
+cmd +=   + options[--amttool-path]
 
 # --ip / -a
 cmd +=   + options[--ip]
@@ -77,7 +101,10 @@ def create_command(options, action):
 elif action == off:
 cmd = echo \y\| + cmd
 cmd +=  powerdown
-if action in [on, off] and options.has_key(--boot-options):
+elif action == cycle:
+cmd = echo \y\| + cmd
+cmd +=  powercycle
+if action in [on, off, cycle] and options.has_key(--boot-options):
 cmd += options[--boot-options]
 
 # --use-sudo / -d
@@ -86,25 +113,40 @@ def create_command(options, action):
 
 return cmd
 
-def main():
-
-atexit.register(atexit_handler)
-
-device_opt = [ ipaddr, no_login, passwd, boot_option, no_port, 
sudo]
-
+def define_new_opts():
 all_opt[boot_option] = {
 getopt : b:,
 longopt : boot-option,
-help:-b, --boot-option=[option] Change the default boot behavior of 
the machine. (pxe|hd|hdsafe|cd|diag),
+help:-b, --boot-option=[option] Change the default boot 
behavior of the machine. (pxe|hd|hdsafe|cd|diag),
 required : 0,
 shortdesc : Change the default boot behavior of the machine.,
 choices : [pxe, hd, hdsafe, cd, diag],
   order : 1
 }
+all_opt[amttool_path] = {
+getopt : i:,
+longopt : amttool-path,
+help : --amttool-path=[path]  Path to amttool binary,
+required : 0,
+shortdesc : Path to amttool binary,
+default : /usr/bin/amttool,
+order: 200
+}
+
+
+def main():
+
+atexit.register(atexit_handler)
+
+device_opt = [ ipaddr, no_login, passwd, boot_option, no_port,
+ sudo, amttool_path, method ]
+
+define_new_opts()
 
 options = check_input(device_opt, process_input(device_opt))
 
-options[amttool_path] = /usr/bin/amttool
+if not is_executable(options[--amttool-path]):
+fail_usage(Amttool not found or not accessible)
 
 docs = { }
 docs[shortdesc] = Fence agent for AMT
@@ -112,7 +154,7 @@ def main():
 docs[vendorurl] = http://www.intel.com/;
 show_docs(options, docs)
 
-result = fence_action(None, options, set_power_status, get_power_status, 
None)
+result = fence_action(None, options, set_power_status, get_power_status, 
None, reboot_cycle)
 
 sys.exit(result)
 
-- 
1.8.3.1



[Cluster-devel] [PATCH 2/3] fence_ipmilan: option --method and new option --ipmitool-path

2013-11-29 Thread Ondrej Mular
Add support for option --method and new option --ipmitool-path

---
 fence/agents/ipmilan/fence_ipmilan.py | 80 +++
 1 file changed, 54 insertions(+), 26 deletions(-)

diff --git a/fence/agents/ipmilan/fence_ipmilan.py 
b/fence/agents/ipmilan/fence_ipmilan.py
index 5c32690..4d33234 100644
--- a/fence/agents/ipmilan/fence_ipmilan.py
+++ b/fence/agents/ipmilan/fence_ipmilan.py
@@ -11,14 +11,6 @@ REDHAT_COPYRIGHT=
 BUILD_DATE=
 #END_VERSION_GENERATION
 
-PATHS = [/usr/local/bull/NSMasterHW/bin/ipmitool,
-/usr/bin/ipmitool,
-/usr/sbin/ipmitool,
-/bin/ipmitool,
-/sbin/ipmitool,
-/usr/local/bin/ipmitool,
-/usr/local/sbin/ipmitool]
-
 def get_power_status(_, options):
 
 cmd = create_command(options, status)
@@ -28,9 +20,8 @@ def get_power_status(_, options):
 
 try:
 process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, 
stderr=subprocess.PIPE)
-except OSError, ex:
-print ex
-fail(EC_TOOL_FAIL)
+except OSError:
+fail_usage(Ipmitool not found or not accessible)
 
 process.wait()
 
@@ -54,13 +45,31 @@ def set_power_status(_, options):
 process = subprocess.Popen(shlex.split(cmd), stdout=null, stderr=null)
 except OSError:
 null.close()
-fail(EC_TOOL_FAIL)
+fail_usage(Ipmitool not found or not accessible)
 
 process.wait()
 null.close()
 
 return
 
+def reboot_cycle(_, options):
+cmd = create_command(options, cycle)
+
+if options[log] = LOG_MODE_VERBOSE:
+options[debug_fh].write(executing:  + cmd + \n)
+
+try:
+process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, 
stderr=subprocess.PIPE)
+except OSError:
+fail_usage(Ipmitool not found or not accessible)
+
+process.wait()
+
+out = process.communicate()
+process.stdout.close()
+
+return bool(re.search('chassis power control: cycle', str(out).lower()))
+
 def is_executable(path):
 if os.path.exists(path):
 stats = os.stat(path)
@@ -68,13 +77,17 @@ def is_executable(path):
 return True
 return False
 
-def get_ipmitool_path():
-for path in PATHS:
-if is_executable(path):
-return path
+def get_ipmitool_path(options):
+if type(options[--ipmitool-path]) == type(list()):
+for path in options[--ipmitool-path]:
+if is_executable(path):
+return path
+else:
+if is_executable(options[--ipmitool-path]):
+return options[--ipmitool-path]
 return None
 
-def create_command(options, action):
+def create_command(options, action):
 cmd = options[ipmitool_path]
 
 # --lanplus / -L
@@ -120,7 +133,7 @@ def define_new_opts():
 all_opt[lanplus] = {
 getopt : L,
 longopt : lanplus,
-help : -L, --lanplusUse Lanplus to improve security of 
connection,
+help : -L, --lanplus  Use Lanplus to improve 
security of connection,
 required : 0,
 shortdesc : Use Lanplus to improve security of connection,
 order: 1
@@ -128,7 +141,7 @@ def define_new_opts():
 all_opt[auth] = {
 getopt : A:,
 longopt : auth,
-help : -A, --auth=[auth]IPMI Lan Auth type (md5|password|none),
+help : -A, --auth=[auth]  IPMI Lan Auth type 
(md5|password|none),
 required : 0,
 shortdesc : IPMI Lan Auth type.,
 default : none,
@@ -138,7 +151,7 @@ def define_new_opts():
 all_opt[cipher] = {
 getopt : C:,
 longopt : cipher,
-help : -C, --cipher=[cipher]Ciphersuite to use (same as 
ipmitool -C parameter),
+help : -C, --cipher=[cipher]  Ciphersuite to use (same as 
ipmitool -C parameter),
 required : 0,
 shortdesc : Ciphersuite to use (same as ipmitool -C parameter),
 default : 0,
@@ -147,28 +160,44 @@ def define_new_opts():
 all_opt[privlvl] = {
 getopt : P:,
 longopt : privlvl,
-help : -P, --privlvl=[level]Privilege level on IPMI device 
(callback|user|operator|administrator),
+help : -P, --privlvl=[level]  Privilege level on IPMI 
device (callback|user|operator|administrator),
 required : 0,
 shortdesc : Privilege level on IPMI device,
 default : administrator,
 choices : [callback, user, operator, administrator],
 order: 1
 }
+all_opt[ipmitool_path] = {
+getopt : i:,
+longopt : ipmitool-path,
+help : --ipmitool-path=[path] Path to ipmitool binary,
+required : 0,
+shortdesc : Path to ipmitool binary,
+default : [/usr/local/bull/NSMasterHW/bin/ipmitool,
+/usr/bin/ipmitool,
+/usr/sbin/ipmitool,
+/bin/ipmitool,
+/sbin/ipmitool,
+/usr/local/bin/ipmitool,
+/usr/local/sbin/ipmitool],
+order: 200
+}
 
 

[Cluster-devel] [PATCH 2/2] fence_amt: new fence agent for Intel AMT

2013-11-21 Thread Ondrej Mular
New fence agent for Intel AMT.

---
 fence/agents/amt/fence_amt.py | 120 ++
 1 file changed, 120 insertions(+)
 create mode 100755 fence/agents/amt/fence_amt.py

diff --git a/fence/agents/amt/fence_amt.py b/fence/agents/amt/fence_amt.py
new file mode 100755
index 000..8fe2dbc
--- /dev/null
+++ b/fence/agents/amt/fence_amt.py
@@ -0,0 +1,120 @@
+#!/usr/bin/python
+
+import sys, subprocess, re
+from pipes import quote
+sys.path.append(@FENCEAGENTSLIBDIR@)
+from fencing import *
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION=Fence agent for Intel AMT
+REDHAT_COPYRIGHT=
+BUILD_DATE=
+#END_VERSION_GENERATION
+
+def get_power_status(_, options):
+
+cmd = create_command(options, status)
+
+if options[log] = LOG_MODE_VERBOSE:
+options[debug_fh].write(executing:  + cmd + \n)
+
+try:
+process = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
stderr=subprocess.PIPE, shell=True)
+except OSError:
+fail(EC_TOOL_FAIL)
+
+process.wait()
+
+output = process.communicate()
+
+process.stdout.close()
+
+match = re.search('Powerstate:[\\s]*(..)', str(output))
+status = match.group(1) if match else None
+
+if (status == None):
+return fail
+elif (status == S0): # SO = on; S3 = sleep; S5 = off
+return on
+else:
+return off
+
+def set_power_status(_, options):
+
+cmd = create_command(options, options[--action])
+
+if options[log] = LOG_MODE_VERBOSE:
+options[debug_fh].write(executing:  + cmd + \n)
+
+null = open('/dev/null', 'w')
+try:
+process = subprocess.Popen(cmd, stdout=null, stderr=null, shell=True)
+except OSError:
+null.close()
+fail(EC_TOOL_FAIL)
+
+process.wait()
+null.close()
+
+return
+
+def create_command(options, action):
+
+# --password / -p
+cmd = AMT_PASSWORD= + quote(options[--password])
+
+cmd +=   + options[amttool_path]
+
+# --ip / -a
+cmd +=   + options[--ip]
+
+# --action / -o
+if action == status:
+cmd +=  info
+elif action == on:
+cmd = echo \y\| + cmd
+cmd +=  powerup
+elif action == off:
+cmd = echo \y\| + cmd
+cmd +=  powerdown
+if action in [on, off] and options.has_key(--boot-options):
+cmd += options[--boot-options]
+
+# --use-sudo / -d
+if options.has_key(--use-sudo):
+cmd = SUDO_PATH +   + cmd
+
+return cmd
+
+def main():
+
+atexit.register(atexit_handler)
+
+device_opt = [ ipaddr, no_login, passwd, boot_option, no_port, 
sudo]
+
+all_opt[boot_option] = {
+getopt : b:,
+longopt : boot-option,
+help:-b, --boot-option=[option] Change the default boot behavior of 
the machine. (pxe|hd|hdsafe|cd|diag),
+required : 0,
+shortdesc : Change the default boot behavior of the machine.,
+choices : [pxe, hd, hdsafe, cd, diag],
+  order : 1
+}
+
+options = check_input(device_opt, process_input(device_opt))
+
+options[amttool_path] = /usr/bin/amttool
+
+docs = { }
+docs[shortdesc] = Fence agent for AMT
+docs[longdesc] = Fence agent for AMT
+docs[vendorurl] = http://www.intel.com/;
+show_docs(options, docs)
+
+result = fence_action(None, options, set_power_status, get_power_status, 
None)
+
+sys.exit(result)
+
+if __name__ == __main__:
+main()
-- 
1.8.3.1



[Cluster-devel] [PATCH 1/2] fence_ipmilan: port fencing agent to fencing library

2013-11-21 Thread Ondrej Mular
This is port of fence_ipmilan to fencing library. Also added fail message to 
fencing library if tool (e.g. impitool, amttool...) is not accessible.

---
 fence/agents/ipmilan/fence_ipmilan.py | 184 ++
 fence/agents/lib/fencing.py.py|   4 +-
 2 files changed, 187 insertions(+), 1 deletion(-)
 create mode 100644 fence/agents/ipmilan/fence_ipmilan.py

diff --git a/fence/agents/ipmilan/fence_ipmilan.py 
b/fence/agents/ipmilan/fence_ipmilan.py
new file mode 100644
index 000..5c32690
--- /dev/null
+++ b/fence/agents/ipmilan/fence_ipmilan.py
@@ -0,0 +1,184 @@
+#!/usr/bin/python
+
+import sys, shlex, stat, subprocess, re, os
+from pipes import quote
+sys.path.append(@FENCEAGENTSLIBDIR@)
+from fencing import *
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION=
+REDHAT_COPYRIGHT=
+BUILD_DATE=
+#END_VERSION_GENERATION
+
+PATHS = [/usr/local/bull/NSMasterHW/bin/ipmitool,
+/usr/bin/ipmitool,
+/usr/sbin/ipmitool,
+/bin/ipmitool,
+/sbin/ipmitool,
+/usr/local/bin/ipmitool,
+/usr/local/sbin/ipmitool]
+
+def get_power_status(_, options):
+
+cmd = create_command(options, status)
+
+if options[log] = LOG_MODE_VERBOSE:
+options[debug_fh].write(executing:  + cmd + \n)
+
+try:
+process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, 
stderr=subprocess.PIPE)
+except OSError, ex:
+print ex
+fail(EC_TOOL_FAIL)
+
+process.wait()
+
+out = process.communicate()
+process.stdout.close()
+
+match = re.search('[Cc]hassis [Pp]ower is [\\s]*([a-zA-Z]{2,3})', str(out))
+status = match.group(1) if match else None
+
+return status
+
+def set_power_status(_, options):
+
+cmd = create_command(options, options[--action])
+
+if options[log] = LOG_MODE_VERBOSE:
+options[debug_fh].write(executing:  + cmd + \n)
+
+null = open('/dev/null', 'w')
+try:
+process = subprocess.Popen(shlex.split(cmd), stdout=null, stderr=null)
+except OSError:
+null.close()
+fail(EC_TOOL_FAIL)
+
+process.wait()
+null.close()
+
+return
+
+def is_executable(path):
+if os.path.exists(path):
+stats = os.stat(path)
+if stat.S_ISREG(stats.st_mode) and os.access(path, os.X_OK):
+return True
+return False
+
+def get_ipmitool_path():
+for path in PATHS:
+if is_executable(path):
+return path
+return None
+
+def create_command(options, action):
+cmd = options[ipmitool_path]
+
+# --lanplus / -L
+if options.has_key(--lanplus):
+cmd +=  -I lanplus
+else:
+cmd +=  -I lan
+# --ip / -a
+cmd +=  -H  + options[--ip]
+
+# --username / -l
+if options.has_key(--username) and len(options[--username]) != 0:
+cmd +=  -U  + quote(options[--username])
+
+# --auth / -A
+if options.has_key(--auth):
+cmd +=  -A  + options[--auth]
+
+# --password / -p
+if options.has_key(--password):
+cmd +=  -P  + quote(options[--password])
+
+# --cipher / -C
+cmd +=  -C  + options[--cipher]
+
+# --port / -n
+if options.has_key(--ipport):
+cmd +=  -p  + options[--ipport]
+
+if options.has_key(--privlvl):
+cmd +=  -L  + options[--privlvl]
+
+# --action / -o
+cmd +=  chassis power  + action
+
+ # --use-sudo / -d
+if options.has_key(--use-sudo):
+cmd = SUDO_PATH +   + cmd
+
+return cmd
+
+def define_new_opts():
+all_opt[lanplus] = {
+getopt : L,
+longopt : lanplus,
+help : -L, --lanplusUse Lanplus to improve security of 
connection,
+required : 0,
+shortdesc : Use Lanplus to improve security of connection,
+order: 1
+}
+all_opt[auth] = {
+getopt : A:,
+longopt : auth,
+help : -A, --auth=[auth]IPMI Lan Auth type (md5|password|none),
+required : 0,
+shortdesc : IPMI Lan Auth type.,
+default : none,
+choices : [md5, password, none],
+order: 1
+}
+all_opt[cipher] = {
+getopt : C:,
+longopt : cipher,
+help : -C, --cipher=[cipher]Ciphersuite to use (same as 
ipmitool -C parameter),
+required : 0,
+shortdesc : Ciphersuite to use (same as ipmitool -C parameter),
+default : 0,
+order: 1
+}
+all_opt[privlvl] = {
+getopt : P:,
+longopt : privlvl,
+help : -P, --privlvl=[level]Privilege level on IPMI device 
(callback|user|operator|administrator),
+required : 0,
+shortdesc : Privilege level on IPMI device,
+default : administrator,
+choices : [callback, user, operator, administrator],
+order: 1
+}
+
+def main():
+
+atexit.register(atexit_handler)
+
+device_opt = [ ipaddr, login, no_login, no_password, passwd, 
lanplus, auth, cipher, privlvl, sudo]
+define_new_opts()
+
+all_opt[ipport][default] = 623
+
+