[project-kimchi][PATCHv4 0/5] Storage server query support

From: Royce Lv <lvroyce@linux.vnet.ibm.com> v3>v4, fix inconsistency between doc and json schema v1>v3, fix racing problem, fix style. Add parameters to GET request so that we will query storage server as: /storageservers?type=netfs Royce Lv (5): Support params for GET method Add testcase for GET param Storage server: Update API.md storage server: update controller.py storage server: Update model and mockmodel docs/API.md | 13 +++++++++++++ src/kimchi/API.json | 11 +++++++++++ src/kimchi/controller.py | 26 ++++++++++++++++++++++++-- src/kimchi/mockmodel.py | 13 +++++++++++++ src/kimchi/model.py | 14 +++++++++++++- src/kimchi/root.py | 1 + tests/test_rest.py | 37 +++++++++++++++++++++++++++++++++++++ 7 files changed, 112 insertions(+), 3 deletions(-) -- 1.8.1.2

From: Royce Lv <lvroyce@linux.vnet.ibm.com> Add support for passing params for GET method, we will call it like: GET /vms?state=running Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/controller.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/kimchi/controller.py b/src/kimchi/controller.py index 2940278..c99a811 100644 --- a/src/kimchi/controller.py +++ b/src/kimchi/controller.py @@ -71,6 +71,10 @@ def mime_in_header(header, mime): def parse_request(): + method = validate_method(('GET', 'DELETE', 'PUT', 'POST')) + if method == 'GET': + return cherrypy.request.params + if 'Content-Length' not in cherrypy.request.headers: return {} rawbody = cherrypy.request.body.read() @@ -274,8 +278,9 @@ class Collection(object): def _get_resources(self): try: + params = parse_request() get_list = getattr(self.model, model_fn(self, 'get_list')) - idents = get_list(*self.model_args) + idents = get_list(*self.model_args, **params) res_list = [] for ident in idents: # internal text, get_list changes ident to unicode for sorted @@ -302,7 +307,7 @@ class Collection(object): 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: -- 1.8.1.2

Reviewed-by: Aline Manera <alinefm@linux.vnet.ibm.com> On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Add support for passing params for GET method, we will call it like: GET /vms?state=running
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/controller.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/kimchi/controller.py b/src/kimchi/controller.py index 2940278..c99a811 100644 --- a/src/kimchi/controller.py +++ b/src/kimchi/controller.py @@ -71,6 +71,10 @@ def mime_in_header(header, mime):
def parse_request(): + method = validate_method(('GET', 'DELETE', 'PUT', 'POST')) + if method == 'GET': + return cherrypy.request.params + if 'Content-Length' not in cherrypy.request.headers: return {} rawbody = cherrypy.request.body.read() @@ -274,8 +278,9 @@ class Collection(object):
def _get_resources(self): try: + params = parse_request() get_list = getattr(self.model, model_fn(self, 'get_list')) - idents = get_list(*self.model_args) + idents = get_list(*self.model_args, **params) res_list = [] for ident in idents: # internal text, get_list changes ident to unicode for sorted @@ -302,7 +307,7 @@ class Collection(object): 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:

From: Royce Lv <lvroyce@linux.vnet.ibm.com> Add a testcase to test GET param passing. Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- tests/test_rest.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/test_rest.py b/tests/test_rest.py index f597796..42573fc 100644 --- a/tests/test_rest.py +++ b/tests/test_rest.py @@ -1056,6 +1056,43 @@ class RestTests(unittest.TestCase): self.assertIn('net_recv_rate', stats) self.assertIn('net_sent_rate', stats) + def test_get_param(self): + def hack_model(func): + def _get_param_func(*args, **kwargs): + key = kwargs.pop('name', None) + res = func(**kwargs) + if key and key in res: + res = [key] + return res + return _get_param_func + + global model + old_handler = model.vms_get_list + model.vms_get_list = hack_model(model.vms_get_list) + + req = json.dumps({'name': 'test', 'cdrom': '/nonexistent.iso'}) + self.request('/templates', req, 'POST') + + # Create a VM + req = json.dumps({'name': 'test-vm1', 'template': '/templates/test'}) + resp = self.request('/vms', req, 'POST') + self.assertEquals(201, resp.status) + req = json.dumps({'name': 'test-vm2', 'template': '/templates/test'}) + resp = self.request('/vms', req, 'POST') + self.assertEquals(201, resp.status) + + resp = request(host, port, '/vms') + self.assertEquals(200, resp.status) + res = json.loads(resp.read()) + self.assertEquals(2, len(res)) + + resp = request(host, port, '/vms?name=test-vm1') + self.assertEquals(200, resp.status) + res = json.loads(resp.read()) + self.assertEquals(1, len(res)) + self.assertEquals('test-vm1', res[0]['name']) + + model.vms_get_list = old_handler class HttpsRestTests(RestTests): """ -- 1.8.1.2

Reviewed-by: Aline Manera <alinefm@linux.vnet.ibm.com> On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Add a testcase to test GET param passing.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- tests/test_rest.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)
diff --git a/tests/test_rest.py b/tests/test_rest.py index f597796..42573fc 100644 --- a/tests/test_rest.py +++ b/tests/test_rest.py @@ -1056,6 +1056,43 @@ class RestTests(unittest.TestCase): self.assertIn('net_recv_rate', stats) self.assertIn('net_sent_rate', stats)
+ def test_get_param(self): + def hack_model(func): + def _get_param_func(*args, **kwargs): + key = kwargs.pop('name', None) + res = func(**kwargs) + if key and key in res: + res = [key] + return res + return _get_param_func + + global model + old_handler = model.vms_get_list + model.vms_get_list = hack_model(model.vms_get_list) + + req = json.dumps({'name': 'test', 'cdrom': '/nonexistent.iso'}) + self.request('/templates', req, 'POST') + + # Create a VM + req = json.dumps({'name': 'test-vm1', 'template': '/templates/test'}) + resp = self.request('/vms', req, 'POST') + self.assertEquals(201, resp.status) + req = json.dumps({'name': 'test-vm2', 'template': '/templates/test'}) + resp = self.request('/vms', req, 'POST') + self.assertEquals(201, resp.status) + + resp = request(host, port, '/vms') + self.assertEquals(200, resp.status) + res = json.loads(resp.read()) + self.assertEquals(2, len(res)) + + resp = request(host, port, '/vms?name=test-vm1') + self.assertEquals(200, resp.status) + res = json.loads(resp.read()) + self.assertEquals(1, len(res)) + self.assertEquals('test-vm1', res[0]['name']) + + model.vms_get_list = old_handler
class HttpsRestTests(RestTests): """

It seems that this test case is a generic test case for GET parameter, not a test case showing the storage servers listing by target type. Why should you have a generic test case? 2013/12/30 10:17, lvroyce@linux.vnet.ibm.com:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Add a testcase to test GET param passing.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- tests/test_rest.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)
diff --git a/tests/test_rest.py b/tests/test_rest.py index f597796..42573fc 100644 --- a/tests/test_rest.py +++ b/tests/test_rest.py @@ -1056,6 +1056,43 @@ class RestTests(unittest.TestCase): self.assertIn('net_recv_rate', stats) self.assertIn('net_sent_rate', stats)
+ def test_get_param(self): + def hack_model(func): + def _get_param_func(*args, **kwargs): + key = kwargs.pop('name', None) + res = func(**kwargs) + if key and key in res: + res = [key] + return res + return _get_param_func + + global model + old_handler = model.vms_get_list + model.vms_get_list = hack_model(model.vms_get_list) + + req = json.dumps({'name': 'test', 'cdrom': '/nonexistent.iso'}) + self.request('/templates', req, 'POST') + + # Create a VM + req = json.dumps({'name': 'test-vm1', 'template': '/templates/test'}) + resp = self.request('/vms', req, 'POST') + self.assertEquals(201, resp.status) + req = json.dumps({'name': 'test-vm2', 'template': '/templates/test'}) + resp = self.request('/vms', req, 'POST') + self.assertEquals(201, resp.status) + + resp = request(host, port, '/vms') + self.assertEquals(200, resp.status) + res = json.loads(resp.read()) + self.assertEquals(2, len(res)) + + resp = request(host, port, '/vms?name=test-vm1') + self.assertEquals(200, resp.status) + res = json.loads(resp.read()) + self.assertEquals(1, len(res)) + self.assertEquals('test-vm1', res[0]['name']) + + model.vms_get_list = old_handler
class HttpsRestTests(RestTests): """

From: Royce Lv <lvroyce@linux.vnet.ibm.com> Update API.md to specify storage server api. Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- docs/API.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/API.md b/docs/API.md index 9edc551..ad58889 100644 --- a/docs/API.md +++ b/docs/API.md @@ -440,6 +440,19 @@ creation. not tested yet * **POST**: *See Configuration Actions* +**Actions (POST):** + +*No actions defined* + +### Collection: Storage Servers + +**URI:** /storageservers + +**Methods:** + +* **GET**: Retrieve a summarized list of used storage servers. + * target_type: Filter server list with given type, currently support 'netfs'. + ### Collection: Distros **URI:** /config/distros -- 1.8.1.2

Reviewed-by: Aline Manera <alinefm@linux.vnet.ibm.com> On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Update API.md to specify storage server api.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- docs/API.md | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/docs/API.md b/docs/API.md index 9edc551..ad58889 100644 --- a/docs/API.md +++ b/docs/API.md @@ -440,6 +440,19 @@ creation. not tested yet * **POST**: *See Configuration Actions*
+**Actions (POST):** + +*No actions defined* + +### Collection: Storage Servers + +**URI:** /storageservers + +**Methods:** + +* **GET**: Retrieve a summarized list of used storage servers. + * target_type: Filter server list with given type, currently support 'netfs'. + ### Collection: Distros
**URI:** /config/distros

From: Royce Lv <lvroyce@linux.vnet.ibm.com> Add storage server collection and resource to report used storage server. Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/API.json | 11 +++++++++++ src/kimchi/controller.py | 17 +++++++++++++++++ src/kimchi/root.py | 1 + 3 files changed, 29 insertions(+) diff --git a/src/kimchi/API.json b/src/kimchi/API.json index 7b90826..29d8172 100644 --- a/src/kimchi/API.json +++ b/src/kimchi/API.json @@ -205,6 +205,17 @@ } }, "additionalProperties": false + }, + "storageservers_get_list": { + "type": "object", + "properties": { + "target_type": { + "description": "List storage servers of given type", + "type": "string", + "pattern": "^netfs$", + "required": true + } + } } } } diff --git a/src/kimchi/controller.py b/src/kimchi/controller.py index c99a811..bdd3cab 100644 --- a/src/kimchi/controller.py +++ b/src/kimchi/controller.py @@ -647,6 +647,23 @@ class DebugReport(Resource): 'time': self.info['ctime']} +class StorageServers(Collection): + def __init__(self, model): + super(StorageServers, self).__init__(model) + self.resource = StorageServer + + def get(self): + res_list = [] + params = parse_request() + validate_params(params, self, 'get_list') + get_list = getattr(self.model, model_fn(self, 'get_list')) + res_list = get_list(*self.model_args, **params) + return kimchi.template.render(get_class_name(self), res_list) + + +class StorageServer(Resource): + pass + class Config(Resource): def __init__(self, model, id=None): super(Config, self).__init__(model, id) diff --git a/src/kimchi/root.py b/src/kimchi/root.py index c43897c..0f80785 100644 --- a/src/kimchi/root.py +++ b/src/kimchi/root.py @@ -67,6 +67,7 @@ class Root(controller.Resource): self.logout = controller.logout self.debugreports = controller.DebugReports(model) self.plugins = controller.Plugins(model) + self.storageservers = controller.StorageServers(model) self.api_schema = json.load(open(get_api_schema_file())) def get(self): -- 1.8.1.2

On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Add storage server collection and resource to report used storage server.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/API.json | 11 +++++++++++ src/kimchi/controller.py | 17 +++++++++++++++++ src/kimchi/root.py | 1 + 3 files changed, 29 insertions(+)
diff --git a/src/kimchi/API.json b/src/kimchi/API.json index 7b90826..29d8172 100644 --- a/src/kimchi/API.json +++ b/src/kimchi/API.json @@ -205,6 +205,17 @@ } }, "additionalProperties": false + }, + "storageservers_get_list": { + "type": "object", + "properties": { + "target_type": { + "description": "List storage servers of given type", + "type": "string", + "pattern": "^netfs$", + "required": true + } + } } } } diff --git a/src/kimchi/controller.py b/src/kimchi/controller.py index c99a811..bdd3cab 100644 --- a/src/kimchi/controller.py +++ b/src/kimchi/controller.py @@ -647,6 +647,23 @@ class DebugReport(Resource): 'time': self.info['ctime']}
+class StorageServers(Collection): + def __init__(self, model): + super(StorageServers, self).__init__(model) + self.resource = StorageServer +
+ def get(self): + res_list = [] + params = parse_request() + validate_params(params, self, 'get_list') + get_list = getattr(self.model, model_fn(self, 'get_list')) + res_list = get_list(*self.model_args, **params) + return kimchi.template.render(get_class_name(self), res_list) +
I didn't understand why it is needed as you have already changed Collection._get_resources() to use query parameters. The change in Collection._get_resources() should be enough and work for any collection
+ +class StorageServer(Resource): + pass + class Config(Resource): def __init__(self, model, id=None): super(Config, self).__init__(model, id) diff --git a/src/kimchi/root.py b/src/kimchi/root.py index c43897c..0f80785 100644 --- a/src/kimchi/root.py +++ b/src/kimchi/root.py @@ -67,6 +67,7 @@ class Root(controller.Resource): self.logout = controller.logout self.debugreports = controller.DebugReports(model) self.plugins = controller.Plugins(model) + self.storageservers = controller.StorageServers(model) self.api_schema = json.load(open(get_api_schema_file()))
def get(self):

On 2013年12月31日 03:28, Aline Manera wrote:
On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Add storage server collection and resource to report used storage server.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/API.json | 11 +++++++++++ src/kimchi/controller.py | 17 +++++++++++++++++ src/kimchi/root.py | 1 + 3 files changed, 29 insertions(+)
diff --git a/src/kimchi/API.json b/src/kimchi/API.json index 7b90826..29d8172 100644 --- a/src/kimchi/API.json +++ b/src/kimchi/API.json @@ -205,6 +205,17 @@ } }, "additionalProperties": false + }, + "storageservers_get_list": { + "type": "object", + "properties": { + "target_type": { + "description": "List storage servers of given type", + "type": "string", + "pattern": "^netfs$", + "required": true + } + } } } } diff --git a/src/kimchi/controller.py b/src/kimchi/controller.py index c99a811..bdd3cab 100644 --- a/src/kimchi/controller.py +++ b/src/kimchi/controller.py @@ -647,6 +647,23 @@ class DebugReport(Resource): 'time': self.info['ctime']}
+class StorageServers(Collection): + def __init__(self, model): + super(StorageServers, self).__init__(model) + self.resource = StorageServer +
+ def get(self): + res_list = [] + params = parse_request() + validate_params(params, self, 'get_list') + get_list = getattr(self.model, model_fn(self, 'get_list')) + res_list = get_list(*self.model_args, **params) + return kimchi.template.render(get_class_name(self), res_list) +
I didn't understand why it is needed as you have already changed Collection._get_resources() to use query parameters. The change in Collection._get_resources() should be enough and work for any collection :) Glad you notice this, I only exposed /storageservers/ collection query and server itself does not have any data to return. Because each server may serve as multiple kinds of server(iscsi, nfs, gluster,etc at the same time). So I move target information to a single
collection called storagetargets. So change in collection is to support generic GET params and since we have several scenario to use it(e.g. interface type query) I wrote that and demo with a test of the impl. > >> + >> +class StorageServer(Resource): >> + pass >> + >> class Config(Resource): >> def __init__(self, model, id=None): >> super(Config, self).__init__(model, id) >> diff --git a/src/kimchi/root.py b/src/kimchi/root.py >> index c43897c..0f80785 100644 >> --- a/src/kimchi/root.py >> +++ b/src/kimchi/root.py >> @@ -67,6 +67,7 @@ class Root(controller.Resource): >> self.logout = controller.logout >> self.debugreports = controller.DebugReports(model) >> self.plugins = controller.Plugins(model) >> + self.storageservers = controller.StorageServers(model) >> self.api_schema = json.load(open(get_api_schema_file())) >> >> def get(self): >

On 01/02/2014 12:47 AM, Royce Lv wrote:
On 2013年12月31日 03:28, Aline Manera wrote:
On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Add storage server collection and resource to report used storage server.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/API.json | 11 +++++++++++ src/kimchi/controller.py | 17 +++++++++++++++++ src/kimchi/root.py | 1 + 3 files changed, 29 insertions(+)
diff --git a/src/kimchi/API.json b/src/kimchi/API.json index 7b90826..29d8172 100644 --- a/src/kimchi/API.json +++ b/src/kimchi/API.json @@ -205,6 +205,17 @@ } }, "additionalProperties": false + }, + "storageservers_get_list": { + "type": "object", + "properties": { + "target_type": { + "description": "List storage servers of given type", + "type": "string", + "pattern": "^netfs$", + "required": true + } + } } } } diff --git a/src/kimchi/controller.py b/src/kimchi/controller.py index c99a811..bdd3cab 100644 --- a/src/kimchi/controller.py +++ b/src/kimchi/controller.py @@ -647,6 +647,23 @@ class DebugReport(Resource): 'time': self.info['ctime']}
+class StorageServers(Collection): + def __init__(self, model): + super(StorageServers, self).__init__(model) + self.resource = StorageServer +
+ def get(self): + res_list = [] + params = parse_request() + validate_params(params, self, 'get_list') + get_list = getattr(self.model, model_fn(self, 'get_list')) + res_list = get_list(*self.model_args, **params) + return kimchi.template.render(get_class_name(self), res_list) +
I didn't understand why it is needed as you have already changed Collection._get_resources() to use query parameters. The change in Collection._get_resources() should be enough and work for any collection :) Glad you notice this, I only exposed /storageservers/ collection query and server itself does not have any data to return.
Why doesn't storageservers have any data to return? GET /storageservers should return all servers, right? At least the ident should be returned there.
Because each server may serve as multiple kinds of server(iscsi, nfs, gluster,etc at the same time). So I move target information to a single collection called storagetargets. So change in collection is to support generic GET params and since we have several scenario to use it(e.g. interface type query) I wrote that and demo with a test of the impl.
Sorry, but I still didn't understand why this change is needed. Or you will remove it in next version?
+ +class StorageServer(Resource): + pass + class Config(Resource): def __init__(self, model, id=None): super(Config, self).__init__(model, id) diff --git a/src/kimchi/root.py b/src/kimchi/root.py index c43897c..0f80785 100644 --- a/src/kimchi/root.py +++ b/src/kimchi/root.py @@ -67,6 +67,7 @@ class Root(controller.Resource): self.logout = controller.logout self.debugreports = controller.DebugReports(model) self.plugins = controller.Plugins(model) + self.storageservers = controller.StorageServers(model) self.api_schema = json.load(open(get_api_schema_file()))
def get(self):

于 2014/1/2 10:47, Royce Lv 写道:
On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Add storage server collection and resource to report used storage server.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/API.json | 11 +++++++++++ src/kimchi/controller.py | 17 +++++++++++++++++ src/kimchi/root.py | 1 + 3 files changed, 29 insertions(+)
diff --git a/src/kimchi/API.json b/src/kimchi/API.json index 7b90826..29d8172 100644 --- a/src/kimchi/API.json +++ b/src/kimchi/API.json @@ -205,6 +205,17 @@ } }, "additionalProperties": false + }, + "storageservers_get_list": { + "type": "object", + "properties": { + "target_type": { + "description": "List storage servers of given type", + "type": "string", + "pattern": "^netfs$", + "required": true + } + } } } } diff --git a/src/kimchi/controller.py b/src/kimchi/controller.py index c99a811..bdd3cab 100644 --- a/src/kimchi/controller.py +++ b/src/kimchi/controller.py @@ -647,6 +647,23 @@ class DebugReport(Resource): 'time': self.info['ctime']}
+class StorageServers(Collection): + def __init__(self, model): + super(StorageServers, self).__init__(model) + self.resource = StorageServer +
+ def get(self): + res_list = [] + params = parse_request() + validate_params(params, self, 'get_list') + get_list = getattr(self.model, model_fn(self, 'get_list')) + res_list = get_list(*self.model_args, **params) + return kimchi.template.render(get_class_name(self), res_list) +
I didn't understand why it is needed as you have already changed Collection._get_resources() to use query parameters. The change in Collection._get_resources() should be enough and work for any collection :) Glad you notice this, I only exposed /storageservers/ collection query and server itself does not have any data to return. Because each server may serve as multiple kinds of server(iscsi, nfs, gluster,etc at the same time). So I move target information to a single collection called storagetargets. So change in collection is to support generic GET params and since we have several scenario to use it(e.g. interface type query) I wrote
On 2013年12月31日 03:28, Aline Manera wrote: that and demo with a test of the impl.
Do you mean that the code in Collection._get_resources() will not be used now? And you expect other scenario will be used in it in the future? It seems that you have duplicate in Collection._get_resources() and StorageServers.get()
+ +class StorageServer(Resource): + pass + class Config(Resource): def __init__(self, model, id=None): super(Config, self).__init__(model, id) diff --git a/src/kimchi/root.py b/src/kimchi/root.py index c43897c..0f80785 100644 --- a/src/kimchi/root.py +++ b/src/kimchi/root.py @@ -67,6 +67,7 @@ class Root(controller.Resource): self.logout = controller.logout self.debugreports = controller.DebugReports(model) self.plugins = controller.Plugins(model) + self.storageservers = controller.StorageServers(model) self.api_schema = json.load(open(get_api_schema_file()))
def get(self):
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel

On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Add storage server collection and resource to report used storage server.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/API.json | 11 +++++++++++ src/kimchi/controller.py | 17 +++++++++++++++++ src/kimchi/root.py | 1 + 3 files changed, 29 insertions(+)
diff --git a/src/kimchi/API.json b/src/kimchi/API.json index 7b90826..29d8172 100644 --- a/src/kimchi/API.json +++ b/src/kimchi/API.json @@ -205,6 +205,17 @@ } }, "additionalProperties": false + }, + "storageservers_get_list": { + "type": "object", + "properties": { + "target_type": { + "description": "List storage servers of given type", + "type": "string", + "pattern": "^netfs$", + "required": true + } + } } } } diff --git a/src/kimchi/controller.py b/src/kimchi/controller.py index c99a811..bdd3cab 100644 --- a/src/kimchi/controller.py +++ b/src/kimchi/controller.py @@ -647,6 +647,23 @@ class DebugReport(Resource): 'time': self.info['ctime']}
+class StorageServers(Collection): + def __init__(self, model): + super(StorageServers, self).__init__(model) + self.resource = StorageServer + + def get(self): + res_list = [] + params = parse_request() + validate_params(params, self, 'get_list') + get_list = getattr(self.model, model_fn(self, 'get_list')) + res_list = get_list(*self.model_args, **params) + return kimchi.template.render(get_class_name(self), res_list) + + +class StorageServer(Resource): + pass
You also need to expose which values will be returned: @property def data(self): return self.info
+ class Config(Resource): def __init__(self, model, id=None): super(Config, self).__init__(model, id) diff --git a/src/kimchi/root.py b/src/kimchi/root.py index c43897c..0f80785 100644 --- a/src/kimchi/root.py +++ b/src/kimchi/root.py @@ -67,6 +67,7 @@ class Root(controller.Resource): self.logout = controller.logout self.debugreports = controller.DebugReports(model) self.plugins = controller.Plugins(model) + self.storageservers = controller.StorageServers(model) self.api_schema = json.load(open(get_api_schema_file()))
def get(self):

On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Add storage server collection and resource to report used storage server.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/API.json | 11 +++++++++++ src/kimchi/controller.py | 17 +++++++++++++++++ src/kimchi/root.py | 1 + 3 files changed, 29 insertions(+)
diff --git a/src/kimchi/API.json b/src/kimchi/API.json index 7b90826..29d8172 100644 --- a/src/kimchi/API.json +++ b/src/kimchi/API.json @@ -205,6 +205,17 @@ } }, "additionalProperties": false + }, + "storageservers_get_list": { + "type": "object", + "properties": { + "target_type": { + "description": "List storage servers of given type", + "type": "string", + "pattern": "^netfs$", + "required": true + } + } } } } diff --git a/src/kimchi/controller.py b/src/kimchi/controller.py index c99a811..bdd3cab 100644 --- a/src/kimchi/controller.py +++ b/src/kimchi/controller.py @@ -647,6 +647,23 @@ class DebugReport(Resource): 'time': self.info['ctime']}
+class StorageServers(Collection): + def __init__(self, model): + super(StorageServers, self).__init__(model) + self.resource = StorageServer + + def get(self): + res_list = [] + params = parse_request() + validate_params(params, self, 'get_list') + get_list = getattr(self.model, model_fn(self, 'get_list')) + res_list = get_list(*self.model_args, **params) + return kimchi.template.render(get_class_name(self), res_list) + + +class StorageServer(Resource): + pass
You also need to expose which values will be returned:
@property def data(self): return self.info
On 2013年12月31日 03:30, Aline Manera wrote: paths only return in storageTarget resource, so this resource does not have any data yet.
+ class Config(Resource): def __init__(self, model, id=None): super(Config, self).__init__(model, id) diff --git a/src/kimchi/root.py b/src/kimchi/root.py index c43897c..0f80785 100644 --- a/src/kimchi/root.py +++ b/src/kimchi/root.py @@ -67,6 +67,7 @@ class Root(controller.Resource): self.logout = controller.logout self.debugreports = controller.DebugReports(model) self.plugins = controller.Plugins(model) + self.storageservers = controller.StorageServers(model) self.api_schema = json.load(open(get_api_schema_file()))
def get(self):

On 01/02/2014 12:41 AM, Royce Lv wrote:
On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Add storage server collection and resource to report used storage server.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/API.json | 11 +++++++++++ src/kimchi/controller.py | 17 +++++++++++++++++ src/kimchi/root.py | 1 + 3 files changed, 29 insertions(+)
diff --git a/src/kimchi/API.json b/src/kimchi/API.json index 7b90826..29d8172 100644 --- a/src/kimchi/API.json +++ b/src/kimchi/API.json @@ -205,6 +205,17 @@ } }, "additionalProperties": false + }, + "storageservers_get_list": { + "type": "object", + "properties": { + "target_type": { + "description": "List storage servers of given type", + "type": "string", + "pattern": "^netfs$", + "required": true + } + } } } } diff --git a/src/kimchi/controller.py b/src/kimchi/controller.py index c99a811..bdd3cab 100644 --- a/src/kimchi/controller.py +++ b/src/kimchi/controller.py @@ -647,6 +647,23 @@ class DebugReport(Resource): 'time': self.info['ctime']}
+class StorageServers(Collection): + def __init__(self, model): + super(StorageServers, self).__init__(model) + self.resource = StorageServer + + def get(self): + res_list = [] + params = parse_request() + validate_params(params, self, 'get_list') + get_list = getattr(self.model, model_fn(self, 'get_list')) + res_list = get_list(*self.model_args, **params) + return kimchi.template.render(get_class_name(self), res_list) + + +class StorageServer(Resource): + pass
You also need to expose which values will be returned:
@property def data(self): return self.info
On 2013年12月31日 03:30, Aline Manera wrote: paths only return in storageTarget resource, so this resource does not have any data yet.
At least the ident should be exposed. GET /storageservers should return a list of idents
+ class Config(Resource): def __init__(self, model, id=None): super(Config, self).__init__(model, id) diff --git a/src/kimchi/root.py b/src/kimchi/root.py index c43897c..0f80785 100644 --- a/src/kimchi/root.py +++ b/src/kimchi/root.py @@ -67,6 +67,7 @@ class Root(controller.Resource): self.logout = controller.logout self.debugreports = controller.DebugReports(model) self.plugins = controller.Plugins(model) + self.storageservers = controller.StorageServers(model) self.api_schema = json.load(open(get_api_schema_file()))
def get(self):

From: Royce Lv <lvroyce@linux.vnet.ibm.com> Query all storage pool to retrieve storage server we used. Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/mockmodel.py | 13 +++++++++++++ src/kimchi/model.py | 14 +++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py index 348127a..f53e799 100644 --- a/src/kimchi/mockmodel.py +++ b/src/kimchi/mockmodel.py @@ -405,6 +405,19 @@ class MockModel(object): iso_volumes.append(res) return iso_volumes + def storageservers_get_list(self, target_type): + pools = self.storagepools_get_list() + server_list = [] + for pool in pools: + try: + pool_info = self.storagepool_lookup(pool) + if pool_info['type'] == target_type: + server_list.append(pool_info['source']['addr']) + except NotFoundError: + pass + + return server_list + def dummy_interfaces(self): interfaces = {} ifaces = {"eth1": "nic", "bond0": "bonding", diff --git a/src/kimchi/model.py b/src/kimchi/model.py index 3bc5d6d..20f68f6 100644 --- a/src/kimchi/model.py +++ b/src/kimchi/model.py @@ -1220,6 +1220,19 @@ class Model(object): else: raise + def storageservers_get_list(self, target_type): + pools = self.storagepools_get_list() + server_list = [] + for pool in pools: + try: + pool_info = self.storagepool_lookup(pool) + if pool_info['type'] == target_type: + server_list.append(pool_info['source']['addr']) + except NotFoundError: + pass + + return server_list + def _get_screenshot(self, vm_uuid): with self.objstore as session: try: @@ -1400,7 +1413,6 @@ class LibvirtVMTemplate(VMTemplate): pool.createXML(v['xml'].encode('utf-8'), 0) return vol_list - class LibvirtVMScreenshot(VMScreenshot): def __init__(self, vm_uuid, conn): VMScreenshot.__init__(self, vm_uuid) -- 1.8.1.2

On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Query all storage pool to retrieve storage server we used.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/mockmodel.py | 13 +++++++++++++ src/kimchi/model.py | 14 +++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py index 348127a..f53e799 100644 --- a/src/kimchi/mockmodel.py +++ b/src/kimchi/mockmodel.py @@ -405,6 +405,19 @@ class MockModel(object): iso_volumes.append(res) return iso_volumes
+ def storageservers_get_list(self, target_type): + pools = self.storagepools_get_list() + server_list = [] + for pool in pools: + try: + pool_info = self.storagepool_lookup(pool) + if pool_info['type'] == target_type: + server_list.append(pool_info['source']['addr']) + except NotFoundError: + pass + + return server_list
If any target_type is passed we should return all values
+ def dummy_interfaces(self): interfaces = {} ifaces = {"eth1": "nic", "bond0": "bonding", diff --git a/src/kimchi/model.py b/src/kimchi/model.py index 3bc5d6d..20f68f6 100644 --- a/src/kimchi/model.py +++ b/src/kimchi/model.py @@ -1220,6 +1220,19 @@ class Model(object): else: raise
+ def storageservers_get_list(self, target_type): + pools = self.storagepools_get_list() + server_list = [] + for pool in pools: + try: + pool_info = self.storagepool_lookup(pool) + if pool_info['type'] == target_type: + server_list.append(pool_info['source']['addr']) + except NotFoundError: + pass +
Same as I commented for model.py
+ return server_list + def _get_screenshot(self, vm_uuid): with self.objstore as session: try: @@ -1400,7 +1413,6 @@ class LibvirtVMTemplate(VMTemplate): pool.createXML(v['xml'].encode('utf-8'), 0) return vol_list
- class LibvirtVMScreenshot(VMScreenshot): def __init__(self, vm_uuid, conn): VMScreenshot.__init__(self, vm_uuid)

On 2013年12月31日 03:35, Aline Manera wrote:
On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Query all storage pool to retrieve storage server we used.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/mockmodel.py | 13 +++++++++++++ src/kimchi/model.py | 14 +++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py index 348127a..f53e799 100644 --- a/src/kimchi/mockmodel.py +++ b/src/kimchi/mockmodel.py @@ -405,6 +405,19 @@ class MockModel(object): iso_volumes.append(res) return iso_volumes
+ def storageservers_get_list(self, target_type): + pools = self.storagepools_get_list() + server_list = [] + for pool in pools: + try: + pool_info = self.storagepool_lookup(pool) + if pool_info['type'] == target_type: + server_list.append(pool_info['source']['addr']) + except NotFoundError: + pass + + return server_list
If any target_type is passed we should return all values By all value you mean iscsi servers and nfs servers and other possible remote servers, technically it is easy, temprorily I haven't had a usecase for this yet..
+ def dummy_interfaces(self): interfaces = {} ifaces = {"eth1": "nic", "bond0": "bonding", diff --git a/src/kimchi/model.py b/src/kimchi/model.py index 3bc5d6d..20f68f6 100644 --- a/src/kimchi/model.py +++ b/src/kimchi/model.py @@ -1220,6 +1220,19 @@ class Model(object): else: raise
+ def storageservers_get_list(self, target_type): + pools = self.storagepools_get_list() + server_list = [] + for pool in pools: + try: + pool_info = self.storagepool_lookup(pool) + if pool_info['type'] == target_type: + server_list.append(pool_info['source']['addr']) + except NotFoundError: + pass +
Same as I commented for model.py
+ return server_list + def _get_screenshot(self, vm_uuid): with self.objstore as session: try: @@ -1400,7 +1413,6 @@ class LibvirtVMTemplate(VMTemplate): pool.createXML(v['xml'].encode('utf-8'), 0) return vol_list
- class LibvirtVMScreenshot(VMScreenshot): def __init__(self, vm_uuid, conn): VMScreenshot.__init__(self, vm_uuid)

On 01/02/2014 12:40 AM, Royce Lv wrote:
On 2013年12月31日 03:35, Aline Manera wrote:
On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Query all storage pool to retrieve storage server we used.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/mockmodel.py | 13 +++++++++++++ src/kimchi/model.py | 14 +++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py index 348127a..f53e799 100644 --- a/src/kimchi/mockmodel.py +++ b/src/kimchi/mockmodel.py @@ -405,6 +405,19 @@ class MockModel(object): iso_volumes.append(res) return iso_volumes
+ def storageservers_get_list(self, target_type): + pools = self.storagepools_get_list() + server_list = [] + for pool in pools: + try: + pool_info = self.storagepool_lookup(pool) + if pool_info['type'] == target_type: + server_list.append(pool_info['source']['addr']) + except NotFoundError: + pass + + return server_list
If any target_type is passed we should return all values By all value you mean iscsi servers and nfs servers and other possible remote servers, technically it is easy, temprorily I haven't had a usecase for this yet..
The query param should be optional. It is an additional feature. If user would like to know all servers he can use he can use it.
+ def dummy_interfaces(self): interfaces = {} ifaces = {"eth1": "nic", "bond0": "bonding", diff --git a/src/kimchi/model.py b/src/kimchi/model.py index 3bc5d6d..20f68f6 100644 --- a/src/kimchi/model.py +++ b/src/kimchi/model.py @@ -1220,6 +1220,19 @@ class Model(object): else: raise
+ def storageservers_get_list(self, target_type): + pools = self.storagepools_get_list() + server_list = [] + for pool in pools: + try: + pool_info = self.storagepool_lookup(pool) + if pool_info['type'] == target_type: + server_list.append(pool_info['source']['addr']) + except NotFoundError: + pass +
Same as I commented for model.py
+ return server_list + def _get_screenshot(self, vm_uuid): with self.objstore as session: try: @@ -1400,7 +1413,6 @@ class LibvirtVMTemplate(VMTemplate): pool.createXML(v['xml'].encode('utf-8'), 0) return vol_list
- class LibvirtVMScreenshot(VMScreenshot): def __init__(self, vm_uuid, conn): VMScreenshot.__init__(self, vm_uuid)

于 2014/1/3 0:17, Aline Manera 写道:
On 01/02/2014 12:40 AM, Royce Lv wrote:
On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Query all storage pool to retrieve storage server we used.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/mockmodel.py | 13 +++++++++++++ src/kimchi/model.py | 14 +++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py index 348127a..f53e799 100644 --- a/src/kimchi/mockmodel.py +++ b/src/kimchi/mockmodel.py @@ -405,6 +405,19 @@ class MockModel(object): iso_volumes.append(res) return iso_volumes
+ def storageservers_get_list(self, target_type): + pools = self.storagepools_get_list() + server_list = [] + for pool in pools: + try: + pool_info = self.storagepool_lookup(pool) + if pool_info['type'] == target_type: + server_list.append(pool_info['source']['addr']) + except NotFoundError: + pass + + return server_list
If any target_type is passed we should return all values By all value you mean iscsi servers and nfs servers and other
On 2013年12月31日 03:35, Aline Manera wrote: possible remote servers, technically it is easy, temprorily I haven't had a usecase for this yet..
The query param should be optional. It is an additional feature. If user would like to know all servers he can use he can use it.
I think it is a generic question to validate the parameters. Can we validate the possible value in API.josn? We may have possible value "any", "iSCSI", "netfs", "FC" &etc? I am not necessary asking for "any" value, but I think we can validate the value earlier in the API.
+ def dummy_interfaces(self): interfaces = {} ifaces = {"eth1": "nic", "bond0": "bonding", diff --git a/src/kimchi/model.py b/src/kimchi/model.py index 3bc5d6d..20f68f6 100644 --- a/src/kimchi/model.py +++ b/src/kimchi/model.py @@ -1220,6 +1220,19 @@ class Model(object): else: raise
+ def storageservers_get_list(self, target_type): + pools = self.storagepools_get_list() + server_list = [] + for pool in pools: + try: + pool_info = self.storagepool_lookup(pool) + if pool_info['type'] == target_type: + server_list.append(pool_info['source']['addr']) + except NotFoundError: + pass +
Same as I commented for model.py
+ return server_list + def _get_screenshot(self, vm_uuid): with self.objstore as session: try: @@ -1400,7 +1413,6 @@ class LibvirtVMTemplate(VMTemplate): pool.createXML(v['xml'].encode('utf-8'), 0) return vol_list
- class LibvirtVMScreenshot(VMScreenshot): def __init__(self, vm_uuid, conn): VMScreenshot.__init__(self, vm_uuid)
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel

On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
v3>v4, fix inconsistency between doc and json schema v1>v3, fix racing problem, fix style.
Add parameters to GET request so that we will query storage server as: /storageservers?type=netfs
Royce Lv (5): Support params for GET method Add testcase for GET param Storage server: Update API.md storage server: update controller.py storage server: Update model and mockmodel
docs/API.md | 13 +++++++++++++ src/kimchi/API.json | 11 +++++++++++ src/kimchi/controller.py | 26 ++++++++++++++++++++++++-- src/kimchi/mockmodel.py | 13 +++++++++++++ src/kimchi/model.py | 14 +++++++++++++- src/kimchi/root.py | 1 + tests/test_rest.py | 37 +++++++++++++++++++++++++++++++++++++ 7 files changed, 112 insertions(+), 3 deletions(-)
Let me explain what I expect with this patch set: GET /storageservers will return all storage servers Example: [ {'host': 'localhost', 'target_type': 'netfs', 'sources': ['/srv', '/mnt/isos'], } {'host': '123.234.123.12', 'target_type': 'iscsi', 'sources': ['iqn.2013-06.com.example:iscsi-pool'], } ] GET /storageservers?target_type=<server-type> will return only the storage servers with type <server-type> Example: GET /storageservers?target_type=netfs [ {'host': 'localhost', 'target_type': 'netfs', 'sources': ['/srv', '/mnt/isos'], } ] GET /storageservers/<id> will return data related to this specific server Example: GET /storageservers/localhost {'host': 'localhost', 'target_type': 'netfs', 'sources': ['/srv', '/mnt/isos'], } The 'sources' for netfs, for example, will be the parsed output from "showmount -e <host>" command. So when the user want to create NFS pool with a new server (never used before) POST /storageservers/new-nfs-server {'host': 'new-nfs-server', 'target_type': 'netfs', 'sources': ['/srv', '/mnt'], } Then the user know which paths are available to create the NFS pool Does that make sense for you?

On 2013?12?31? 03:49, Aline Manera wrote:
On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv<lvroyce@linux.vnet.ibm.com>
v3>v4, fix inconsistency between doc and json schema v1>v3, fix racing problem, fix style.
Add parameters to GET request so that we will query storage server as: /storageservers?type=netfs
Royce Lv (5): Support params for GET method Add testcase for GET param Storage server: Update API.md storage server: update controller.py storage server: Update model and mockmodel
docs/API.md | 13 +++++++++++++ src/kimchi/API.json | 11 +++++++++++ src/kimchi/controller.py | 26 ++++++++++++++++++++++++-- src/kimchi/mockmodel.py | 13 +++++++++++++ src/kimchi/model.py | 14 +++++++++++++- src/kimchi/root.py | 1 + tests/test_rest.py | 37 +++++++++++++++++++++++++++++++++++++ 7 files changed, 112 insertions(+), 3 deletions(-)
Let me explain what I expect with this patch set:
GET /storageservers will return all storage servers Example:
[ {'host': 'localhost', 'target_type': 'netfs', 'sources': ['/srv', '/mnt/isos'], } {'host': '123.234.123.12', 'target_type': 'iscsi', 'sources': ['iqn.2013-06.com.example:iscsi-pool'], } ] Aline, as posted inn my RFC patch: [project-kimchi][RFC]Storage backend targets probe I explained, this is to give users a ref when he wants to fill the "host" blank of storagepool creation.
GET /storageservers only returns *servers* we uses as source as storagepool, *targets* will not be covered here. We can return non query parameter results here, but I haven't figured out a usecase for this one. Normally we only create storagepool of a given kind.
GET /storageservers?target_type=<server-type> will return only the storage servers with type <server-type> Example: GET /storageservers?target_type=netfs
[ {'host': 'localhost', 'target_type': 'netfs', 'sources': ['/srv', '/mnt/isos'], } ]
GET /storageservers/<id> will return data related to this specific server Example: GET /storageservers/localhost
{'host': 'localhost', 'target_type': 'netfs', 'sources': ['/srv', '/mnt/isos'], }
Because a host can serve as multiple server(iscsi, gluster, nfs) at same time. So I choose to make user query a specific kind by: GET /storageservers/localhost?target_type=netfs or GET /storageservers/localhost?target_type=iscsi like this. This functionality is covered by [project-kimchi][PATCHv1 0/3] Storage targets support patchset.
The 'sources' for netfs, for example, will be the parsed output from "showmount -e <host>" command.
So when the user want to create NFS pool with a new server (never used before)
POST /storageservers/new-nfs-server
{'host': 'new-nfs-server', 'target_type': 'netfs', 'sources': ['/srv', '/mnt'], }
Then the user know which paths are available to create the NFS pool I don't quite agree... 'POST' to storage server means you want to create a storage server.
When he wants to create a new NFS pool: 1. If he knows his server, he fills it, if not he take a look at used NFS server by: GET /storageservers?target_type=netfs {'localhost', '9.1.1.2', 'a-nfs-server.com'} Then he choose '9.1.1.2' as host 2. Now he manually fills path or query the exposed path by: GET /storageservers/9.1.1.2?target_type=netfs {'type':'nfs', 'targets': ['/a-path', '/b-path'], } He decides to use 'a-path' 3. Then it comes to real storagepool creation by sending request: POST /storagepools {'host': '9.1.1.2', 'path': '/a-path', 'name': 'a-pool'}
Does that make sense for you?

On 01/02/2014 12:32 AM, Royce Lv wrote:
On 2013年12月31日 03:49, Aline Manera wrote:
On 12/30/2013 12:17 AM, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv<lvroyce@linux.vnet.ibm.com>
v3>v4, fix inconsistency between doc and json schema v1>v3, fix racing problem, fix style.
Add parameters to GET request so that we will query storage server as: /storageservers?type=netfs
Royce Lv (5): Support params for GET method Add testcase for GET param Storage server: Update API.md storage server: update controller.py storage server: Update model and mockmodel
docs/API.md | 13 +++++++++++++ src/kimchi/API.json | 11 +++++++++++ src/kimchi/controller.py | 26 ++++++++++++++++++++++++-- src/kimchi/mockmodel.py | 13 +++++++++++++ src/kimchi/model.py | 14 +++++++++++++- src/kimchi/root.py | 1 + tests/test_rest.py | 37 +++++++++++++++++++++++++++++++++++++ 7 files changed, 112 insertions(+), 3 deletions(-)
Let me explain what I expect with this patch set:
GET /storageservers will return all storage servers Example:
[ {'host': 'localhost', 'target_type': 'netfs', 'sources': ['/srv', '/mnt/isos'], } {'host': '123.234.123.12', 'target_type': 'iscsi', 'sources': ['iqn.2013-06.com.example:iscsi-pool'], } ] Aline, as posted inn my RFC patch: [project-kimchi][RFC]Storage backend targets probe I explained, this is to give users a ref when he wants to fill the "host" blank of storagepool creation.
GET /storageservers only returns *servers* we uses as source as storagepool, *targets* will not be covered here. We can return non query parameter results here, but I haven't figured out a usecase for this one. Normally we only create storagepool of a given kind.
GET /storageservers?target_type=<server-type> will return only the storage servers with type <server-type> Example: GET /storageservers?target_type=netfs
[ {'host': 'localhost', 'target_type': 'netfs', 'sources': ['/srv', '/mnt/isos'], } ]
GET /storageservers/<id> will return data related to this specific server Example: GET /storageservers/localhost
{'host': 'localhost', 'target_type': 'netfs', 'sources': ['/srv', '/mnt/isos'], }
Because a host can serve as multiple server(iscsi, gluster, nfs) at same time. So I choose to make user query a specific kind by: GET /storageservers/localhost?target_type=netfs or GET /storageservers/localhost?target_type=iscsi like this.
This functionality is covered by [project-kimchi][PATCHv1 0/3] Storage targets support patchset.
The 'sources' for netfs, for example, will be the parsed output from "showmount -e <host>" command.
So when the user want to create NFS pool with a new server (never used before)
POST /storageservers/new-nfs-server
{'host': 'new-nfs-server', 'target_type': 'netfs', 'sources': ['/srv', '/mnt'], }
Then the user know which paths are available to create the NFS pool I don't quite agree... 'POST' to storage server means you want to create a storage server.
I am thinking the scenario the user will use a new server (never used before) and we should expose the paths to him. So I need to add/create a new storageserver, right? 1) Use entry a new server IP POST /storageserver/new-host 2) Expose the paths of this server GET /storageservers/new-host/storagetargets
When he wants to create a new NFS pool:
1. If he knows his server, he fills it, if not he take a look at used NFS server by: GET /storageservers?target_type=netfs {'localhost', '9.1.1.2', 'a-nfs-server.com'} Then he choose '9.1.1.2' as host
2. Now he manually fills path or query the exposed path by: GET /storageservers/9.1.1.2?target_type=netfs {'type':'nfs', 'targets': ['/a-path', '/b-path'], } He decides to use 'a-path'
3. Then it comes to real storagepool creation by sending request: POST /storagepools {'host': '9.1.1.2', 'path': '/a-path', 'name': 'a-pool'}
Does that make sense for you?
participants (4)
-
Aline Manera
-
lvroyce@linux.vnet.ibm.com
-
Royce Lv
-
Shu Ming