Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion cterasdk/clients/async_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,15 @@ class BaseRequest:
def __init__(self, method, url, **kwargs):
self.method = method
self.url = url
self.kwargs = kwargs
self.kwargs = BaseRequest.accept(**kwargs)

@staticmethod
def accept(**kwargs):
timeout = kwargs.get('timeout', None)
if timeout:
logger.debug('Setting request timeout. %s', timeout)
kwargs['timeout'] = aiohttp.ClientTimeout(**timeout)
return kwargs


class GetRequest(BaseRequest):
Expand Down
80 changes: 40 additions & 40 deletions cterasdk/clients/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,31 +59,31 @@ async def download(self, path, **kwargs):
return await super().get(path, on_error=XMLHandler(), **kwargs)

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

@decorators.authenticated
async def mkcol(self, path):
request = async_requests.MkcolRequest(self._builder(path))
async def mkcol(self, path, **kwargs):
request = async_requests.MkcolRequest(self._builder(path), **kwargs)
response = await self.a_request(request, on_error=XMLHandler())
return await response.text()

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

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

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

def _webdav_headers(self, destination, overwrite):
Expand Down Expand Up @@ -138,21 +138,21 @@ async def delete(self, path, **kwargs):
class AsyncExtended(AsyncXML):
"""CTERA Schema"""

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

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

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

async def _execute(self, path, _type, name, param):
async def _execute(self, path, _type, name, param, **kwargs):
data = Object()
data.type = _type
data.name = name
data.param = param
return await super().post(path, data)
return await super().post(path, data, **kwargs)


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

@decorators.authenticated
def propfind(self, path, depth):
request = async_requests.PropfindRequest(self._builder(path), headers={'depth': str(depth)})
def propfind(self, path, depth, **kwargs):
request = async_requests.PropfindRequest(self._builder(path), headers={'depth': str(depth)}, **kwargs)
response = self.request(request, on_error=XMLHandler())
return response.dav()

@decorators.authenticated
def mkcol(self, path):
request = async_requests.MkcolRequest(self._builder(path))
def mkcol(self, path, **kwargs):
request = async_requests.MkcolRequest(self._builder(path), **kwargs)
response = self.request(request, on_error=XMLHandler())
return response.text()

@decorators.authenticated
def copy(self, source, destination, *, overwrite=False):
request = async_requests.CopyRequest(self._builder(source), headers=self._webdav_headers(destination, overwrite))
def copy(self, source, destination, *, overwrite=False, **kwargs):
request = async_requests.CopyRequest(self._builder(source), headers=self._webdav_headers(destination, overwrite), **kwargs)
response = self.request(request, on_error=XMLHandler())
return response.xml()

@decorators.authenticated
def move(self, source, destination, *, overwrite=False):
request = async_requests.MoveRequest(self._builder(source), headers=self._webdav_headers(destination, overwrite))
def move(self, source, destination, *, overwrite=False, **kwargs):
request = async_requests.MoveRequest(self._builder(source), headers=self._webdav_headers(destination, overwrite), **kwargs)
response = self.request(request, on_error=XMLHandler())
return response.xml()

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

def _webdav_headers(self, destination, overwrite):
Expand Down Expand Up @@ -347,27 +347,27 @@ def delete(self, path, **kwargs):
class Extended(XML):
"""CTERA Schema"""

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

def show_multi(self, path, paths):
print(Serializers.JSON(self.get_multi(path, paths), no_log=False))
def show_multi(self, path, paths, **kwargs):
print(Serializers.JSON(self.get_multi(path, paths, **kwargs), no_log=False))

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

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

def add(self, path, param=None):
return self.database(path, 'add', param)
def add(self, path, param=None, **kwargs):
return self.database(path, 'add', param, **kwargs)

def _execute(self, path, _type, name, param):
def _execute(self, path, _type, name, param, **kwargs):
data = Object()
data.type = _type
data.name = name
data.param = param
return super().post(path, data)
return super().post(path, data, **kwargs)


class API(Extended):
Expand Down
6 changes: 5 additions & 1 deletion cterasdk/edge/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,11 @@ def tcp_connect(self, service):

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

task = self._edge.api.execute("/status/network", "tcpconnect", param)
task = self._edge.api.execute("/status/network", "tcpconnect", param, {
'timeout': {
'sock_read': 120
}
})
try:
task = self._edge.tasks.wait(task)
logger.debug("Obtained connection status. %s", {'status': task.result.rc})
Expand Down
12 changes: 12 additions & 0 deletions docs/source/UserGuides/Miscellaneous/Changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
Changelog
=========

2.20.12
-------

Improvements
^^^^^^^^^^^^

* Support for overriding timeout settings on a per-request basis.
* Increased the ``sock_read`` timeout to 2 minutes when invoking :py:func:`cterasdk.edge.network.Network.tcp_connect`.

Related issues and pull requests on GitHub: `#302 <https://github.com/ctera/ctera-python-sdk/pull/302>`_


2.20.11
-------

Expand Down
12 changes: 9 additions & 3 deletions tests/ut/edge/test_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ def setUp(self):
self._proxy_user = 'admin'
self._proxy_pass = 'password'

self._timeout = {
'timeout': {
'sock_read': 120
}
}

def test_network_status(self):
get_response = 'Success'
self._init_filer(get_response=get_response)
Expand Down Expand Up @@ -137,7 +143,7 @@ def test_tcp_connect_success(self):

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

self._filer.api.execute.assert_called_once_with('/status/network', 'tcpconnect', mock.ANY)
self._filer.api.execute.assert_called_once_with('/status/network', 'tcpconnect', mock.ANY, self._timeout)
self._filer.tasks.wait.assert_called_once_with(self._task_id)

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

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

self._filer.api.execute.assert_called_once_with('/status/network', 'tcpconnect', mock.ANY)
self._filer.api.execute.assert_called_once_with('/status/network', 'tcpconnect', mock.ANY, self._timeout)
self._filer.tasks.wait.assert_called_once_with(self._task_id)

expected_param = self._get_tcp_connect_object()
Expand Down Expand Up @@ -200,7 +206,7 @@ def test_tcp_connect_task_error(self):

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

self._filer.api.execute.assert_called_once_with('/status/network', 'tcpconnect', mock.ANY)
self._filer.api.execute.assert_called_once_with('/status/network', 'tcpconnect', mock.ANY, self._timeout)
self._filer.tasks.wait.assert_called_once_with(self._task_id)

expected_param = self._get_tcp_connect_object()
Expand Down