Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from unittest.mock import MagicMock
2import pytest
3import copy
5from pdu import PDUState
6from drivers.apc import ApcMasterswitchPDU
7from drivers.cyberpower import PDU41004
8from drivers.dummy import DummyPDU
9from drivers.snmp import BaseSnmpPDU, SnmpPDU, snmp_get, snmp_set, snmp_walk
12@pytest.fixture(autouse=True)
13def reset_easysnmp_mock(monkeypatch):
14 import drivers.snmp
15 global snmp_get, snmp_set, snmp_walk
16 m1, m2, m3 = MagicMock(), MagicMock(), MagicMock()
17 # REVIEW: I wonder if there's a clever way of covering the
18 # difference in import locations between here and snmp.py
19 monkeypatch.setattr(drivers.snmp, "snmp_walk", m1)
20 monkeypatch.setattr(drivers.snmp, "snmp_get", m2)
21 monkeypatch.setattr(drivers.snmp, "snmp_set", m3)
22 snmp_walk = m1
23 snmp_get = m2
24 snmp_set = m3
27def test_driver_BaseSnmpPDU_listing_ports():
28 pdu = BaseSnmpPDU("MyPDU", "127.0.0.1", "label_base")
29 snmp_walk.return_value = [MagicMock(value="P1"), MagicMock(value="P2")]
30 snmp_walk.assert_not_called()
31 ports = pdu.ports
32 snmp_walk.assert_called_with(pdu.oid_outlets_label_base,
33 hostname=pdu.hostname, community=pdu.community,
34 version=1)
36 # Check that the labels are stored, and the port IDs are 1-indexed
37 for i in range(0, 2):
38 assert ports[i].port_id == i+1
39 assert ports[i].label == f"P{i+1}"
41 snmp_walk.side_effect = SystemError("An error")
42 with pytest.raises(ValueError):
43 pdu.ports
46def test_driver_BaseSnmpPDU_port_label_mapping():
47 pdu = BaseSnmpPDU("MyPDU", "127.0.0.1", "label_base")
48 pdu.port_oid = MagicMock(return_value="oid_port_1")
49 snmp_walk.return_value = [
50 MagicMock(value="P1"),
51 MagicMock(value="P2")
52 ]
53 snmp_set.return_value = True
54 assert pdu.set_port_state("P1", PDUState.REBOOT) is True
55 pdu.port_oid.assert_called_with(1)
56 snmp_set.assert_called_with(pdu.port_oid.return_value,
57 pdu.state_to_raw_value(PDUState.REBOOT), 'i',
58 hostname=pdu.hostname, community=pdu.community,
59 version=1)
60 assert pdu.set_port_state("P2", PDUState.REBOOT) is True
61 pdu.port_oid.assert_called_with(2)
62 snmp_set.assert_called_with(pdu.port_oid.return_value,
63 pdu.state_to_raw_value(PDUState.REBOOT), 'i',
64 hostname=pdu.hostname, community=pdu.community,
65 version=1)
66 with pytest.raises(ValueError):
67 pdu.set_port_state("flubberbubber", PDUState.OFF)
70def test_driver_BaseSnmpPDU_get_port():
71 pdu = BaseSnmpPDU("MyPDU", "127.0.0.1", "label_base")
73 with pytest.raises(ValueError):
74 pdu.port_oid(2)
75 pdu.port_oid = MagicMock(return_value="oid_port_2")
77 snmp_get.return_value = pdu.raw_value_to_state(PDUState.REBOOT)
78 snmp_get.assert_not_called()
79 assert pdu.get_port_state(2)
80 pdu.port_oid.assert_called_with(2)
81 snmp_get.assert_called_with(pdu.port_oid.return_value,
82 hostname=pdu.hostname, community=pdu.community,
83 version=1)
85 snmp_get.side_effect = SystemError("An error")
86 with pytest.raises(ValueError):
87 pdu.get_port_state(2)
90def test_driver_BaseSnmpPDU_set_port():
91 pdu = BaseSnmpPDU("MyPDU", "127.0.0.1", "label_base")
93 pdu.port_oid = MagicMock(return_value="oid_port_2")
94 snmp_set.return_value = True
95 snmp_set.assert_not_called()
96 assert pdu.set_port_state(2, PDUState.REBOOT) is True
97 pdu.port_oid.assert_called_with(2)
98 snmp_set.assert_called_with(pdu.port_oid.return_value,
99 pdu.state_to_raw_value(PDUState.REBOOT), 'i',
100 hostname=pdu.hostname, community=pdu.community,
101 version=1)
103 snmp_set.side_effect = SystemError("An error")
104 with pytest.raises(ValueError):
105 pdu.set_port_state(2, PDUState.REBOOT)
108def test_driver_BaseSnmpPDU_action_translation():
109 pdu = BaseSnmpPDU("MyPDU", "127.0.0.1", "label_base")
111 # Check the state -> SNMP value translation
112 for action in PDUState.valid_actions():
113 assert pdu.state_to_raw_value(action) == pdu.action_to_snmp_value[action.name]
115 with pytest.raises(ValueError):
116 pdu.state_to_raw_value(PDUState.UNKNOWN)
118 # Check the SNMP value -> state translation
119 for state in PDUState.valid_actions():
120 raw = pdu.state_to_raw_value(state)
121 assert pdu.raw_value_to_state(raw) == state
123 with pytest.raises(AttributeError):
124 pdu.state_to_raw_value(42)
127def test_driver_ApcMasterswitchPDU_check_OIDs():
128 pdu = ApcMasterswitchPDU("MyPDU", config={"hostname": "127.0.0.1"})
130 assert pdu.oid_outlets_label_base == "SNMPv2-SMI::enterprises.318.1.1.4.4.2.1.4"
131 assert pdu.port_oid(10) == "SNMPv2-SMI::enterprises.318.1.1.4.4.2.1.3.10"
134def test_driver_ApcMasterswitchPDU_invalid_config():
135 with pytest.raises(ValueError):
136 ApcMasterswitchPDU("MyPDU", config={})
139def test_driver_PDU41004_check_OIDs():
140 pdu = PDU41004("MyPDU", config={"hostname": "127.0.0.1"})
142 assert pdu.oid_outlets_label_base == "SNMPv2-SMI::enterprises.3808.1.1.3.3.3.1.1.2"
143 assert pdu.port_oid(10) == "SNMPv2-SMI::enterprises.3808.1.1.3.3.3.1.1.4.10"
146def test_driver_PDU41004_invalid_config():
147 with pytest.raises(ValueError):
148 PDU41004("MyPDU", config={})
151def test_driver_DummyPDU():
152 ports = ['P1', 'P2', 'P3']
153 pdu = DummyPDU("MyPDU", {"ports": ports})
155 assert [p.label for p in pdu.ports] == ports
156 assert pdu.get_port_state(0) == PDUState.ON
157 pdu.set_port_state(0, PDUState.OFF)
158 assert pdu.get_port_state(0) == PDUState.OFF
161def test_driver_SnmpPDU_check_OIDs_and_default_actions():
162 pdu = SnmpPDU("MyPDU", config={
163 "hostname": "127.0.0.1",
164 "oid_outlets_label_base": "label_base",
165 "oid_outlets_base": "outlet_base",
166 })
168 assert pdu.community == "private"
169 assert pdu.oid_outlets_label_base == "label_base"
170 assert pdu.port_oid(10) == "outlet_base.10"
171 assert pdu.action_to_snmp_value == super(SnmpPDU, pdu).action_to_snmp_value
174def test_driver_SnmpPDU_actions():
175 pdu = SnmpPDU("MyPDU", config={
176 "hostname": "127.0.0.1",
177 "oid_outlets_label_base": "label_base",
178 "oid_outlets_base": "outlet_base",
179 "community": "public",
180 "action_to_snmp_value": {
181 "ON": 42,
182 "OFF": 43,
183 "REBOOT": 44
184 }
185 })
187 assert pdu.community == "public"
188 assert pdu.action_to_snmp_value == {
189 "ON": 42,
190 "OFF": 43,
191 "REBOOT": 44
192 }
195def test_driver_SnmpPDU_invalid_actions():
196 with pytest.raises(ValueError):
197 SnmpPDU("MyPDU", config={
198 "hostname": "127.0.0.1",
199 "oid_outlets_label_base": "label_base",
200 "oid_outlets_base": "outlet_base",
201 "community": "public",
202 "action_to_snmp_value": {
203 "ON": "TOTO",
204 "OFF": 43,
205 "REBOOT": 44
206 }
207 })
210def test_driver_SnmpPDU_missing_actions():
211 with pytest.raises(ValueError):
212 SnmpPDU("MyPDU", config={
213 "hostname": "127.0.0.1",
214 "oid_outlets_label_base": "label_base",
215 "oid_outlets_base": "outlet_base",
216 "community": "public",
217 "action_to_snmp_value": {
218 "OFF": 43,
219 "REBOOT": 44
220 }
221 })
224def test_driver_SnmpPDU_missing_parameters():
225 valid_config = {
226 "hostname": "127.0.0.1",
227 "oid_outlets_label_base": "label_base",
228 "oid_outlets_base": "outlet_base",
229 "community": "public",
230 "action_to_snmp_value": {
231 "ON": 42,
232 "OFF": 43,
233 "REBOOT": 44
234 }
235 }
237 SnmpPDU("MyPDU", config=valid_config)
238 for required_param in ["hostname", "oid_outlets_label_base", "oid_outlets_base"]:
239 new_config = copy.deepcopy(valid_config)
240 del new_config[required_param]
241 with pytest.raises(ValueError):
242 SnmpPDU("MyPDU", config=new_config)