<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div class="moz-cite-prefix">On 01/13/2014 01:50 PM, Royce Lv wrote:<br>
    </div>
    <blockquote cite="mid:52D37E97.9000805@linux.vnet.ibm.com"
      type="cite">
      <meta content="text/html; charset=ISO-8859-1"
        http-equiv="Content-Type">
      <div class="moz-cite-prefix">Sheldon,<br>
        &nbsp;&nbsp; As we discussed, pls refer to demo decorator of PATCH 2/8. If
        you want to support GET_LIST of some function without change
        model.py, pls wrap it with my decorator and it will work. Also,
        if guys agree, I will put all these wrap in a single patchset.<br>
      </div>
    </blockquote>
    Just a suggestion. <br>
    <br>
    Though I prefer the entry of&nbsp; GET "method" to get and check query
    parameters, this is more simple.<br>
    &nbsp;Then we can trust cherrypy without any test case for getting query
    parameters, And other developer do not need to get and check query
    parameters again.<br>
    <br>
    You can use your way. <br>
    <br>
    <blockquote cite="mid:52D37E97.9000805@linux.vnet.ibm.com"
      type="cite">
      <div class="moz-cite-prefix"> <br>
        On 2014&#24180;01&#26376;11&#26085; 08:48, Sheldon wrote:<br>
      </div>
      <blockquote cite="mid:52D094D6.7040804@linux.vnet.ibm.com"
        type="cite">
        <meta content="text/html; charset=ISO-8859-1"
          http-equiv="Content-Type">
        <div class="moz-cite-prefix"><b>Not sure 'GET' method always
            mean "get_list" <br>
            <br>
            I have tried just add validate_params at the entry of check
            'GET', it can works well.</b><br>
          <br>
          @@ -242,11 +245,13 @@ class Collection(object):<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return kimchi.template.render(get_class_name(self),
          data)<br>
          &nbsp;<br>
          &nbsp;&nbsp;&nbsp;&nbsp; @cherrypy.expose<br>
          -&nbsp;&nbsp;&nbsp; def index(self, *args):<br>
          +&nbsp;&nbsp;&nbsp; def index(self, *args, **argv):<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; method = validate_method(('GET', 'POST'))<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if method == 'GET':<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try:<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; params = cherrypy.request.params<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; validate_params(params, self, 'get_list')<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return self.get()<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; except InvalidOperation, param:<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; error = "Invalid operation: '%s'" % param<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise cherrypy.HTTPError(400, error)<br>
          <br>
          <b>add a test for </b><b><br>
          </b><b>/storagepools?pool_type=dir</b><b><br>
          </b><b>and</b><b><br>
          </b><b>storagepools/default/storagevolumes?volume_type=file</b><br>
          <br>
          diff --git a/src/kimchi/API.json b/src/kimchi/API.json<br>
          index 19b1c51..fe3a85a 100644<br>
          --- a/src/kimchi/API.json<br>
          +++ b/src/kimchi/API.json<br>
          @@ -73,6 +73,26 @@<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "storagepools_get_list": {<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "type": "object",<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "properties": {<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "pool_type": {<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "description": "type of storagepools",<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "type": "string",<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "pattern": "^dir$"<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "storagevolumes_get_list": {<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "type": "object",<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "properties": {<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "volume_type": {<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "description": "type of storagevolumes",<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "type": "string",<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "pattern": "^file$"<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
          +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "vms_create": {<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "type": "object",<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "properties": {<br>
          <br>
          <br>
          <br>
          <br>
          <br>
          <b>$ curl -u &lt;user&gt;:&lt;password&gt; -H 'Content-type:
            application/json' -H 'Accept: application/json' -X GET
            http//localhost:8000/storagepools?pool_type=dir</b><br>
          <i>[</i><i><br>
          </i><i>&nbsp; {</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "available":27511504896,</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "source":{},</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "state":"active",</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "capacity":195949113344,</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "name":"default",</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "nr_volumes":2,</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "path":"/home/shhfeng/var/lib/libvirt/images",</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "allocated":168437608448,</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "autostart":true,</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "type":"dir"</i><i><br>
          </i><i>&nbsp; },</i><i><br>
          </i><i>&nbsp; {</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "state":"active",</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "type":"kimchi-iso",</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "name":"kimchi_isos"</i><i><br>
          </i><i>&nbsp; }</i><i><br>
          </i><i>]</i><br>
          <b>$ curl -u &lt;user&gt;:&lt;password&gt; -H 'Content-type:
            application/json' -H 'Accept: application/json' -X GET
            http//localhost:8000/storagepools?pool_type=dirxxx</b><br>
          <i>{</i><i><br>
          </i><i>&nbsp; "reason":"The server encountered an unexpected
            condition which prevented it from fulfilling the request.",</i><i><br>
          </i><i>&nbsp; "code":"500 Internal Server Error",</i><i><br>
          </i><i>&nbsp; "call_stack":"Traceback (most recent call last):\n&nbsp;
            File
            \"/usr/lib/python2.7/site-packages/cherrypy/_cprequest.py\",
            line 656, in respond\n&nbsp;&nbsp;&nbsp; response.body = self.handler()\n&nbsp;
            File
            \"/usr/lib/python2.7/site-packages/cherrypy/lib/encoding.py\",
            line 188, in __call__\n&nbsp;&nbsp;&nbsp; self.body =
            self.oldhandler(*args, **kwargs)\n&nbsp; File
            \"/usr/lib/python2.7/site-packages/cherrypy/_cpdispatch.py\",
            line 34, in __call__\n&nbsp;&nbsp;&nbsp; return self.callable(*self.args,
            **self.kwargs)\n&nbsp; File
            \"/home/shhfeng/work/workdir/kimchi/src/kimchi/control/base.py\",
            line 254, in index\n&nbsp;&nbsp;&nbsp;
            validate_params(cherrypy.request.params, self,
            'get_list')\n&nbsp; File
            \"/home/shhfeng/work/workdir/kimchi/src/kimchi/control/utils.py\",
            line 105, in validate_params\n&nbsp;&nbsp;&nbsp; e.message for e in
            validator.iter_errors(request)))\nInvalidParameter:
            u'dirxxx' does not match u'^dir$'\n"</i><br>
          <br>
          <b><br>
          </b><b>$ curl -u &lt;user&gt;:&lt;password&gt; -H
            'Content-type: application/json' -H 'Accept:
            application/json' -X GET
http//localhost:8000/storagepools/default/storagevolumes?volume_type=file</b><br>
          <i>[</i><i><br>
          </i><i>&nbsp; {</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "capacity":21474836480,</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "name":"RHEL6.5.img",</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "format":"qcow2",</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "allocation":5200818176,</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp;
            "path":"/home/shhfeng/var/lib/libvirt/images/RHEL6.5.img",</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "type":"file"</i><i><br>
          </i><i>&nbsp; },</i><i><br>
          </i><i>&nbsp; {</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "capacity":21474836480,</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "name":"RHEL6.5.img.back",</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "format":"qcow2",</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "allocation":3681751040,</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp;
            "path":"/home/shhfeng/var/lib/libvirt/images/RHEL6.5.img.back",</i><i><br>
          </i><i>&nbsp;&nbsp;&nbsp; "type":"file"</i><i><br>
          </i><i>&nbsp; }</i><i><br>
          </i><i>]</i><br>
          <b>$ curl -u &lt;user&gt;:&lt;password&gt; -H 'Content-type:
            application/json' -H 'Accept: application/json' -X GET
http//localhost:8000/storagepools/default/storagevolumes?volume_type=filexxx</b><br>
          <i>{</i><i><br>
          </i><i>&nbsp; "reason":"The server encountered an unexpected
            condition which prevented it from fulfilling the request.",</i><i><br>
          </i><i>&nbsp; "code":"500 Internal Server Error",</i><i><br>
          </i><i>&nbsp; "call_stack":"Traceback (most recent call last):\n&nbsp;
            File
            \"/usr/lib/python2.7/site-packages/cherrypy/_cprequest.py\",
            line 656, in respond\n&nbsp;&nbsp;&nbsp; response.body = self.handler()\n&nbsp;
            File
            \"/usr/lib/python2.7/site-packages/cherrypy/lib/encoding.py\",
            line 188, in __call__\n&nbsp;&nbsp;&nbsp; self.body =
            self.oldhandler(*args, **kwargs)\n&nbsp; File
            \"/usr/lib/python2.7/site-packages/cherrypy/_cpdispatch.py\",
            line 34, in __call__\n&nbsp;&nbsp;&nbsp; return self.callable(*self.args,
            **self.kwargs)\n&nbsp; File
            \"/home/shhfeng/work/workdir/kimchi/src/kimchi/control/base.py\",
            line 254, in index\n&nbsp;&nbsp;&nbsp;
            validate_params(cherrypy.request.params, self,
            'get_list')\n&nbsp; File
            \"/home/shhfeng/work/workdir/kimchi/src/kimchi/control/utils.py\",
            line 105, in validate_params\n&nbsp;&nbsp;&nbsp; e.message for e in
            validator.iter_errors(request)))\nInvalidParameter:
            u'filexxx' does not match u'^file$'\n"</i><i><br>
          </i><br>
          <br>
          <br>
          On 01/08/2014 11:50 PM, <a moz-do-not-send="true"
            class="moz-txt-link-abbreviated"
            href="mailto:lvroyce0210@gmail.com">lvroyce0210@gmail.com</a>
          wrote:<br>
        </div>
        <blockquote
          cite="mid:1389196210-15213-2-git-send-email-lvroyce0210@gmail.com"
          type="cite">
          <pre wrap="">From: Royce Lv <a moz-do-not-send="true" class="moz-txt-link-rfc2396E" href="mailto:lvroyce@linux.vnet.ibm.com">&lt;lvroyce@linux.vnet.ibm.com&gt;</a>

Add support for passing params for GET method,
we will call it like:
    GET /vms?state=running

Signed-off-by: Royce Lv <a moz-do-not-send="true" class="moz-txt-link-rfc2396E" href="mailto:lvroyce@linux.vnet.ibm.com">&lt;lvroyce@linux.vnet.ibm.com&gt;</a>
---
 src/kimchi/control/base.py         | 26 +++++++++++++++++++-------
 src/kimchi/control/storagepools.py |  4 ++--
 src/kimchi/control/utils.py        |  2 ++
 3 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/src/kimchi/control/base.py b/src/kimchi/control/base.py
index 185c8d8..73b70fb 100644
--- a/src/kimchi/control/base.py
+++ b/src/kimchi/control/base.py
@@ -28,7 +28,7 @@ import urllib2

 import kimchi.template
 from kimchi.control.utils import get_class_name, internal_redirect, model_fn
-from kimchi.control.utils import parse_request, validate_method
+from kimchi.control.utils import parse_request, parse_param, validate_method
 from kimchi.control.utils import validate_params
 from kimchi.exception import InvalidOperation, InvalidParameter
 from kimchi.exception import MissingParameter, NotFoundError,  OperationFailed
@@ -212,10 +212,11 @@ class Collection(object):

         return res.get()

-    def _get_resources(self):
+    def _get_resources(self, filter_params):
         try:
+            validate_params(filter_params, self, 'get_list')
             get_list = getattr(self.model, model_fn(self, 'get_list'))
-            idents = get_list(*self.model_args)
+            idents = get_list(*self.model_args, **filter_params)
             res_list = []
             for ident in idents:
                 # internal text, get_list changes ident to unicode for sorted
@@ -234,15 +235,26 @@ class Collection(object):
             args = self.resource_args + [ident.decode("utf-8")]
             return self.resource(self.model, *args)

-    def get(self):
-        resources = self._get_resources()
+    def filter_data(self, resources, filter_params):
         data = []
         for res in resources:
-            data.append(res.data)
+            valid = True
+            for key, val in filter_params.items():
+                if not ( key in res.data and res.data[key] == val):
+                    valid = False
+                    break
+            if valid:
+                data.append(res.data)
+        return data
+
+    def get(self):
+        filter_params = parse_param()
+        resources = self._get_resources(filter_params)
+        data = self.filter_data(resources, filter_params)
         return kimchi.template.render(get_class_name(self), data)

     @cherrypy.expose
-    def index(self, *args):
+    def index(self, *args, **kwargs):
         method = validate_method(('GET', 'POST'))
         if method == 'GET':
             try:
diff --git a/src/kimchi/control/storagepools.py b/src/kimchi/control/storagepools.py
index 466b4b6..0df14c5 100644
--- a/src/kimchi/control/storagepools.py
+++ b/src/kimchi/control/storagepools.py
@@ -61,9 +61,9 @@ class StoragePools(Collection):

         return resp

-    def _get_resources(self):
+    def _get_resources(self, filter_params):
         try:
-            res_list = super(StoragePools, self)._get_resources()
+            res_list = super(StoragePools, self)._get_resources(filter_params)
             # Append reserved pools
             isos = getattr(self, ISO_POOL_NAME)
             isos.lookup()
diff --git a/src/kimchi/control/utils.py b/src/kimchi/control/utils.py
index c3c5f8e..4b3c4b0 100644
--- a/src/kimchi/control/utils.py
+++ b/src/kimchi/control/utils.py
@@ -81,6 +81,8 @@ def parse_request():
         raise cherrypy.HTTPError(415, "This API only supports"
                                       " 'application/json'")

+def parse_param():
+    return cherrypy.request.params

 def internal_redirect(url):
     raise cherrypy.InternalRedirect(url.encode("utf-8"))
</pre>
        </blockquote>
        <br>
        <br>
        <pre class="moz-signature" cols="72">-- 
Thanks and best regards!

Sheldon Feng(&#20911;&#23569;&#21512;)<a moz-do-not-send="true" class="moz-txt-link-rfc2396E" href="mailto:shaohef@linux.vnet.ibm.com">&lt;shaohef@linux.vnet.ibm.com&gt;</a>
IBM Linux Technology Center</pre>
        <br>
        <fieldset class="mimeAttachmentHeader"></fieldset>
        <br>
        <pre wrap="">_______________________________________________
Kimchi-devel mailing list
<a moz-do-not-send="true" class="moz-txt-link-abbreviated" href="mailto:Kimchi-devel@ovirt.org">Kimchi-devel@ovirt.org</a>
<a moz-do-not-send="true" class="moz-txt-link-freetext" href="http://lists.ovirt.org/mailman/listinfo/kimchi-devel">http://lists.ovirt.org/mailman/listinfo/kimchi-devel</a>
</pre>
      </blockquote>
      <br>
    </blockquote>
    <br>
    <br>
    <pre class="moz-signature" cols="72">-- 
Thanks and best regards!

Sheldon Feng(&#20911;&#23569;&#21512;)<a class="moz-txt-link-rfc2396E" href="mailto:shaohef@linux.vnet.ibm.com">&lt;shaohef@linux.vnet.ibm.com&gt;</a>
IBM Linux Technology Center</pre>
  </body>
</html>