2
0
mirror of https://opendev.org/x/pyghmi synced 2025-01-28 20:07:42 +00:00

Use distinct exceptions for many cases

Caller is likely going to want to catch certain conditions.  For those,
use more specific exception classes.  Exceptions indicating either TODO
or usage errors are being left as 'Exception' for the time being.

Change-Id: I4d68a2dbc394b534d54586b9f770160c1409f720
This commit is contained in:
Jarrod Johnson 2013-09-24 09:49:53 -04:00
parent ccac817f2b
commit ffe493df0f
4 changed files with 66 additions and 25 deletions

30
pyghmi/exceptions.py Normal file
View File

@ -0,0 +1,30 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 IBM Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# The Exceptions that Pyghmi can throw
class PyghmiException(Exception):
pass
class IpmiException(PyghmiException):
pass
class InvalidParameterValue(PyghmiException):
pass

View File

@ -15,6 +15,8 @@
# limitations under the License.
# This represents the low layer message framing portion of IPMI
import pyghmi.exceptions as exc
from pyghmi.ipmi.private import session
@ -160,11 +162,12 @@ class Command(object):
:returns: dict -- A dict describing the response retrieved
"""
if powerstate not in power_states:
raise Exception("Unknown power state %s requested" % powerstate)
raise exc.InvalidParameterValue(
"Unknown power state %s requested" % powerstate)
self.newpowerstate = powerstate
response = self.ipmi_session.raw_command(netfn=0, command=1)
if 'error' in response:
raise Exception(response['error'])
raise exc.IpmiException(response['error'])
self.powerstate = 'on' if (response['data'][0] & 1) else 'off'
if self.powerstate == self.newpowerstate:
return {'powerstate': self.powerstate}
@ -173,7 +176,7 @@ class Command(object):
response = self.ipmi_session.raw_command(
netfn=0, command=2, data=[power_states[self.newpowerstate]])
if 'error' in response:
raise Exception(response['error'])
raise exc.IpmiException(response['error'])
self.lastresponse = {'pendingpowerstate': self.newpowerstate}
waitattempts = 300
if not isinstance(wait, bool):
@ -193,7 +196,8 @@ class Command(object):
currpowerstate = 'on' if (response['data'][0] & 1) else 'off'
waitattempts -= 1
if currpowerstate != self.waitpowerstate:
raise Exception("System did not accomplish power state change")
raise exc.IpmiException(
"System did not accomplish power state change")
return {'powerstate': currpowerstate}
else:
return self.lastresponse
@ -281,8 +285,7 @@ class Command(object):
"""
response = self.ipmi_session.raw_command(netfn=0, command=1)
if 'error' in response:
raise Exception(response['error'])
return
raise exc.IpmiException(response['error'])
assert(response['command'] == 1 and response['netfn'] == 1)
self.powerstate = 'on' if (response['data'][0] & 1) else 'off'
return {'powerstate': self.powerstate}

View File

@ -41,7 +41,7 @@ class Console(object):
#TODO(jbjohnso): still need an exit and a data callin function
def __init__(self, bmc, userid, password,
iohandler=None, port=623,
iohandler, port=623,
force=False, kg=None):
if type(iohandler) == tuple: # two file handles
self.console_in = iohandler[0]
@ -53,8 +53,6 @@ class Console(object):
self.console_out = None
self.console_in = None
self.out_handler = iohandler
else:
raise(Exception('No IO handler provided'))
if self.console_in is not None:
fcntl.fcntl(self.console_in.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
self.remseq = 0
@ -136,7 +134,8 @@ class Console(object):
#data[6:7] is the promise of how small packets are going to be, but we
#don't have any reason to worry about it
if (data[8] + (data[9] << 8)) != 623:
raise Exception("TODO(jbjohnso): support atypical SOL port number")
#TODO(jbjohnso): support atypical SOL port number
raise NotImplementedError("Non-standard SOL Port Number")
#ignore data[10:11] for now, the vlan detail, shouldn't matter to this
#code anyway...
self.ipmi_session.sol_handler = self._got_sol_payload

View File

@ -29,6 +29,7 @@ from Crypto.Cipher import AES
from Crypto.Hash import HMAC
from Crypto.Hash import SHA
import pyghmi.exceptions as exc
from pyghmi.ipmi.private import constants
@ -184,7 +185,7 @@ class Session:
a client-provided callback.
"""
if 'error' in response:
raise Exception(response['error'])
raise exc.IpmiException(response['error'])
def __init__(self,
bmc,
@ -370,9 +371,11 @@ class Session:
if (self.ipmiversion == 2.0):
message.append(payload_type)
if (baretype == 2):
raise Exception("TODO(jbjohnso): OEM Payloads")
#TODO(jbjohnso): OEM payload types
raise NotImplementedError("OEM Payloads")
elif baretype not in constants.payload_types.values():
raise Exception("Unrecognized payload type %d" % baretype)
raise NotImplementedError(
"Unrecognized payload type %d" % baretype)
message += struct.unpack("!4B", struct.pack("<I", self.sessionid))
message += struct.unpack("!4B", struct.pack("<I", self.sequencenumber))
if (self.ipmiversion == 1.5):
@ -448,7 +451,7 @@ class Session:
password = self.password
padneeded = 16 - len(password)
if padneeded < 0:
raise Exception("Password is too long for ipmi 1.5")
raise exc.IpmiException("Password is too long for ipmi 1.5")
password += '\x00' * padneeded
passdata = struct.unpack("16B", password)
if checkremotecode:
@ -547,7 +550,8 @@ class Session:
def _get_session_challenge(self):
reqdata = [2]
if len(self.userid) > 16:
raise Exception("Username too long for IPMI, must not exceed 16")
raise exc.IpmiException(
"Username too long for IPMI, must not exceed 16")
padneeded = 16 - len(self.userid)
userid = self.userid + ('\x00' * padneeded)
reqdata += struct.unpack("!16B", userid)
@ -1080,16 +1084,21 @@ class Session:
Session.socket.sendto(self.netpacket, self.sockaddr)
else: # he have not yet picked a working sockaddr for this connection,
# try all the candidates that getaddrinfo provides
for res in socket.getaddrinfo(self.bmc,
self.port,
0,
socket.SOCK_DGRAM):
sockaddr = res[4]
if (res[0] == socket.AF_INET): # convert the sockaddr AF_INET6
newhost = '::ffff:' + sockaddr[0]
sockaddr = (newhost, sockaddr[1], 0, 0)
Session.bmc_handlers[sockaddr] = self
Session.socket.sendto(self.netpacket, sockaddr)
try:
for res in socket.getaddrinfo(self.bmc,
self.port,
0,
socket.SOCK_DGRAM):
sockaddr = res[4]
if (res[0] == socket.AF_INET): # convert the sockaddr
# to AF_INET6
newhost = '::ffff:' + sockaddr[0]
sockaddr = (newhost, sockaddr[1], 0, 0)
Session.bmc_handlers[sockaddr] = self
Session.socket.sendto(self.netpacket, sockaddr)
except socket.gaierror:
raise exc.IpmiException(
"Unable to transmit to specified address")
def logout(self, callback=None, callback_args=None):
if not self.logged: