[Kimchi-devel] [PATCH 5/8] refactor exception: Update all exceptions

Aline Manera alinefm at linux.vnet.ibm.com
Tue Feb 11 12:24:04 UTC 2014


On 02/11/2014 01:10 AM, Leonardo Augusto Guimarães Garcia wrote:
> On 02/09/2014 08:47 PM, Aline Manera wrote:
>> From: Aline Manera <alinefm at br.ibm.com>
>>
>> Update all Kimchi exceptions to translate backend messages.
>> Use message code to get the correct messages in i18n.py and raise a
>> message like: "<code>: <translated-message>"
>>
>> Signed-off-by: Aline Manera <alinefm at br.ibm.com>
>> ---
>>   plugins/sample/model.py                |   12 ++--
>>   src/kimchi/asynctask.py                |    4 +-
>>   src/kimchi/auth.py                     |    3 +-
>>   src/kimchi/disks.py                    |    5 +-
>>   src/kimchi/distroloader.py             |    5 +-
>>   src/kimchi/exception.py                |   14 ++--
>>   src/kimchi/iscsi.py                    |    6 +-
>>   src/kimchi/isoinfo.py                  |   17 +++--
>>   src/kimchi/mockmodel.py                |  113 +++++++++++++++++++-------------
>>   src/kimchi/model/config.py             |    2 +-
>>   src/kimchi/model/debugreports.py       |   18 ++---
>>   src/kimchi/model/host.py               |   10 +--
>>   src/kimchi/model/interfaces.py         |    4 +-
>>   src/kimchi/model/libvirtstoragepool.py |   14 ++--
>>   src/kimchi/model/networks.py           |   37 ++++++-----
>>   src/kimchi/model/storagepools.py       |   39 ++++++-----
>>   src/kimchi/model/storageservers.py     |    2 +-
>>   src/kimchi/model/storagevolumes.py     |   37 ++++++-----
>>   src/kimchi/model/templates.py          |   44 ++++++-------
>>   src/kimchi/model/utils.py              |    2 +-
>>   src/kimchi/model/vmifaces.py           |   15 ++---
>>   src/kimchi/model/vms.py                |   28 ++++----
>>   src/kimchi/objectstore.py              |    4 +-
>>   src/kimchi/template.py                 |    2 +-
>>   src/kimchi/utils.py                    |   12 ++--
>>   src/kimchi/vmtemplate.py               |    7 +-
>>   tests/test_exception.py                |    4 +-
>>   tests/test_rest.py                     |    4 +-
>>   tests/utils.py                         |    5 +-
>>   29 files changed, 255 insertions(+), 214 deletions(-)
>>
>> diff --git a/plugins/sample/model.py b/plugins/sample/model.py
>> index 184864d..f7ca319 100644
>> --- a/plugins/sample/model.py
>> +++ b/plugins/sample/model.py
>> @@ -31,7 +31,7 @@ class CirclesModel(object):
>>       def create(self, params):
>>           name = params['name']
>>           if name in self._circles:
>> -            raise InvalidOperation("Circle %s already exists" % name)
>> +            raise InvalidOperation("SPCIRCLE0001E", {'name': name})
>>           self._circles[name] = Circle(params['radius'])
>>           return name
>>
>> @@ -48,12 +48,12 @@ class CircleModel(object):
>>           try:
>>               circle = self._circles[name]
>>           except KeyError:
>> -            raise NotFoundError("Circle %s not found" % name)
>> +            raise NotFoundError("SPCIRC0002E", {'name': name})
>>           return {'radius': circle.radius}
>>
>>       def update(self, name, params):
>>           if name not in self._circles:
>> -            raise NotFoundError("Circle %s not found" % name)
>> +            raise NotFoundError("SPCIRC0002E", {'name': name})
>>           self._circles[name].radius = params['radius']
>>           return name
>>
>> @@ -71,7 +71,7 @@ class RectanglesModel(object):
>>       def create(self, params):
>>           name = params['name']
>>           if name in self._rectangles:
>> -            raise InvalidOperation("Rectangle %s already exists" % name)
>> +            raise InvalidOperation("SPRET0001E", {'name': name})
>>           self._rectangles[name] = Rectangle(params['length'], params['width'])
>>           return name
>>
>> @@ -87,12 +87,12 @@ class RectangleModel(object):
>>           try:
>>               rectangle = self._rectangles[name]
>>           except KeyError:
>> -            raise NotFoundError("Rectangle %s not found" % name)
>> +            raise NotFoundError("SPRET0002E", {'name': name})
>>           return {'length': rectangle.length, 'width': rectangle.width}
>>
>>       def update(self, name, params):
>>           if name not in self._rectangles:
>> -            raise NotFoundError("Rectangle %s not found" % name)
>> +            raise NotFoundError("SPRET0002E", {'name': name})
>>           try:
>>               self._rectangles[name].length = params['length']
>>           except KeyError:
>> diff --git a/src/kimchi/asynctask.py b/src/kimchi/asynctask.py
>> index 4ff76e4..f5cba50 100644
>> --- a/src/kimchi/asynctask.py
>> +++ b/src/kimchi/asynctask.py
>> @@ -31,8 +31,8 @@ from kimchi.exception import OperationFailed
>>   class AsyncTask(object):
>>       def __init__(self, id, target_uri, fn, objstore, opaque=None):
>>           if objstore is None:
>> -            raise OperationFailed("Datastore is not initiated in "
>> -                                  "the model object")
>> +            raise OperationFailed("KCHASYNC0001E")
>> +
>>           self.id = str(id)
>>           self.target_uri = target_uri
>>           self.fn = fn
>> diff --git a/src/kimchi/auth.py b/src/kimchi/auth.py
>> index 242fdcf..1cae45d 100644
>> --- a/src/kimchi/auth.py
>> +++ b/src/kimchi/auth.py
>> @@ -68,7 +68,8 @@ def authenticate(username, password, service="passwd"):
>>       try:
>>           auth.authenticate()
>>       except PAM.error, (resp, code):
>> -        raise OperationFailed(resp, code)
>> +        msg_args = {'userid': username, 'code': code}
>> +        raise OperationFailed("KCHAUTH0001E", msg_args)
>>
>>       return True
>>
>> diff --git a/src/kimchi/disks.py b/src/kimchi/disks.py
>> index 941aaca..83d5cc6 100644
>> --- a/src/kimchi/disks.py
>> +++ b/src/kimchi/disks.py
>> @@ -44,7 +44,7 @@ def _get_lsblk_devs(keys, devs=[]):
>>           stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>       out, err = lsblk.communicate()
>>       if lsblk.returncode != 0:
>> -        raise OperationFailed('Error executing lsblk: %s' % err)
>> +        raise OperationFailed("KCHDISKS0001E", {'err': err})
>>
>>       return _parse_lsblk_output(out, keys)
>>
>> @@ -60,8 +60,7 @@ def _get_dev_major_min(name):
>>               maj_min = dev['maj:min']
>>               break
>>       else:
>> -        msg = "Failed to find major and minor number for %s" % name
>> -        raise OperationFailed(msg)
>> +        raise OperationFailed("KCHDISKS0002E", {'device': name})
>>
>>       return maj_min
>>
>> diff --git a/src/kimchi/distroloader.py b/src/kimchi/distroloader.py
>> index 98fd764..f0b0208 100644
>> --- a/src/kimchi/distroloader.py
>> +++ b/src/kimchi/distroloader.py
>> @@ -37,10 +37,11 @@ class DistroLoader(object):
>>           self.location = location or config.get_distros_store()
>>
>>       def _get_json_info(self, fname):
>> +        msg_args = {'filename': fname}
>>           if not os.path.isfile(fname):
>>               msg = "DistroLoader: failed to find distro file: %s" % fname
>>               kimchi_log.error(msg)
>> -            raise NotFoundError(msg)
>> +            raise NotFoundError("KCHDL0001E", msg_args)
>>           try:
>>               with open(fname) as f:
>>                   data = json.load(f)
>> @@ -48,7 +49,7 @@ class DistroLoader(object):
>>           except ValueError:
>>               msg = "DistroLoader: failed to parse distro file: %s" % fname
>>               kimchi_log.error(msg)
>> -            raise OperationFailed(msg)
>> +            raise OperationFailed("KCHDL0002E", msg_args)
>>
>>       def get(self):
>>           all_json_files = glob.glob("%s/%s" % (self.location, "*.json"))
>> diff --git a/src/kimchi/exception.py b/src/kimchi/exception.py
>> index 7fcce54..952e243 100644
>> --- a/src/kimchi/exception.py
>> +++ b/src/kimchi/exception.py
>> @@ -49,29 +49,29 @@ class KimchiException(Exception):
>>           Exception.__init__(self, pattern)
>>
>>
>> -class NotFoundError(Exception):
>> +class NotFoundError(KimchiException):
>>       pass
>>
>>
>> -class OperationFailed(Exception):
>> +class OperationFailed(KimchiException):
>>       pass
>>
>>
>> -class MissingParameter(Exception):
>> +class MissingParameter(KimchiException):
>>       pass
>>
>>
>> -class InvalidParameter(Exception):
>> +class InvalidParameter(KimchiException):
>>       pass
>>
>>
>> -class InvalidOperation(Exception):
>> +class InvalidOperation(KimchiException):
>>       pass
>>
>>
>> -class IsoFormatError(Exception):
>> +class IsoFormatError(KimchiException):
>>       pass
>>
>>
>> -class TimeoutExpired(Exception):
>> +class TimeoutExpired(KimchiException):
>>       pass
>> diff --git a/src/kimchi/iscsi.py b/src/kimchi/iscsi.py
>> index 35c0b8a..248188c 100644
>> --- a/src/kimchi/iscsi.py
>> +++ b/src/kimchi/iscsi.py
>> @@ -55,7 +55,8 @@ class TargetClient(object):
>>               stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>           out, err = iscsiadm.communicate()
>>           if iscsiadm.returncode != 0:
>> -            raise OperationFailed('Error executing iscsiadm: %s' % err)
>> +            msg_args = {'portal': self.portal, 'err': err}
>> +            raise OperationFailed("KCHISCSI0001E", msg_args)
>>           return out
>>
>>       def _discover(self):
>> @@ -65,7 +66,8 @@ class TargetClient(object):
>>               stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>           out, err = iscsiadm.communicate()
>>           if iscsiadm.returncode != 0:
>> -            raise OperationFailed('Error executing iscsiadm: %s' % err)
>> +            msg_args = {'portal': self.portal, 'err': err}
>> +            raise OperationFailed("KCHISCSI0001E", msg_args)
>>           return out
>>
>>       def _run_op(self, op):
>> diff --git a/src/kimchi/isoinfo.py b/src/kimchi/isoinfo.py
>> index a3cd4cd..5629391 100644
>> --- a/src/kimchi/isoinfo.py
>> +++ b/src/kimchi/isoinfo.py
>> @@ -149,11 +149,11 @@ class IsoImage(object):
>>           if check_url_path(self.path):
>>               return True
>>
>> -        raise IsoFormatError('ISO %s does not exist' % self.path)
>> +        raise IsoFormatError("KCHISO0001E", {'filename': self.path})
>>
>>       def probe(self):
>>           if not self.bootable:
>> -            raise IsoFormatError("ISO %s not bootable" % self.path)
>> +            raise IsoFormatError("KCHISO0002E", {'filename': self.path})
>>
>>           matcher = Matcher(self.volume_id)
>>
>> @@ -197,7 +197,8 @@ class IsoImage(object):
>>               if vd_type == 0:  # Found El-Torito Boot Record
>>                   break
>>           if not et_ident.startswith('EL TORITO SPECIFICATION'):
>> -            raise IsoFormatError("Invalid El Torito boot record")
>> +            raise IsoFormatError("KCHISO0003E",
>> +                                 {'filename': self.path})
>>
>>           offset = IsoImage.SECTOR_SIZE * boot_cat
>>           size = IsoImage.EL_TORITO_VALIDATION_ENTRY.size + \
>> @@ -210,7 +211,8 @@ class IsoImage(object):
>>           (hdr_id, platform_id, pad0,
>>            ident, csum, key55, keyAA) = self._unpack(fmt, tmp_data)
>>           if key55 != 0x55 or keyAA != 0xaa:
>> -            raise IsoFormatError("Invalid El Torito validation entry")
>> +            raise IsoFormatError("KCHISO0004E",
>> +                                 {'filename': self.path})
>>
>>           fmt = IsoImage.EL_TORITO_BOOT_ENTRY
>>           tmp_data = data[ptr:ptr+fmt.size]
>> @@ -221,7 +223,8 @@ class IsoImage(object):
>>           elif boot == 0:
>>               self.bootable = False
>>           else:
>> -            raise IsoFormatError("Invalid El Torito boot indicator")
>> +            raise IsoFormatError("KCHISO0005E",
>> +                                 {'filename': self.path})
>>
>>       def _scan_primary_vol(self, data):
>>           """
>> @@ -232,9 +235,9 @@ class IsoImage(object):
>>           info = self._unpack(IsoImage.VOL_DESC, primary_vol_data)
>>           (vd_type, vd_ident, vd_ver, pad0, sys_id, vol_id) = info
>>           if vd_type != 1:
>> -            raise IsoFormatError("Unexpected volume type for primary volume")
>> +            raise IsoFormatError("KCHISO0006E", {'filename': self.path})
>>           if vd_ident != 'CD001' or vd_ver != 1:
>> -            raise IsoFormatError("Bad format while reading volume descriptor")
>> +            raise IsoFormatError("KCHISO0007E", {'filename': self.path})
>>           self.volume_id = vol_id
>>
>>       def _get_iso_data(self, offset, size):
>> diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py
>> index 4e276eb..e5425b2 100644
>> --- a/src/kimchi/mockmodel.py
>> +++ b/src/kimchi/mockmodel.py
>> @@ -83,7 +83,8 @@ class MockModel(object):
>>
>>           if 'name' in params:
>>               if state == 'running' or params['name'] in self.vms_get_list():
>> -                raise InvalidParameter("VM name existed or vm not shutoff.")
>> +                msg_args = {'name': dom.name, 'new_name': params['name']}
>> +                raise InvalidParameter("KCHVM0003E", msg_args)
>>               else:
>>                   del self._mock_vms[dom.name]
>>                   dom.name = params['name']
>> @@ -134,7 +135,7 @@ class MockModel(object):
>>           name = get_vm_name(params.get('name'), t_name,
>>                                         self._mock_vms.keys())
>>           if name in self._mock_vms:
>> -            raise InvalidOperation("VM already exists")
>> +            raise InvalidOperation("KCHVM0001E", {'name': name})
>>
>>           vm_uuid = str(uuid.uuid4())
>>           vm_overrides = dict()
>> @@ -166,7 +167,8 @@ class MockModel(object):
>>       def vmscreenshot_lookup(self, name):
>>           vm = self._get_vm(name)
>>           if vm.info['state'] != 'running':
>> -            raise NotFoundError('No screenshot for stopped vm')
>> +            raise NotFoundError("KCHVM0004E", {'name': name})
>> +
>>           screenshot = self._mock_screenshots.setdefault(
>>               vm.uuid, MockVMScreenshot({'uuid': vm.uuid}))
>>           return screenshot.lookup()
>> @@ -185,18 +187,19 @@ class MockModel(object):
>>           try:
>>               del self._mock_templates[name]
>>           except KeyError:
>> -            raise NotFoundError()
>> +            raise NotFoundError("KCHTMPL0002E", {'name': name})
>>
>>       def templates_create(self, params):
>>           name = params['name']
>>           if name in self._mock_templates:
>> -            raise InvalidOperation("Template already exists")
>> +            raise InvalidOperation("KCHTMPL0001E", {'name': name})
>> +
>>           for net_name in params.get(u'networks', []):
>>               try:
>>                   self._get_network(net_name)
>>               except NotFoundError:
>> -                raise InvalidParameter("Network '%s' specified by template "
>> -                                       "does not exist" % net_name)
>> +                msg_args = {'network': net_name, 'template': name}
>> +                raise InvalidParameter("KCHTMPL0003E", msg_args)
>>
>>           t = MockVMTemplate(params, self)
>>           self._mock_templates[name] = t
>> @@ -212,15 +215,16 @@ class MockModel(object):
>>           new_storagepool = new_t.get(u'storagepool', '')
>>           try:
>>               self._get_storagepool(pool_name_from_uri(new_storagepool))
>> -        except Exception as e:
>> -            raise InvalidParameter("Storagepool specified is not valid: %s." % e.message)
>> +        except Exception:
>> +            msg_args = {'pool': new_storagepool, 'template': name}
>> +            raise InvalidParameter("KCHTMPL0004E", msg_args)
>>
>>           for net_name in params.get(u'networks', []):
>>               try:
>>                   self._get_network(net_name)
>>               except NotFoundError:
>> -                raise InvalidParameter("Network '%s' specified by template "
>> -                                       "does not exist" % net_name)
>> +                msg_args = {'network': net_name, 'template': name}
>> +                raise InvalidParameter("KCHTMPL0003E", msg_args)
>>
>>           self.template_delete(name)
>>           try:
>> @@ -243,7 +247,7 @@ class MockModel(object):
>>               else:
>>                   return t
>>           except KeyError:
>> -            raise NotFoundError()
>> +            raise NotFoundError("KCHTMPL0002E", {'name': name})
>>
>>       def debugreport_lookup(self, name):
>>           path = config.get_debugreports_path()
>> @@ -251,7 +255,7 @@ class MockModel(object):
>>           try:
>>               file_target = glob.glob(file_pattern)[0]
>>           except IndexError:
>> -            raise NotFoundError('no such report')
>> +            raise NotFoundError("KCHDR0001E", {'name', name})
>>
>>           ctime = os.stat(file_target).st_ctime
>>           ctime = time.strftime("%Y-%m-%d-%H:%M:%S", time.localtime(ctime))
>> @@ -269,7 +273,7 @@ class MockModel(object):
>>           try:
>>               file_target = glob.glob(file_pattern)[0]
>>           except IndexError:
>> -            raise NotFoundError('no such report')
>> +            raise NotFoundError("KCHDR0001E", {'name', name})
>>
>>           os.remove(file_target)
>>
>> @@ -291,7 +295,7 @@ class MockModel(object):
>>           try:
>>               return self._mock_vms[name]
>>           except KeyError:
>> -            raise NotFoundError()
>> +            raise NotFoundError("KCHVM0002E", {'name': name})
>>
>>       def storagepools_create(self, params):
>>           try:
>> @@ -304,9 +308,12 @@ class MockModel(object):
>>               else:
>>                   pool.info['autostart'] = False
>>           except KeyError, item:
>> -            raise MissingParameter(item)
>> +            raise MissingParameter("KCHPOOL0004E",
>> +                                   {'item': item, 'name': name})
>> +
>>           if name in self._mock_storagepools or name in (ISO_POOL_NAME,):
>> -            raise InvalidOperation("StoragePool already exists")
>> +            raise InvalidOperation("KCHPOOL0001E", {'name': name})
>> +
>>           self._mock_storagepools[name] = pool
>>           return name
>>
>> @@ -318,7 +325,8 @@ class MockModel(object):
>>       def storagepool_update(self, name, params):
>>           autostart = params['autostart']
>>           if autostart not in [True, False]:
>> -            raise InvalidOperation("Autostart flag must be true or false")
>> +            raise InvalidOperation("KCHPOOL0003E")
>> +
>>           storagepool = self._get_storagepool(name)
>>           storagepool.info['autostart'] = autostart
>>           ident = storagepool.name
>> @@ -342,12 +350,15 @@ class MockModel(object):
>>           try:
>>               return self._mock_storagepools[name]
>>           except KeyError:
>> -            raise NotFoundError()
>> +            raise NotFoundError("KCHPOOL0002E", {'name': name})
>>
>>       def storagevolumes_create(self, pool_name, params):
>>           pool = self._get_storagepool(pool_name)
>>           if pool.info['state'] == 'inactive':
>> -            raise InvalidOperation("StoragePool not active")
>> +            raise InvalidOperation("KCHVOL0003E",
>> +                                   {'pool': pool_name,
>> +                                    'volume': params['name']})
>> +
>>           try:
>>               name = params['name']
>>               volume = MockStorageVolume(pool, name, params)
>> @@ -356,15 +367,20 @@ class MockModel(object):
>>               volume.info['path'] = os.path.join(
>>                   pool.info['path'], name)
>>           except KeyError, item:
>> -            raise MissingParameter(item)
>> +            raise MissingParameter("KCHVOL0004E",
>> +                                   {'item': item, 'volume': name})
>> +
>>           if name in pool._volumes:
>> -            raise InvalidOperation("StorageVolume already exists")
>> +            raise InvalidOperation("KCHVOL0001E", {'name': name})
>> +
>>           pool._volumes[name] = volume
>>           return name
>>
>>       def storagevolume_lookup(self, pool, name):
>>           if self._get_storagepool(pool).info['state'] != 'active':
>> -            raise InvalidOperation("StoragePool %s is not active" % pool)
>> +            raise InvalidOperation("KCHVOL0005E", {'pool': pool,
>> +                                                         'volume': name})
>> +
>>           storagevolume = self._get_storagevolume(pool, name)
>>           return storagevolume.info
>>
>> @@ -384,8 +400,7 @@ class MockModel(object):
>>       def storagevolumes_get_list(self, pool):
>>           res = self._get_storagepool(pool)
>>           if res.info['state'] == 'inactive':
>> -            raise InvalidOperation(
>> -                "Unable to list volumes of inactive storagepool %s" % pool)
>> +            raise InvalidOperation("KCHVOL0006E", {'pool': pool})
>>           return res._volumes.keys()
>>
>>       def isopool_lookup(self, name):
>> @@ -438,7 +453,7 @@ class MockModel(object):
>>               # Avoid inconsistent pool result because of lease between list and lookup
>>                   pass
>>
>> -        raise NotFoundError("storage server %s not used by kimchi" % server)
>> +        raise NotFoundError("KCHSR0001E", {'server': server})
>>
>>       def dummy_interfaces(self):
>>           interfaces = {}
>> @@ -461,7 +476,8 @@ class MockModel(object):
>>       def networks_create(self, params):
>>           name = params['name']
>>           if name in self.networks_get_list():
>> -            raise InvalidOperation("Network %s already exists" % name)
>> +            raise InvalidOperation("KCHNET0001E", {'name': name})
>> +
>>           network = MockNetwork(name)
>>           connection = params['connection']
>>           network.info['connection'] = connection
>> @@ -469,22 +485,23 @@ class MockModel(object):
>>               try:
>>                   interface = params['interface']
>>                   network.info['interface'] = interface
>> -            except KeyError, key:
>> -                raise MissingParameter(key)
>> +            except KeyError:
>> +                raise MissingParameter("KCHNET0004E",
>> +                                       {'name': name})
>>
>>           subnet = params.get('subnet', '')
>>           if subnet:
>>               network.info['subnet'] = subnet
>>               try:
>>                   net = ipaddr.IPNetwork(subnet)
>> -            except ValueError, e:
>> -                raise InvalidParameter(e)
>> +            except ValueError:
>> +                msg_args = {'subnet':subnet, 'network': name}
>> +                raise InvalidParameter("KCHNET0003E", msg_args)
>>
>>               network.info['dhcp'] = {
>>                   'start': str(net.network + net.numhosts / 2),
>>                   'stop': str(net.network + net.numhosts - 2)}
>> -        if name in self._mock_networks:
>> -            raise InvalidOperation("Network already exists")
>> +
>>           self._mock_networks[name] = network
>>           return name
>>
>> @@ -492,7 +509,7 @@ class MockModel(object):
>>           try:
>>               return self._mock_networks[name]
>>           except KeyError:
>> -            raise NotFoundError("Network '%s'" % name)
>> +            raise NotFoundError("KCHNET0002E", {'name': name})
>>
>>       def _get_vms_attach_to_a_network(self, network):
>>           vms = []
>> @@ -523,8 +540,9 @@ class MockModel(object):
>>       def vmifaces_create(self, vm, params):
>>           if (params["type"] == "network" and
>>               params["network"] not in self.networks_get_list()):
>> -            raise InvalidParameter("%s is not an available network" %
>> -                                   params["network"])
>> +            msg_args = {'network': params["network"], 'name': vm}
>> +            raise InvalidParameter("KCHVMIF0002E", msg_args)
>> +
>>           dom = self._get_vm(vm)
>>           iface = MockVMIface(params["network"])
>>           ("model" in params.keys() and
>> @@ -544,7 +562,7 @@ class MockModel(object):
>>           try:
>>               info = dom.ifaces[mac].info
>>           except KeyError:
>> -            raise NotFoundError('iface: "%s"' % mac)
>> +            raise NotFoundError("KCHVMIF0001E", {'iface': mac, 'name': vm})
>>           return info
>>
>>       def vmiface_delete(self, vm, mac):
>> @@ -552,7 +570,7 @@ class MockModel(object):
>>           try:
>>              del dom.ifaces[mac]
>>           except KeyError:
>> -            raise NotFoundError('iface: "%s"' % mac)
>> +            raise NotFoundError("KCHVMIF0001E", {'iface': mac, 'name': vm})
>>
>>       def tasks_get_list(self):
>>           with self.objstore as session:
>> @@ -573,7 +591,7 @@ class MockModel(object):
>>           try:
>>               return self._get_storagepool(pool)._volumes[name]
>>           except KeyError:
>> -            raise NotFoundError()
>> +            raise NotFoundError("KCHVOL0002E", {'name': name, 'pool': pool})
>>
>>       def _get_distros(self):
>>           distroloader = DistroLoader()
>> @@ -586,7 +604,7 @@ class MockModel(object):
>>           try:
>>               return self.distros[name]
>>           except KeyError:
>> -            raise NotFoundError("distro '%s' not found" % name)
>> +            raise NotFoundError("KCHDISTRO0001E", {'name': name})
>>
>>       def _gen_debugreport_file(self, ident):
>>           return self.add_task('', self._create_log, ident)
>> @@ -638,14 +656,14 @@ class MockModel(object):
>>           # Check for running vms before shutdown
>>           running_vms = self.vms_get_list_by_state('running')
>>           if len(running_vms) > 0:
>> -            raise OperationFailed("Shutdown not allowed: VMs are running!")
>> +            raise OperationFailed("KCHHOST0001E")
>>           cherrypy.engine.exit()
>>
>>       def host_reboot(self, args=None):
>>           # Find running VMs
>>           running_vms = self.vms_get_list_by_state('running')
>>           if len(running_vms) > 0:
>> -            raise OperationFailed("Reboot not allowed: VMs are running!")
>> +            raise OperationFailed("KCHHOST0002E")
>>           cherrypy.engine.stop()
>>           time.sleep(10)
>>           cherrypy.engine.start()
>> @@ -656,8 +674,8 @@ class MockModel(object):
>>
>>       def partition_lookup(self, name):
>>           if name not in disks.get_partitions_names():
>> -            raise NotFoundError("Partition %s not found in the host"
>> -                                % name)
>> +            raise NotFoundError("KCHPART0001E", {'name': name})
>> +
>>           return disks.get_partition_details(name)
>>
>>       def config_lookup(self, name):
>> @@ -677,9 +695,12 @@ class MockVMTemplate(VMTemplate):
>>           try:
>>               pool = self.model._get_storagepool(pool_name)
>>           except NotFoundError:
>> -            raise InvalidParameter('Storage specified by template does not exist')
>> +            msg_args = {'pool': pool_name, 'template': self.name}
>> +            raise InvalidParameter("KCHTMPL0004E", msg_args)
>> +
>>           if pool.info['state'] != 'active':
>> -            raise InvalidParameter('Storage specified by template is not active')
>> +            msg_args = {'pool': pool_name, 'template': self.name}
>> +            raise InvalidParameter("KCHTMPL0005E", msg_args)
>>
>>           return pool
>>
>> diff --git a/src/kimchi/model/config.py b/src/kimchi/model/config.py
>> index 0e66e02..9b5814a 100644
>> --- a/src/kimchi/model/config.py
>> +++ b/src/kimchi/model/config.py
>> @@ -95,4 +95,4 @@ class DistroModel(object):
>>           try:
>>               return self._distros.distros[name]
>>           except KeyError:
>> -            raise NotFoundError("Distro '%s' not found." % name)
>> +            raise NotFoundError("KCHDISTRO0001E", {'name': name})
>> diff --git a/src/kimchi/model/debugreports.py b/src/kimchi/model/debugreports.py
>> index a1cb19c..2c5b13a 100644
>> --- a/src/kimchi/model/debugreports.py
>> +++ b/src/kimchi/model/debugreports.py
>> @@ -59,7 +59,7 @@ class DebugReportsModel(object):
>>           if gen_cmd is not None:
>>               return add_task('', gen_cmd, self.objstore, name)
>>
>> -        raise OperationFailed("debugreport tool not found")
>> +        raise OperationFailed("KCHDR0002E")
>>
>>       @staticmethod
>>       def sosreport_generate(cb, name):
>> @@ -68,9 +68,11 @@ class DebugReportsModel(object):
>>               retcode = subprocess.call(command, shell=True,
>>                                         stdout=subprocess.PIPE)
>>               if retcode < 0:
>> -                raise OperationFailed('Command terminated with signal')
>> +                raise OperationFailed("KCHDR0003E", {'name': name,
>> +                                                     'err': retcode})
>>               elif retcode > 0:
>> -                raise OperationFailed('Command failed: rc = %i' % retcode)
>> +                raise OperationFailed("KCHDR0003E", {'name': name,
>> +                                                     'err': retcode})
>>               pattern = '/tmp/sosreport-%s-*' % name
>>               for reportFile in glob.glob(pattern):
>>                   if not fnmatch.fnmatch(reportFile, '*.md5'):
>> @@ -83,8 +85,8 @@ class DebugReportsModel(object):
>>                   # runs successfully. In future we might have a general name
>>                   # mangling function in kimchi to format the name before passing
>>                   # it to sosreport. Then we can delete this exception.
>> -                raise OperationFailed('Can not find generated debug report '
>> -                                      'named by %s' % pattern)
>> +                raise OperationFailed("KCHDR0004E", {'name': pattern})
>> +
>>               ext = output.split('.', 1)[1]
>>               path = config.get_debugreports_path()
>>               target = os.path.join(path, name)
>> @@ -104,7 +106,7 @@ class DebugReportsModel(object):
>>               # and update the task status there
>>               log = logging.getLogger('Model')
>>               log.warning('Exception in generating debug file: %s', e)
>> -            raise OperationFailed(e)
>> +            raise OperationFailed("KCHDR0005E", {'name': name, 'err': e})
>>
>>       @staticmethod
>>       def get_system_report_tool():
>> @@ -139,7 +141,7 @@ class DebugReportModel(object):
>>           try:
>>               file_target = glob.glob(file_pattern)[0]
>>           except IndexError:
>> -            raise NotFoundError('no such report')
>> +            raise NotFoundError("KCHDR0001E", {'name': name})
>>
>>           ctime = os.stat(file_target).st_ctime
>>           ctime = time.strftime("%Y-%m-%d-%H:%M:%S", time.localtime(ctime))
>> @@ -154,7 +156,7 @@ class DebugReportModel(object):
>>           try:
>>               file_target = glob.glob(file_pattern)[0]
>>           except IndexError:
>> -            raise NotFoundError('no such report')
>> +            raise NotFoundError("KCHDR0001E", {'name': name})
>>
>>           os.remove(file_target)
>>
>> diff --git a/src/kimchi/model/host.py b/src/kimchi/model/host.py
>> index a3d9e38..80f93db 100644
>> --- a/src/kimchi/model/host.py
>> +++ b/src/kimchi/model/host.py
>> @@ -67,7 +67,8 @@ class HostModel(object):
>>           # Check for running vms before shutdown
>>           running_vms = self._get_vms_list_by_state('running')
>>           if len(running_vms) > 0:
>> -            raise OperationFailed("Shutdown not allowed: VMs are running!")
>> +            raise OperationFailed("KCHHOST0001E")
>> +
>>           kimchi_log.info('Host is going to shutdown.')
>>           os.system('shutdown -h now')
>>
>> @@ -75,7 +76,8 @@ class HostModel(object):
>>           # Find running VMs
>>           running_vms = self._get_vms_list_by_state('running')
>>           if len(running_vms) > 0:
>> -            raise OperationFailed("Reboot not allowed: VMs are running!")
>> +            raise OperationFailed("KCHHOST0002E")
>> +
>>           kimchi_log.info('Host is going to reboot.')
>>           os.system('reboot')
>>
>> @@ -196,6 +198,6 @@ class PartitionModel(object):
>>
>>       def lookup(self, name):
>>           if name not in disks.get_partitions_names():
>> -            raise NotFoundError("Partition %s not found in the host"
>> -                                % name)
>> +            raise NotFoundError("KCHPART0001E", {'name': name})
>> +
>>           return disks.get_partition_details(name)
>> diff --git a/src/kimchi/model/interfaces.py b/src/kimchi/model/interfaces.py
>> index 52c6bae..96b1261 100644
>> --- a/src/kimchi/model/interfaces.py
>> +++ b/src/kimchi/model/interfaces.py
>> @@ -42,5 +42,5 @@ class InterfaceModel(object):
>>       def lookup(self, name):
>>           try:
>>               return netinfo.get_interface_info(name)
>> -        except ValueError, e:
>> -            raise NotFoundError(e)
>> +        except ValueError:
>> +            raise NotFoundError("KCHIFACE0001E", {'name': name})
>> diff --git a/src/kimchi/model/libvirtstoragepool.py b/src/kimchi/model/libvirtstoragepool.py
>> index f4dbf2e..f9b395c 100644
>> --- a/src/kimchi/model/libvirtstoragepool.py
>> +++ b/src/kimchi/model/libvirtstoragepool.py
>> @@ -38,7 +38,7 @@ class StoragePoolDef(object):
>>           for klass in cls.__subclasses__():
>>               if poolArgs['type'] == klass.poolType:
>>                   return klass(poolArgs)
>> -        raise OperationFailed('Unsupported pool type: %s' % poolArgs['type'])
>> +        raise OperationFailed("KCHPOOL0014E", {'type': poolArgs['type']})
>>
>>       def __init__(self, poolArgs):
>>           self.poolArgs = poolArgs
>> @@ -56,7 +56,7 @@ class StoragePoolDef(object):
>>           idempotent'''
>>           # TODO: When add new pool type, should also add the related test in
>>           # tests/test_storagepool.py
>> -        raise OperationFailed('self.xml is not implemented: %s' % self)
>> +        raise OperationFailed("KCHPOOL0015E", {'pool': self})
>>
>>
>>   class DirPoolDef(StoragePoolDef):
>> @@ -101,8 +101,7 @@ class NetfsPoolDef(StoragePoolDef):
>>                   run_command(mount_cmd, 30)
>>                   rollback.prependDefer(run_command, umount_cmd)
>>               except TimeoutExpired:
>> -                err = "Export path %s may block during nfs mount"
>> -                raise InvalidParameter(err % export_path)
>> +                raise InvalidParameter("KCHPOOL0012E", {'path': export_path})
>>
>>               with open("/proc/mounts", "rb") as f:
>>                   rawMounts = f.read()
>> @@ -113,8 +112,7 @@ class NetfsPoolDef(StoragePoolDef):
>>                       mounted = True
>>
>>               if not mounted:
>> -                err = "Export path %s mount failed during nfs mount"
>> -                raise InvalidParameter(err % export_path)
>> +                raise InvalidParameter("KCHPOOL0013E", {'path': export_path})
>>
>>       @property
>>       def xml(self):
>> @@ -181,8 +179,8 @@ class IscsiPoolDef(StoragePoolDef):
>>       def prepare(self, conn):
>>           source = self.poolArgs['source']
>>           if not TargetClient(**source).validate():
>> -            raise OperationFailed("Can not login to iSCSI host %s target %s" %
>> -                                  (source['host'], source['target']))
>> +            msg_args = {'host': source['host'], 'target': source['target']}
>> +            raise OperationFailed("KCHISCSI0002E", msg_args)
>>           self._prepare_auth(conn)
>>
>>       def _prepare_auth(self, conn):
>> diff --git a/src/kimchi/model/networks.py b/src/kimchi/model/networks.py
>> index b164141..05105df 100644
>> --- a/src/kimchi/model/networks.py
>> +++ b/src/kimchi/model/networks.py
>> @@ -39,7 +39,7 @@ class NetworksModel(object):
>>           conn = self.conn.get()
>>           name = params['name']
>>           if name in self.get_list():
>> -            raise InvalidOperation("Network %s already exists" % name)
>> +            raise InvalidOperation("KCHNET0001E", {'name': name})
>>
>>           connection = params["connection"]
>>           # set forward mode, isolated do not need forward
>> @@ -60,7 +60,8 @@ class NetworksModel(object):
>>               network = conn.networkDefineXML(xml)
>>               network.setAutostart(True)
>>           except libvirt.libvirtError as e:
>> -            raise OperationFailed(e.get_error_message())
>> +            raise OperationFailed("KCHNET0008E",
>> +                                  {'name': name, 'err': e.get_error_message()})
>>
>>           return name
>>
>> @@ -80,13 +81,13 @@ class NetworksModel(object):
>>                   subnet and net_addrs.append(ipaddr.IPNetwork(subnet))
>>               netaddr = knetwork.get_one_free_network(net_addrs)
>>               if not netaddr:
>> -                raise OperationFailed("can not find a free IP address for "
>> -                                      "network '%s'" % params['name'])
>> +                raise OperationFailed("KCHNET0009E", {'name': params['name']})
>>
>>           try:
>>               ip = ipaddr.IPNetwork(netaddr)
>> -        except ValueError as e:
>> -            raise InvalidParameter("%s" % e)
>> +        except ValueError:
>> +            raise InvalidParameter("KCHNET0003E", {'subent': netaddr,
>> +                                                   'network': params['name']})
>>
>>           if ip.ip == ip.network:
>>               ip.ip = ip.ip + 1
>> @@ -101,10 +102,11 @@ class NetworksModel(object):
>>           try:
>>               iface = params['interface']
>>               if iface in self.get_all_networks_interfaces():
>> -                raise InvalidParameter("interface '%s' already in use." %
>> -                                       iface)
>> -        except KeyError, e:
>> -            raise MissingParameter(e)
>> +                msg_args = {'iface': iface, 'network': params['name']}
>> +                raise InvalidParameter("KCHNET0006E", msg_args)
>> +        except KeyError:
>> +            raise MissingParameter("KCHNET0004E", {'name': params['name']})
>> +
>>           if netinfo.is_bridge(iface):
>>               params['bridge'] = iface
>>           elif netinfo.is_bare_nic(iface) or netinfo.is_bonding(iface):
>> @@ -115,8 +117,7 @@ class NetworksModel(object):
>>                       self._create_vlan_tagged_bridge(str(iface),
>>                                                       str(params['vlan_id']))
>>           else:
>> -            raise InvalidParameter("the interface should be bare nic, "
>> -                                   "bonding or bridge device.")
>> +            raise InvalidParameter("KCHNET0007E")
>>
>>       def get_all_networks_interfaces(self):
>>           net_names = self.get_list()
>> @@ -144,7 +145,8 @@ class NetworksModel(object):
>>               vlan_tagged_br.create()
>>           except libvirt.libvirtError as e:
>>               conn.changeRollback()
>> -            raise OperationFailed(e.message)
>> +            raise OperationFailed("KCHNET0010E", {'iface': interface,
>> +                                                  'err': e.message})
>>           else:
>>               conn.changeCommit()
>>               return br_name
>> @@ -211,8 +213,8 @@ class NetworkModel(object):
>>       def delete(self, name):
>>           network = self._get_network(name)
>>           if network.isActive():
>> -            raise InvalidOperation(
>> -                "Unable to delete the active network %s" % name)
>> +            raise InvalidOperation("KCHNET0005E", {'name': name})
>> +
>>           self._remove_vlan_tagged_bridge(network)
>>           network.undefine()
>>
>> @@ -220,9 +222,8 @@ class NetworkModel(object):
>>           conn = self.conn.get()
>>           try:
>>               return conn.networkLookupByName(name)
>> -        except libvirt.libvirtError as e:
>> -            raise NotFoundError("Network '%s' not found: %s" %
>> -                                (name, e.get_error_message()))
>> +        except libvirt.libvirtError:
>> +            raise NotFoundError("KCHNET0002E", {'name': name})
>>
>>       @staticmethod
>>       def get_network_from_xml(xml):
>> diff --git a/src/kimchi/model/storagepools.py b/src/kimchi/model/storagepools.py
>> index 233a8a7..fa73ce9 100644
>> --- a/src/kimchi/model/storagepools.py
>> +++ b/src/kimchi/model/storagepools.py
>> @@ -55,7 +55,8 @@ class StoragePoolsModel(object):
>>               names += conn.listDefinedStoragePools()
>>               return sorted(names)
>>           except libvirt.libvirtError as e:
>> -            raise OperationFailed(e.get_error_message())
>> +            raise OperationFailed("KCHPOOL0006E",
>> +                                  {'err': e.get_error_message()})
>>
>>       def create(self, params):
>>           task_id = None
>> @@ -63,19 +64,19 @@ class StoragePoolsModel(object):
>>           try:
>>               name = params['name']
>>               if name in (ISO_POOL_NAME, ):
>> -                raise InvalidOperation("StoragePool already exists")
>> +                raise InvalidOperation("KCHPOOL0001E", {'name': name})
>>
>>               if params['type'] == 'kimchi-iso':
>>                   task_id = self._do_deep_scan(params)
>>               poolDef = StoragePoolDef.create(params)
>>               poolDef.prepare(conn)
>>               xml = poolDef.xml
>> -        except KeyError, key:
>> -            raise MissingParameter(key)
>> +        except KeyError, item:
>> +            raise MissingParameter("KCHPOOL0004E",
>> +                                   {'item': item, 'name': name})
>>
>>           if name in self.get_list():
>> -            err = "The name %s has been used by a pool"
>> -            raise InvalidOperation(err % name)
>> +            raise InvalidOperation("KCHPOOL0001E", {'name': name})
>>
>>           try:
>>               if task_id:
>> @@ -92,9 +93,9 @@ class StoragePoolsModel(object):
>>                   # disable autostart for others
>>                   pool.setAutostart(0)
>>           except libvirt.libvirtError as e:
>> -            msg = "Problem creating Storage Pool: %s"
>> -            kimchi_log.error(msg, e)
>> -            raise OperationFailed(e.get_error_message())
>> +            kimchi_log.error("Problem creating Storage Pool: %s", e)
>> +            raise OperationFailed("KCHPOOL0007E",
>> +                                  {'name': name, 'err': e.get_error_message()})
>>           return name
>>
>>       def _clean_scan(self, pool_name):
>> @@ -144,7 +145,7 @@ class StoragePoolModel(object):
>>               return conn.storagePoolLookupByName(name)
>>           except libvirt.libvirtError as e:
>>               if e.get_error_code() == libvirt.VIR_ERR_NO_STORAGE_POOL:
>> -                raise NotFoundError("Storage Pool '%s' not found" % name)
>> +                raise NotFoundError("KCHTMPL0002E", {'name': name})
>>               else:
>>                   raise
>>
>> @@ -156,7 +157,8 @@ class StoragePoolModel(object):
>>               else:
>>                   return 0
>>           except libvirt.libvirtError as e:
>> -            raise OperationFailed(e.get_error_message())
>> +            raise OperationFailed("KCHPOOL0008E",
>> +                                  {'name': pool, 'err': e.get_error_message()})
>>
>>       def _get_storage_source(self, pool_type, pool_xml):
>>           source = {}
>> @@ -203,7 +205,8 @@ class StoragePoolModel(object):
>>       def update(self, name, params):
>>           autostart = params['autostart']
>>           if autostart not in [True, False]:
>> -            raise InvalidOperation("Autostart flag must be true or false")
>> +            raise InvalidOperation("KCHPOOL0003E")
>> +
>>           pool = self.get_storagepool(name, self.conn)
>>           if autostart:
>>               pool.setAutostart(1)
>> @@ -217,24 +220,26 @@ class StoragePoolModel(object):
>>           try:
>>               pool.create(0)
>>           except libvirt.libvirtError as e:
>> -            raise OperationFailed(e.get_error_message())
>> +            raise OperationFailed("KCHPOOL0009E",
>> +                                  {'name': name, 'err': e.get_error_message()})
>>
>>       def deactivate(self, name):
>>           pool = self.get_storagepool(name, self.conn)
>>           try:
>>               pool.destroy()
>>           except libvirt.libvirtError as e:
>> -            raise OperationFailed(e.get_error_message())
>> +            raise OperationFailed("KCHPOOL0010E",
>> +                                  {'name': name, 'err': e.get_error_message()})
>>
>>       def delete(self, name):
>>           pool = self.get_storagepool(name, self.conn)
>>           if pool.isActive():
>> -            err = "Unable to delete the active storagepool %s"
>> -            raise InvalidOperation(err % name)
>> +            raise InvalidOperation("KCHPOOL0005E", {'name': name})
>>           try:
>>               pool.undefine()
>>           except libvirt.libvirtError as e:
>> -            raise OperationFailed(e.get_error_message())
>> +            raise OperationFailed("KCHPOOL0011E",
>> +                                  {'name': name, 'err': e.get_error_message()})
>>
>>
>>   class IsoPoolModel(object):
>> diff --git a/src/kimchi/model/storageservers.py b/src/kimchi/model/storageservers.py
>> index 6a7c14a..26e1f6f 100644
>> --- a/src/kimchi/model/storageservers.py
>> +++ b/src/kimchi/model/storageservers.py
>> @@ -75,4 +75,4 @@ class StorageServerModel(object):
>>                   # lookup
>>                   pass
>>
>> -        raise NotFoundError('server %s does not used by kimchi' % server)
>> +        raise NotFoundError("KCHSR0001E", {'server': server})
>> diff --git a/src/kimchi/model/storagevolumes.py b/src/kimchi/model/storagevolumes.py
>> index 8440a76..e3f00ca 100644
>> --- a/src/kimchi/model/storagevolumes.py
>> +++ b/src/kimchi/model/storagevolumes.py
>> @@ -57,29 +57,33 @@ class StorageVolumesModel(object):
>>           params.setdefault('allocation', 0)
>>           params.setdefault('format', 'qcow2')
>>
>> +        name = params['name']
>>           try:
>>               pool = StoragePoolModel.get_storagepool(pool, self.conn)
>> -            name = params['name']
>>               xml = vol_xml % params
>> -        except KeyError, key:
>> -            raise MissingParameter(key)
>> +        except KeyError, item:
>> +            raise MissingParameter("KCHVOL0004E", {'item': item,
>> +                                                   'volume': name})
>>
>>           try:
>>               pool.createXML(xml, 0)
>>           except libvirt.libvirtError as e:
>> -            raise OperationFailed(e.get_error_message())
>> +            raise OperationFailed("KCHVOL0007E",
>> +                                  {'name': name, 'pool': pool,
>> +                                   'err': e.get_error_message()})
>>           return name
>>
>> -    def get_list(self, pool):
>> -        pool = StoragePoolModel.get_storagepool(pool, self.conn)
>> +    def get_list(self, pool_name):
>> +        pool = StoragePoolModel.get_storagepool(pool_name, self.conn)
>>           if not pool.isActive():
>> -            err = "Unable to list volumes in inactive storagepool %s"
>> -            raise InvalidOperation(err % pool.name())
>> +            raise InvalidOperation("KCHVOL0006E", {'pool': pool_name})
>>           try:
>>               pool.refresh(0)
>>               return pool.listVolumes()
>>           except libvirt.libvirtError as e:
>> -            raise OperationFailed(e.get_error_message())
>> +            raise OperationFailed("KCHVOL0008E",
>> +                                  {'pool': pool_name,
>> +                                   'err': e.get_error_message()})
>>
>>
>>   class StorageVolumeModel(object):
>> @@ -89,13 +93,13 @@ class StorageVolumeModel(object):
>>       def _get_storagevolume(self, pool, name):
>>           pool = StoragePoolModel.get_storagepool(pool, self.conn)
>>           if not pool.isActive():
>> -            err = "Unable to list volumes in inactive storagepool %s"
>> -            raise InvalidOperation(err % pool.name())
>> +            raise InvalidOperation("KCHVOL0006E", {'name': pool})
>>           try:
>>               return pool.storageVolLookupByName(name)
>>           except libvirt.libvirtError as e:
>>               if e.get_error_code() == libvirt.VIR_ERR_NO_STORAGE_VOL:
>> -                raise NotFoundError("Storage Volume '%s' not found" % name)
>> +                raise NotFoundError("KCHVOL0002E", {'name': name,
>> +                                                    'pool': pool})
>>               else:
>>                   raise
>>
>> @@ -131,14 +135,16 @@ class StorageVolumeModel(object):
>>           try:
>>               volume.wipePattern(libvirt.VIR_STORAGE_VOL_WIPE_ALG_ZERO, 0)
>>           except libvirt.libvirtError as e:
>> -            raise OperationFailed(e.get_error_message())
>> +            raise OperationFailed("KCHVOL0009E",
>> +                                  {'name': name, 'err': e.get_error_message()})
>>
>>       def delete(self, pool, name):
>>           volume = self._get_storagevolume(pool, name)
>>           try:
>>               volume.delete(0)
>>           except libvirt.libvirtError as e:
>> -            raise OperationFailed(e.get_error_message())
>> +            raise OperationFailed("KCHVOL0010E",
>> +                                  {'name': name, 'err': e.get_error_message()})
>>
>>       def resize(self, pool, name, size):
>>           size = size << 20
>> @@ -146,7 +152,8 @@ class StorageVolumeModel(object):
>>           try:
>>               volume.resize(size, 0)
>>           except libvirt.libvirtError as e:
>> -            raise OperationFailed(e.get_error_message())
>> +            raise OperationFailed("KCHVOL0011E",
>> +                                  {'name': name, 'err': e.get_error_message()})
>>
>>
>>   class IsoVolumesModel(object):
>> diff --git a/src/kimchi/model/templates.py b/src/kimchi/model/templates.py
>> index 03632a6..0eb7faa 100644
>> --- a/src/kimchi/model/templates.py
>> +++ b/src/kimchi/model/templates.py
>> @@ -25,7 +25,7 @@ import copy
>>   import libvirt
>>
>>   from kimchi import xmlutils
>> -from kimchi.exception import InvalidOperation, InvalidParameter, NotFoundError
>> +from kimchi.exception import InvalidOperation, InvalidParameter
>>   from kimchi.utils import pool_name_from_uri
>>   from kimchi.vmtemplate import VMTemplate
>>
>> @@ -44,20 +44,20 @@ class TemplatesModel(object):
>>               pool_name = pool_name_from_uri(pool_uri)
>>               try:
>>                   conn.storagePoolLookupByName(pool_name)
>> -            except Exception as e:
>> -                err = "Storagepool specified is not valid: %s."
>> -                raise InvalidParameter(err % e.message)
>> +            except Exception:
>> +                raise InvalidParameter("KCHTMPL0004E", {'pool': pool_name,
>> +                                                        'template': name})
>>
>>           for net_name in params.get(u'networks', []):
>>               try:
>>                   conn.networkLookupByName(net_name)
>> -            except Exception, e:
>> -                raise InvalidParameter("Network '%s' specified by template "
>> -                                       "does not exist." % net_name)
>> +            except Exception:
>> +                raise InvalidParameter("KCHTMPL0003E", {'network': net_name,
>> +                                                        'template': name})
>>
>>           with self.objstore as session:
>>               if name in session.get_list('template'):
>> -                raise InvalidOperation("Template already exists")
>> +                raise InvalidOperation("KCHTMPL0001E", {'name': name})
>>               t = LibvirtVMTemplate(params, scan=True)
>>               session.store('template', name, t.info)
>>           return name
>> @@ -100,17 +100,17 @@ class TemplateModel(object):
>>           try:
>>               conn = self.conn.get()
>>               conn.storagePoolLookupByName(pool_name)
>> -        except Exception as e:
>> -            err = "Storagepool specified is not valid: %s."
>> -            raise InvalidParameter(err % e.message)
>> +        except Exception:
>> +            raise InvalidParameter("KCHTMPL0004E", {'pool': pool_name,
>> +                                                    'template': name})
>>
>>           for net_name in params.get(u'networks', []):
>>               try:
>>                   conn = self.conn.get()
>>                   conn.networkLookupByName(net_name)
>> -            except Exception, e:
>> -                raise InvalidParameter("Network '%s' specified by template "
>> -                                       "does not exist" % net_name)
>> +            except Exception:
>> +                raise InvalidParameter("KCHTMPL0003E", {'network': net_name,
>> +                                                        'template': name})
>>
>>           self.delete(name)
>>           try:
>> @@ -133,12 +133,12 @@ class LibvirtVMTemplate(VMTemplate):
>>               conn = self.conn.get()
>>               pool = conn.storagePoolLookupByName(pool_name)
>>           except libvirt.libvirtError:
>> -            err = 'Storage specified by template does not exist'
>> -            raise InvalidParameter(err)
>> +            raise InvalidParameter("KCHTMPL0004E", {'pool': pool_name,
>> +                                                    'template': self.name})
>>
>>           if not pool.isActive():
>> -            err = 'Storage specified by template is not active'
>> -            raise InvalidParameter(err)
>> +            raise InvalidParameter("KCHTMPL0005E", {'pool': pool_name,
>> +                                                    'template': self.name})
>>
>>           return pool
>>
>> @@ -149,12 +149,12 @@ class LibvirtVMTemplate(VMTemplate):
>>                   conn = self.conn.get()
>>                   network = conn.networkLookupByName(name)
>>               except libvirt.libvirtError:
>> -                err = 'Network specified by template does not exist'
>> -                raise InvalidParameter(err)
>> +                raise InvalidParameter("KCHTMPL0003E", {'network': name,
>> +                                                        'template': self.name})
>>
>>               if not network.isActive():
>> -                err = 'Network specified by template is not active'
>> -                raise InvalidParameter(err)
>> +                raise InvalidParameter("KCHTMPL0007E", {'network': name,
>> +                                                        'template': self.name})
>>
>>       def _get_storage_path(self):
>>           pool = self._storage_validate()
>> diff --git a/src/kimchi/model/utils.py b/src/kimchi/model/utils.py
>> index a27b867..b642f05 100644
>> --- a/src/kimchi/model/utils.py
>> +++ b/src/kimchi/model/utils.py
>> @@ -30,4 +30,4 @@ def get_vm_name(vm_name, t_name, name_list):
>>           vm_name = "%s-vm-%i" % (t_name, i)
>>           if vm_name not in name_list:
>>               return vm_name
>> -    raise OperationFailed("Unable to choose a VM name")
>> +    raise OperationFailed("KCHUTILS0003E")
>> diff --git a/src/kimchi/model/vmifaces.py b/src/kimchi/model/vmifaces.py
>> index f3eddb2..f526e0d 100644
>> --- a/src/kimchi/model/vmifaces.py
>> +++ b/src/kimchi/model/vmifaces.py
>> @@ -52,13 +52,12 @@ class VMIfacesModel(object):
>>           networks = conn.listNetworks() + conn.listDefinedNetworks()
>>
>>           if params["type"] == "network" and params["network"] not in networks:
>> -            raise InvalidParameter("%s is not an available network" %
>> -                                   params["network"])
>> +            raise InvalidParameter("KCHVMIF0002E",
>> +                                   {'name': vm, 'network': params["network"]})
>>
>>           dom = VMModel.get_vm(vm, self.conn)
>>           if DOM_STATE_MAP[dom.info()[0]] != "shutoff":
>> -            raise InvalidOperation("do not support hot plugging attach "
>> -                                   "guest interface")
>> +            raise InvalidOperation("KCHVMIF0003E")
>>
>>           macs = (iface.mac.get('address')
>>                   for iface in self.get_vmifaces(vm, self.conn))
>> @@ -108,7 +107,7 @@ class VMIfaceModel(object):
>>
>>           iface = self._get_vmiface(vm, mac)
>>           if iface is None:
>> -            raise NotFoundError('iface: "%s"' % mac)
>> +            raise NotFoundError("KCHVMIF0001E", {'name': vm, 'iface': mac})
>>
>>           info['type'] = iface.attrib['type']
>>           info['mac'] = iface.mac.get('address')
>> @@ -126,10 +125,10 @@ class VMIfaceModel(object):
>>           iface = self._get_vmiface(vm, mac)
>>
>>           if DOM_STATE_MAP[dom.info()[0]] != "shutoff":
>> -            raise InvalidOperation("do not support hot plugging detach "
>> -                                   "guest interface")
>> +            raise InvalidOperation("KCHVMIF0003E")
>> +
>>           if iface is None:
>> -            raise NotFoundError('iface: "%s"' % mac)
>> +            raise NotFoundError("KCHVMIF0001E", {'name': vm, 'iface': mac})
>>
>>           dom.detachDeviceFlags(etree.tostring(iface),
>>                                 libvirt.VIR_DOMAIN_AFFECT_CURRENT)
>> diff --git a/src/kimchi/model/vms.py b/src/kimchi/model/vms.py
>> index d4384a1..d9e4f20 100644
>> --- a/src/kimchi/model/vms.py
>> +++ b/src/kimchi/model/vms.py
>> @@ -163,7 +163,7 @@ class VMsModel(object):
>>           name = get_vm_name(params.get('name'), t_name, vm_list)
>>           # incoming text, from js json, is unicode, do not need decode
>>           if name in vm_list:
>> -            raise InvalidOperation("VM already exists")
>> +            raise InvalidOperation("KCHVM0001E", {'name': name})
>>
>>           vm_overrides = dict()
>>           pool_uri = params.get('storagepool')
>> @@ -173,8 +173,7 @@ class VMsModel(object):
>>                                          vm_overrides)
>>
>>           if not self.caps.qemu_stream and t.info.get('iso_stream', False):
>> -            err = "Remote ISO image is not supported by this server."
>> -            raise InvalidOperation(err)
>> +            raise InvalidOperation("KCHVM0005E")
>>
>>           t.validate()
>>           vol_list = t.fork_vm_storage(vm_uuid)
>> @@ -201,7 +200,8 @@ class VMsModel(object):
>>               for v in vol_list:
>>                   vol = conn.storageVolLookupByPath(v['path'])
>>                   vol.delete(0)
>> -            raise OperationFailed(e.get_error_message())
>> +            raise OperationFailed("KCHVM0007E", {'name': name,
>> +                                                 'err': e.get_error_message()})
>>
>>           return name
>>
>> @@ -237,15 +237,16 @@ class VMModel(object):
>>           try:
>>               if 'name' in params:
>>                   if state == 'running':
>> -                    err = "VM name only can be updated when vm is powered off."
>> -                    raise InvalidParameter(err)
>> +                    msg_args = {'name': dom.name(), 'new_name': params['name']}
>> +                    raise InvalidParameter("KCHVM0003E", msg_args)
>>                   else:
>>                       dom.undefine()
>>               conn = self.conn.get()
>>               dom = conn.defineXML(new_xml)
>>           except libvirt.libvirtError as e:
>>               dom = conn.defineXML(old_xml)
>> -            raise OperationFailed(e.get_error_message())
>> +            raise OperationFailed("KCHVM0008E", {'name': dom.name(),
>> +                                                 'err': e.get_error_message()})
>>           return dom
>>
>>       def _live_vm_update(self, dom, params):
>> @@ -308,8 +309,8 @@ class VMModel(object):
>>           except NotFoundError:
>>               return False
>>           except Exception, e:
>> -            err = "Unable to retrieve VM '%s': %s"
>> -            raise OperationFailed(err % (name, e.message))
>> +            raise OperationFailed("KCHVM0009E", {'name': name,
>> +                                                 'err': e.message})
>>
>>       @staticmethod
>>       def get_vm(name, conn):
>> @@ -319,7 +320,7 @@ class VMModel(object):
>>               return conn.lookupByName(name.encode("utf-8"))
>>           except libvirt.libvirtError as e:
>>               if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
>> -                raise NotFoundError("Virtual Machine '%s' not found" % name)
>> +                raise NotFoundError("KCHVM0002E", {'name': name})
>>               else:
>>                   raise
>>
>> @@ -384,8 +385,7 @@ class VMModel(object):
>>           if graphics_port is not None:
>>               vnc.add_proxy_token(name, graphics_port)
>>           else:
>> -            raise OperationFailed("Only able to connect to running vm's vnc "
>> -                                  "graphics.")
>> +            raise OperationFailed("KCHVM0010E", {'name': name})
>>
>>       def _vmscreenshot_delete(self, vm_uuid):
>>           screenshot = VMScreenshotModel.get_screenshot(vm_uuid, self.objstore,
>> @@ -405,7 +405,7 @@ class VMScreenshotModel(object):
>>           d_info = dom.info()
>>           vm_uuid = dom.UUIDString()
>>           if DOM_STATE_MAP[d_info[0]] != 'running':
>> -            raise NotFoundError('No screenshot for stopped vm')
>> +            raise NotFoundError("KCHVM0004E", {'name': name})
>>
>>           screenshot = self.get_screenshot(vm_uuid, self.objstore, self.conn)
>>           img_path = screenshot.lookup()
>> @@ -448,7 +448,7 @@ class LibvirtVMScreenshot(VMScreenshot):
>>                   stream.abort()
>>               except:
>>                   pass
>> -            raise NotFoundError("Screenshot not supported for %s" % vm_name)
>> +            raise NotFoundError("KCHVM0006E", {'name': vm_name})
>>           else:
>>               stream.finish()
>>           finally:
>> diff --git a/src/kimchi/objectstore.py b/src/kimchi/objectstore.py
>> index 7b567f3..5cb8ae1 100644
>> --- a/src/kimchi/objectstore.py
>> +++ b/src/kimchi/objectstore.py
>> @@ -54,7 +54,7 @@ class ObjectStoreSession(object):
>>               jsonstr = res.fetchall()[0][0]
>>           except IndexError:
>>               self.conn.rollback()
>> -            raise NotFoundError(ident)
>> +            raise NotFoundError("KCHOBJST0001E", {'item': ident})
>>           return json.loads(jsonstr)
>>
>>       def delete(self, obj_type, ident, ignore_missing=False):
>> @@ -63,7 +63,7 @@ class ObjectStoreSession(object):
>>                     (obj_type, ident))
>>           if c.rowcount != 1 and not ignore_missing:
>>               self.conn.rollback()
>> -            raise NotFoundError(ident)
>> +            raise NotFoundError("KCHOBJST0001E", {'item': ident})
>>           self.conn.commit()
>>
>>       def store(self, obj_type, ident, data):
>> diff --git a/src/kimchi/template.py b/src/kimchi/template.py
>> index 173e7c6..fd1d591 100644
>> --- a/src/kimchi/template.py
>> +++ b/src/kimchi/template.py
>> @@ -27,6 +27,7 @@ import json
>>   import os
>>
>>
>> +from kimchi.config import paths
>>   from Cheetah.Template import Template
>>   from glob import iglob
>>
>> @@ -53,7 +54,6 @@ def get_lang():
>>
>>
>>   def get_support_languages():
>> -    paths = cherrypy.request.app.root.paths
>>       mopath = "%s/*" % paths.mo_dir
>>       return [path.rsplit('/', 1)[1] for path in iglob(mopath)]
>>
>> diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py
>> index 8795957..a1410c0 100644
>> --- a/src/kimchi/utils.py
>> +++ b/src/kimchi/utils.py
>> @@ -29,12 +29,10 @@ import urllib2
>>   from threading import Timer
>>
>>   from cherrypy.lib.reprconf import Parser
>> -from kimchi.config import paths, PluginPaths
>> -from kimchi.exception import TimeoutExpired
>> -
>>
>>   from kimchi.asynctask import AsyncTask
>> -from kimchi.exception import InvalidParameter
>> +from kimchi.config import paths, PluginPaths
>> +from kimchi.exception import InvalidParameter, TimeoutExpired
>>
>>
>>   kimchi_log = cherrypy.log.error_log
>> @@ -45,7 +43,7 @@ def _uri_to_name(collection, uri):
>>       expr = '/%s/(.*?)/?$' % collection
>>       m = re.match(expr, uri)
>>       if not m:
>> -        raise InvalidParameter(uri)
>> +        raise InvalidParameter("KCHUTILS0001E", {'uri': uri})
>>       return m.group(1)
>>
>>
>> @@ -169,7 +167,9 @@ def run_command(cmd, timeout=None):
>>               msg = ("subprocess is killed by signal.SIGKILL for "
>>                      "timeout %s seconds" % timeout)
>>               kimchi_log.error(msg)
>> -            raise TimeoutExpired(msg)
>> +
>> +            msg_args = {'cmd': cmd, 'seconds': timeout}
>> +            raise TimeoutExpired("KCHUTILS0002E", msg_args)
>>
>>           return out, error, proc.returncode
>>       except TimeoutExpired:
>> diff --git a/src/kimchi/vmtemplate.py b/src/kimchi/vmtemplate.py
>> index 58147e3..7aa0a65 100644
>> --- a/src/kimchi/vmtemplate.py
>> +++ b/src/kimchi/vmtemplate.py
>> @@ -27,7 +27,6 @@ import urllib
>>   import urlparse
>>
>>
>> -from kimchi import isoinfo
> Is this change related to this patch?

Seems I removed an useless import.
I will revert and send a separated patch for that.

>>   from kimchi import osinfo
>>   from kimchi.exception import InvalidParameter, IsoFormatError
>>   from kimchi.isoinfo import IsoImage
>> @@ -58,7 +57,7 @@ class VMTemplate(object):
>>
>>               iso_prefixes = ['/', 'http', 'https', 'ftp', 'ftps', 'tftp']
>>               if len(filter(iso.startswith, iso_prefixes)) == 0:
>> -                raise InvalidParameter("Invalid parameter specified for cdrom.")
>> +                raise InvalidParameter("KCHTMPL0006E", {'param': iso})
>>
>>               if not iso.startswith('/'):
>>                   self.info.update({'iso_stream': True})
>> @@ -66,8 +65,8 @@ class VMTemplate(object):
>>               try:
>>                   iso_img = IsoImage(iso)
>>                   iso_distro, iso_version = iso_img.probe()
>> -            except IsoFormatError, e:
>> -                raise InvalidParameter(e)
>> +            except IsoFormatError:
>> +                raise InvalidParameter("KCHISO0001E", {'filename': iso})
>>
>>           # Fetch defaults based on the os distro and version
>>           os_distro = args.get('os_distro', iso_distro)
>> diff --git a/tests/test_exception.py b/tests/test_exception.py
>> index b64ab94..79c8e4f 100644
>> --- a/tests/test_exception.py
>> +++ b/tests/test_exception.py
>> @@ -77,8 +77,8 @@ class ExceptionTests(unittest.TestCase):
>>           # test 400 missing required parameter
>>           req = json.dumps({})
>>           resp = json.loads(request(host, port, '/vms', req, 'POST').read())
>> -        msg = u"Invalid parameter: 'u'template' is a required property'"
>>           self.assertEquals('400 Bad Request', resp.get('code'))
>> +        msg = u"KCHVM0016E: Specify a template to create a Virtual Machine from"
>>           self.assertEquals(msg, resp.get('reason'))
>>           self.assertNotIn('call_stack', resp)
>>
>> @@ -107,7 +107,7 @@ class ExceptionTests(unittest.TestCase):
>>           # test 400 missing required parameter
>>           req = json.dumps({})
>>           resp = json.loads(request(host, port, '/vms', req, 'POST').read())
>> -        msg = u"Invalid parameter: 'u'template' is a required property'"
>> +        msg = u"KCHVM0016E: Specify a template to create a Virtual Machine from"
>>           self.assertEquals('400 Bad Request', resp.get('code'))
>>           self.assertEquals(msg, resp.get('reason'))
>>           self.assertIn('call_stack', resp)
>> diff --git a/tests/test_rest.py b/tests/test_rest.py
>> index 0ed293b..4b58e18 100644
>> --- a/tests/test_rest.py
>> +++ b/tests/test_rest.py
>> @@ -568,7 +568,7 @@ class RestTests(unittest.TestCase):
>>           resp = self.request('/vms', req, 'POST')
>>           self.assertEquals(400, resp.status)
>>           resp = json.loads(resp.read())
>> -        self.assertIn('Invalid parameter', resp['reason'])
>> +        self.assertIn(u"KCHVM0016E:", resp['reason'])
>>
>>       def test_create_vm_with_bad_template_uri(self):
>>           req = json.dumps({'name': 'vm-bad-template',
>> @@ -576,7 +576,7 @@ class RestTests(unittest.TestCase):
>>           resp = self.request('/vms', req, 'POST')
>>           self.assertEquals(400, resp.status)
>>           resp = json.loads(resp.read())
>> -        self.assertIn('Invalid parameter', resp['reason'])
>> +        self.assertIn(u"KCHVM0012E", resp['reason'])
>>
>>       def test_get_storagepools(self):
>>           storagepools = json.loads(self.request('/storagepools').read())
>> diff --git a/tests/utils.py b/tests/utils.py
>> index 40dfae2..14c57d4 100644
>> --- a/tests/utils.py
>> +++ b/tests/utils.py
>> @@ -155,8 +155,9 @@ def patch_auth():
>>       def _authenticate(username, password, service="passwd"):
>>           try:
>>               return fake_user[username] == password
>> -        except KeyError:
>> -            raise OperationFailed('Bad login')
>> +        except KeyError, e:
>> +            raise OperationFailed("KCHAUTH0001E", {'userid': 'username',
>> +                                                   'code': e.message})
>>
>>       import kimchi.auth
>>       kimchi.auth.authenticate = _authenticate
> I see some parts of the code raising exceptions that are still not
> following this translation model. For instance, ImportError at
> src/kimchi/utils.py, and Exception in src/kimchi/config.py and
> src/kimchi/websocket.py. Shouldn't we translate all exception messages?

The translated messages are those shown to the user. Which means they 
need to be raise through Kimchi
exceptions (all those in src/kimchi/exception.py)
Any other exception needs to converted to the Kimchi exceptions.
For example:

def raise_common_exception():
     raise Exception()

If this message will be shown to the user it needs to be:

try:
     raise_common_exception()
except:
     raise OperarionFailed(<translatable-msg>)

I will check all those causes you pointed out to verify if they are 
follow this principle.

> Best regards,
>
> Leonardo Garcia




More information about the Kimchi-devel mailing list