Skip to content

Commit 70070fe

Browse files
authored
Saimon/override timeout tcp connect (#302)
1 parent 0a62490 commit 70070fe

File tree

5 files changed

+75
-45
lines changed

5 files changed

+75
-45
lines changed

cterasdk/clients/async_requests.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,15 @@ class BaseRequest:
103103
def __init__(self, method, url, **kwargs):
104104
self.method = method
105105
self.url = url
106-
self.kwargs = kwargs
106+
self.kwargs = BaseRequest.accept(**kwargs)
107+
108+
@staticmethod
109+
def accept(**kwargs):
110+
timeout = kwargs.get('timeout', None)
111+
if timeout:
112+
logger.debug('Setting request timeout. %s', timeout)
113+
kwargs['timeout'] = aiohttp.ClientTimeout(**timeout)
114+
return kwargs
107115

108116

109117
class GetRequest(BaseRequest):

cterasdk/clients/clients.py

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -59,31 +59,31 @@ async def download(self, path, **kwargs):
5959
return await super().get(path, on_error=XMLHandler(), **kwargs)
6060

6161
@decorators.authenticated
62-
async def propfind(self, path, depth):
63-
request = async_requests.PropfindRequest(self._builder(path), headers={'depth': str(depth)})
62+
async def propfind(self, path, depth, **kwargs):
63+
request = async_requests.PropfindRequest(self._builder(path), headers={'depth': str(depth)}, **kwargs)
6464
response = await self.a_request(request, on_error=XMLHandler())
6565
return await response.dav()
6666

6767
@decorators.authenticated
68-
async def mkcol(self, path):
69-
request = async_requests.MkcolRequest(self._builder(path))
68+
async def mkcol(self, path, **kwargs):
69+
request = async_requests.MkcolRequest(self._builder(path), **kwargs)
7070
response = await self.a_request(request, on_error=XMLHandler())
7171
return await response.text()
7272

7373
@decorators.authenticated
74-
async def copy(self, source, destination, *, overwrite=False):
75-
request = async_requests.CopyRequest(self._builder(source), headers=self._webdav_headers(destination, overwrite))
74+
async def copy(self, source, destination, *, overwrite=False, **kwargs):
75+
request = async_requests.CopyRequest(self._builder(source), headers=self._webdav_headers(destination, overwrite), **kwargs)
7676
response = await self.a_request(request, on_error=XMLHandler())
7777
return await response.xml()
7878

7979
@decorators.authenticated
80-
async def move(self, source, destination, *, overwrite=False):
81-
request = async_requests.MoveRequest(self._builder(source), headers=self._webdav_headers(destination, overwrite))
80+
async def move(self, source, destination, *, overwrite=False, **kwargs):
81+
request = async_requests.MoveRequest(self._builder(source), headers=self._webdav_headers(destination, overwrite), **kwargs)
8282
response = await self.a_request(request, on_error=XMLHandler())
8383
return await response.xml()
8484

85-
async def delete(self, path): # pylint: disable=arguments-differ
86-
response = await super().delete(path, on_error=XMLHandler())
85+
async def delete(self, path, **kwargs): # pylint: disable=arguments-differ
86+
response = await super().delete(path, on_error=XMLHandler(), **kwargs)
8787
return await response.text()
8888

8989
def _webdav_headers(self, destination, overwrite):
@@ -138,21 +138,21 @@ async def delete(self, path, **kwargs):
138138
class AsyncExtended(AsyncXML):
139139
"""CTERA Schema"""
140140

141-
async def get_multi(self, path, paths):
142-
return await self.database(path, 'get-multi', paths)
141+
async def get_multi(self, path, paths, **kwargs):
142+
return await self.database(path, 'get-multi', paths, **kwargs)
143143

144-
async def execute(self, path, name, param=None): # schema method
145-
return await self._execute(path, 'user-defined', name, param)
144+
async def execute(self, path, name, param=None, **kwargs): # schema method
145+
return await self._execute(path, 'user-defined', name, param, **kwargs)
146146

147-
async def database(self, path, name, param=None): # schema method
148-
return await self._execute(path, 'db', name, param)
147+
async def database(self, path, name, param=None, **kwargs): # schema method
148+
return await self._execute(path, 'db', name, param, **kwargs)
149149

150-
async def _execute(self, path, _type, name, param):
150+
async def _execute(self, path, _type, name, param, **kwargs):
151151
data = Object()
152152
data.type = _type
153153
data.name = name
154154
data.param = param
155-
return await super().post(path, data)
155+
return await super().post(path, data, **kwargs)
156156

157157

158158
class AsyncAPI(AsyncExtended):
@@ -262,31 +262,31 @@ def download(self, path, **kwargs):
262262
return super().handle(path, on_error=XMLHandler(), **kwargs)
263263

264264
@decorators.authenticated
265-
def propfind(self, path, depth):
266-
request = async_requests.PropfindRequest(self._builder(path), headers={'depth': str(depth)})
265+
def propfind(self, path, depth, **kwargs):
266+
request = async_requests.PropfindRequest(self._builder(path), headers={'depth': str(depth)}, **kwargs)
267267
response = self.request(request, on_error=XMLHandler())
268268
return response.dav()
269269

270270
@decorators.authenticated
271-
def mkcol(self, path):
272-
request = async_requests.MkcolRequest(self._builder(path))
271+
def mkcol(self, path, **kwargs):
272+
request = async_requests.MkcolRequest(self._builder(path), **kwargs)
273273
response = self.request(request, on_error=XMLHandler())
274274
return response.text()
275275

276276
@decorators.authenticated
277-
def copy(self, source, destination, *, overwrite=False):
278-
request = async_requests.CopyRequest(self._builder(source), headers=self._webdav_headers(destination, overwrite))
277+
def copy(self, source, destination, *, overwrite=False, **kwargs):
278+
request = async_requests.CopyRequest(self._builder(source), headers=self._webdav_headers(destination, overwrite), **kwargs)
279279
response = self.request(request, on_error=XMLHandler())
280280
return response.xml()
281281

282282
@decorators.authenticated
283-
def move(self, source, destination, *, overwrite=False):
284-
request = async_requests.MoveRequest(self._builder(source), headers=self._webdav_headers(destination, overwrite))
283+
def move(self, source, destination, *, overwrite=False, **kwargs):
284+
request = async_requests.MoveRequest(self._builder(source), headers=self._webdav_headers(destination, overwrite), **kwargs)
285285
response = self.request(request, on_error=XMLHandler())
286286
return response.xml()
287287

288-
def delete(self, path): # pylint: disable=arguments-differ
289-
response = super().delete(path, on_error=XMLHandler())
288+
def delete(self, path, **kwargs): # pylint: disable=arguments-differ
289+
response = super().delete(path, on_error=XMLHandler(), **kwargs)
290290
return response.text()
291291

292292
def _webdav_headers(self, destination, overwrite):
@@ -347,27 +347,27 @@ def delete(self, path, **kwargs):
347347
class Extended(XML):
348348
"""CTERA Schema"""
349349

350-
def get_multi(self, path, paths):
351-
return self.database(path, 'get-multi', paths)
350+
def get_multi(self, path, paths, **kwargs):
351+
return self.database(path, 'get-multi', paths, **kwargs)
352352

353-
def show_multi(self, path, paths):
354-
print(Serializers.JSON(self.get_multi(path, paths), no_log=False))
353+
def show_multi(self, path, paths, **kwargs):
354+
print(Serializers.JSON(self.get_multi(path, paths, **kwargs), no_log=False))
355355

356-
def execute(self, path, name, param=None): # schema method
357-
return self._execute(path, 'user-defined', name, param)
356+
def execute(self, path, name, param=None, **kwargs): # schema method
357+
return self._execute(path, 'user-defined', name, param, **kwargs)
358358

359-
def database(self, path, name, param=None): # schema method
360-
return self._execute(path, 'db', name, param)
359+
def database(self, path, name, param=None, **kwargs): # schema method
360+
return self._execute(path, 'db', name, param, **kwargs)
361361

362-
def add(self, path, param=None):
363-
return self.database(path, 'add', param)
362+
def add(self, path, param=None, **kwargs):
363+
return self.database(path, 'add', param, **kwargs)
364364

365-
def _execute(self, path, _type, name, param):
365+
def _execute(self, path, _type, name, param, **kwargs):
366366
data = Object()
367367
data.type = _type
368368
data.name = name
369369
data.param = param
370-
return super().post(path, data)
370+
return super().post(path, data, **kwargs)
371371

372372

373373
class API(Extended):

cterasdk/edge/network.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,11 @@ def tcp_connect(self, service):
126126

127127
logger.info("Testing connection. %s", {'host': service.host, 'port': service.port})
128128

129-
task = self._edge.api.execute("/status/network", "tcpconnect", param)
129+
task = self._edge.api.execute("/status/network", "tcpconnect", param, {
130+
'timeout': {
131+
'sock_read': 120
132+
}
133+
})
130134
try:
131135
task = self._edge.tasks.wait(task)
132136
logger.debug("Obtained connection status. %s", {'status': task.result.rc})

docs/source/UserGuides/Miscellaneous/Changelog.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
Changelog
22
=========
33

4+
2.20.12
5+
-------
6+
7+
Improvements
8+
^^^^^^^^^^^^
9+
10+
* Support for overriding timeout settings on a per-request basis.
11+
* Increased the ``sock_read`` timeout to 2 minutes when invoking :py:func:`cterasdk.edge.network.Network.tcp_connect`.
12+
13+
Related issues and pull requests on GitHub: `#302 <https://github.com/ctera/ctera-python-sdk/pull/302>`_
14+
15+
416
2.20.11
517
-------
618

tests/ut/edge/test_network.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ def setUp(self):
4949
self._proxy_user = 'admin'
5050
self._proxy_pass = 'password'
5151

52+
self._timeout = {
53+
'timeout': {
54+
'sock_read': 120
55+
}
56+
}
57+
5258
def test_network_status(self):
5359
get_response = 'Success'
5460
self._init_filer(get_response=get_response)
@@ -137,7 +143,7 @@ def test_tcp_connect_success(self):
137143

138144
ret = network.Network(self._filer).tcp_connect(TCPService(self._tcp_connect_address, self._tcp_connect_port))
139145

140-
self._filer.api.execute.assert_called_once_with('/status/network', 'tcpconnect', mock.ANY)
146+
self._filer.api.execute.assert_called_once_with('/status/network', 'tcpconnect', mock.ANY, self._timeout)
141147
self._filer.tasks.wait.assert_called_once_with(self._task_id)
142148

143149
expected_param = self._get_tcp_connect_object()
@@ -157,7 +163,7 @@ def test_tcp_connect_failure(self):
157163

158164
ret = network.Network(self._filer).tcp_connect(TCPService(self._tcp_connect_address, self._tcp_connect_port))
159165

160-
self._filer.api.execute.assert_called_once_with('/status/network', 'tcpconnect', mock.ANY)
166+
self._filer.api.execute.assert_called_once_with('/status/network', 'tcpconnect', mock.ANY, self._timeout)
161167
self._filer.tasks.wait.assert_called_once_with(self._task_id)
162168

163169
expected_param = self._get_tcp_connect_object()
@@ -200,7 +206,7 @@ def test_tcp_connect_task_error(self):
200206

201207
ret = network.Network(self._filer).tcp_connect(TCPService(self._tcp_connect_address, self._tcp_connect_port))
202208

203-
self._filer.api.execute.assert_called_once_with('/status/network', 'tcpconnect', mock.ANY)
209+
self._filer.api.execute.assert_called_once_with('/status/network', 'tcpconnect', mock.ANY, self._timeout)
204210
self._filer.tasks.wait.assert_called_once_with(self._task_id)
205211

206212
expected_param = self._get_tcp_connect_object()

0 commit comments

Comments
 (0)