summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Kenna <cjk@cs.unc.edu>2012-09-11 15:20:55 -0400
committerChristopher Kenna <cjk@cs.unc.edu>2012-09-11 15:20:55 -0400
commite65475c098f1291fad5392b57518e17c92131b0b (patch)
tree4b102632ed4d314f39594693c39fba50722bdedf
parent2240a1abbb239f1c280f40cd5e1f9a20517fddd9 (diff)
Add power management script for the IP 9258.
-rwxr-xr-xpowermanager.py133
1 files changed, 133 insertions, 0 deletions
diff --git a/powermanager.py b/powermanager.py
new file mode 100755
index 0000000..89aad80
--- /dev/null
+++ b/powermanager.py
@@ -0,0 +1,133 @@
1#!/usr/bin/env python
2
3from __future__ import print_function
4
5import sys
6import argparse
7import os.path
8import urllib2
9
10from operator import methodcaller
11from time import sleep
12
13
14"""Manages the power for the IP Power 9258.
15
16You are meant to create symlinks to this file for each port.
17
18"""
19
20class PowerManagerException(RuntimeError):
21 def __init__(self, reason):
22 super(PowerManagerException, self).__init__()
23 self.reason = reason
24
25class PowerManager(object):
26 """Manages the power for a single port of the IP Power 9258."""
27
28 def __init__(self, host, username, password, port):
29 self.host = host
30 self.username = username
31 self.password = password
32 self.port = port
33
34 def __call_url(self, port_value):
35 port_state = '{}={}'.format(self.port, port_value)
36 full_url = 'http://{}/Set.cmd?CMD=SetPower+{}'.format(self.host,
37 port_state)
38 basic_handler = urllib2.HTTPBasicAuthHandler()
39 basic_handler.add_password(realm='IP9258',
40 uri='http://{}/'.format(self.host),
41 user=self.username,
42 passwd=self.password)
43 opener = urllib2.build_opener(basic_handler)
44 urllib2.install_opener(opener)
45 try:
46 url_res = urllib2.urlopen(full_url)
47 txt = url_res.read()
48 if -1 == txt.find(port_state):
49 """Response should be the port_state we wanted, plus HTML."""
50 raise PowerManagerException('Bad response: {}'.format(txt))
51 except urllib2.URLError as e:
52 raise PowerManagerException('Error opening URL: {}'.format(
53 e.reason))
54
55 def power_on(self):
56 print("Power on.")
57 self.__call_url('1')
58
59 def power_off(self):
60 print("Power off.")
61 self.__call_url('0')
62
63 def power_cycle(self):
64 self.power_off()
65 sleep(1)
66 self.power_on()
67
68 @classmethod
69 def dispatch_action(cls, power_manager, action):
70 ACTION_CALLBACKS = {'on': methodcaller('power_on'),
71 'off': methodcaller('power_off'),
72 'cycle': methodcaller('power_cycle')}
73 actions = ACTION_CALLBACKS.keys()
74 try:
75 action_method = ACTION_CALLBACKS[action]
76 except KeyError:
77 raise ValueError('Invalid action: {}'.format(action))
78 action_method(power_manager)
79
80
81def parse_args():
82 p = argparse.ArgumentParser(description='Control power.')
83 p.add_argument('action', help='on|off|cycle')
84 return p.parse_args(sys.argv[1:])
85
86def find_port():
87 """Finds port to use based on script name.
88
89 Assumes the script is named <SOMETHING>-power.py, where the part before the
90 dash is a dict key.
91
92 """
93 POWER_PORTS = { 'pound': 'P60', 'pandaboard': 'P61' }
94
95 script_name = os.path.basename(sys.argv[0])
96 dash_pos = script_name.find('-')
97 if -1 == dash_pos:
98 raise ValueError('No dash found in script name: {}'.format(script_name))
99 port_key = script_name[:dash_pos]
100 try:
101 return POWER_PORTS[port_key]
102 except KeyError:
103 raise KeyError('Port key not found in dict: {}'.format(port_key))
104
105def read_password():
106 fname = os.path.expanduser('~/.poundpower')
107 with open(fname) as f:
108 password = f.read().strip()
109 return password
110
111def main():
112 HOST = 'pound-pwr.cs.unc.edu'
113 USERNAME = 'admin'
114
115 try:
116 password = read_password()
117 except IOError as e:
118 print('Error reading password file: {}'.format(e), file=sys.stderr)
119 sys.exit(1)
120
121 args = parse_args()
122
123 port = find_port()
124 mgr = PowerManager(HOST, USERNAME, password, port)
125 try:
126 PowerManager.dispatch_action(mgr, args.action)
127 except PowerManagerException as e:
128 print('Exception: {}'.format(e.reason), file=sys.stderr)
129 sys.exit(1)
130 sys.exit(0)
131
132if __name__ == '__main__':
133 main()