Skip to content

Commit

Permalink
Merge pull request #1156 from LukaszMrugala/feature/raritan_pdu
Browse files Browse the repository at this point in the history
driver/power: add raritan pdu network power driver
  • Loading branch information
jluebbe committed May 4, 2023
2 parents 573550e + c413de1 commit d63247b
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 32 deletions.
3 changes: 3 additions & 0 deletions doc/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ Currently available are:
``netio_kshell``
Controls a NETIO 4C PDU via a Telnet interface.

``raritan``
Controls Raritan PDUs via SNMP.

``rest``
This is a generic backend for PDU implementations which can be controlled via
HTTP PUT and GET requests.
Expand Down
35 changes: 3 additions & 32 deletions labgrid/driver/power/eaton.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,15 @@
from pysnmp import hlapi
from ..exception import ExecutionError
from ...util.snmp import SimpleSNMP


OID = ".1.3.6.1.4.1.534.6.6.7.6.6.1"
NUMBER_OF_OUTLETS = 16


class _Snmp:
"""A class that helps wrap pysnmp"""
def __init__(self, host, community, port=161):
if port is None:
port = 161

self.engine = hlapi.SnmpEngine()
self.transport = hlapi.UdpTransportTarget((host, port))
self.community = hlapi.CommunityData(community, mpModel=0)
self.context = hlapi.ContextData()

def get(self, oid):
g = hlapi.getCmd(self.engine, self.community, self.transport,
self.context, hlapi.ObjectType(hlapi.ObjectIdentity(oid)),
lookupMib=False)

error_indication, error_status, _, res = next(g)
if error_indication or error_status:
raise ExecutionError("Failed to get SNMP value")
return res[0][1]

def set(self, oid, value):
identify = hlapi.ObjectType(hlapi.ObjectIdentity(oid),
hlapi.Integer(value))
g = hlapi.setCmd(self.engine, self.community, self.transport,
self.context, identify, lookupMib=False)
next(g)


def power_set(host, port, index, value):
assert 1 <= int(index) <= NUMBER_OF_OUTLETS

_snmp = _Snmp(host, 'public', port=port)
_snmp = SimpleSNMP(host, 'public', port=port)
cmd_id = 4 if int(value) else 3
outlet_control_oid = "{}.{}.0.{}".format(OID, cmd_id, index)

Expand All @@ -48,7 +19,7 @@ def power_set(host, port, index, value):
def power_get(host, port, index):
assert 1 <= int(index) <= NUMBER_OF_OUTLETS

_snmp = _Snmp(host, 'public', port=port)
_snmp = SimpleSNMP(host, 'public', port=port)
output_status_oid = "{}.2.0.{}".format(OID, index)

value = _snmp.get(output_status_oid)
Expand Down
38 changes: 38 additions & 0 deletions labgrid/driver/power/raritan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""Driver for the Raritan PDUs
Documentation sources:
* https://www.circitor.fr/Mibs/Html/P/PDU2-MIB.php
* http://support.raritan.com/px3/version-3.0.3/user-guides/PX3-0B-v3.0-E.pdf
* https://cdn1.raritan.com/download/pdu-g2/4.0.20/MIB_Usage_4.0.20_49038.pdf
"""
from ..exception import ExecutionError
from ...util.snmp import SimpleSNMP


OID = ".1.3.6.1.4.1.13742.6.4.1.2.1"
NUMBER_OF_OUTLETS = 16


def power_set(host, port, index, value):
assert 1 <= int(index) <= NUMBER_OF_OUTLETS

_snmp = SimpleSNMP(host, 'private', port=port)
outlet_control_oid = "{}.2.1.{}".format(OID, index)

_snmp.set(outlet_control_oid, str(int(value)))


def power_get(host, port, index):
assert 1 <= int(index) <= NUMBER_OF_OUTLETS

_snmp = SimpleSNMP(host, 'public', port=port)
output_status_oid = "{}.3.1.{}".format(OID, index)

value = _snmp.get(output_status_oid)

if value == 7: # On
return True
if value == 8: # Off
return False

raise ExecutionError("failed to get SNMP value")
31 changes: 31 additions & 0 deletions labgrid/util/snmp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from pysnmp import hlapi
from ..driver.exception import ExecutionError


class SimpleSNMP:
"""A class that helps wrap pysnmp"""
def __init__(self, host, community, port=161):
if port is None:
port = 161

self.engine = hlapi.SnmpEngine()
self.transport = hlapi.UdpTransportTarget((host, port))
self.community = hlapi.CommunityData(community, mpModel=0)
self.context = hlapi.ContextData()

def get(self, oid):
g = hlapi.getCmd(self.engine, self.community, self.transport,
self.context, hlapi.ObjectType(hlapi.ObjectIdentity(oid)),
lookupMib=False)

error_indication, error_status, _, res = next(g)
if error_indication or error_status:
raise ExecutionError("Failed to get SNMP value.")
return res[0][1]

def set(self, oid, value):
identify = hlapi.ObjectType(hlapi.ObjectIdentity(oid),
hlapi.Integer(value))
g = hlapi.setCmd(self.engine, self.community, self.transport,
self.context, identify, lookupMib=False)
next(g)

0 comments on commit d63247b

Please sign in to comment.