Skip to content

Commit

Permalink
Added timeout option to MinIO storage plugin (#1071)
Browse files Browse the repository at this point in the history
Added timeout option to MinIO storage plugin. 

Although not implemented as described in issue #1067, this PR address the intension or that issue.

Also disabled test ex1-test, since it fails on GitHub because the python library cannot be found.
  • Loading branch information
jesper-friis authored Jan 20, 2025
1 parent bc1bda7 commit 609e510
Show file tree
Hide file tree
Showing 11 changed files with 46 additions and 8 deletions.
8 changes: 8 additions & 0 deletions bindings/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,14 @@ install(
PATTERN ".gitignore" EXCLUDE
PATTERN "*~" EXCLUDE
)
install(
DIRECTORY ${dlite_SOURCE_DIR}/storages/python/python-storage-plugins
DESTINATION ${Python3_PREFIX}share/dlite
USE_SOURCE_PERMISSIONS
PATTERN ".gitignore" EXCLUDE
PATTERN "*.json" EXCLUDE
PATTERN "*~" EXCLUDE
)

add_subdirectory(scripts)

Expand Down
2 changes: 1 addition & 1 deletion bindings/python/dlite-python.i
Original file line number Diff line number Diff line change
Expand Up @@ -1354,7 +1354,7 @@ PyObject *dlite_run_file(const char *path, PyObject *globals, PyObject *locals)
argout = Py_None;
Py_INCREF(argout);
}
#if SWIG_VERSION >= 0x040100
#if SWIG_VERSION > 0x040101
$result = SWIG_Python_AppendOutput($result, argout, 0);
#else
$result = SWIG_Python_AppendOutput($result, argout);
Expand Down
12 changes: 11 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,22 @@ macro(test_example example)
)
add_test(
NAME ${example}-test
COMMAND ${CMAKE_COMMAND} --build . --target test
COMMAND ${CMAKE_CTEST_COMMAND} --rerun-failed --output-on-failure
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${example}
)
set_property(TEST ${example}-config PROPERTY DEPENDS ${example}-mkdir)
set_property(TEST ${example}-build PROPERTY DEPENDS ${example}-config)
set_property(TEST ${example}-test PROPERTY DEPENDS ${example}-build)
set_property(TEST ${example}-test PROPERTY ENVIRONMENT
LD_LIBRARY_PATH="${dlite_LD_LIBRARY_PATH_NATIVE}:${Python3_LIBRARY_DIRS}"
)

# FIXME - enable this test again
# Currently the tests fails on GitHub with the message
#
# error while loading shared libraries: libpython3.10.so.1.0: cannot open shared object file: No such file or directory
#
set_property(TEST ${example}-test PROPERTY DISABLED True)
endmacro()


Expand Down
1 change: 1 addition & 0 deletions requirements_full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ requests>=2.10,<3
redis>=5.0,<6
minio>=6.0,<8
pymongo>=4.4.0,<5
urllib3>=1.0.0,<2
#psycopg2>=2,<3

# Utilities
Expand Down
2 changes: 2 additions & 0 deletions src/dlite-errors.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const char *dlite_errname(DLiteErrCode code)
case dliteMappingError: return "DLiteMapping";
case dliteProtocolError: return "DLiteProtocol";
case dlitePythonError: return "DLitePython";
case dliteTimeoutError: return "DLiteTimeout";

case dliteLastError: return "DLiteUndefined";
}
Expand Down Expand Up @@ -97,6 +98,7 @@ const char *dlite_errdescr(DLiteErrCode code)
case dliteMappingError: return "Error in instance mappings";
case dliteProtocolError: return "Error in a protocol plugin";
case dlitePythonError: return "Error calling Python API";
case dliteTimeoutError: return "Raised when a function times out";
case dliteLastError: return NULL;
}
return NULL;
Expand Down
3 changes: 2 additions & 1 deletion src/dlite-errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ typedef enum {
dliteMappingError=-32, /*!< Error in instance mappings */
dliteProtocolError=-33, /*!< Error in a protocol plugin */
dlitePythonError=-34, /*!< Error calling Python API */
dliteTimeoutError=-35, /*!< Raised when a function times out */

/* Should always be the last error */
dliteLastError=-35
dliteLastError=-36
} DLiteErrCode;


Expand Down
1 change: 1 addition & 0 deletions src/pyembed/dlite-pyembed.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ PyObject *dlite_pyembed_exception(DLiteErrCode code)
case dliteMappingError: break;
case dliteProtocolError: break;
case dlitePythonError: break;
case dliteTimeoutError: return PyExc_TimeoutError;
case dliteLastError: break;
}
return PyExc_Exception;
Expand Down
12 changes: 10 additions & 2 deletions storages/python/python-storage-plugins/minio.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def open(self, location: str, options=None):
- `session_token`: Session token of your account in S3 service.
- `secure`: Whether to use secure (TLS) connection to S3 service.
- `region`: Region name of buckets in S3 service.
- `timeout`: Timeout for connecting to minio service. Requires urllib3
Currently unsupported Minio arguments:
- `http_client`: Customized HTTP client.
Expand All @@ -34,9 +35,16 @@ def open(self, location: str, options=None):
# Pop out bucket-related options
self.bucket_name = opts.pop("bucket_name", "dlite")

# Fix option types and create MinIO connection
# Remove timeout from opts and fix types
timeout = opts.pop("timeout", None)
opts.secure = dlite.asbool(opts.secure)
self.client = Minio(endpoint=location, **opts)

# Handle timeout and create MinIO connection
kwargs = opts.copy()
if timeout is not None:
import urllib3
kwargs["http_client"] = urllib3.PoolManager(timeout=float(timeout))
self.client = Minio(endpoint=location, **kwargs)

if not self.client.bucket_exists(self.bucket_name):
kw = {"region": opts.region} if "region" in opts else {}
Expand Down
2 changes: 2 additions & 0 deletions storages/python/tests-c/test_postgresql_storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@

DLiteStorage *db=NULL;
#ifdef PASSWORD
// cppcheck-suppress [syntaxError, unknownMacro]
char *options = "database=" DATABASE ";user=" USER ";password=" PASSWORD;
#else
// cppcheck-suppress [syntaxError, unknownMacro]
char *options = "database=" DATABASE ";user=" USER;
#endif

Expand Down
2 changes: 1 addition & 1 deletion storages/python/tests-python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,5 @@ endforeach()

# Skip minio test if the minio playground storage is full
set_property(TEST test_minio PROPERTY
SKIP_REGULAR_EXPRESSION "XMinioStorageFull"
SKIP_REGULAR_EXPRESSION "(XMinioStorageFull)|(ConnectTimeoutError)"
)
9 changes: 7 additions & 2 deletions storages/python/tests-python/test_minio.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
from dlite.testutils import importskip, serverskip


importskip("minio") # skip this test if minio is not available
# skip this test if minio or urllib3 are not available
importskip("minio")
importskip("urllib3")
#serverskip("play.min.io", 9000) # skip test if minio is down


Expand All @@ -18,7 +20,10 @@
# Access and secret keys for free MinIO playground
access_key = "Q3AM3UQ867SPQQA43P2F"
secret_key = "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG"
options = f"bucket_name=dlite-test;access_key={access_key};secret_key={secret_key}"
options = (
f"bucket_name=dlite-test;access_key={access_key};"
f"secret_key={secret_key};timeout=2"
)

inst1 = dlite.get_instance("2f8ba28c-add6-5718-a03c-ea46961d6ca7")
inst2 = dlite.get_instance("52522ba5-6bfe-4a64-992d-e9ec4080fbac")
Expand Down

0 comments on commit 609e510

Please sign in to comment.