Skip to content

Commit a9a465a

Browse files
committed
Add support for replication and cluster API
1 parent 412d584 commit a9a465a

33 files changed

+3255
-1144
lines changed

arango/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
from arango.client import ArangoClient # noqa: F401
22
from arango.exceptions import * # noqa: F401 F403
33
from arango.http import * # noqa: F401 F403
4-
from . import errno # noqa: F401
4+
import arango.errno as errno # noqa: F401

arango/api.py

+9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ def __init__(self, connection, executor):
1616
self._conn = connection
1717
self._executor = executor
1818

19+
@property
20+
def conn(self):
21+
"""Return HTTP connection object.
22+
23+
:return: HTTP connection.
24+
:rtype: arango.connection.Connection
25+
"""
26+
return self._conn
27+
1928
@property
2029
def db_name(self):
2130
"""Return the name of the current database.

arango/aql.py

+11-67
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121
AQLCacheConfigureError,
2222
AQLCachePropertiesError
2323
)
24+
from arango.formatter import (
25+
format_aql_cache,
26+
format_aql_query,
27+
format_aql_tracking
28+
)
2429
from arango.request import Request
2530

2631

@@ -39,45 +44,6 @@ def __init__(self, connection, executor):
3944
def __repr__(self):
4045
return '<AQL in {}>'.format(self._conn.db_name)
4146

42-
# noinspection PyMethodMayBeStatic
43-
def _format_tracking_properties(self, body):
44-
"""Format the tracking properties.
45-
46-
:param body: Response body.
47-
:type body: dict
48-
:return: Formatted body.
49-
:rtype: dict
50-
"""
51-
body.pop('code', None)
52-
body.pop('error', None)
53-
if 'maxQueryStringLength' in body:
54-
body['max_query_string_length'] = body.pop('maxQueryStringLength')
55-
if 'maxSlowQueries' in body:
56-
body['max_slow_queries'] = body.pop('maxSlowQueries')
57-
if 'slowQueryThreshold' in body:
58-
body['slow_query_threshold'] = body.pop('slowQueryThreshold')
59-
if 'trackBindVars' in body:
60-
body['track_bind_vars'] = body.pop('trackBindVars')
61-
if 'trackSlowQueries' in body:
62-
body['track_slow_queries'] = body.pop('trackSlowQueries')
63-
return body
64-
65-
# noinspection PyMethodMayBeStatic
66-
def _format_queries(self, body):
67-
"""Format the list of queries.
68-
69-
:param body: Response body.
70-
:type body: dict
71-
:return: Formatted body.
72-
:rtype: dict
73-
"""
74-
for query in body:
75-
if 'bindVars' in query:
76-
query['bind_vars'] = query.pop('bindVars')
77-
if 'runTime' in query:
78-
query['runtime'] = query.pop('runTime')
79-
return body
80-
8147
@property
8248
def cache(self):
8349
"""Return the query cache API wrapper.
@@ -359,7 +325,7 @@ def queries(self):
359325
def response_handler(resp):
360326
if not resp.is_success:
361327
raise AQLQueryListError(resp, request)
362-
return self._format_queries(resp.body)
328+
return [format_aql_query(q) for q in resp.body]
363329

364330
return self._execute(request, response_handler)
365331

@@ -378,7 +344,7 @@ def slow_queries(self):
378344
def response_handler(resp):
379345
if not resp.is_success:
380346
raise AQLQueryListError(resp, request)
381-
return self._format_queries(resp.body)
347+
return [format_aql_query(q) for q in resp.body]
382348

383349
return self._execute(request, response_handler)
384350

@@ -416,7 +382,7 @@ def tracking(self):
416382
def response_handler(resp):
417383
if not resp.is_success:
418384
raise AQLQueryTrackingGetError(resp, request)
419-
return self._format_tracking_properties(resp.body)
385+
return format_aql_tracking(resp.body)
420386

421387
return self._execute(request, response_handler)
422388

@@ -456,7 +422,7 @@ def set_tracking(self,
456422
def response_handler(resp):
457423
if not resp.is_success:
458424
raise AQLQueryTrackingSetError(resp, request)
459-
return self._format_tracking_properties(resp.body)
425+
return format_aql_tracking(resp.body)
460426

461427
return self._execute(request, response_handler)
462428

@@ -554,28 +520,6 @@ class AQLQueryCache(APIWrapper):
554520
def __repr__(self):
555521
return '<AQLQueryCache in {}>'.format(self._conn.db_name)
556522

557-
# noinspection PyMethodMayBeStatic
558-
def _format_cache_properties(self, body):
559-
"""Format the query cache properties.
560-
561-
:param body: Response body.
562-
:type body: dict
563-
:return: Formatted body.
564-
:rtype: dict
565-
"""
566-
body.pop('code', None)
567-
body.pop('error', None)
568-
569-
if 'maxResults' in body:
570-
body['max_results'] = body.pop('maxResults')
571-
if 'maxResultsSize' in body:
572-
body['max_results_size'] = body.pop('maxResultsSize')
573-
if 'maxEntrySize' in body:
574-
body['max_entry_size'] = body.pop('maxEntrySize')
575-
if 'includeSystem' in body:
576-
body['include_system'] = body.pop('includeSystem')
577-
return body
578-
579523
def properties(self):
580524
"""Return the query cache properties.
581525
@@ -591,7 +535,7 @@ def properties(self):
591535
def response_handler(resp):
592536
if not resp.is_success:
593537
raise AQLCachePropertiesError(resp, request)
594-
return self._format_cache_properties(resp.body)
538+
return format_aql_cache(resp.body)
595539

596540
return self._execute(request, response_handler)
597541

@@ -642,7 +586,7 @@ def configure(self,
642586
def response_handler(resp):
643587
if not resp.is_success:
644588
raise AQLCacheConfigureError(resp, request)
645-
return self._format_cache_properties(resp.body)
589+
return format_aql_cache(resp.body)
646590

647591
return self._execute(request, response_handler)
648592

arango/cluster.py

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
from __future__ import absolute_import, unicode_literals
2+
3+
__all__ = ['Cluster']
4+
5+
from arango.api import APIWrapper
6+
from arango.exceptions import (
7+
ClusterHealthError,
8+
ClusterMaintenanceModeError,
9+
ClusterServerIDError,
10+
ClusterServerRoleError,
11+
ClusterStatisticsError,
12+
)
13+
from arango.request import Request
14+
15+
16+
class Cluster(APIWrapper): # pragma: no cover
17+
18+
def __init__(self, connection, executor):
19+
super(Cluster, self).__init__(connection, executor)
20+
21+
def server_id(self):
22+
"""Return the server ID.
23+
24+
:return: Server ID.
25+
:rtype: str | unicode
26+
:raise arango.exceptions.ClusterServerIDError: If retrieval fails.
27+
"""
28+
request = Request(
29+
method='get',
30+
endpoint='/_admin/server/id'
31+
)
32+
33+
def response_handler(resp):
34+
if resp.is_success:
35+
return resp.body['id']
36+
raise ClusterServerIDError(resp, request)
37+
38+
return self._execute(request, response_handler)
39+
40+
def server_role(self):
41+
"""Return the server role.
42+
43+
:return: Server role. Possible values are "SINGLE" (server which is
44+
not in a cluster), "COORDINATOR" (cluster coordinator), "PRIMARY",
45+
"SECONDARY", "AGENT" (Agency node in a cluster) or "UNDEFINED".
46+
:rtype: str | unicode
47+
:raise arango.exceptions.ClusterServerRoleError: If retrieval fails.
48+
"""
49+
request = Request(
50+
method='get',
51+
endpoint='/_admin/server/role'
52+
)
53+
54+
def response_handler(resp):
55+
if resp.is_success:
56+
return resp.body['role']
57+
raise ClusterServerRoleError(resp, request)
58+
59+
return self._execute(request, response_handler)
60+
61+
def statistics(self, server_id):
62+
"""Return the cluster statistics for the given server.
63+
64+
:param server_id: Server ID.
65+
:type server_id: str | unicode
66+
:return: Cluster statistics for the given server.
67+
:rtype: dict
68+
:raise arango.exceptions.ClusterStatisticsError: If retrieval fails.
69+
"""
70+
request = Request(
71+
method='get',
72+
endpoint='/_admin/clusterStatistics',
73+
params={'DBserver': server_id}
74+
)
75+
76+
def response_handler(resp):
77+
if resp.is_success:
78+
return resp.body
79+
raise ClusterStatisticsError(resp, request)
80+
81+
return self._execute(request, response_handler)
82+
83+
def health(self):
84+
"""Return the cluster health.
85+
86+
:return: Cluster health.
87+
:rtype: dict
88+
:raise arango.exceptions.ClusterHealthError: If retrieval fails.
89+
"""
90+
request = Request(
91+
method='get',
92+
endpoint='/_admin/cluster/health',
93+
)
94+
95+
def response_handler(resp):
96+
if resp.is_success:
97+
resp.body.pop('error')
98+
resp.body.pop('code')
99+
return resp.body
100+
raise ClusterHealthError(resp, request)
101+
102+
return self._execute(request, response_handler)
103+
104+
def toggle_maintenance_mode(self, mode):
105+
"""Enable or disable the cluster supervision (agency) maintenance mode.
106+
107+
:param mode: Maintenance mode. Allowed values are "on" and "off".
108+
:type mode: str | unicode
109+
:return: Result of the operation.
110+
:rtype: dict
111+
:raise arango.exceptions.ClusterMaintenanceModeError: If toggle fails.
112+
"""
113+
request = Request(
114+
method='put',
115+
endpoint='/_admin/cluster/maintenance',
116+
data='"{}"'.format(mode)
117+
)
118+
119+
def response_handler(resp):
120+
if resp.is_success:
121+
return resp.body
122+
raise ClusterMaintenanceModeError(resp, request)
123+
124+
return self._execute(request, response_handler)

0 commit comments

Comments
 (0)