From b69508b230f6a0e883660014ab9a825d6392c9a4 Mon Sep 17 00:00:00 2001 From: JamFuller Date: Tue, 14 Jun 2016 14:20:09 +0200 Subject: [PATCH] prelim status support --- marklogic/connection.py | 21 ++++- marklogic/models/cluster.py | 44 ++++++++++ marklogic/models/database/__init__.py | 21 +++++ marklogic/models/forest/__init__.py | 29 +++++++ marklogic/models/group/__init__.py | 21 +++++ marklogic/models/host.py | 22 +++++ marklogic/models/server/__init__.py | 22 +++++ tests/test_views.py | 119 ++++++++++++++++++++++++++ 8 files changed, 297 insertions(+), 2 deletions(-) create mode 100644 tests/test_views.py diff --git a/marklogic/connection.py b/marklogic/connection.py index 6b7dca4..f93f899 100644 --- a/marklogic/connection.py +++ b/marklogic/connection.py @@ -102,12 +102,29 @@ def client_uri(self, path, protocol=None, host=None, port=None, version=None): return uri + def view_uri(self, path, protocol=None, host=None, port=None, version=None, view=None): + if protocol is None: + protocol = self.protocol + if host is None: + host = self.host + if port is None: + port = self.port + if version is None: + version = self.client_version + if view is None: + view = "default" + + uri = "{0}://{1}:{2}/manage/{3}/{4}?view={5}" \ + .format(protocol, host, port, version, path, view) + + return uri + def head(self, uri, accept="application/json"): self.logger.debug("HEAD {0}...".format(uri)) self.response = requests.head(uri, auth=self.auth) return self._response() - def get(self, uri, accept="application/json", headers=None): + def get(self, uri, accept="application/json", headers=None, parameters=None): if headers is None: headers = {'accept': accept} else: @@ -117,7 +134,7 @@ def get(self, uri, accept="application/json", headers=None): self.payload_logger.debug("Headers:") self.payload_logger.debug(json.dumps(headers, indent=2)) - self.response = requests.get(uri, auth=self.auth, headers=headers) + self.response = requests.get(uri, auth=self.auth, headers=headers, params=parameters) return self._response() def post(self, uri, payload=None, etag=None, headers=None, diff --git a/marklogic/models/cluster.py b/marklogic/models/cluster.py index 46eb595..14132f4 100644 --- a/marklogic/models/cluster.py +++ b/marklogic/models/cluster.py @@ -31,6 +31,7 @@ from marklogic.models.model import Model from marklogic.models.host import Host from marklogic.exceptions import UnexpectedManagementAPIResponse +from marklogic.utilities.validators import ValidationError class LocalCluster(Model): @@ -297,6 +298,27 @@ def set_cluster_name(self, value): self._validate(value, 'string') return self._set_config_property('cluster-name', value) + @classmethod + def get_status_view(self, connection, name=None): + version = connection.version + port = connection.port + protocol = connection.protocol + if name == None: + viewuri = connection.view_uri(version=version,port=port,path="", protocol=protocol,view="status") + else: + viewuri = connection.view_uri(version=version,port=port,path="clusters/"+name, protocol=protocol,view="status") + return connection.get(viewuri, accept="application/json") + + @classmethod + def get_metric_view(self, connection, name=None): + version = connection.version + port = connection.port + protocol = connection.protocol + if name == None: + viewuri = connection.view_uri(version=version,port=port,path="", protocol=protocol,view="metrics") + else: + viewuri = connection.view_uri(version=version,port=port,path="clusters/"+name, protocol=protocol,view="metrics") + return connection.get(viewuri, accept="application/json") class ForeignCluster(Model): """ @@ -560,6 +582,28 @@ def set_xdqp_ssl_ciphers(self, value): self._validate(value, 'string') return self._set_config_property('xdqp-ssl-ciphers', value) + @classmethod + def get_status_view(self, connection, name=None): + version = connection.version + port = connection.port + protocol = connection.protocol + if name == None: + raise ValidationError("ForeignCluster name expected.") + else: + viewuri = connection.view_uri(version=version,port=port,path="clusters/"+name, protocol=protocol,view="status") + return connection.get(viewuri, accept="application/json") + + @classmethod + def get_metric_view(self, connection, name=None): + version = connection.version + port = connection.port + protocol = connection.protocol + if name == None: + viewuri = connection.view_uri(version=version,port=port,path="clusters", protocol=protocol,view="metrics") + else: + viewuri = connection.view_uri(version=version,port=port,path="clusters/"+name, protocol=protocol,view="metrics") + return connection.get(viewuri, accept="application/json") + class BootstrapHost(Model): """ diff --git a/marklogic/models/database/__init__.py b/marklogic/models/database/__init__.py index 39f0c83..d24fb57 100644 --- a/marklogic/models/database/__init__.py +++ b/marklogic/models/database/__init__.py @@ -3924,3 +3924,24 @@ def get_document(self, connection, document_uri, content_type='*/*'): else: raise UnexpectedAPIResponse(response.text) + @classmethod + def get_status_view(self, connection, name=None): + version = connection.version + port = connection.port + protocol = connection.protocol + if name == None: + raise ValidationError("Database name expected.") + else: + viewuri = connection.view_uri(version=version,port=port,path="databases/"+name, protocol=protocol,view="status") + return connection.get(viewuri, accept="application/json") + + @classmethod + def get_metric_view(self, connection, name=None): + version = connection.version + port = connection.port + protocol = connection.protocol + if name == None: + viewuri = connection.view_uri(version=version,port=port,path="databases", protocol=protocol,view="metrics") + else: + viewuri = connection.view_uri(version=version,port=port,path="databases/"+name, protocol=protocol,view="metrics") + return connection.get(viewuri, accept="application/json") diff --git a/marklogic/models/forest/__init__.py b/marklogic/models/forest/__init__.py index c6c3d4a..15665b2 100644 --- a/marklogic/models/forest/__init__.py +++ b/marklogic/models/forest/__init__.py @@ -455,3 +455,32 @@ def marshal(self): else: struct[key] = self._config[key]; return struct + + @classmethod + def get_status_view(self, connection, name=None): + version = connection.version + port = connection.port + protocol = connection.protocol + if name == None: + viewuri = connection.view_uri(version=version,port=port,path="forests", protocol=protocol,view="status") + else: + viewuri = connection.view_uri(version=version,port=port,path="forests/"+name, protocol=protocol,view="status") + return connection.get(viewuri, accept="application/json") + + @classmethod + def get_metric_view(self, connection, name=None, period=None, start=None, end=None, detail=None, summary=None): + version = connection.version + port = connection.port + protocol = connection.protocol + params = {} + if period: + params.update({'period':period}) + if summary: + params.update({'summary':summary}) + if detail: + params.update({'detail':detail}) + if name == None: + viewuri = connection.view_uri(version=version,port=port,path="forests", protocol=protocol,view="metrics") + else: + viewuri = connection.view_uri(version=version,port=port,path="forests/"+name, protocol=protocol,view="metrics") + return connection.get(viewuri, accept="application/json",parameters=params) diff --git a/marklogic/models/group/__init__.py b/marklogic/models/group/__init__.py index 66340b6..a0eb581 100644 --- a/marklogic/models/group/__init__.py +++ b/marklogic/models/group/__init__.py @@ -1138,3 +1138,24 @@ def set_retry_timeout(self,value): self._validate(value, {'max': 4294967295, 'min': 0}) return self._set_config_property('retry-timeout', value) + @classmethod + def get_status_view(self, connection, name=None): + version = connection.version + port = connection.port + protocol = connection.protocol + if name == None: + raise ValidationError("Group name expected.") + else: + viewuri = connection.view_uri(version=version,port=port,path="groups/"+name, protocol=protocol,view="status") + return connection.get(viewuri, accept="application/json") + + @classmethod + def get_metric_view(self, connection, name=None): + version = connection.version + port = connection.port + protocol = connection.protocol + if name == None: + viewuri = connection.view_uri(version=version,port=port,path="groups", protocol=protocol,view="metrics") + else: + viewuri = connection.view_uri(version=version,port=port,path="groups/"+name, protocol=protocol,view="metrics") + return connection.get(viewuri, accept="application/json") diff --git a/marklogic/models/host.py b/marklogic/models/host.py index c7824d1..605e439 100644 --- a/marklogic/models/host.py +++ b/marklogic/models/host.py @@ -307,3 +307,25 @@ def _post_cluster_config(self, cfgzip, connection): raise UnexpectedManagementAPIResponse(response.text) data = json.loads(response.text) + + @classmethod + def get_status_view(self, connection, name=None): + version = connection.version + port = connection.port + protocol = connection.protocol + if name == None: + viewuri = connection.view_uri(version=version,port=port,path="hosts", protocol=protocol,view="status") + else: + viewuri = connection.view_uri(version=version,port=port,path="hosts/"+name, protocol=protocol,view="status") + return connection.get(viewuri, accept="application/json") + + @classmethod + def get_metric_view(self, connection, name=None): + version = connection.version + port = connection.port + protocol = connection.protocol + if name == None: + viewuri = connection.view_uri(version=version,port=port,path="hosts", protocol=protocol,view="metrics") + else: + viewuri = connection.view_uri(version=version,port=port,path="hosts/"+name, protocol=protocol,view="metrics") + return connection.get(viewuri, accept="application/json") diff --git a/marklogic/models/server/__init__.py b/marklogic/models/server/__init__.py index 9bea453..15112f5 100644 --- a/marklogic/models/server/__init__.py +++ b/marklogic/models/server/__init__.py @@ -1624,6 +1624,28 @@ def marshal(self): struct[key] = self._config[key]; return struct + @classmethod + def get_status_view(self, connection, name=None, group=None): + version = connection.version + port = connection.port + protocol = connection.protocol + if name == None: + viewuri = connection.view_uri(version=version,port=port,path="servers", protocol=protocol,view="status") + else: + viewuri = connection.view_uri(version=version,port=port,path="servers/"+name, protocol=protocol,view="status&group-id="+group) + return connection.get(viewuri, accept="application/json") + + @classmethod + def get_metric_view(self, connection, name=None, group=None): + version = connection.version + port = connection.port + protocol = connection.protocol + if name == None: + viewuri = connection.view_uri(version=version,port=port,path="servers", protocol=protocol,view="metrics") + else: + viewuri = connection.view_uri(version=version,port=port,path="servers/"+name, protocol=protocol,view="metrics&group-id="+group) + return connection.get(viewuri, accept="application/json") + class HttpServer(Server): def __init__(self, name, group="Default", port=None, root=None, content_db_name=None, modules_db_name=None, diff --git a/tests/test_views.py b/tests/test_views.py new file mode 100644 index 0000000..671971b --- /dev/null +++ b/tests/test_views.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2015 MarkLogic Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0# +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# File History +# ------------ +# +# James Fuller 12 Jun 2016 Initial development +# +import json +from mlconfig import MLConfig +from marklogic.models.amp import Amp +from marklogic.exceptions import UnexpectedManagementAPIResponse +from marklogic.models.cluster import LocalCluster,ForeignCluster +from marklogic.models import Forest,Database,Server,Host + +class TestView(MLConfig): + + def test__connection_view_uri(self): + connection = self.connection + viewuri = connection.view_uri(version="v2",port=8002,path="forests", protocol="http",view="status") + assert viewuri == "http://localhost:8002/manage/v2/forests?view=status" + + def test__connection_status_view(self): + connection = self.connection + viewuri = connection.view_uri(version="v2",port=8002,path="forests", protocol="http",view="status") + response = connection.get(viewuri, accept="application/json") + assert response.status_code == 200 + assert response.json()["forest-status-list"]["meta"]["uri"] == "/manage/v2/forests?view=status" + assert response.json()["forest-status-list"]["status-list-summary"]["total-forests"] + + def test__connection_metrics_view(self): + connection = self.connection + viewuri = connection.view_uri(version="v2",port=8002,path="forests", protocol="http",view="metrics") + response = connection.get(viewuri, accept="application/json") + assert response.status_code == 200 + assert response.json()["forest-metrics-list"]["meta"]["uri"] == "/manage/v2/forests?view=metrics" + assert response.json()["forest-metrics-list"]["metrics-relations"]["forest-metrics-list"]["metrics"][0]["active-fragment-count"]["name"] == "active-fragment-count" + def test__model_get_all_forest_status(self): + connection = self.connection + response = Forest.get_status_view(connection) + assert response.status_code == 200 + assert response.json()["forest-status-list"]["status-list-summary"]["total-forests"] + + def test__model_get_all_forest_metrics(self): + connection = self.connection + response = Forest.get_metric_view(connection,period="hour",summary="false",detail="false") + assert response.status_code == 200 + #assert response.json()["forest-metrics-list"]["meta"]["uri"] == "/manage/v2/forests?view=metrics&detail=false&period=hour&summary=false" + assert response.json()["forest-metrics-list"]["metric-properties"]["period"] == "hour" + assert response.json()["forest-metrics-list"]["metric-properties"]["summary"] == "false" + assert response.json()["forest-metrics-list"]["metric-properties"]["detail"] == "false" + assert response.json()["forest-metrics-list"]["metrics-relations"]["forest-metrics-list"]["metrics"][0]["active-fragment-count"]["name"] == "active-fragment-count" + + def test__model_get_specific_forest_status(self): + connection = self.connection + response = Forest.get_status_view(connection,name="Documents") + assert response.status_code == 200 + assert response.json()["forest-status"]["name"] + + def test__model_get_specific_database_status(self): + connection = self.connection + response = Database.get_status_view(connection,"Documents") + assert response.status_code == 200 + assert response.json()["database-status"] + + # def test__model_get_specific_group_status(self): + # connection = self.connection + # response = Group.get_status_view(connection,"Default") + # assert response.status_code == 200 + # assert response.json()["group-status"] + + def test__model_get_server_status(self): + connection = self.connection + response = Server.get_status_view(connection) + assert response.status_code == 200 + assert response.json()["server-status-list"] + + def test__model_get_specific_server_status(self): + connection = self.connection + response = Server.get_status_view(connection,"Manage","Default") + assert response.status_code == 200 + assert response.json()["server-status"] + + def test__model_get_host_status(self): + connection = self.connection + response = Host.get_status_view(connection) + assert response.status_code == 200 + assert response.json()["host-status-list"] + + def test__model_get_specific_host_status(self): + connection = self.connection + response = Host.get_status_view(connection,"127.0.0.1") + assert response.status_code == 200 + assert response.json()["host-status"] + + def test__model_get_local_cluster_status(self): + connection = self.connection + response = LocalCluster.get_status_view(connection) + assert response.status_code == 200 + assert response.json()["local-cluster-status"] + + # def test__model_get_specific_foreign_cluster_status(self): + # connection = self.connection + # response = ForeignCluster.get_status_view(connection) + # assert response.status_code == 200 + # assert response.json()["local-cluster-status"]