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(a)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(a)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