[Cluster-devel] Adding a fence agent

Dwight Hubbard dwight.hubbard at efausol.com
Fri Jul 3 02:39:07 UTC 2009


Here's what I have so far:

#!/usr/bin/python
#######
# Fencing agent for Digital Loggers Web PowerSwitch II
# Written by Dwight Hubbard dwight.hubbard at efausol.com
# Licensed as GPL Version 2
######
# $Revision: 1.4 $
######
# Information for this device is available at:
# http://www.digital-loggers.com/lpc.html
######
## The Following Agent Has Been Tested On:
##
##    Version                  Firmware
## +-----------------------+--------------------------------------+
##  DLI Web PowerSwitch II  Version 1.2.C (Apr 12 2009 / 14:28:13)
#####
#
# Note, this specific switch only supports managment via http on
# port 80 so the only option is to use screen scraping.  This means
# that firmware updates have a good chance of causing this fence
# script to quit working.

import re,time,sys,pycurl,BeautifulSoup
sys.path.append("/usr/share/fence")
from fencing import *

DEBUG=False

class DLIPower:
    def __init__(self,userid='admin',password='4321',hostname='192.168.0.100'):
        self.userid=userid
        self.password=password
        self.hostname=hostname
        self.contents=''
    def body_callback(self,buf):
        self.contents=self.contents+buf
    def geturl(self,url='index.htm') :
        self.contents=''
        curl = pycurl.Curl()
        curl.setopt(curl.URL, 'http://%s:%s@%s/%s' %
(self.userid,self.password,self.hostname,url))
        curl.setopt(curl.WRITEFUNCTION, self.body_callback)
        curl.perform()
        curl.close()
        return self.contents
    def off(self,outlet=0):
        # Return Values
        # 0 - Sucessfully turned off the outlet
        # 1 - Failed to turn off the outlet
        self.geturl(url= 'outlet?%d=OFF' % outlet)
        time.sleep(1)
        if self.status(outlet) == 2:
            return 0
        else:
            print 'bad status returned'
            return 1
    def on(self,outlet=0):
        # Return Values
        # 0 - Sucessfully turned on the outlet
        # 1 - Failed to turn on the outlet
        self.geturl(url= 'outlet?%d=ON' % outlet)
        time.sleep(1)
        if self.status(outlet) == 0:
            return 0
        else:
            return 1
    def reboot(self,outlet=0):
        # Return Values
        # 0 - Sucessfully turned on the outlet
        # 1 - Failed to turn on the outlet
        if self.status(outlet) == 0:
            rc=self.off(outlet)
        else:
            rc=0
        if rc == 0:
            self.on(outlet)
        return rc
    def statuslist(self):
        # Return status informaton in a list format
        # each list item consists of a list with 3 items (port #,
name, state)
        outlets=[]
        soup=BeautifulSoup.BeautifulSoup(self.geturl('index.htm'))
        powertable=soup.findAll('table')[5]
        for temp in powertable.findAll('tr')[2:]:
            columns=temp.findAll('td')
            plugnumber=columns[0].string
            hostname=columns[1].string
            state=columns[2].find('font').string
            outlets.append([int(plugnumber),hostname,state])
        return outlets
    def allstatus(self):
        # print all the outlet status
        print 'Outlet\t%-15.15s\tState' % 'Hostname'
        for item in self.statuslist():
            print '%d\t%-15.15s\t%s' % (item[0],item[1],item[2])
    def status(self,outlet=0):
        # Return Values
        # 0 - The port is on
        # 1 - We got an unexpected result (possible wrong device??)
        # 2 - The port is off
        outlets=self.statuslist()
        if outlet:
            for plug in outlets:
                if plug[0] == outlet:
                    state=plug[2]
                    if state in ['ON','On', 'on']:
                        return 0
                    else:
                        return 2
        return 1

def parsestdin():
    options={}
    for line in sys.stdin.readlines():
        item=line.strip().split('=')
        if len(item) > 1:
            options[item[0]]=item[1]
    return options

if __name__ == "__main__":
    # Parse the input and verify we have all required options
    options=parsestdin()
    if DEBUG:
        d=open('/tmp/fence_dli.debug','a')
        d.write('BEGIN------------------------------\n')
        for item in options.keys():
            d.write('%s=%s' % (item,options[item]))
            d.write('\n')
    if ('port' in options.keys() and 'option' in options.keys()) and
('name' in options.keys() or 'ipaddr' in options.keys()):
        # Set the userid/password to the defaults for the switch
        # and then allow the options to override them.
        password='4321'
        userid  ='admin'
        if 'passwd' in options.keys(): password=options['passwd']
        if 'login'  in options.keys(): userid  =options['login']
        if 'name'   in options.keys(): host    =options['name']
        if 'ipaddr' in options.keys(): host    =options['ipaddr']
        port=int(options['port'])

        # Connect to the switch and perform the requested operation
        switch=DLIPower(userid=userid,password=password,hostname=host)
        if options['option'] == 'off':
            sys.exit(switch.off(port))
        if options['option'] == 'on':
            sys.exit(switch.on(port))
        if options['option'] == 'reboot':
            rc=switch.reboot(port)
            if DEBUG:
                d.write('calling reboot, return code %d\n' % rc )
            sys.exit(rc)
        if options['option'] == 'status':
            sys.exit(switch.status(port))
    else:
        if DEBUG:
            d.write('Missing options\n')
            d.write('\n')
            d.close()
        exit(1)


On Wed, Jul 1, 2009 at 9:52 PM, Fabio M. Di Nitto <fdinitto at redhat.com> wrote:
>
> Hi Dwight,
>
> On Wed, 2009-07-01 at 17:20 -0700, Dwight Hubbard wrote:
> > I created a fence agent script for the Digital Loggers WebSwitch II
> > which seems to be working in accordance to the fencing documentation.
> >
> > Now I have a question.  How do I install the script to work properly
> > with the cluster management tools?
> >
> > It looks like system-config-cluster is pretty monolithic and I would
> > like to be able to install it in a way that updates, etc don't end up
> > overwriting everything. Not to mention, the manual editing of the
> > cluster.conf is a royal pain.
>
> The best solution would be for you to submit the fence agents to us so
> that it can be included in standard releases and maintained together
> with management tools. This would solve the problem in the long run.
>
> For the short term you can install the agent in the same /sbin
> or /usr/sbin directories as the others (it won't be overwritten), but
> unless you are dealing to patch the management tools, they won't be able
> to know anything about it.
>
> I believe the management tools (conga specifically) are changing to
> automatically import fence agents data and adapt automatically but they
> are not there yet.
>
> Fabio
>



--
Dwight Hubbard
Owner Effective Automation Solutions
Website: http://effectiveautomationsolutions.com
Blog: http://computing.dwighthubbard.info
Email: dwight at dwighthubbard.com
Phone: (503) 616-4493
Redhat Certified Engineer - RHCE #804007137224095
VMware Certified Professional - VCP #18529




More information about the Cluster-devel mailing list