diff --git a/pyghmi/exceptions.py b/pyghmi/exceptions.py new file mode 100644 index 00000000..eb7ff4fd --- /dev/null +++ b/pyghmi/exceptions.py @@ -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 diff --git a/pyghmi/ipmi/command.py b/pyghmi/ipmi/command.py index eed1102b..ed0b19f0 100644 --- a/pyghmi/ipmi/command.py +++ b/pyghmi/ipmi/command.py @@ -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} diff --git a/pyghmi/ipmi/console.py b/pyghmi/ipmi/console.py index 2399a498..012e74b8 100644 --- a/pyghmi/ipmi/console.py +++ b/pyghmi/ipmi/console.py @@ -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 diff --git a/pyghmi/ipmi/private/session.py b/pyghmi/ipmi/private/session.py index 049fa24b..bcc9ce6e 100644 --- a/pyghmi/ipmi/private/session.py +++ b/pyghmi/ipmi/private/session.py @@ -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(" 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: