Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3151987
fence_lindypdu.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
fence_lindypdu.py
View Options
#!@PYTHON@ -tt
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see
# <http://www.gnu.org/licenses/>.
# The Following agent has been tested on:
# Lindy PDU model 32657
# Firmware release s4.82-091012-1cb08s
# Probably works on different models with same MIB .. but is better test on them
#
# (C) 2021 Daimonlab -- Damiano Scaramuzza (cesello) cesello@daimonlab.it
import
sys
import
atexit
import
logging
sys
.
path
.
append
(
"@FENCEAGENTSLIBDIR@"
)
from
fencing
import
*
from
fencing
import
fail_usage
from
fencing_snmp
import
FencingSnmp
### CONSTANTS ###
# oid defining fence device
OID_SYS_OBJECT_ID
=
'.1.3.6.1.2.1.1.2.0'
### GLOBAL VARIABLES ###
# Device - see Lindy PDU
device
=
None
# Port ID
port_id
=
None
# Switch ID
switch_id
=
None
# Classes describing Device params
# Here I follow the MIBS specs that use "switch" and "plug" concepts but
# the pdu really have one switch only and 8-16 plugs.
# Probably the "switch" term is used for future uses or more advanced pdus
class
LindyPDU
(
object
):
# PDU
status_oid
=
'.1.3.6.1.4.1.17420.1.2.9.
%d
.13.0'
control_oid
=
'.1.3.6.1.4.1.17420.1.2.9.
%d
.13.0'
outlet_table_oid
=
'.1.3.6.1.4.1.17420.1.2.9.
%d
.14'
pdu_table_oid
=
'.1.3.6.1.4.1.17420.1.2.9'
attached_pdus
=
'.1.3.6.1.4.1.17420.1.2.5.0'
ident_str
=
"Lindy 32657 PDU"
state_on
=
1
state_off
=
0
turn_on
=
1
turn_off
=
0
has_switches
=
True
### FUNCTIONS ###
def
lpdu_set_device
(
conn
,
options
):
global
device
agents_dir
=
{
'.1.3.6.1.4.1.17420'
:
LindyPDU
}
# First resolve type of PDU device
pdu_type
=
conn
.
walk
(
OID_SYS_OBJECT_ID
)
if
not
((
len
(
pdu_type
)
==
1
)
and
(
pdu_type
[
0
][
1
]
in
agents_dir
)):
pdu_type
=
[[
None
,
None
]]
device
=
agents_dir
[
pdu_type
[
0
][
1
]]
logging
.
debug
(
"Trying
%s
"
%
(
device
.
ident_str
))
def
lpdu_resolv_port_id
(
conn
,
options
):
if
device
==
None
:
lpdu_set_device
(
conn
,
options
)
port_id
=
switch_id
=
None
# Now we resolv port_id/switch_id
if
options
[
"--plug"
]
.
isdigit
()
and
((
not
device
.
has_switches
)
or
(
options
[
"--switch"
]
.
isdigit
())):
port_id
=
int
(
options
[
"--plug"
])
if
device
.
has_switches
:
switch_id
=
int
(
options
[
"--switch"
])
else
:
table
=
conn
.
walk
(
device
.
pdu_table_oid
,
30
)
for
x
in
table
:
if
x
[
1
]
.
strip
(
'"'
)
.
split
(
','
)[
0
]
==
options
[
"--plug"
]:
t
=
x
[
0
]
.
split
(
'.'
)
if
device
.
has_switches
:
port_id
=
int
(
t
[
len
(
t
)
-
1
])
switch_id
=
int
(
t
[
len
(
t
)
-
3
])
else
:
port_id
=
int
(
t
[
len
(
t
)
-
1
])
if
port_id
==
None
:
fail_usage
(
"Can't find port with name
%s
!"
%
(
options
[
"--plug"
]))
return
(
switch_id
,
port_id
)
def
get_power_status
(
conn
,
options
):
(
switch_id
,
port_id
)
=
lpdu_resolv_port_id
(
conn
,
options
)
oid
=
((
device
.
has_switches
)
and
device
.
status_oid
%
(
switch_id
)
or
device
.
status_oid
%
(
port_id
))
try
:
(
oid
,
status
)
=
conn
.
get
(
oid
)
# status is a comma separated string
# one line only as "1,1,1,0,1,1,1,1".
state
=
status
.
strip
(
'"'
)
.
split
(
','
)[
port_id
-
1
]
if
state
==
str
(
device
.
state_on
):
return
"on"
elif
state
==
str
(
device
.
state_off
):
return
"off"
else
:
return
None
except
Exception
:
return
None
def
set_power_status
(
conn
,
options
):
(
switch_id
,
port_id
)
=
lpdu_resolv_port_id
(
conn
,
options
)
oid
=
((
device
.
has_switches
)
and
device
.
control_oid
%
(
switch_id
)
or
device
.
control_oid
%
(
port_id
))
(
oid
,
status
)
=
conn
.
get
(
oid
)
# status is a comma separated string
state
=
status
.
strip
(
'"'
)
.
split
(
','
)
state
[
port_id
-
1
]
=
str
((
options
[
"--action"
]
==
"on"
and
device
.
turn_on
or
device
.
turn_off
))
conn
.
set
(
oid
,
","
.
join
(
state
))
def
get_outlets_status
(
conn
,
options
):
result
=
{}
pdu_id
=
[]
if
device
==
None
:
lpdu_set_device
(
conn
,
options
)
if
(
device
.
has_switches
and
options
[
"--switch"
]
.
isdigit
()):
pdu_id
.
append
(
options
[
"--switch"
])
elif
(
device
.
has_switches
):
#search for all pdu
pdus
=
conn
.
walk
(
device
.
attached_pdus
,
30
)
pdus_info
=
pdus
[
0
][
1
]
.
strip
(
'"'
)
.
split
(
','
)
pdu_id
=
pdus_info
[
1
:]
else
:
#I really don't know what to do with this case. I haven't a different lindy pdu to test
table_oid
=
device
.
pdu_table_oid
for
switch
in
pdu_id
:
table_oid
=
device
.
outlet_table_oid
%
int
(
switch
)
res_ports
=
conn
.
walk
(
table_oid
,
30
)
status_oid
=
device
.
status_oid
%
int
(
switch
)
port_status
=
conn
.
walk
(
status_oid
,
30
)
state
=
port_status
[
0
][
1
]
.
strip
(
'"'
)
.
split
(
','
)
for
x
in
res_ports
:
t
=
x
[
0
]
.
split
(
'.'
)
port_num
=
((
device
.
has_switches
)
and
"
%s
:
%s
"
%
(
t
[
len
(
t
)
-
4
],
t
[
len
(
t
)
-
2
])
or
"
%s
"
%
(
t
[
len
(
t
)
-
2
]))
port_name
=
x
[
1
]
.
strip
(
'"'
)
.
split
(
','
)[
0
]
result
[
port_num
]
=
(
port_name
,
"on"
if
state
[
int
(
t
[
len
(
t
)
-
2
])
-
1
]
==
'1'
else
"off"
)
return
result
# Main agent method
def
main
():
global
device
device_opt
=
[
"ipaddr"
,
"login"
,
"passwd"
,
"no_login"
,
"no_password"
,
\
"port"
,
"snmp_version"
,
"snmp"
,
"switch"
]
atexit
.
register
(
atexit_handler
)
all_opt
[
"snmp_version"
][
"default"
]
=
"1"
all_opt
[
"community"
][
"default"
]
=
"public"
all_opt
[
"switch"
][
"default"
]
=
"1"
device
=
LindyPDU
options
=
check_input
(
device_opt
,
process_input
(
device_opt
))
docs
=
{}
docs
[
"shortdesc"
]
=
"Fence agent for Lindy over SNMP"
docs
[
"longdesc"
]
=
"fence_lindypdu is an I/O Fencing agent
\
which can be used with the Lindy PDU network power switch. It logs
\
into a device via SNMP and reboots a specified outlet. It supports
\
SNMP v1 with all combinations of authenticity/privacy settings."
docs
[
"vendorurl"
]
=
"http://www.lindy.co.uk"
show_docs
(
options
,
docs
)
# Operate the fencing device
result
=
fence_action
(
FencingSnmp
(
options
),
options
,
set_power_status
,
get_power_status
,
get_outlets_status
)
sys
.
exit
(
result
)
if
__name__
==
"__main__"
:
main
()
File Metadata
Details
Attached
Mime Type
text/x-script.python
Expires
Mon, Feb 24, 2:14 PM (9 h, 12 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1464252
Default Alt Text
fence_lindypdu.py (5 KB)
Attached To
Mode
rF Fence Agents
Attached
Detach File
Event Timeline
Log In to Comment