[PATCH v4 0/4] Transient Object Handling

In order to prevent benign error messages from being displayed to the user, some POST requests for transient objects should be handled as special cases. This patchset introduces a way to mark an action as destructive so that the subsequent GET after a POST is bypassed. It also adds that logic to the three types of transient objects that Kimchi deals with: VMs, Networks, and Storage Pools. It also prevents Delete from being called on a VM, but does not need to prevent delete for the other objects as it does not apply. Christy Perez (4): Handle requests differently for transient objects Transient VM POST request handling Transient Network POST request handling Transient StoragePool POST request handling src/kimchi/control/base.py | 15 ++++++++++----- src/kimchi/control/networks.py | 3 ++- src/kimchi/control/storagepools.py | 4 ++-- src/kimchi/control/vms.py | 9 ++++++--- src/kimchi/i18n.py | 1 + src/kimchi/model/vms.py | 3 +++ 6 files changed, 24 insertions(+), 11 deletions(-) -- 1.9.3

If a transient (or non-persistent) object (e.g. VM, network or storage pool) is created outside of Kimchi, it will (expectedly) be deleted when shutdown. Since Kimchi calls a GET after shutdown and other POST requests, the GET fails, and a user will receive an error. However, this is not an error condition. This patch does not call the GET function for transient objects if the function will delete the object (as indicated by a new parameter passed to generate_action_handler). Signed-off-by: Christy Perez <christy@linux.vnet.ibm.com> --- src/kimchi/control/base.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/kimchi/control/base.py b/src/kimchi/control/base.py index 484e9b9..b50ea5c 100644 --- a/src/kimchi/control/base.py +++ b/src/kimchi/control/base.py @@ -71,7 +71,8 @@ def _redirect(self, action_result, code=303): safe="")] raise cherrypy.HTTPRedirect(self.uri_fmt % tuple(uri_params), code) - def generate_action_handler(self, action_name, action_args=None): + def generate_action_handler(self, action_name, action_args=None, + destructive=False): def _render_element(self, ident): self._redirect(ident) uri_params = [] @@ -83,7 +84,8 @@ def _render_element(self, ident): raise internal_redirect(self.uri_fmt % tuple(uri_params)) return self._generate_action_handler_base(action_name, _render_element, - action_args) + destructive=destructive, + action_args=action_args) def generate_action_handler_task(self, action_name, action_args=None): def _render_task(self, task): @@ -91,10 +93,10 @@ def _render_task(self, task): return kimchi.template.render('Task', task) return self._generate_action_handler_base(action_name, _render_task, - action_args) + action_args=action_args) def _generate_action_handler_base(self, action_name, render_fn, - action_args=None): + destructive=False, action_args=None): def wrapper(*args, **kwargs): validate_method(('POST'), self.role_key, self.admin_methods) try: @@ -109,7 +111,10 @@ def wrapper(*args, **kwargs): action_fn = getattr(self.model, model_fn(self, action_name)) action_result = action_fn(*model_args) - return render_fn(self, action_result) + if destructive is False or \ + ('persistent' in self.info.keys() + and self.info['persistent'] is True): + return render_fn(self, action_result) except MissingParameter, e: raise cherrypy.HTTPError(400, e.message) except InvalidParameter, e: -- 1.9.3

Do not call GET for PowerOff, Shutdown, and Reset actions for transient VMs. Also return an error for Delete of transient VMs, since libvirt does not support this operation. Signed-off-by: Christy Perez <christy@linux.vnet.ibm.com> --- src/kimchi/control/vms.py | 9 ++++++--- src/kimchi/i18n.py | 1 + src/kimchi/model/vms.py | 3 +++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/kimchi/control/vms.py b/src/kimchi/control/vms.py index 1a84b6c..5068b7c 100644 --- a/src/kimchi/control/vms.py +++ b/src/kimchi/control/vms.py @@ -40,9 +40,12 @@ def __init__(self, model, ident): for ident, node in sub_nodes.items(): setattr(self, ident, node(model, self.ident)) self.start = self.generate_action_handler('start') - self.poweroff = self.generate_action_handler('poweroff') - self.shutdown = self.generate_action_handler('shutdown') - self.reset = self.generate_action_handler('reset') + self.poweroff = self.generate_action_handler('poweroff', + destructive=True) + self.shutdown = self.generate_action_handler('shutdown', + destructive=True) + self.reset = self.generate_action_handler('reset', + destructive=True) self.connect = self.generate_action_handler('connect') self.clone = self.generate_action_handler_task('clone') diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py index 4eccc3e..4ab08d1 100644 --- a/src/kimchi/i18n.py +++ b/src/kimchi/i18n.py @@ -106,6 +106,7 @@ "KCHVM0033E": _("Virtual machine '%(name)s' must be stopped before cloning it."), "KCHVM0034E": _("Insufficient disk space to clone virtual machine '%(name)s'"), "KCHVM0035E": _("Unable to clone VM '%(name)s'. Details: %(err)s"), + "KCHVM0036E": _("Invalid operation for non-persistent virtual machine %(name)s"), "KCHVMHDEV0001E": _("VM %(vmid)s does not contain directly assigned host device %(dev_name)s."), "KCHVMHDEV0002E": _("The host device %(dev_name)s is not allowed to directly assign to VM."), diff --git a/src/kimchi/model/vms.py b/src/kimchi/model/vms.py index 9987786..86a2a1f 100644 --- a/src/kimchi/model/vms.py +++ b/src/kimchi/model/vms.py @@ -836,6 +836,9 @@ def get_vm(name, conn): def delete(self, name): conn = self.conn.get() dom = self.get_vm(name, self.conn) + if not dom.isPersistent(): + raise InvalidOperation("KCHVM0036E", {'name': name}) + self._vmscreenshot_delete(dom.UUIDString()) paths = self._vm_get_disk_paths(dom) info = self.lookup(name) -- 1.9.3

Set the Deactivate action as a destructive one so that the GET will not be called for transient networks afterward. Signed-off-by: Christy Perez <christy@linux.vnet.ibm.com> --- src/kimchi/control/networks.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/kimchi/control/networks.py b/src/kimchi/control/networks.py index 7cb1572..6506546 100644 --- a/src/kimchi/control/networks.py +++ b/src/kimchi/control/networks.py @@ -37,7 +37,8 @@ def __init__(self, model, ident): self.admin_methods = ['PUT', 'POST', 'DELETE'] self.uri_fmt = "/networks/%s" self.activate = self.generate_action_handler('activate') - self.deactivate = self.generate_action_handler('deactivate') + self.deactivate = self.generate_action_handler('deactivate', + destructive=True) @property def data(self): -- 1.9.3

Set the Deactivate action as a destructive one so that the GET will not be called for transient storage pools afterward. Signed-off-by: Christy Perez <christy@linux.vnet.ibm.com> --- src/kimchi/control/storagepools.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kimchi/control/storagepools.py b/src/kimchi/control/storagepools.py index 872ad04..ee74bee 100644 --- a/src/kimchi/control/storagepools.py +++ b/src/kimchi/control/storagepools.py @@ -19,7 +19,6 @@ import cherrypy - from kimchi.control.base import Collection, Resource from kimchi.control.storagevolumes import IsoVolumes, StorageVolumes from kimchi.control.utils import get_class_name, model_fn @@ -79,7 +78,8 @@ def __init__(self, model, ident): self.admin_methods = ['PUT', 'POST', 'DELETE'] self.uri_fmt = "/storagepools/%s" self.activate = self.generate_action_handler('activate') - self.deactivate = self.generate_action_handler('deactivate') + self.deactivate = self.generate_action_handler('deactivate', + destructive=True) self.storagevolumes = StorageVolumes(self.model, ident) @property -- 1.9.3

Reviewed-by: Royce Lv<lvroyce@linux.vnet.ibm.com> On 01/30/2015 12:15 PM, Christy Perez wrote:
In order to prevent benign error messages from being displayed to the user, some POST requests for transient objects should be handled as special cases.
This patchset introduces a way to mark an action as destructive so that the subsequent GET after a POST is bypassed. It also adds that logic to the three types of transient objects that Kimchi deals with: VMs, Networks, and Storage Pools.
It also prevents Delete from being called on a VM, but does not need to prevent delete for the other objects as it does not apply.
Christy Perez (4): Handle requests differently for transient objects Transient VM POST request handling Transient Network POST request handling Transient StoragePool POST request handling
src/kimchi/control/base.py | 15 ++++++++++----- src/kimchi/control/networks.py | 3 ++- src/kimchi/control/storagepools.py | 4 ++-- src/kimchi/control/vms.py | 9 ++++++--- src/kimchi/i18n.py | 1 + src/kimchi/model/vms.py | 3 +++ 6 files changed, 24 insertions(+), 11 deletions(-)
participants (3)
-
Aline Manera
-
Christy Perez
-
Royce Lv