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 | 8 ++-
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/root.py | 7 +-
src/kimchi/template.py | 2 +-
src/kimchi/utils.py | 12 ++--
src/kimchi/vmtemplate.py | 6 +-
tests/test_exception.py | 12 ++--
tests/test_rest.py | 4 +-
tests/utils.py | 5 +-
30 files changed, 266 insertions(+), 222 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..c5c6266 100644
--- a/src/kimchi/auth.py
+++ b/src/kimchi/auth.py
@@ -29,7 +29,7 @@ import re
from kimchi import template
-from kimchi.exception import OperationFailed
+from kimchi.exception import InvalidOperation, OperationFailed
SESSION_USER = 'userid'
@@ -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
@@ -152,4 +153,5 @@ def kimchiauth(*args, **kwargs):
if not from_browser():
cherrypy.response.headers['WWW-Authenticate'] = 'Basic
realm=kimchi'
- raise cherrypy.HTTPError("401 Unauthorized")
+ e = InvalidOperation('KCHAUTH0002E')
+ raise cherrypy.HTTPError(401, e.message)
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/root.py b/src/kimchi/root.py
index 2b5c4b8..37d59e2 100644
--- a/src/kimchi/root.py
+++ b/src/kimchi/root.py
@@ -33,7 +33,7 @@ from kimchi.config import paths
from kimchi.control import sub_nodes
from kimchi.control.base import Resource
from kimchi.control.utils import parse_request
-from kimchi.exception import OperationFailed
+from kimchi.exception import MissingParameter, OperationFailed
class Root(Resource):
@@ -105,8 +105,9 @@ class KimchiRoot(Root):
try:
userid = params['userid']
password = params['password']
- except KeyError, key:
- raise cherrypy.HTTPError(400, "Missing parameter: '%s'" %
key)
+ except KeyError, item:
+ e = MissingParameter('KCHAUTH0003E', {'item': item})
+ raise cherrypy.HTTPError(400, e.message)
try:
auth.login(userid, password)
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..3545de4 100644
--- a/src/kimchi/vmtemplate.py
+++ b/src/kimchi/vmtemplate.py
@@ -58,7 +58,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 +66,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..2209319 100644
--- a/tests/test_exception.py
+++ b/tests/test_exception.py
@@ -63,13 +63,13 @@ class ExceptionTests(unittest.TestCase):
# test 405 wrong method
resp = json.loads(request(host, port, '/', None,
'DELETE').read())
- msg = 'Delete is not allowed for kimchiroot'
+ msg = u'KCHAPI0002E: Delete is not allowed for kimchiroot'
self.assertEquals('405 Method Not Allowed', resp.get('code'))
self.assertEquals(msg, resp.get('reason'))
# test 400 parse error
resp = json.loads(request(host, port, '/vms', '{',
'POST').read())
- msg = 'Unable to parse JSON request'
+ msg = u'KCHAPI0006E: Unable to parse JSON request'
self.assertEquals('400 Bad Request', resp.get('code'))
self.assertEquals(msg, resp.get('reason'))
self.assertNotIn('call_stack', resp)
@@ -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)
@@ -93,13 +93,13 @@ class ExceptionTests(unittest.TestCase):
# test 405 wrong method
resp = json.loads(request(host, port, '/', None,
'DELETE').read())
- msg = 'Delete is not allowed for kimchiroot'
+ msg = u'KCHAPI0002E: Delete is not allowed for kimchiroot'
self.assertEquals('405 Method Not Allowed', resp.get('code'))
self.assertEquals(msg, resp.get('reason'))
# test 400 parse error
resp = json.loads(request(host, port, '/vms', '{',
'POST').read())
- msg = 'Unable to parse JSON request'
+ msg = u'KCHAPI0006E: Unable to parse JSON request'
self.assertEquals('400 Bad Request', resp.get('code'))
self.assertEquals(msg, resp.get('reason'))
self.assertIn('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
--
1.7.10.4