fence-agents: master - fencing: Fix documentation for action 'monitor'
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=d2b7fb...
Commit: d2b7fb001fc50a8e14da8f2b6b974a5b5ade50fc
Parent: 1204c484a089ba337c6d4c9797eafce24a71915a
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Mon Feb 18 09:56:50 2013 +0100
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Mon Feb 18 09:56:50 2013 +0100
fencing: Fix documentation for action 'monitor'
---
fence/agents/lib/fence2man.xsl | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/fence/agents/lib/fence2man.xsl b/fence/agents/lib/fence2man.xsl
index 89baf7f..13e24da 100644
--- a/fence/agents/lib/fence2man.xsl
+++ b/fence/agents/lib/fence2man.xsl
@@ -20,7 +20,7 @@
<xsl:when test="@name = 'enable'">Enable fabric access.</xsl:when>
<xsl:when test="@name = 'disable'">Disable fabric access.</xsl:when>
<xsl:when test="@name = 'reboot'">Reboot machine.</xsl:when>
-<xsl:when test="@name = 'monitor'">Check if fencing device is running. List available plugs/virtual machines or get status of machine (if it does not support more).</xsl:when>
+<xsl:when test="@name = 'monitor'">Check the health of fence device</xsl:when>
<xsl:when test="@name = 'metadata'">Display the XML metadata describing this resource.</xsl:when>
<xsl:when test="@name = 'list'">List available plugs with aliases/virtual machines if there is support for more then one device. Returns N/A otherwise.</xsl:when>
<xsl:when test="@name = 'status'">This returns the status of the plug/virtual machine.</xsl:when>
11 years, 2 months
fence-agents: master - COMPATIBILITY BREAK: remove --uuid (use standard -n / --plug instead)
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=1204c4...
Commit: 1204c484a089ba337c6d4c9797eafce24a71915a
Parent: dfff684d59a6c427c9bb680f9a26b9b960005486
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Wed Feb 13 10:26:18 2013 +0100
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Wed Feb 13 10:26:18 2013 +0100
COMPATIBILITY BREAK: remove --uuid (use standard -n / --plug instead)
when --plug is UUID then it is automatically detected.
---
fence/agents/lib/fencing.py.py | 12 ------------
fence/agents/vmware_soap/fence_vmware_soap.py | 4 ++--
fence/agents/xenapi/fence_xenapi.py | 3 +--
3 files changed, 3 insertions(+), 16 deletions(-)
diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py
index 188ee1f..907d654 100644
--- a/fence/agents/lib/fencing.py.py
+++ b/fence/agents/lib/fencing.py.py
@@ -338,13 +338,6 @@ all_opt = {
"required" : "1",
"shortdesc" : "The URL of the XenServer host.",
"order" : 1},
- "uuid" : {
- "getopt" : "U:",
- "longopt" : "uuid",
- "help" : "-U, --uuid UUID of the VM to fence",
- "required" : "0",
- "shortdesc" : "The UUID of the virtual machine to fence.",
- "order" : 1},
"sudo" : {
"getopt" : "d",
"longopt" : "use-sudo",
@@ -646,11 +639,6 @@ def check_input(device_opt, opt):
if options["--action"] == "disable":
options["--action"] = "off"
- # UUID is now only alias for --plug; because we can detect it automatically
- if options.has_key("--uuid"):
- options["--plug"] == options["--uuid"]
- del options["--uuid"]
-
## automatic detection and set of valid UUID from --plug
try:
options["--uuid"] = str(uuid.UUID(options["--plug"]))
diff --git a/fence/agents/vmware_soap/fence_vmware_soap.py b/fence/agents/vmware_soap/fence_vmware_soap.py
index 3c08eeb..aeafa26 100644
--- a/fence/agents/vmware_soap/fence_vmware_soap.py
+++ b/fence/agents/vmware_soap/fence_vmware_soap.py
@@ -156,7 +156,7 @@ def set_power_status(conn, options):
conn.service.PowerOffVM_Task(mo_machine)
def main():
- device_opt = [ "ipaddr", "login", "passwd", "ssl", "port", "uuid" ]
+ device_opt = [ "ipaddr", "login", "passwd", "ssl", "port" ]
atexit.register(atexit_handler)
@@ -174,7 +174,7 @@ that have SOAP API v4.1+. \
Name of virtual machine (-n / port) has to be used in inventory path \
format (e.g. /datacenter/vm/Discovered virtual machine/myMachine). \
In the cases when name of yours VM is unique you can use it instead. \
-Alternatively you can always use UUID (-U / uuid) to access virtual machine."
+Alternatively you can always use UUID to access virtual machine."
docs["vendorurl"] = "http://www.vmware.com"
show_docs(options, docs)
diff --git a/fence/agents/xenapi/fence_xenapi.py b/fence/agents/xenapi/fence_xenapi.py
index 25e6056..de42c6c 100644
--- a/fence/agents/xenapi/fence_xenapi.py
+++ b/fence/agents/xenapi/fence_xenapi.py
@@ -200,8 +200,7 @@ def return_vm_reference(session, options):
def main():
- device_opt = [ "login", "passwd", "port", "no_login", "no_password", "session_url",
- "uuid" ]
+ device_opt = [ "login", "passwd", "port", "no_login", "no_password", "session_url" ]
atexit.register(atexit_handler)
11 years, 2 months
fence-agents: master - fence_apc: Add support for firmware 5.x
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=dfff68...
Commit: dfff684d59a6c427c9bb680f9a26b9b960005486
Parent: f0969886c13feae734547d4cb9241f9f6eae0d9f
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Mon Feb 11 19:07:36 2013 +0100
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Mon Feb 11 19:07:36 2013 +0100
fence_apc: Add support for firmware 5.x
New major version of firmware is now supported.
Resolves: rhbz#886614
---
fence/agents/apc/fence_apc.py | 51 ++++++++++++++++++++++++++++++++++++---
fence/agents/lib/fencing.py.py | 14 +++++++++-
tests/actions.d/list.cfg | 2 +
tests/test-apc2.py | 17 +++++++++++++
tests/test-apc5.py | 17 +++++++++++++
5 files changed, 95 insertions(+), 6 deletions(-)
diff --git a/fence/agents/apc/fence_apc.py b/fence/agents/apc/fence_apc.py
index 1d82957..13b1e69 100644
--- a/fence/agents/apc/fence_apc.py
+++ b/fence/agents/apc/fence_apc.py
@@ -68,7 +68,7 @@ def get_power_status(conn, options):
conn.send_eol(options["--switch"])
while True:
- exp_result = conn.log_expect(options, [ options["--command-prompt"], "Press <ENTER>" ], int(options["--shell-timeout"]))
+ exp_result = conn.log_expect(options, options["--command-prompt"] + [ "Press <ENTER>" ], int(options["--shell-timeout"]))
lines = conn.before.split("\n")
show_re = re.compile('(^|\x0D)\s*(\d+)- (.*?)\s+(ON|OFF)\s*')
for x in lines:
@@ -146,7 +146,7 @@ def set_power_status(conn, options):
else:
conn.send_eol(options["--switch"])
- while 1 == conn.log_expect(options, [ options["--command-prompt"], "Press <ENTER>" ], int(options["--shell-timeout"])):
+ while 1 == conn.log_expect(options, options["--command-prompt"] + [ "Press <ENTER>" ], int(options["--shell-timeout"])):
conn.send_eol("")
conn.send_eol(options["--plug"]+"")
@@ -173,13 +173,47 @@ def set_power_status(conn, options):
conn.log_expect(options, "- Logout", int(options["--shell-timeout"]))
conn.log_expect(options, options["--command-prompt"], int(options["--shell-timeout"]))
+def get_power_status5(conn, options):
+ exp_result = 0
+ outlets = {}
+
+ conn.send_eol("olStatus all")
+
+ exp_result = conn.log_expect(options, options["--command-prompt"], int(options["--shell-timeout"]))
+ lines = conn.before.split("\n")
+
+ show_re = re.compile('^\s*(\d+): (.*): (On|Off)\s*$', re.IGNORECASE)
+
+ for x in lines:
+ res = show_re.search(x)
+ if (res != None):
+ outlets[res.group(1)] = (res.group(2), res.group(3))
+
+ if ["list", "monitor"].count(options["--action"]) == 1:
+ return outlets
+ else:
+ try:
+ (_, status) = outlets[options["--plug"]]
+ return status.lower().strip()
+ except KeyError:
+ fail(EC_STATUS)
+
+def set_power_status5(conn, options):
+ action = {
+ 'on' : "olOn",
+ 'off': "olOff"
+ }[options["--action"]]
+
+ conn.send_eol(action + " " + options["--plug"])
+ conn.log_expect(options, options["--command-prompt"], int(options["--power-timeout"]))
+
def main():
device_opt = [ "ipaddr", "login", "passwd", "cmd_prompt", "secure", \
"port", "switch" ]
atexit.register(atexit_handler)
- all_opt["cmd_prompt"]["default"] = "\n>"
+ all_opt["cmd_prompt"]["default"] = [ "\n>", "\napc>" ]
all_opt["ssh_options"]["default"] = "-1 -c blowfish"
options = check_input(device_opt, process_input(device_opt))
@@ -204,7 +238,16 @@ will block any necessary fencing actions."
## Operate the fencing device
####
conn = fence_login(options)
- result = fence_action(conn, options, set_power_status, get_power_status, get_power_status)
+
+ ## Detect firmware version (ASCII menu vs command-line interface)
+ ## and continue with proper action
+ ####
+ result = -1
+ firmware_version = re.compile('\s*v(\d)*\.').search(conn.before)
+ if (firmware_version != None) and (firmware_version.group(1) == "5"):
+ result = fence_action(conn, options, set_power_status5, get_power_status5, get_power_status5)
+ else:
+ result = fence_action(conn, options, set_power_status, get_power_status, get_power_status)
##
## Logout from system
diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py
index 37be50e..188ee1f 100644
--- a/fence/agents/lib/fencing.py.py
+++ b/fence/agents/lib/fencing.py.py
@@ -862,7 +862,8 @@ def fence_login(options):
time.sleep(int(options["--delay"]))
try:
- re_login = re.compile("(login\s*: )|(Login Name: )|(username: )|(User Name :)", re.IGNORECASE)
+ re_login_string = "(login\s*: )|(Login Name: )|(username: )|(User Name :)"
+ re_login = re.compile(re_login_string, re.IGNORECASE)
re_pass = re.compile("(password)|(pass phrase)", re.IGNORECASE)
if options.has_key("--ssl"):
@@ -955,7 +956,16 @@ def fence_login(options):
try:
conn.send_eol(options["--password"])
- conn.log_expect(options, options["--command-prompt"], int(options["--shell-timeout"]))
+ valid_password = conn.log_expect(options, [ re_login_string ] + options["--command-prompt"], int(options["--shell-timeout"]))
+ if valid_password == 0:
+ ## password is invalid or we have to change EOL separator
+ options["eol"] = "\r"
+ conn.send_eol("")
+ conn.send_eol("")
+ conn.send_eol(options["--username"])
+ conn.log_expect(options, re_pass, int(options["--login-timeout"]))
+ conn.send_eol(options["--password"])
+ conn.log_expect(options, options["--command-prompt"], int(options["--login-timeout"]))
except KeyError:
fail(EC_PASSWORD_MISSING)
except pexpect.EOF:
diff --git a/tests/actions.d/list.cfg b/tests/actions.d/list.cfg
new file mode 100644
index 0000000..b7ed552
--- /dev/null
+++ b/tests/actions.d/list.cfg
@@ -0,0 +1,2 @@
+name = "List plugs and check port 6"
+actions = [ { "command" : "list", "return_code" : "^0$" } ]
diff --git a/tests/test-apc2.py b/tests/test-apc2.py
new file mode 100755
index 0000000..bb5aefd
--- /dev/null
+++ b/tests/test-apc2.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+
+from fence_testing import test_action
+
+def main():
+ DEVICE = "devices.d/apc-v2.cfg"
+
+ ACT_STATUS = "actions.d/status.cfg"
+ ACT_ONOFF = "actions.d/power-on-off.cfg"
+ ACT_LIST = "actions.d/list.cfg"
+
+ test_action(DEVICE, ACT_STATUS, "getopt")
+ test_action(DEVICE, ACT_ONOFF, "stdin")
+ test_action(DEVICE, ACT_LIST, "getopt")
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
diff --git a/tests/test-apc5.py b/tests/test-apc5.py
new file mode 100755
index 0000000..7e86a91
--- /dev/null
+++ b/tests/test-apc5.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+
+from fence_testing import test_action
+
+def main():
+ DEVICE = "devices.d/apc-v5.cfg"
+
+ ACT_STATUS = "actions.d/status.cfg"
+ ACT_ONOFF = "actions.d/power-on-off.cfg"
+ ACT_LIST = "actions.d/list.cfg"
+
+ test_action(DEVICE, ACT_STATUS, "getopt")
+ test_action(DEVICE, ACT_ONOFF, "stdin")
+ test_action(DEVICE, ACT_LIST, "getopt")
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
11 years, 2 months
fence-agents: master - testing: Add verbose mode to testing library
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=f09698...
Commit: f0969886c13feae734547d4cb9241f9f6eae0d9f
Parent: 81dfafdf982309ded440c1806c28da82aff49ba0
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Mon Feb 11 15:46:49 2013 +0100
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Mon Feb 11 15:46:49 2013 +0100
testing: Add verbose mode to testing library
---
tests/fence_testing.py | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/tests/fence_testing.py b/tests/fence_testing.py
index 566872e..166eaf8 100755
--- a/tests/fence_testing.py
+++ b/tests/fence_testing.py
@@ -55,7 +55,7 @@ def _prepare_command(agent_file, method):
return (final_command, stdin_values)
-def test_action(agent, action_file, method):
+def test_action(agent, action_file, method, verbose = False):
""" Run defined sequence of actions on a given fence agent.
This function will run one set of test on a fence agent. Test itself consists of
@@ -110,7 +110,11 @@ def test_action(agent, action_file, method):
if method == "stdin" and sleep_wait == None:
current_command = "/bin/echo -e \"" + current_stdin_options + "\" | " + current_command
- result = os.system(current_command + " &> /dev/null")
+ if verbose == False:
+ result = os.system(current_command + " &> /dev/null")
+ else:
+ print current_command
+ result = os.system(current_command)
exitcode = (result >> 8) & 0xFF
is_valid_result_code = re.search(action["return_code"], str(exitcode), re.IGNORECASE)
11 years, 2 months
fence-agents: master - testing: Add test suite for fence_drac on Dell DRAC IV
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=81dfaf...
Commit: 81dfafdf982309ded440c1806c28da82aff49ba0
Parent: d98df955e17fa6e85e0ea51997e55387389803a5
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Mon Feb 11 15:45:59 2013 +0100
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Mon Feb 11 15:45:59 2013 +0100
testing: Add test suite for fence_drac on Dell DRAC IV
---
.gitignore | 1 +
tests/test-drac4.py | 15 +++++++++++++++
2 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
index c1b028c..245592f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -81,3 +81,4 @@ fence/agents/zvm/fence_zvm
.fence*.tmp
fence-agents*
.version
+tests/devices.d/*
diff --git a/tests/test-drac4.py b/tests/test-drac4.py
new file mode 100755
index 0000000..75c24c5
--- /dev/null
+++ b/tests/test-drac4.py
@@ -0,0 +1,15 @@
+#!/usr/bin/python
+
+from fence_testing import test_action
+
+def main():
+ DRAC4 = "devices.d/dell-drac-4I.cfg"
+
+ ACT_STATUS = "actions.d/status.cfg"
+ ACT_ONOFF = "actions.d/power-on-off.cfg"
+
+ test_action(DRAC4, ACT_STATUS, "getopt")
+ test_action(DRAC4, ACT_ONOFF, "stdin")
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
11 years, 2 months
fence-agents: master - COMPATIBILITY BREAK: remove support for Dell DRAC III and older
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=d98df9...
Commit: d98df955e17fa6e85e0ea51997e55387389803a5
Parent: 5c8d1f68bc3e7a21338e1aa1a7fdea3a6febebf1
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Mon Feb 11 15:23:34 2013 +0100
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Mon Feb 11 15:23:34 2013 +0100
COMPATIBILITY BREAK: remove support for Dell DRAC III and older
Support for older DRAC devices was removed and fence agent was ported to fencing
library. fence_drac should be now used only for Dell DRAC IV.
---
fence/agents/drac/Makefile.am | 4 +-
fence/agents/drac/fence_drac.pl | 768 ---------------------------------------
fence/agents/drac/fence_drac.py | 80 ++++
fence/agents/drac/test_drac.sh | 83 -----
4 files changed, 82 insertions(+), 853 deletions(-)
diff --git a/fence/agents/drac/Makefile.am b/fence/agents/drac/Makefile.am
index 392415f..0616c57 100644
--- a/fence/agents/drac/Makefile.am
+++ b/fence/agents/drac/Makefile.am
@@ -2,7 +2,7 @@ MAINTAINERCLEANFILES = Makefile.in
TARGET = fence_drac
-SRC = $(TARGET).pl
+SRC = $(TARGET).py
EXTRA_DIST = $(SRC)
@@ -11,7 +11,7 @@ sbin_SCRIPTS = $(TARGET)
man_MANS = $(TARGET).8
include $(top_srcdir)/make/fencebuild.mk
-include $(top_srcdir)/make/fencemanperl.mk
+include $(top_srcdir)/make/fenceman.mk
clean-local: clean-man
rm -f $(TARGET)
diff --git a/fence/agents/drac/fence_drac.pl b/fence/agents/drac/fence_drac.pl
deleted file mode 100644
index 536badd..0000000
--- a/fence/agents/drac/fence_drac.pl
+++ /dev/null
@@ -1,768 +0,0 @@
-#!/usr/bin/perl
-
-# The following agent has been tested on:
-#
-# Model DRAC Version Firmware
-# ------------------- -------------- ----------------------
-# PowerEdge 750 DRAC III/XT 3.20 (Build 10.25)
-# Dell Remote Access Controller - ERA and DRAC III/XT, v.3.20, A00
-#
-# PowerEdge 1855 DRAC/MC 1.1 (Build 03.03)
-# PowerEdge 1855 DRAC/MC 1.2 (Build 03.03)
-# PowerEdge 1855 DRAC/MC 1.3 (Build 06.12)
-# PowerEdge 1850 DRAC 4/I 1.35 (Build 09.27)
-# PowerEdge 1850 DRAC 4/I 1.40 (Build 08.24)
-# PowerEdge 1950 DRAC 5 1.0 (Build 06.05.12)
-#
-
-use Getopt::Std;
-use Net::Telnet ();
-
-my $ME = $0;
-
-END {
- defined fileno STDOUT or return;
- close STDOUT and return;
- warn "$ME: failed to close standard output: $!\n";
- $? ||= 1;
-}
-
-# Get the program name from $0 and strip directory names
-$_=$0;
-s/.*\///;
-my $pname = $_;
-
-my $telnet_timeout = 10; # Seconds to wait for matching telent response
-my $power_timeout = 20; # time to wait in seconds for power state changes
-$action = 'reboot'; # Default fence action.
-
-my $logged_in = 0;
-my $quiet = 0;
-
-my $t = new Net::Telnet;
-
-my $DRAC_VERSION_UNKNOWN = '__unknown__';
-my $DRAC_VERSION_III_XT = 'DRAC III/XT';
-my $DRAC_VERSION_MC = 'DRAC/MC';
-my $DRAC_VERSION_4I = 'DRAC 4/I';
-my $DRAC_VERSION_4P = 'DRAC 4/P';
-my $DRAC_VERSION_5 = 'DRAC 5';
-
-my $PWR_CMD_SUCCESS = "/^OK/";
-my $PWR_CMD_SUCCESS_DRAC5 = "/^Server power operation successful$/";
-
-# WARNING!! Do not add code bewteen "#BEGIN_VERSION_GENERATION" and
-# "#END_VERSION_GENERATION" It is generated by the Makefile
-
-#BEGIN_VERSION_GENERATION
-$RELEASE_VERSION="";
-$REDHAT_COPYRIGHT="";
-$BUILD_DATE="";
-#END_VERSION_GENERATION
-
-sub usage
-{
- print "Usage:\n";
- print "\n";
- print "$pname [options]\n";
- print "\n";
- print "Options:\n";
- print " -a <ip> IP address or hostname of DRAC\n";
- print " -c <cmd_prompt> force DRAC command prompt\n";
- print " -d <dracversion> force DRAC version to use\n";
- print " -D <debugfile> debugging output file\n";
- print " -h usage\n";
- print " -l <name> Login name\n";
- print " -m <modulename> DRAC/MC module name\n";
- print " -o <string> Action: reboot (default), off, on or metadata\n";
- print " -p <string> Login password\n";
- print " -S <path> Script to run to retrieve password\n";
- print " -f <seconds> Wait X seconds before fencing is started\n";
- print " -q quiet mode\n";
- print " -V version\n";
- print "\n";
- print "CCS Options:\n";
- print " action = \"string\" Action: reboot (default), off or on\n";
- print " debug = \"debugfile\" debugging output file\n";
- print " ipaddr = \"ip\" IP address or hostname of DRAC\n";
- print " login = \"name\" Login name\n";
- print " passwd = \"string\" Login password\n";
- print " passwd_script = \"path\" Script to run to retrieve password\n";
- print " delay = \"seconds\" Wait X seconds before fencing is started\n";
-
- exit 0;
-}
-
-sub msg
-{
- ($msg)=@_;
- print $msg."\n" unless $quiet;
-}
-
-sub fail
-{
- ($msg)=@_;
- print $msg."\n" unless $quiet;
-
- if (defined $t)
- {
- # make sure we don't get stuck in a loop due to errors
- $t->errmode('return');
-
- logout() if $logged_in;
- $t->close
- }
- exit 1;
-}
-
-sub fail_usage
-{
- ($msg)=@_;
- print STDERR $msg."\n" if $msg;
- print STDERR "Please use '-h' for usage.\n";
- exit 1;
-}
-
-sub version
-{
- print "$pname $RELEASE_VERSION $BUILD_DATE\n";
- print "$REDHAT_COPYRIGHT\n" if ( $REDHAT_COPYRIGHT );
- exit 0;
-}
-
-sub print_metadata
-{
-print '<?xml version="1.0" ?>
-<resource-agent name="fence_drac" shortdesc="fencing agent for Dell Remote Access Card" >
-<longdesc>
-fence_drac is an I/O Fencing agent which can be used with the Dell Remote Access Card (DRAC). This card provides remote access to controlling power to a server. It logs into the DRAC through the telnet interface of the card. By default, the telnet interface is not enabled. To enable the interface, you will need to use the racadm command in the racser-devel rpm available from Dell. To enable telnet on the DRAC:
-
-[root]# racadm config -g cfgSerial -o cfgSerialTelnetEnable 1
-
-[root]# racadm racreset
-</longdesc>
-<vendor-url>http://www.dell.com</vendor-url>
-<parameters>
- <parameter name="action" unique="0" required="1">
- <getopt mixed="-o [action]" />
- <content type="string" default="reboot" />
- <shortdesc lang="en">Fencing Action</shortdesc>
- </parameter>
- <parameter name="ipaddr" unique="0" required="1">
- <getopt mixed="-a [ip]" />
- <content type="string" />
- <shortdesc lang="en">IP Address or Hostname</shortdesc>
- </parameter>
- <parameter name="login" unique="0" required="1">
- <getopt mixed="-l [name]" />
- <content type="string" />
- <shortdesc lang="en">Login Name</shortdesc>
- </parameter>
- <parameter name="passwd" unique="0" required="0">
- <getopt mixed="-p [password]" />
- <content type="string" />
- <shortdesc lang="en">Login password or passphrase</shortdesc>
- </parameter>
- <parameter name="passwd_script" unique="0" required="0">
- <getopt mixed="-S [script]" />
- <content type="string" />
- <shortdesc lang="en">Script to retrieve password</shortdesc>
- </parameter>
- <parameter name="cmd_prompt" unique="0" required="0">
- <getopt mixed="-c [prompt]" />
- <content type="string" />
- <shortdesc lang="en">Force fence_drac to use cmd_prompt as the command prompt</shortdesc>
- </parameter>
- <parameter name="drac_version" unique="0" required="0">
- <getopt mixed="-d [version]" />
- <content type="string" />
- <shortdesc lang="en">Force fence_drac to treat the device as though it was for the specified drac version</shortdesc>
- </parameter>
- <parameter name="module_name" unique="0" required="0">
- <getopt mixed="-m [modulename]" />
- <content type="string"/>
- <shortdesc lang="en">The module name of the blade when using DRAC/MC firmware.</shortdesc>
- </parameter>
- <parameter name="debug" unique="0" required="0">
- <getopt mixed="-D [dumpfile]" />
- <content type="string"/>
- <shortdesc lang="en">Debug file of the telnet interaction</shortdesc>
- </parameter>
- <parameter name="delay" unique="0" required="0">
- <getopt mixed="-f [seconds]" />
- <content type="string" default="0"/>
- <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
- </parameter>
- <parameter name="help" unique="0" required="0">
- <getopt mixed="-h" />
- <content type="string" />
- <shortdesc lang="en">Display help and exit</shortdesc>
- </parameter>
-</parameters>
-<actions>
- <action name="on" />
- <action name="off" />
- <action name="reboot" />
- <action name="status" />
- <action name="metadata" />
-</actions>
-</resource-agent>
-';
-}
-
-
-sub login
-{
- $t->open($address) or
- fail "failed: telnet open failed: ". $t->errmsg."\n";
-
- # Expect 'Login: '
- ($_) = $t->waitfor(Match => "/[Ll]ogin: /", Timeout=>15) or
- fail "failed: telnet failed: ". $t->errmsg."\n" ;
-
- # Determine DRAC version
- if (/Dell Embedded Remote Access Controller \(ERA(\/O)?\)\nFirmware Version/m)
- {
- $drac_version = $DRAC_VERSION_III_XT;
- } else {
- if (/.*\((DRAC[^)]*)\)/m)
- {
- print "detected drac version '$1'\n" if $verbose;
- $drac_version = $1 unless defined $drac_version;
-
- print "WARNING: detected drac version '$1' but using "
- . "user defined version '$drac_version'\n"
- if ($drac_version ne $1);
- }
- else
- {
- $drac_version = $DRAC_VERSION_UNKNOWN;
- }
- }
-
- # Setup prompt
- if ($drac_version =~ /$DRAC_VERSION_III_XT/)
- {
- $cmd_prompt = "/\\[$login\\]# /"
- unless defined $cmd_prompt;
- }
- elsif ($drac_version =~ /$DRAC_VERSION_MC/)
- {
- $cmd_prompt = "/DRAC\\/MC:/"
- unless defined $cmd_prompt;
- }
- elsif ($drac_version =~ /$DRAC_VERSION_4I/)
- {
- $cmd_prompt = "/\\[$login\\]# /"
- unless defined $cmd_prompt;
- }
- elsif ($drac_version =~ /$DRAC_VERSION_4P/)
- {
- $cmd_prompt = "/\\[$login\\]# /"
- unless defined $cmd_prompt;
- }
- else
- {
- $drac_version = $DRAC_VERSION_UNKNOWN;
- }
-
- # Take a guess as to what the prompt might be if not already defined
- $cmd_prompt="/(\\[$login\\]# |DRAC\\/MC:|\\\$ )/" unless defined $cmd_prompt;
-
-
- # Send login
- $t->print($login);
-
- # Expect 'Password: '
- $t->waitfor("/Password: /") or
- fail "failed: timeout waiting for password";
-
- # Send password
- $t->print($passwd);
-
- # DRAC5 prints version controller version info
- # only after you've logged in.
- if ($drac_version eq $DRAC_VERSION_UNKNOWN) {
- if ($t->waitfor(Match => "/.*\($DRAC_VERSION_5\)/m")) {
- $drac_version = $DRAC_VERSION_5;
- $cmd_prompt = "/\\\$ /";
- $PWR_CMD_SUCCESS = $PWR_CMD_SUCCESS_DRAC5;
- } else {
- print "WARNING: unable to detect DRAC version '$_'\n";
- }
- }
-
- $t->waitfor($cmd_prompt) or
- fail "failed: invalid username or password";
-
- if ($drac_version eq $DRAC_VERSION_UNKNOWN) {
- print "WARNING: unsupported DRAC version '$drac_version'\n";
- }
-
- $logged_in = 1;
-}
-
-#
-# Set the power status of the node
-#
-sub set_power_status
-{
- my ($state,$dummy) = @_;
- my $cmd,$svr_action;
-
- if ( $state =~ /^on$/) { $svr_action = "powerup" }
- elsif( $state =~ /^off$/) { $svr_action = "powerdown" }
-
- if ($drac_version eq $DRAC_VERSION_MC)
- {
- $cmd = "serveraction -m $modulename -d 0 $svr_action";
- }
- elsif ($drac_version eq $DRAC_VERSION_5) {
- $cmd = "racadm serveraction $svr_action";
- } else
- {
- $cmd = "serveraction -d 0 $svr_action";
- }
-
- $t->print($cmd);
-
- # Expect /$cmd_prompt/
- ($_) = $t->waitfor($cmd_prompt) or
- fail "failed: unexpected serveraction response";
-
- my @cmd_out = split /\n/;
-
- # discard command sent to DRAC
- $_ = shift @cmd_out;
- s/\e\[(([0-9]+;)*[0-9]+)*[ABCDfHJKmsu]//g; #strip ansi chars
- s/^.*\x0D//;
-
- fail "failed: unkown dialog exception: '$_'" unless (/^$cmd$/);
-
- # Additional lines of output probably means an error.
- # Aborting to be safe. Note: additional user debugging will be
- # necessary, run with -D and -v flags
- my $err;
- while (@cmd_out)
- {
- $_ = shift @cmd_out;
- #firmware vers 1.2 on DRAC/MC sends ansi chars - evil
- s/\e\[(([0-9]+;)*[0-9]+)*[ABCDfHJKmsu]//g;
- s/^.*\x0D//;
-
- next if (/^\s*$/); # skip empty lines
- if (defined $err)
- {
- $err = $err."\n$_";
- }
- else
- {
- next if ($PWR_CMD_SUCCESS);
- $err = $_;
- }
- }
- fail "failed: unexpected response: '$err'" if defined $err;
-}
-
-
-#
-# get the power status of the node and return it in $status and $_
-#
-sub get_power_status
-{
- my $status;
- my $modname = $modulename;
- my $cmd;
-
- if ($drac_version eq $DRAC_VERSION_5) {
- $cmd = "racadm serveraction powerstatus";
- } else {
- $cmd = "getmodinfo";
- }
-
- $t->print($cmd);
-
- ($_) = $t->waitfor($cmd_prompt);
-
- my $found_header = 0;
- my $found_module = 0;
-
- my @cmd_out = split /\n/;
-
- # discard command sent to DRAC
- $_ = shift @cmd_out;
- #strip ansi control chars
- s/\e\[(([0-9]+;)*[0-9]+)*[ABCDfHJKmsu]//g;
- s/^.*\x0D//;
-
- fail "failed: unkown dialog exception: '$_'" unless (/^$cmd$/);
-
- if ($drac_version ne $DRAC_VERSION_5) {
- #Expect:
- # #<group> <module> <presence> <pwrState> <health> <svcTag>
- # 1 ----> chassis Present ON Normal CQXYV61
- #
- # Note: DRAC/MC has many entries in the table whereas DRAC III has only
- # a single table entry.
-
- while (1)
- {
- $_ = shift @cmd_out;
- if (/^#<group>\s*<module>\s*<presence>\s*<pwrState>\s*<health>\s*<svcTag>/)
- {
- $found_header = 1;
- last;
- }
- }
- fail "failed: invalid 'getmodinfo' header: '$_'" unless $found_header;
- }
-
- foreach (@cmd_out)
- {
- s/^\s+//g; #strip leading space
- s/\s+$//g; #strip training space
-
- if ($drac_version eq $DRAC_VERSION_5) {
- if(m/^Server power status: (\w+)/) {
- $status = lc($1);
- }
- } else {
- my ($group,$arrow,$module,$presence,$pwrstate,$health,
- $svctag,$junk) = split /\s+/;
-
- if ($drac_version eq $DRAC_VERSION_III_XT || $drac_version eq $DRAC_VERSION_4I || $drac_version eq $DRAC_VERSION_4P)
- {
- fail "failed: extraneous output detected from 'getmodinfo'" if $found_module;
- $found_module = 1;
- $modname = $module;
- }
-
- if ($modname eq $module)
- {
- fail "failed: duplicate module names detected" if $status;
- $found_module = 1;
-
- fail "failed: module not reported present" unless ($presence =~ /Present/);
- $status = $pwrstate;
- }
-
- }
- }
-
- if ($drac_version eq $DRAC_VERSION_MC)
- {
- fail "failed: module '$modulename' not detected" unless $found_module;
- }
-
- $_=$status;
- if(/^(on|off)$/i)
- {
- # valid power states
- }
- elsif ($status)
- {
- fail "failed: unknown power state '$status'";
- }
- else
- {
- fail "failed: unable to determine power state";
- }
-}
-
-
-# Wait upto $power_timeout seconds for node power state to change to
-# $state before erroring out.
-#
-# return 1 on success
-# return 0 on failure
-#
-sub wait_power_status
-{
- my ($state,$dummy) = @_;
- my $status;
-
- $state = lc $state;
-
- for (my $i=0; $i<$power_timeout ; $i++)
- {
- get_power_status;
- $status = $_;
- my $check = lc $status;
-
- if ($state eq $check ) { return 1 }
- sleep 1;
- }
- $_ = "timed out waiting to power $state";
- return 0;
-}
-
-#
-# logout of the telnet session
-#
-sub logout
-{
- $t->print("");
- $t->print("exit");
-}
-
-#
-# error routine for Net::Telnet instance
-#
-sub telnet_error
-{
- fail "failed: telnet returned: ".$t->errmsg."\n";
-}
-
-#
-# execute the action. Valid actions are 'on' 'off' 'reboot' and 'status'.
-# TODO: add 'configure' that uses racadm rpm to enable telnet on the drac
-#
-sub do_action
-{
- if (($action =~ /^off$/i) || ($action =~ /^reboot$/i)) {
- sleep ($delay) if defined($delay);
- }
-
- get_power_status;
- my $status = $_;
-
- if ($action =~ /^on$/i)
- {
- if ($status =~ /^on$/i)
- {
- msg "success: already on";
- return 0;
- }
-
- set_power_status on;
- fail "failed: $_" unless wait_power_status on;
-
- msg "success: powered on";
- }
- elsif ($action =~ /^off$/i)
- {
- if ($status =~ /^off$/i)
- {
- msg "success: already off";
- return 0;
- }
-
- set_power_status off;
- fail "failed: $_" unless wait_power_status off;
-
- msg "success: powered off";
- }
- elsif ($action =~ /^reboot$/i)
- {
- if ( !($status =~ /^off$/i) )
- {
- set_power_status off;
- }
- fail "failed: $_" unless wait_power_status off;
-
- set_power_status on;
- fail "failed: $_" unless wait_power_status on;
-
- msg "success: rebooted";
- }
- elsif ($action =~ /^status$/i)
- {
- msg "status: $status";
- if ($status =~ /on/i)
- {
- return 0;
- } else {
- return 2;
- }
- }
- else
- {
- fail "failed: unrecognised action: '$action'";
- }
-
- return 0;
-}
-
-#
-# Decipher STDIN parameters
-#
-sub get_options_stdin
-{
- my $opt;
- my $line = 0;
- while( defined($in = <>) )
- {
- $_ = $in;
- chomp;
-
- # strip leading and trailing whitespace
- s/^\s*//;
- s/\s*$//;
-
- # skip comments
- next if /^#/;
-
- $line+=1;
- $opt=$_;
- next unless $opt;
-
- ($name,$val)=split /\s*=\s*/, $opt;
-
- if ( $name eq "" )
- {
- print STDERR "parse error: illegal name in option $line\n";
- exit 2;
- }
- # DO NOTHING -- this field is used by fenced
- elsif ($name eq "agent" )
- {
- }
- elsif ($name eq "ipaddr" )
- {
- $address = $val;
- }
- elsif ($name eq "login" )
- {
- $login = $val;
- }
- elsif ($name eq "action" )
- {
- $action = $val;
- }
- elsif ($name eq "passwd" )
- {
- $passwd = $val;
- }
- elsif ($name eq "passwd_script" )
- {
- $passwd_script = $val;
- }
- elsif ($name eq "debug" )
- {
- $debug = $val;
- }
- elsif ($name eq "modulename" )
- {
- $modulename = $val;
- }
- elsif ($name eq "drac_version" )
- {
- $drac_version = $val;
- }
- elsif ($name eq "cmd_prompt" )
- {
- $cmd_prompt = $val;
- }
- elsif ($name eq "delay")
- {
- $delay = $val;
- }
- }
-}
-
-
-### MAIN #######################################################
-
-#
-# Check parameters
-#
-if (@ARGV > 0) {
- getopts("a:c:d:D:hl:m:o:p:S:qVvf:") || fail_usage ;
-
- usage if defined $opt_h;
- version if defined $opt_V;
-
- $quiet = 1 if defined $opt_q;
- $debug = $opt_D;
-
- fail_usage "Unknown parameter." if (@ARGV > 0);
-
- if ((defined $opt_o) && ($opt_o =~ /metadata/i)) {
- print_metadata();
- exit 0;
- }
-
- fail_usage "No '-a' flag specified." unless defined $opt_a;
- $address = $opt_a;
-
- fail_usage "No '-l' flag specified." unless defined $opt_l;
- $login = $opt_l;
-
- $modulename = $opt_m if defined $opt_m;
- $delay = $opt_f if defined $opt_f;
-
- if (defined $opt_S) {
- $pwd_script_out = `$opt_S`;
- chomp($pwd_script_out);
- if ($pwd_script_out) {
- $opt_p = $pwd_script_out;
- }
- }
-
- fail_usage "No '-p' or '-S' flag specified." unless defined $opt_p;
- $passwd = $opt_p;
-
- $verbose = $opt_v if defined $opt_v;
-
- $cmd_prompt = $opt_c if defined $opt_c;
- $drac_version = $opt_d if defined $opt_d;
-
- if ($opt_o)
- {
- fail_usage "Unrecognised action '$opt_o' for '-o' flag"
- unless $opt_o =~ /^(Off|On|Reboot|status)$/i;
- $action = $opt_o;
- }
-
-} else {
- get_options_stdin();
-
- if ((defined $action) && ($action =~ /metadata/i)) {
- print_metadata();
- exit 0;
- }
-
- fail "failed: no IP address" unless defined $address;
- fail "failed: no login name" unless defined $login;
-
- if (defined $passwd_script) {
- $pwd_script_out = `$passwd_script`;
- chomp($pwd_script_out);
- if ($pwd_script_out) {
- $passwd = $pwd_script_out;
- }
- }
-
- fail "failed: no password" unless defined $passwd;
- fail "failed: unrecognised action: $action"
- unless $action =~ /^(Off|On|Reboot|status)$/i;
-}
-
-
-$t->timeout($telnet_timeout);
-$t->input_log($debug) if $debug;
-$t->errmode('return');
-
-login;
-
-# Abort on failure beyond here
-$t->errmode(\&telnet_error);
-
-if ($drac_version eq $DRAC_VERSION_III_XT)
-{
- fail "failed: option 'modulename' not compatilble with DRAC version '$drac_version'"
- if defined $modulename;
-}
-elsif ($drac_version eq $DRAC_VERSION_MC)
-{
- fail "failed: option 'modulename' required for DRAC version '$drac_version'"
- unless defined $modulename;
-}
-
-my $res = do_action;
-
-logout;
-
-exit $res;
-
-
diff --git a/fence/agents/drac/fence_drac.py b/fence/agents/drac/fence_drac.py
new file mode 100644
index 0000000..e081001
--- /dev/null
+++ b/fence/agents/drac/fence_drac.py
@@ -0,0 +1,80 @@
+#!/usr/bin/python
+
+import sys, re, pexpect, exceptions
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION=""
+REDHAT_COPYRIGHT=""
+BUILD_DATE=""
+#END_VERSION_GENERATION
+
+def get_power_status(conn, options):
+ conn.send_eol("getmodinfo")
+ conn.log_expect(options, options["--command-prompt"], int(options["--shell-timeout"]))
+ status = re.compile("\s+(on|off)\s+", re.IGNORECASE).search(conn.before).group(1)
+ return (status.lower().strip())
+
+def set_power_status(conn, options):
+ action = {
+ 'on' : "powerup",
+ 'off': "powerdown"
+ }[options["--action"]]
+
+ conn.send_eol("serveraction -d 0 " + action)
+ conn.log_expect(options, options["--command-prompt"], int(options["--shell-timeout"]))
+
+def main():
+ device_opt = [ "ipaddr", "login", "passwd", "cmd_prompt" ]
+
+ atexit.register(atexit_handler)
+
+ opt = process_input(device_opt)
+ if "--username" in opt:
+ all_opt["cmd_prompt"]["default"] = "\\[" + opt["--username"] + "\\]# "
+ else:
+ all_opt["cmd_prompt"]["default"] = "\\[" "username" + "\\]# "
+
+ options = check_input(device_opt, opt)
+
+ docs = { }
+ docs["shortdesc"] = "I/O Fencing agent for Dell DRAC IV"
+ docs["longdesc"] = "fence_drac is an I/O Fencing agent which can be used with \
+the Dell Remote Access Card (DRAC). This card provides remote access to controlling \
+power to a server. It logs into the DRAC through the telnet interface of the card. By \
+default, the telnet interface is not enabled. To enable the interface, you will need \
+to use the racadm command in the racser-devel rpm available from Dell. \
+\
+To enable telnet on the DRAC: \
+\
+[root]# racadm config -g cfgSerial -o cfgSerialTelnetEnable 1 \
+\
+[root]# racadm racreset \
+"
+ docs["vendorurl"] = "http://www.dell.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ####
+ conn = fence_login(options)
+ result = fence_action(conn, options, set_power_status, get_power_status, None)
+
+ ##
+ ## Logout from system
+ ##
+ ## In some special unspecified cases it is possible that
+ ## connection will be closed before we run close(). This is not
+ ## a problem because everything is checked before.
+ ######
+ try:
+ conn.send_eol("exit")
+ conn.close()
+ except:
+ pass
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/fence/agents/drac/test_drac.sh b/fence/agents/drac/test_drac.sh
deleted file mode 100644
index 55ebc4d..0000000
--- a/fence/agents/drac/test_drac.sh
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/bin/bash
-
-verbose="-D /dev/stdout -v "
-passwd="calvin"
-login="root"
-
-drac="drac.localhost.localdomain"
-modulename=" -m Server-1 "
-
-
-fence_drac="./fence_drac.pl"
-i=0
-
-cmd()
-{
- echo $*
- out=$(echo $*; $*)
- out_exit=$?
-
- echo "$out" > out.log.$i
- echo "Exit $out_exit" >> out.log.$i
-
- if [ $out_exit -ne 0 ]
- then
- echo "ASSERTION FAILURE: command failed: see out.log.$i" >&2
- exit 1
- fi
-
- : $((i++))
-}
-
-pause()
-{
- echo "press ENTER to continue"
- read
-}
-
-assert()
-{
- get_status
- if [ "$status" != "$1" ]
- then
- echo "ASSERTION FAILURE: power status is '$status' not '$1'" >&2
- exit 1
- fi
-}
-
-get_status()
-{
- cmd $fence_drac -o status -a $drac -l $login -p $passwd $modulename $verbose
- status=$(echo "$out" | awk '($1 == "status:") { print tolower($2)}')
- echo "status -> $status"
-}
-
-get_status
-pause
-
-cmd $fence_drac -o off -a $drac -l $login -p $passwd $modulename $verbose
-assert off
-
-cmd $fence_drac -o on -a $drac -l $login -p $passwd $modulename $verbose
-assert on
-
-cmd $fence_drac -o off -a $drac -l $login -p $passwd $modulename $verbose
-assert off
-
-cmd $fence_drac -o reboot -a $drac -l $login -p $passwd $modulename $verbose
-assert on
-
-cmd $fence_drac -o on -a $drac -l $login -p $passwd $modulename $verbose
-assert on
-
-cmd $fence_drac -o reboot -a $drac -l $login -p $passwd $modulename $verbose
-assert on
-
-cmd $fence_drac -o off -a $drac -l $login -p $passwd $modulename $verbose
-assert off
-
-cmd $fence_drac -o off -a $drac -l $login -p $passwd $modulename $verbose
-assert off
-
-echo SUCCESS
-exit 0
11 years, 2 months
fence-agents: master - fence agents: Fence agents errors are logged to syslog
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=5c8d1f...
Commit: 5c8d1f68bc3e7a21338e1aa1a7fdea3a6febebf1
Parent: d8872849a6a45537ffe70c5643187f3753e19ddd
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Mon Feb 11 14:33:09 2013 +0100
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Mon Feb 11 14:33:09 2013 +0100
fence agents: Fence agents errors are logged to syslog
Related: rhbz#879761
---
fence/agents/lib/fencing.py.py | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py
index 98e8fd2..37be50e 100644
--- a/fence/agents/lib/fencing.py.py
+++ b/fence/agents/lib/fencing.py.py
@@ -1,7 +1,7 @@
#!/usr/bin/python
import sys, getopt, time, os, uuid, pycurl
-import pexpect, re, atexit
+import pexpect, re, atexit, syslog
import __main__
## do not add code here.
@@ -387,6 +387,7 @@ def atexit_handler():
os.close(1)
except IOError:
sys.stderr.write("%s failed to close standard output\n"%(sys.argv[0]))
+ syslog.syslog(syslog.LOG_ERR, "Failed to close standard output")
sys.exit(EC_GENERIC_ERROR)
def add_dependency_options(options):
@@ -422,6 +423,7 @@ def fail(error_code):
EC_PASSWORD_MISSING : "Failed: You have to set login password"
}[error_code] + "\n"
sys.stderr.write(message)
+ syslog.syslog(syslog.LOG_ERR, message)
sys.exit(EC_GENERIC_ERROR)
def usage(avail_opt):
@@ -578,6 +580,7 @@ def process_input(avail_opt):
if avail_opt.count(name) == 0:
sys.stderr.write("Parse error: Ignoring unknown option '"+line+"'\n")
+ syslog.syslog(syslog.LOG_WARNING, "Parse error: Ignoring unknown option '"+line)
continue
if all_opt[name]["getopt"].endswith(":"):
@@ -815,11 +818,13 @@ def fence_action(tn, options, set_power_fn, get_power_fn, get_outlet_list = None
# 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 power_on == False:
# this should not fail as node was fenced succesfully
sys.stderr.write('Timed out waiting to power ON\n')
+ syslog.syslog(syslog.LOG_NOTICE, "Timed out waiting to power ON")
print "Success: Rebooted"
elif options["--action"] == "status":
@@ -834,6 +839,7 @@ def fence_action(tn, options, set_power_fn, get_power_fn, get_outlet_list = None
fail(EC_TIMED_OUT)
except pycurl.error, ex:
sys.stderr.write(ex[1] + "\n")
+ syslog.syslog(syslog.LOG_ERR, ex[1])
fail(EC_TIMED_OUT)
return result
@@ -866,6 +872,7 @@ def fence_login(options):
except pexpect.ExceptionPexpect, ex:
## SSL telnet is part of the fencing package
sys.stderr.write(str(ex) + "\n")
+ syslog.syslog(syslog.LOG_ERR, str(ex))
sys.exit(EC_GENERIC_ERROR)
elif options.has_key("--ssh") and 0 == options.has_key("--identity-file"):
command = '%s %s %s@%s -p %s' % (SSH_PATH, force_ipvx, options["--username"], options["--ip"], options["--ipport"])
@@ -875,6 +882,7 @@ def fence_login(options):
conn = fspawn(options, command)
except pexpect.ExceptionPexpect, ex:
sys.stderr.write(str(ex) + "\n")
+ syslog.syslog(syslog.LOG_ERR, str(ex))
sys.stderr.write("Due to limitations, binary dependencies on fence agents "
"are not in the spec file and must be installed separately." + "\n")
sys.exit(EC_GENERIC_ERROR)
@@ -904,6 +912,7 @@ def fence_login(options):
conn = fspawn(options, command)
except pexpect.ExceptionPexpect, ex:
sys.stderr.write(str(ex) + "\n")
+ syslog.syslog(syslog.LOG_ERR, str(ex))
sys.stderr.write("Due to limitations, binary dependencies on fence agents "
"are not in the spec file and must be installed separately." + "\n")
sys.exit(EC_GENERIC_ERROR)
@@ -927,6 +936,7 @@ def fence_login(options):
conn.send("open %s -%s\n"%(options["--ip"], options["--ipport"]))
except pexpect.ExceptionPexpect, ex:
sys.stderr.write(str(ex) + "\n")
+ syslog.syslog(syslog.LOG_ERR, str(ex))
sys.stderr.write("Due to limitations, binary dependencies on fence agents "
"are not in the spec file and must be installed separately." + "\n")
sys.exit(EC_GENERIC_ERROR)
11 years, 2 months
fence-agents: master - fencing: Testing tool and dummy fence agent
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=d88728...
Commit: d8872849a6a45537ffe70c5643187f3753e19ddd
Parent: 710a56b931e6431526419d13cfb095d691a6cf84
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Fri Nov 23 15:42:51 2012 +0100
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Thu Feb 7 21:46:35 2013 +0100
fencing: Testing tool and dummy fence agent
New testing tool for repeating sequences of action on given devices is ready. It should
improve testing process of fence agents and simplify it. So more volunteers can test their
devices.
New fence agent "dummy" is used for testing fencing library as it does not require
any hardware/software.
---
configure.ac | 1 +
fence/agents/dummy/Makefile.am | 17 ++++
fence/agents/dummy/fence_dummy.py | 59 +++++++++++++
tests/actions.d/power-on-off.cfg | 2 +
tests/actions.d/sleep.cfg | 2 +
tests/actions.d/status.cfg | 2 +
tests/devices.d/dummy-with_action.cfg | 9 ++
tests/devices.d/dummy.cfg | 3 +
tests/devices.d/invalid-missing_option.cfg | 4 +
tests/devices.d/true-with_action.cfg | 8 ++
tests/devices.d/true.cfg | 8 ++
tests/fence_testing.py | 122 ++++++++++++++++++++++++++++
tests/fence_testing_test.py | 70 ++++++++++++++++
tests/test.py | 21 +++++
14 files changed, 328 insertions(+), 0 deletions(-)
diff --git a/configure.ac b/configure.ac
index e30581c..de4124d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -258,6 +258,7 @@ AC_CONFIG_FILES([Makefile
fence/agents/cpint/Makefile
fence/agents/drac/Makefile
fence/agents/drac5/Makefile
+ fence/agents/dummy/Makefile
fence/agents/eaton_snmp/Makefile
fence/agents/egenera/Makefile
fence/agents/eps/Makefile
diff --git a/fence/agents/dummy/Makefile.am b/fence/agents/dummy/Makefile.am
new file mode 100644
index 0000000..11405eb
--- /dev/null
+++ b/fence/agents/dummy/Makefile.am
@@ -0,0 +1,17 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+TARGET = fence_dummy
+
+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
+
+clean-local: clean-man
+ rm -f $(TARGET)
diff --git a/fence/agents/dummy/fence_dummy.py b/fence/agents/dummy/fence_dummy.py
new file mode 100644
index 0000000..ccf7f20
--- /dev/null
+++ b/fence/agents/dummy/fence_dummy.py
@@ -0,0 +1,59 @@
+#!/usr/bin/python
+
+import sys, re, pexpect, exceptions
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION="New Dummy Agent - test release on steroids"
+REDHAT_COPYRIGHT=""
+BUILD_DATE=""
+#END_VERSION_GENERATION
+
+def get_power_status(conn, options):
+ try:
+ status_file = open(options["--status-file"], 'r')
+ except:
+ return "off"
+
+ status = status_file.read()
+ status_file.close()
+
+ return status.lower()
+
+def set_power_status(conn, options):
+ if not (options["--action"] in [ "on", "off" ]):
+ return
+
+ status_file = open(options["--status-file"], 'w')
+ status_file.write(options["--action"])
+ status_file.close()
+
+def main():
+ device_opt = [ "no_password", "status_file" ]
+
+ atexit.register(atexit_handler)
+
+ all_opt["status_file"] = {
+ "getopt" : "s:",
+ "longopt" : "status-file",
+ "help":"--status-file=<file> Name of file that holds current status",
+ "required" : "0",
+ "shortdesc" : "File with status",
+ "default" : "/tmp/fence_dummy.status",
+ "order": 1
+ }
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = { }
+ docs["shortdesc"] = "Dummy fence agent"
+ docs["longdesc"] = "fence_dummy"
+ docs["vendorurl"] = "http://www.example.com"
+ show_docs(options, docs)
+
+ result = fence_action(None, options, set_power_status, get_power_status, None)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/actions.d/power-on-off.cfg b/tests/actions.d/power-on-off.cfg
new file mode 100644
index 0000000..d9df57a
--- /dev/null
+++ b/tests/actions.d/power-on-off.cfg
@@ -0,0 +1,2 @@
+name = "Power ON & OFF"
+actions = [ { "command" : "on", "return_code" : "^0$" }, { "command" : "status", "return_code" : "^0$" }, { "command" : "off", "return_code" : "^0$" }, { "command" : "status", "return_code" : "^2$" } ]
diff --git a/tests/actions.d/sleep.cfg b/tests/actions.d/sleep.cfg
new file mode 100644
index 0000000..c0fad72
--- /dev/null
+++ b/tests/actions.d/sleep.cfg
@@ -0,0 +1,2 @@
+name = "Pure Sleep"
+actions = [ { "command" : "sleep(1)", "return_code" : "^0$" }, { "command" : "sleep(3)", "return_code" : "^0$" }, { "command" : "sleep(5)", "return_code" : "^0$" } ]
diff --git a/tests/actions.d/status.cfg b/tests/actions.d/status.cfg
new file mode 100644
index 0000000..760f94b
--- /dev/null
+++ b/tests/actions.d/status.cfg
@@ -0,0 +1,2 @@
+name = "Simple Status"
+actions = [ { "command" : "status", "return_code" : "^[02]$" }, { "command" : "sleep(1)", "return_code" : "^0$" } ]
diff --git a/tests/devices.d/dummy-with_action.cfg b/tests/devices.d/dummy-with_action.cfg
new file mode 100644
index 0000000..5550c36
--- /dev/null
+++ b/tests/devices.d/dummy-with_action.cfg
@@ -0,0 +1,9 @@
+name = "Dummy fence device configuration"
+agent = "/bin/true"
+[options]
+ login = "foo", "--username", "-l"
+ passwd = "bar", "--password", "-p"
+ ipaddr = "fence.example.com", "--ip", "-a"
+ port = "1", "--plug"
+ action = "status", "--action", "-o"
+
diff --git a/tests/devices.d/dummy.cfg b/tests/devices.d/dummy.cfg
new file mode 100644
index 0000000..d912475
--- /dev/null
+++ b/tests/devices.d/dummy.cfg
@@ -0,0 +1,3 @@
+name = "Dummy fence device configuration"
+agent = "/home/marx/GIT/fence-agents/fence/agents/dummy/fence_dummy"
+[options]
diff --git a/tests/devices.d/invalid-missing_option.cfg b/tests/devices.d/invalid-missing_option.cfg
new file mode 100644
index 0000000..0805fdc
--- /dev/null
+++ b/tests/devices.d/invalid-missing_option.cfg
@@ -0,0 +1,4 @@
+name = "Invalid device definition: Both short and long options are missing"
+agent = "/bin/true"
+[options]
+ login = "foo"
diff --git a/tests/devices.d/true-with_action.cfg b/tests/devices.d/true-with_action.cfg
new file mode 100644
index 0000000..d95c9fe
--- /dev/null
+++ b/tests/devices.d/true-with_action.cfg
@@ -0,0 +1,8 @@
+name = "Dummy fence device configuration"
+agent = "/bin/true"
+[options]
+ login = [ "foo", "--username", "-l" ]
+ passwd = [ "bar", "--password", "-p" ]
+ ipaddr = [ "fence.example.com", "--ip", "-a" ]
+ port = [ "1", "--plug" ]
+ action = [ "status", "--action", "-o" ]
diff --git a/tests/devices.d/true.cfg b/tests/devices.d/true.cfg
new file mode 100644
index 0000000..4ba0aa5
--- /dev/null
+++ b/tests/devices.d/true.cfg
@@ -0,0 +1,8 @@
+name = "Dummy fence device configuration"
+agent = "/bin/true"
+[options]
+ login = [ "foo", "--username", "-l" ]
+ passwd = [ "bar", "--password", "-p" ]
+ ipaddr = [ "fence.example.com", "--ip", "-a" ]
+ port = [ "1", "--plug" ]
+
diff --git a/tests/fence_testing.py b/tests/fence_testing.py
new file mode 100755
index 0000000..566872e
--- /dev/null
+++ b/tests/fence_testing.py
@@ -0,0 +1,122 @@
+""" Library for fence agents testing via predefined scenarios """
+from configobj import ConfigObj
+import re, sys, os
+
+EC_CONFIG_FAIL = 1
+
+def _prepare_command(agent_file, method):
+ """ Parse configuration of fence device and prepare (command + STDIN values) to execute.
+
+ Fence device configuration is used to generate a command which can be executed.
+ Because fence agents supports several options how to enter data, we can select
+ from three different methods ("stdin", "getopt" - short options, "longopt").
+ When method "stdin" is used then this function will generate also text which should
+ be entered on STDIN instead of command itself.
+
+ Example of agent definition:
+ name = "Dummy fence device configuration"
+ agent = "/bin/true"
+ [options]
+ login = [ "foo", "--username", "-l" ]
+ passwd = [ "bar", "--password", "-p" ]
+ ipaddr = [ "fence.example.com", "--ip", "-a" ]
+ port = [ "1", "--plug" ]
+ """
+ assert (method in ["stdin", "getopt", "longopt"]), "Invalid method entered"
+
+ config = ConfigObj(agent_file, unrepr = True)
+
+ assert (config.has_key("agent")), "Fence agent has to be defined"
+ final_command = config["agent"]
+ stdin_values = None
+
+ for opt in config["options"].keys():
+ assert isinstance(config["options"][opt], list), "Option %s have to have at least value and longopt"% (opt)
+ assert len(config["options"][opt]) >= 2, "Option %s have to have at least value and longopt"% (opt)
+ value = config["options"][opt][0]
+ if opt == "action":
+ ## ignore action as it is not part of fence device definition
+ continue
+
+ if method == "stdin":
+ option = opt
+ if stdin_values == None:
+ stdin_values = ""
+ stdin_values += option + "=" + value + "\n"
+ elif method == "longopt":
+ option = config["options"][opt][1]
+ final_command += " " + option + " " + value
+ elif method == "getopt":
+ if len(config["options"][opt]) == (2 + 1):
+ option = config["options"][opt][2]
+ else:
+ option = config["options"][opt][1]
+ final_command += " " + option + " " + value
+
+ return (final_command, stdin_values)
+
+def test_action(agent, action_file, method):
+ """ Run defined sequence of actions on a given fence agent.
+
+ This function will run one set of test on a fence agent. Test itself consists of
+ sequence of action and expected return codes. User can select from actions supported
+ by fence agent (on, off, reboot, list, status, monitor) and sleep(X) command where X
+ is in seconds and determine the length of pause between commands. Each action has to
+ have defined regular expression which define acceptable return codes from fence agent
+ or sleep.
+
+ Example of action configuration file:
+ name = "Simple Status"
+ actions = [ { "command" : "status", "return_code" : "^[02]$" }, { "command" : "sleep(1)", "return_code" : "^0$" } ]
+ """
+ re_sleep_command = re.compile('sleep\(([0-9]+)\)', re.IGNORECASE)
+ config = ConfigObj(action_file, unrepr = True)
+
+ (command, stdin_options) = _prepare_command(agent, method)
+
+ for action in config["actions"]:
+ assert action.has_key("command"), "Action %s need to have defined 'command'"% (action_file)
+ assert action.has_key("return_code"), "Command %s (in %s) need to have 'return_code' defined"% (action_file, action["command"])
+
+ sleep_wait = None
+ current_command = None
+ current_stdin_options = None
+
+ if not (action["command"] in [ "status", "reboot", "on", "off", "list", "monitor" ]):
+ is_sleep = re.search(re_sleep_command, action["command"])
+ if is_sleep != None:
+ sleep_wait = is_sleep.group(1)
+ else:
+ sys.stderr.write("ERROR: %s contains unsupported action \"%s\"\n"% (action_file, action["command"]))
+ sys.exit(1)
+
+ if sleep_wait != None:
+ current_command = "/bin/sleep " + sleep_wait
+ current_stdin_options = None
+ else:
+ current_command = command
+ current_stdin_options = stdin_options
+
+ if method == "stdin":
+ if current_stdin_options == None:
+ current_stdin_options = ""
+ current_stdin_options += "action=%s"% (action["command"])
+ elif method == "longopt":
+ current_command += " --action=%s"% (action["command"])
+ elif method == "getopt":
+ current_command += " -o %s"% (action["command"])
+
+ # @note: Broken pipe can occur here and I'm not sure why - non-deterministic
+ if method == "stdin" and sleep_wait == None:
+ current_command = "/bin/echo -e \"" + current_stdin_options + "\" | " + current_command
+
+ result = os.system(current_command + " &> /dev/null")
+ exitcode = (result >> 8) & 0xFF
+
+ is_valid_result_code = re.search(action["return_code"], str(exitcode), re.IGNORECASE)
+
+ if is_valid_result_code == None:
+ print "TEST FAILED: %s failed on %s when using (%s)\n"% (agent, action_file, method)
+ print "TEST INFO: %s returns %s\n"% (action["command"], str(exitcode))
+ return
+ print "TEST PASSED: %s worked on %s (%s)\n"% (agent, action_file, method)
diff --git a/tests/fence_testing_test.py b/tests/fence_testing_test.py
new file mode 100755
index 0000000..368ff70
--- /dev/null
+++ b/tests/fence_testing_test.py
@@ -0,0 +1,70 @@
+#!/usr/bin/python
+
+import unittest
+import fence_testing
+
+class TestPrepareCommand(unittest.TestCase):
+ DEVICE_MISSING_OPTION = "devices.d/invalid-missing_option.cfg"
+ DEVICE_CORRECT = "devices.d/true.cfg"
+ DEVICE_CORRECT_WITH_ACTION = "devices.d/true-with_action.cfg"
+
+ def test_missing_device(self):
+ self.assertRaises(fence_testing._prepare_command, None, "getopt")
+
+ def test_missing_option(self):
+ self.assertRaises(AssertionError, fence_testing._prepare_command, self.DEVICE_MISSING_OPTION, "stdin")
+
+ def test_valid_methods(self):
+ fence_testing._prepare_command(self.DEVICE_CORRECT, "getopt")
+ fence_testing._prepare_command(self.DEVICE_CORRECT, "longopt")
+ fence_testing._prepare_command(self.DEVICE_CORRECT, "stdin")
+
+ def test_invalid_method(self):
+ self.assertRaises(AssertionError, fence_testing._prepare_command, self.DEVICE_CORRECT, "invalid")
+
+ def test_is_action_ignored(self):
+ (command1, _) = fence_testing._prepare_command(self.DEVICE_CORRECT, "getopt")
+ (command2, _) = fence_testing._prepare_command(self.DEVICE_CORRECT_WITH_ACTION, "getopt")
+ self.assertEquals(command1, command2)
+
+ def test_is_stdin_empty(self):
+ (_, stdin) = fence_testing._prepare_command(self.DEVICE_CORRECT, "getopt")
+ self.assertEquals(None, stdin)
+ (_, stdin) = fence_testing._prepare_command(self.DEVICE_CORRECT, "longopt")
+ self.assertEquals(None, stdin)
+
+ def test_prepared_command_getopt(self):
+ ## Test also fallback to longopt if short is not present
+ (command, _) = fence_testing._prepare_command(self.DEVICE_CORRECT, "getopt")
+ self.assertEquals("/bin/true -l foo -p bar -a fence.example.com --plug 1", command)
+
+ def test_prepared_command_longopt(self):
+ (command, _) = fence_testing._prepare_command(self.DEVICE_CORRECT, "longopt")
+ self.assertEquals("/bin/true --username foo --password bar --ip fence.example.com --plug 1", command)
+
+ def test_prepared_command_stdin(self):
+ (command, stdin) = fence_testing._prepare_command(self.DEVICE_CORRECT, "stdin")
+ self.assertEquals("/bin/true", command)
+ self.assertEquals("login=foo\npasswd=bar\nipaddr=fence.example.com\nport=1\n", stdin)
+
+class TestTestAction(unittest.TestCase):
+ def test_valid_actions(self):
+ pass
+
+ def test_invalid_actions(self):
+ pass
+
+ def test_valid_return_code(self):
+ pass
+
+ def test_invalid_return_code(self):
+ pass
+
+ def test_valid_re_contains(self):
+ pass
+
+ def test_invalid_re_contains(self):
+ pass
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test.py b/tests/test.py
new file mode 100755
index 0000000..8e82ed9
--- /dev/null
+++ b/tests/test.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python
+
+from fence_testing import test_action
+
+def main():
+ ## @todo: utility1 - run single 'agent' 'action' 'method'
+ ## @todo: utility2 - run complex tests (using utility1?) -> file with test suites
+
+ AGENTDEF = "devices.d/true.cfg"
+ DUMMYDEF = "devices.d/dummy.cfg"
+
+ ACT_STATUS = "actions.d/status.cfg"
+ ACT_ONOFF = "actions.d/power-on-off.cfg"
+
+# test_action(AGENTDEF, ACTIONDEF, "stdin")
+# test_action(AGENTDEF, ACTIONDEF, "getopt")
+ test_action(DUMMYDEF, ACT_STATUS, "getopt")
+ test_action(DUMMYDEF, ACT_ONOFF, "getopt")
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
11 years, 2 months
fence-agents: master - fence_virsh: Replace constant (1) with variable from --power-wait
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=710a56...
Commit: 710a56b931e6431526419d13cfb095d691a6cf84
Parent: ebedf3dfe3a76cc164f590681186b68e0081092e
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Thu Feb 7 21:38:57 2013 +0100
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Thu Feb 7 21:38:57 2013 +0100
fence_virsh: Replace constant (1) with variable from --power-wait
---
fence/agents/virsh/fence_virsh.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/fence/agents/virsh/fence_virsh.py b/fence/agents/virsh/fence_virsh.py
index 1a38940..ccbd6e2 100644
--- a/fence/agents/virsh/fence_virsh.py
+++ b/fence/agents/virsh/fence_virsh.py
@@ -56,7 +56,7 @@ def set_power_status(conn, options):
conn.sendline(prefix + "virsh %s "%(options["--action"] == "on" and "start" or "destroy")+options["--plug"])
conn.log_expect(options, options["--command-prompt"], int(options["--power-timeout"]))
- time.sleep(1)
+ time.sleep(int(options["--power-wait"]))
def main():
device_opt = [ "ipaddr", "login", "passwd", "cmd_prompt", "secure", "port", "sudo" ]
11 years, 2 months
fence-agents: master - fence_cisco_ucs: Fix traceback when hostname cannot be resolved to IP address
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=ebedf3...
Commit: ebedf3dfe3a76cc164f590681186b68e0081092e
Parent: 2424d8c71413d6ba4ace2c002ee80c1f4517b4c8
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Wed Feb 6 16:27:01 2013 +0100
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Wed Feb 6 16:27:01 2013 +0100
fence_cisco_ucs: Fix traceback when hostname cannot be resolved to IP address
---
fence/agents/cisco_ucs/fence_cisco_ucs.py | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/fence/agents/cisco_ucs/fence_cisco_ucs.py b/fence/agents/cisco_ucs/fence_cisco_ucs.py
index 9783250..f70a835 100644
--- a/fence/agents/cisco_ucs/fence_cisco_ucs.py
+++ b/fence/agents/cisco_ucs/fence_cisco_ucs.py
@@ -128,10 +128,13 @@ used with Cisco UCS to fence machines."
time.sleep(int(options["--delay"]))
### Login
- res = send_command(options, "<aaaLogin inName=\"" + options["--username"] + "\" inPassword=\"" + options["--password"] + "\" />", int(options["--login-timeout"]))
- result = RE_COOKIE.search(res)
- if (result == None):
- ## Cookie is absenting in response
+ try:
+ res = send_command(options, "<aaaLogin inName=\"" + options["--username"] + "\" inPassword=\"" + options["--password"] + "\" />", int(options["--login-timeout"]))
+ result = RE_COOKIE.search(res)
+ if (result == None):
+ ## Cookie is absenting in response
+ fail(EC_LOGIN_DENIED)
+ except:
fail(EC_LOGIN_DENIED)
options["cookie"] = result.group(1)
11 years, 3 months