Package Peach :: Package Agent :: Module power
[hide private]

Source Code for Module Peach.Agent.power

  1   
  2  ''' 
  3  Monitors to control networked power strips. 
  4   
  5  @author: Michael Eddington 
  6  @author: Adam Cecchetti 
  7  @version: $Id: power.py 780 2008-03-23 02:58:49Z meddingt $ 
  8  ''' 
  9   
 10  # 
 11  # Copyright (c) 2007 Michael Eddington 
 12  # 
 13  # Permission is hereby granted, free of charge, to any person obtaining a copy  
 14  # of this software and associated documentation files (the "Software"), to deal 
 15  # in the Software without restriction, including without limitation the rights  
 16  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
 17  # copies of the Software, and to permit persons to whom the Software is  
 18  # furnished to do so, subject to the following conditions: 
 19  # 
 20  # The above copyright notice and this permission notice shall be included in     
 21  # all copies or substantial portions of the Software. 
 22  # 
 23  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
 24  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
 25  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
 26  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
 27  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 28  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
 29  # SOFTWARE. 
 30  # 
 31   
 32  # Authors: 
 33  #   Michael Eddington (mike@phed.org) 
 34  #       Adam Cecchetti 
 35   
 36  # $Id: power.py 780 2008-03-23 02:58:49Z meddingt $ 
 37   
 38   
 39  import sys, threading, os, time, thread, re, socket 
 40  import urllib, urllib2, cookielib 
 41  import md5, time   
 42   
 43  from Peach.agent import Monitor 
 44   
45 -class _PowerControl:
46 '''Class to control IP9258 ip power strip. 47 ''' 48 49 uri = "" 50 loginurl = "/tgi/login.tgi" 51 powerurl = "/tgi/iocontrol.tgi" 52 username = "" 53 password = "" 54 55 req_headers = { 56 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)', 57 'Referer':'', 58 } 59
60 - def __init__( self, uri, username, password ):
61 self.uri = uri 62 self.username = username 63 self.password = password 64 self.data = [] 65 cookiejar = cookielib.CookieJar() 66 opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar)) 67 urllib2.install_opener(opener)
68 69
70 - def login( self ):
71 url = self.uri 72 req = urllib2.Request( url, None, self.req_headers ) 73 response = urllib2.urlopen( req ) 74 data = response.read() 75 p = re.compile( 'NAME=\"Challenge\" VALUE=\"(.*)\"> <input' ) 76 m = p.search( data ) 77 challenge = m.group(1) 78 79 md5hex = md5.new() 80 md5hex.update( self.username + self.password + challenge ) 81 md5response = md5hex.hexdigest() 82 83 self.password="" 84 85 login_data = { 86 'Username': self.username, 87 'Response': md5response, 88 'Challenge': '', 89 'Password': '' 90 } 91 92 urldata = urllib.urlencode( login_data ) 93 req = urllib2.Request( self.uri + self.loginurl, urldata, self.req_headers ) 94 response = urllib2.urlopen( req ) 95 data = response.read()
96 97
98 - def powerAllOn(self):
99 return "Not impl"
100
101 - def powerAllOff(self):
102 return "Not impl"
103
104 - def powerOn(self, machine):
105 self.powerchange(machine, "On")
106
107 - def powerOff(self, machine):
108 self.powerchange(machine, "Off")
109
110 - def powerchange(self, machine_id, state):
111 112 if(machine_id < 1 or machine_id > 4): 113 print "Invalid Machine ID" 114 return 115 116 if(state != "On" and state != "Off"): 117 print "Invalid State" 118 return 119 120 req = urllib2.Request( self.uri + self.powerurl, None, self.req_headers ) 121 response = urllib2.urlopen( req ) 122 data = response.read() 123 124 P = ["Off", "Off", "Off", "Off"] 125 126 #fuggly TODO:clean me up later 127 p= re.compile('NAME="P60" VALUE="On" CHECKED>') 128 if( p.search( data ) != None): 129 P[0]="On" 130 else: 131 P[0]="0ff" 132 133 p= re.compile('NAME="P61" VALUE="On" CHECKED>') 134 if( p.search( data ) != None): 135 P[1]="On" 136 else: 137 P[1]="0ff" 138 139 p= re.compile('NAME="P62" VALUE="On" CHECKED>') 140 if( p.search( data ) != None): 141 P[2]="On" 142 else: 143 P[2]="0ff" 144 145 p= re.compile('NAME="P63" VALUE="On" CHECKED>') 146 if( p.search( data ) != None): 147 P[3]="On" 148 else: 149 P[3]="0ff" 150 151 P[machine_id-1] = state 152 153 urldata="P60=" + P[0] + "&P60_TS=0&P60_TC=Off&P61=" + P[1] + "&P61_TS=0&P61_TC=Off&P62=" + P[2] + "&P62_TS=0&P62_TC=Off&P63=" + P[3] + "&P63_TS=0&P63_TC=Off&ButtonName=Apply" 154 #print urldata 155 req = urllib2.Request( self.uri + self.powerurl, urldata, self.req_headers ) 156 response = urllib2.urlopen( req )
157
158 - def powercycle(self, machine):
159 self.powerOff(machine) 160 time.sleep(5) 161 self.powerOn( machine ) 162
163 -class NetworkedPower(Monitor):
164 ''' 165 Monitor that will cycle the power port of a networked 166 power strip. Usefull for rebooting a machine after 167 a fault is detected, or every N tests. 168 169 Currently only works with "IP9258". 170 ''' 171
172 - def __init__(self, args):
173 ''' 174 Constructor. Arguments are supplied via the Peach XML 175 file. 176 177 @type args: Dictionary 178 @param args: Dictionary of parameters 179 ''' 180 181 self.hostname = str(args['hostname']) 182 self.username = str(args['username']) 183 self.password = str(args['password']) 184 self.port = int(args['port']) 185 self.waitTime = int(args['waittime']) 186 187 # Cycle power every N tests. 188 try: 189 self.testCount = int(args['testcount']) 190 except: 191 self.testCount = None 192 193 self.count = 0 194 195 # Our name for this monitor 196 self._name = "NetworkedPower"
197
198 - def OnTestStarting(self):
199 ''' 200 Called right before start of test case or variation 201 ''' 202 if self.testCount != None and self.testCount == self.count: 203 self.count = 0 204 pc = _PowerControl("http://" + self.hostname, self.username, self.password) 205 pc.login() 206 pc.powercycle(self.port) 207 time.sleep(self.waitTime) 208 209 else: 210 self.count += 1
211
212 - def OnFault(self):
213 ''' 214 Called when a fault was detected. 215 ''' 216 pc = _PowerControl("http://" + self.hostname, self.username, self.password) 217 pc.login() 218 pc.powercycle(self.port) 219 pc.powerOn(self.port) 220 221 time.sleep(self.waitTime)
222 223
224 -class AMTPower(Monitor):
225 ''' 226 The tragety that is controling our AMT boxen! 227 ''' 228
229 - def __init__(self, args):
230 ''' 231 Constructor. Arguments are supplied via the Peach XML 232 file. 233 234 @type args: Dictionary 235 @param args: Dictionary of parameters 236 ''' 237 238 self.targethostname = str(args['targethostname']) 239 self.makehostname = str(args['makehostname']) 240 self.makeport = int(args['makeport']) 241 self.hostname = str(args['hostname']) 242 self.username = str(args['username']) 243 self.password = str(args['password']) 244 self.port = int(args['port']) 245 self.waitTime = int(args['waittime']) 246 247 # Cycle power every N tests. 248 try: 249 self.testCount = int(args['testcount']) 250 except: 251 self.testCount = None 252 253 self.count = 0 254 255 # Our name for this monitor 256 self._name = "NetworkedPower"
257
258 - def _canWePing(self):
259 pipe = os.popen("ping -n 2 " + self.targethostname) 260 buff = pipe.read() 261 pipe.close() 262 263 if re.compile(r"Reply from \d+\.\d+\.\d+\.\d+: bytes=", re.M).search(buff) != None: 264 return True 265 266 return False
267
268 - def _powerCycle(self):
269 pc = _PowerControl("http://" + self.hostname, self.username, self.password) 270 pc.login() 271 pc.powercycle(self.port)
272
273 - def _hitDahButton(self):
274 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 275 s.connect((self.makehostname, self.makeport)) 276 s.send('O') 277 s.close()
278
279 - def OnTestStarting(self):
280 ''' 281 Called right before start of test case or variation 282 ''' 283 if self.testCount != None and self.testCount == self.count: 284 self.count = 0 285 286 self._powerCycle() 287 self._hitDahButton() 288 289 while not self._canWePing(): 290 time.sleep(1) 291 292 else: 293 self.count += 1
294
295 - def OnFault(self):
296 ''' 297 Called when a fault was detected. 298 ''' 299 pc = _PowerControl("http://" + self.hostname, self.username, self.password) 300 pc.login() 301 pc.powercycle(self.port) 302 pc.powerOn(self.port) 303 304 time.sleep(self.waitTime)
305 306 307 # end 308