From 37a58d35e89b853a5738195436afbdb43e4e5ac8 Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Thu, 25 Jun 2020 11:38:30 -0400 Subject: [PATCH] Implement limiting of node output Closes #98 --- api-daemon/pvcapid/flaskapi.py | 27 +++++++++++++++++++++++++-- api-daemon/pvcapid/helper.py | 4 ++-- client-cli/cli_lib/node.py | 16 ++++++++++++++-- client-cli/pvc.py | 22 +++++++++++++++++++--- daemon-common/node.py | 16 +++++++++++++++- docs/manuals/swagger.json | 21 +++++++++++++++++++++ 6 files changed, 96 insertions(+), 10 deletions(-) diff --git a/api-daemon/pvcapid/flaskapi.py b/api-daemon/pvcapid/flaskapi.py index 001de8b2..e64c69c8 100755 --- a/api-daemon/pvcapid/flaskapi.py +++ b/api-daemon/pvcapid/flaskapi.py @@ -454,7 +454,10 @@ api.add_resource(API_Status, '/status') # /node class API_Node_Root(Resource): @RequestParser([ - { 'name': 'limit' } + { 'name': 'limit' }, + { 'name': 'daemon_state' }, + { 'name': 'coordinator_state' }, + { 'name': 'domain_state' } ]) @Authenticator def get(self, reqargs): @@ -532,6 +535,21 @@ class API_Node_Root(Resource): type: string required: false description: A search limit; fuzzy by default, use ^/$ to force exact matches + - in: query + name: daemon_state + type: string + required: false + description: Limit results to nodes in the specified daemon state + - in: query + name: coordinator_state + type: string + required: false + description: Limit results to nodes in the specified coordinator state + - in: query + name: domain_state + type: string + required: false + description: Limit results to nodes in the specified domain state responses: 200: description: OK @@ -540,7 +558,12 @@ class API_Node_Root(Resource): items: $ref: '#/definitions/node' """ - return api_helper.node_list(reqargs.get('limit', None)) + return api_helper.node_list( + limit=reqargs.get('limit', None), + daemon_state=reqargs.get('daemon_state', None), + coordinator_state=reqargs.get('coordinator_state', None), + domain_state=reqargs.get('domain_state', None) + ) api.add_resource(API_Node_Root, '/node') # /node/ diff --git a/api-daemon/pvcapid/helper.py b/api-daemon/pvcapid/helper.py index 4659b8d2..a2b19757 100755 --- a/api-daemon/pvcapid/helper.py +++ b/api-daemon/pvcapid/helper.py @@ -114,12 +114,12 @@ def cluster_maintenance(maint_state='false'): # # Node functions # -def node_list(limit=None, is_fuzzy=True): +def node_list(limit=None, daemon_state=None, coordinator_state=None, domain_state=None, is_fuzzy=True): """ Return a list of nodes with limit LIMIT. """ zk_conn = pvc_common.startZKConnection(config['coordinators']) - retflag, retdata = pvc_node.get_list(zk_conn, limit, is_fuzzy=is_fuzzy) + retflag, retdata = pvc_node.get_list(zk_conn, limit, daemon_state=daemon_state, coordinator_state=coordinator_state, domain_state=domain_state, is_fuzzy=is_fuzzy) pvc_common.stopZKConnection(zk_conn) if retflag: diff --git a/client-cli/cli_lib/node.py b/client-cli/cli_lib/node.py index 7f63841b..93338dd7 100644 --- a/client-cli/cli_lib/node.py +++ b/client-cli/cli_lib/node.py @@ -82,7 +82,7 @@ def node_info(config, node): else: return False, response.json()['message'] -def node_list(config, limit): +def node_list(config, limit, target_daemon_state, target_coordinator_state, target_domain_state): """ Get list information about nodes (limited by {limit}) @@ -93,6 +93,12 @@ def node_list(config, limit): params = dict() if limit: params['limit'] = limit + if target_daemon_state: + params['daemon_state'] = target_daemon_state + if target_coordinator_state: + params['coordinator_state'] = target_coordinator_state + if target_domain_state: + params['domain_state'] = target_domain_state response = call_api(config, 'get', '/node', params=params) @@ -161,11 +167,17 @@ def format_info(node_information, long_output): ainformation.append('') return '\n'.join(ainformation) -def format_list(node_list): +def format_list(node_list, raw): # Handle single-element lists if not isinstance(node_list, list): node_list = [ node_list ] + if raw: + ainformation = list() + for node in sorted(item['name'] for item in node_list): + ainformation.append(node) + return '\n'.join(ainformation) + node_list_output = [] # Determine optimal column widths diff --git a/client-cli/pvc.py b/client-cli/pvc.py index 3ab2526a..5b07c473 100755 --- a/client-cli/pvc.py +++ b/client-cli/pvc.py @@ -525,15 +525,31 @@ def node_info(node, long_output): @click.argument( 'limit', default=None, required=False ) +@click.option( + '-ds', '--daemon-state', 'target_daemon_state', default=None, + help='Limit list to nodes in the specified daemon state.' +) +@click.option( + '-cs', '--coordinator-state', 'target_coordinator_state', default=None, + help='Limit list to nodes in the specified coordinator state.' +) +@click.option( + '-vs', '--domain-state', 'target_domain_state', default=None, + help='Limit list to nodes in the specified domain state.' +) +@click.option( + '-r', '--raw', 'raw', is_flag=True, default=False, + help='Display the raw list of node names only.' +) @cluster_req -def node_list(limit): +def node_list(limit, target_daemon_state, target_coordinator_state, target_domain_state, raw): """ List all nodes; optionally only match names matching regex LIMIT. """ - retcode, retdata = pvc_node.node_list(config, limit) + retcode, retdata = pvc_node.node_list(config, limit, target_daemon_state, target_coordinator_state, target_domain_state) if retcode: - retdata = pvc_node.format_list(retdata) + retdata = pvc_node.format_list(retdata, raw) cleanup(retcode, retdata) ############################################################################### diff --git a/daemon-common/node.py b/daemon-common/node.py index 9cf2524e..153dec56 100644 --- a/daemon-common/node.py +++ b/daemon-common/node.py @@ -193,7 +193,7 @@ def get_info(zk_conn, node): return True, node_information -def get_list(zk_conn, limit, is_fuzzy=True): +def get_list(zk_conn, limit, daemon_state=None, coordinator_state=None, domain_state=None, is_fuzzy=True): node_list = [] full_node_list = zkhandler.listchildren(zk_conn, '/nodes') @@ -210,6 +210,20 @@ def get_list(zk_conn, limit, is_fuzzy=True): else: node_list.append(getNodeInformation(zk_conn, node)) + if daemon_state or coordinator_state or domain_state: + limited_node_list = [] + for node in node_list: + add_node = False + if daemon_state and node['daemon_state'] == daemon_state: + add_node = True + if coordinator_state and node['coordinator_state'] == coordinator_state: + add_node = True + if domain_state and node['domain_state'] == domain_state: + add_node = True + if add_node: + limited_node_list.append(node) + node_list = limited_node_list + return True, node_list # diff --git a/docs/manuals/swagger.json b/docs/manuals/swagger.json index 5bc79e2a..f37908c7 100644 --- a/docs/manuals/swagger.json +++ b/docs/manuals/swagger.json @@ -2098,6 +2098,27 @@ "name": "limit", "required": false, "type": "string" + }, + { + "description": "Limit results to nodes in the specified daemon state", + "in": "query", + "name": "daemon_state", + "required": false, + "type": "string" + }, + { + "description": "Limit results to nodes in the specified coordinator state", + "in": "query", + "name": "coordinator_state", + "required": false, + "type": "string" + }, + { + "description": "Limit results to nodes in the specified domain state", + "in": "query", + "name": "domain_state", + "required": false, + "type": "string" } ], "responses": {