On Fri, 2012-06-01 at 04:44 -0700, Digimer wrote:
> One new thing that is not mentioned on the API page is the new '-o
> metadata' output. This is needed now for validating the configuration of
> the fence agent.
> 
> If you run 'fence_<pick_a_few> -o metadata' you will see what the output
> should look like. It's pretty simple XML show what options are valid.
> All resource and fence agents need this now.

This is the same as 'echo option=metadata | fence_<agent>' I assume?  It
seems to be from what's installed.  I have the XML there anyway but can
add the new way to access it as well.

One thing that I did find, initially my code was putting a extra newline
before the XML started, with it like this I could add resources and the
stonith agent would be called correctly if required, I got errors in the
logs about extra output in the xml stream though.  When I remove the
newline this went away which looks to me like it's parsing the XML in
two different places with different parsers.

Attached is what I've come up with so far, I found I had to configure it
with pcmk_host_list=<hostname> and set the hostname of the ipmi card as
an attribute, then define one stonith resource per host.  I also had to
list "start" and "stop" actions or I would get errors when I tried to
configure the resource, even though I don't implement them.

The reason for the delays is we on some systems we use shared-port IPMI
cards and the interfaces go off-line for a time whilst the node is
rebooting and going through the BIOS.

Ashley.

#!/usr/bin/python

import commands
import time
import sys

xml = """<?xml version="1.0" ?>
<resource-agent name="fence_ddn_ipmi" shortdesc="Fence agent for IPMI over LAN">
<longdesc>
fence_ddn_ipmi is an I/O Fencing agent which can be used with machines controlled by IPMI. This agent calls support software using ipmitool (http://ipmitool.sf.net/).
</longdesc>
<parameters>

<parameter name="hostname" unique="1">
<content type="string" />
<shortdesc lang="en">Hostname</shortdesc>
</parameter>

<parameter name="ipaddr" unique="1">
<getopt mixed="-a" />
<content type="string" />
<shortdesc lang="en">IPMI Lan IP to talk to</shortdesc>
</parameter>

<parameter name="hostname" unique="1">
<getopt mixed="-a" />
<content type="string" />
<shortdesc lang="en">IPMI Lan hostname to talk to</shortdesc>
</parameter>

<parameter name="userid" unique="0">
<content type="string" />
<shortdesc lang="en">Login</shortdesc>
</parameter>

<parameter name="passwd" unique="0">
<content type="string" />
<shortdesc lang="en">Password</shortdesc>
</parameter>

<parameter name="on_time" unique="0">
<content type="string" default="10"/>
<shortdesc lang="en">Power-on time.</shortdesc>
</parameter>

<parameter name="min_off_time" unique="0">
<content type="string" default="60"/>
<shortdesc lang="en">Minimal power down time</shortdesc>
</parameter>

<parameter name="off_time" unique="0">
<content type="string" default="10"/>
<shortdesc lang="en">Power-off time.</shortdesc>
</parameter>

<parameter name="interface" unique="0">
<content type="string" default="lanp"/>
<shortdesc lang="en">IPMI interface</shortdesc>
</parameter>

</parameters>
<actions>
	<action name="on" />
	<action name="off" />
	<action name="reboot" />
	<action name="monitor" />
	<action name="start" />
	<action name="stop" />
	<action name="metadata" />
</actions>
</resource-agent>
"""

def go(cmds,cmd):
    i = ['ipmitool','-I',cmds['interface'],'-U',cmds['userid'],'-P',cmds['passwd'],'-H',cmds['ipaddr']]
    i.extend(['chassis','power',cmd])
    (status,output) = commands.getstatusoutput(' '.join(i))
    return (status,output)

def get_power_state(cmds):
    (status, output) = go(cmds,'status')
    if status == 0:
        if 'Chassis Power is on' in output:
            return 'on'
        elif 'Chassis Power is off' in output:
            return 'off'
    return 'mu'    

def mon(cmds):
    (status, output) = go(cmds,'status')
    if status == 0:
        if 'Chassis Power is on' in output:
            sys.exit(0)
        elif 'Chassis Power is off' in output:
            sys.exit(0)
    sys.exit(1)

# Power off.  Send the off command, wait off_time then check it's off.
def power_off(cmds):
    (status, output) = go(cmds,'off')
    if status == 0:
        if 'Chassis Power Control: Down/Off' not in output:
            sys.exit(1)
    time.sleep(int(cmds['off_time']))
    state = get_power_state(cmds)
    if state == 'off':
        sys.exit(0)
    sys.exit(1)

# Power off.  Send the off command, wait off_time then check it's off.
def power_on(cmds):
    (status, output) = go(cmds,'on')
    if status == 0:
        if 'Chassis Power Control: Up/On' not in output:
            sys.exit(1)
    time.sleep(int(cmds['on_time']))
    state = get_power_state(cmds)
    if state == 'on':
        sys.exit(0)
    sys.exit(1)

# Power off.  Send the off command, wait off_time then check it's off.
# Return 0 if the off was succesfully, 1 for everthing else.
def power_reboot(cmds):
    (status, output) = go(cmds,'off')
    if status == 0:
        if 'Chassis Power Control: Down/Off' not in output:
            sys.exit(1)
    time.sleep(int(cmds['off_time']))
    state = get_power_state(cmds)
    if state != 'off':
        sys.exit(1)

    # It's powered off OK, now turn it back on again.
    time.sleep(int(cmds['min_off_time']))
    (status, output) = go(cmds,'on')
    sys.exit(0)
    
f = open('/tmp/dlog','a')

r = sys.stdin.readlines()

cmds = {}

for a in r:
    a = a.rstrip()
    comment_start = a.find('#')
    if comment_start != -1:
        a = a[0:comment_start]
    if len(a) == 0:
        continue

    if '=' not in a:
        continue
    (key,value) = a.split('=',1)
    cmds[key] = value

action=None

if 'option' in cmds:
    action = cmds['option']

if 'action' in cmds:
    action = cmds['action']

if action == 'metadata':
    print xml
    sys.exit(0)
elif action == 'monitor':
    mon(cmds)
elif action == 'off':
    power_off(cmds)
elif action == 'on':
    power_on(cmds)
elif action == 'reboot':
    power_reboot(cmds)

sys.exit(3)
_______________________________________________
Pacemaker mailing list: Pacemaker@oss.clusterlabs.org
http://oss.clusterlabs.org/mailman/listinfo/pacemaker

Project Home: http://www.clusterlabs.org
Getting started: http://www.clusterlabs.org/doc/Cluster_from_Scratch.pdf
Bugs: http://bugs.clusterlabs.org

Reply via email to