Skip to content

Commit fd46dd1

Browse files
Rasmus Oscar Welanderglpatcern
authored andcommitted
Added main class cs3client, configuration and library setup
1 parent a328b20 commit fd46dd1

File tree

6 files changed

+333
-0
lines changed

6 files changed

+333
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ coverage.xml
5151
.pytest_cache/
5252
cover/
5353

54+
# vscode settings
55+
.vscode/
56+
5457
# Translations
5558
*.mo
5659
*.pot

examples/default.conf

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# example configuration file for the CS3client.
2+
#
3+
# Authors: Rasmus Welander, Diogo Castro, Giuseppe Lo Presti
4+
5+
# Last updated: 29/07/2024
6+
7+
[cs3client]
8+
9+
# Required
10+
host = localhost:19000
11+
# Optional, defaults to 4194304
12+
chunk_size = 4194304
13+
# Optional, defaults to 10
14+
grpc_timeout = 10
15+
# Optional, defaults to 10
16+
http_timeout = 10
17+
18+
# Optional, defaults to True
19+
tus_enabled = False
20+
21+
# Optional, defaults to True
22+
ssl_enabled = False
23+
# Optional, defaults to True
24+
ssl_verify = False
25+
# Optional, defaults to an empty string
26+
ssl_client_cert = test_client_cert
27+
# Optional, defaults to an empty string
28+
ssl_client_key = test_client_key
29+
# Optional, defaults to an empty string
30+
ssl_ca_cert = test_ca_cert
31+
32+
# Optinal, defaults to an empty string
33+
auth_client_id = einstein
34+
# Optional, defaults to basic
35+
auth_login_type = basic
36+
37+
# For the future lock implementation
38+
39+
# Optional, defaults to False
40+
# This configuration is used to enable/disable the fallback mechanism
41+
# if the locks are not implemented in the storage provider
42+
lock_by_setting_attr = False
43+
# This configuration is used to enable/disable the fallback mechanism
44+
# if the locks are not implemented in the storage provider
45+
# Optional, defaults to False
46+
lock_not_impl = False
47+
# Optional, defaults to 1800
48+
lock_expiration = 1800
49+

setup.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""
2+
setup.py
3+
4+
setup file for the cs3client package.
5+
6+
Authors: Rasmus Welander, Diogo Castro, Giuseppe Lo Presti.
7+
8+
Last updated: 26/07/2024
9+
"""
10+
11+
from setuptools import setup, find_packages
12+
13+
setup(
14+
name="cs3client",
15+
version="0.1",
16+
author="Rasmus Welander, Diogo Castro, Giuseppe Lo Presti",
17+
package_dir={"": "src"},
18+
packages=find_packages(where="src"),
19+
py_modules=["cs3client"],
20+
install_requires=[
21+
"grpcio>=1.47.0",
22+
"grpcio-tools>=1.47.0",
23+
"pyOpenSSL",
24+
"requests",
25+
"cs3apis>=0.1.dev101",
26+
"PyJWT",
27+
"protobuf",
28+
"cryptography",
29+
],
30+
)

src/__init__.py

Whitespace-only changes.

src/config.py

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
"""
2+
config.py
3+
4+
Authors: Rasmus Welander, Diogo Castro, Giuseppe Lo Presti.
5+
6+
Last updated: 29/07/2024
7+
"""
8+
9+
from configparser import ConfigParser
10+
11+
12+
class Config:
13+
"""
14+
A class to read and store the configuration parameters provided to the CS3 client.
15+
"""
16+
17+
def __init__(self, config: ConfigParser, config_category: str) -> None:
18+
"""
19+
Initializes the Config class with the configuration parameters.
20+
21+
:param config: Dictionary containing configuration parameters.
22+
:param config_category: The category of the configuration parameters.
23+
"""
24+
self._config_category: str = config_category
25+
self._config: ConfigParser = config
26+
27+
@property
28+
def host(self) -> str:
29+
"""
30+
The host property returns the host address and port from the configuration.
31+
32+
:return: host address:port
33+
"""
34+
return self._config.get(self._config_category, "host")
35+
36+
@property
37+
def chunk_size(self) -> int:
38+
"""
39+
The chunk_size property returns the chunk_size value from the configuration,
40+
fallback to 4194304 if not present.
41+
42+
:return: The chunk size value.
43+
"""
44+
return self._config.getint(self._config_category, "chunk_size", fallback=4194304)
45+
46+
@property
47+
def grpc_timeout(self) -> int:
48+
"""
49+
The grpc_timeout property returns the grpc_timeout value from the configuration,
50+
fallback to 10 if not present.
51+
52+
:return: The grpc timeout value.
53+
"""
54+
return self._config.getint(self._config_category, "grpc_timeout", fallback=10)
55+
56+
@property
57+
def http_timeout(self) -> int:
58+
"""
59+
The http_timeout property returns the http_timeout value from the configuration,
60+
fallback to 10 if not present.
61+
62+
:return: The http timeout value.
63+
"""
64+
return self._config.getint(self._config_category, "http_timeout", fallback=10)
65+
66+
@property
67+
def ssl_enabled(self) -> bool:
68+
"""
69+
The ssl_enabled property returns the ssl_enabled value from the configuration,
70+
fallback to True if not present.
71+
72+
:return: ssl_enabled value.
73+
"""
74+
return self._config.getboolean(self._config_category, "ssl_enabled", fallback=False)
75+
76+
@property
77+
def ssl_verify(self) -> bool:
78+
"""
79+
The ssl_verify property returns the ssl_verify value from the configuration,
80+
81+
:return: ssl_verify
82+
"""
83+
return self._config.getboolean(self._config_category, "ssl_verify", fallback=False)
84+
85+
@property
86+
def ssl_client_cert(self) -> str:
87+
"""
88+
The ssl_client_cert property returns the ssl_client_cert value from the configuration,
89+
if not present, fallback to an empty string since it is not required if ssl is not enabled.
90+
91+
:return: ssl_client_cert
92+
"""
93+
return self._config.get(self._config_category, "ssl_client_cert", fallback=None)
94+
95+
@property
96+
def ssl_client_key(self) -> str:
97+
"""
98+
The ssl_client_key property returns the ssl_client_key value from the configuration,
99+
if not present, fallback to an empty string since it is not required if ssl is not enabled.
100+
101+
:return: ssl_client_key
102+
"""
103+
return self._config.get(self._config_category, "ssl_client_key", fallback=None)
104+
105+
@property
106+
def ssl_ca_cert(self) -> str:
107+
"""
108+
The ssl_ca_cert property returns the ssl_ca_cert value from the configuration,
109+
if not present, fallback to an empty string since it is not required if ssl is not enabled.
110+
111+
:return: ssl_ca_cert
112+
"""
113+
return self._config.get(self._config_category, "ssl_ca_cert", fallback=None)
114+
115+
@property
116+
def auth_login_type(self) -> str:
117+
"""
118+
The auth_login_type property returns the auth_login_type value from the configuration.
119+
e.g. basic, bearer, oauth, machine.
120+
121+
:return: auth_login_type
122+
"""
123+
return self._config.get(self._config_category, "auth_login_type", fallback="basic")
124+
125+
@property
126+
def auth_client_id(self) -> str:
127+
"""
128+
The auth_client_id property returns the auth_client_id value from the configuration,
129+
130+
:return: auth_client_id
131+
"""
132+
return self._config.get(self._config_category, "auth_client_id", fallback=None)
133+
134+
@property
135+
def tus_enabled(self) -> bool:
136+
"""
137+
The tus_enabled property returns the tus_enabled value from the configuration,
138+
139+
:return: tus_enabled
140+
"""
141+
return self._config.getboolean(self._config_category, "tus_enabled", fallback=False)
142+
143+
# For the lock implementation
144+
@property
145+
def lock_by_setting_attr(self) -> bool:
146+
"""
147+
The lock_by_setting_attr property returns the lock_by_setting_attr value from the configuration,
148+
fallback to False if not present.
149+
150+
The lock by setting attribute setting should be set if the storage provider does not
151+
implement locking functionality. In which case the client will use the fallback mechanism
152+
by locking resources by setting metadata attributes. If lock_not_impl is set to false and
153+
lock_by_setting_attr is set to true, the client will attempt to lock normally first,
154+
and if that fails, it will attempt to lock by setting metadata attributes.
155+
156+
157+
:return: lock_by_setting_attr
158+
"""
159+
return self._config.getboolean(self._config_category, "lock_by_setting_attr", fallback=False)
160+
161+
# For the lock implementation
162+
@property
163+
def lock_not_impl(self) -> bool:
164+
"""
165+
The lock_not_impl property returns the lock_not_impl value from the configuration,
166+
fallback to False if not present.
167+
168+
The lock not implemented setting should be set if the storage provider
169+
does not implement locking functionality. In which case the client will use the
170+
fallback mechanism by locking resources by setting metadata attributes if the
171+
lock_by_setting_attr is set to True.
172+
173+
:return: lock_not_impl
174+
"""
175+
return self._config.getboolean(self._config_category, "lock_not_impl", fallback=False)
176+
177+
# For the lock implementation
178+
@property
179+
def lock_expiration(self) -> int:
180+
"""
181+
The lock_expiration property returns the lock_expiration value from the configuration,
182+
fallback to 1800 if not present.
183+
184+
The lock expiration setting is used to determine the time
185+
in seconds before a lock is considered expired.
186+
187+
:return: lock_expiration
188+
"""
189+
return self._config.getint(self._config_category, "lock_expiration", fallback=1800)

src/cs3client.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"""
2+
cs3client.py
3+
4+
Authors: Rasmus Welander, Diogo Castro, Giuseppe Lo Presti.
5+
6+
Last updated: 29/07/2024
7+
"""
8+
9+
import grpc
10+
import logging
11+
import cs3.gateway.v1beta1.gateway_api_pb2_grpc as cs3gw_grpc
12+
13+
from configparser import ConfigParser
14+
from auth import Auth
15+
from file import File
16+
from config import Config
17+
18+
19+
class CS3Client:
20+
"""
21+
Client class to interact with the CS3 API.
22+
"""
23+
24+
def __init__(self, config: ConfigParser, config_category: str, log: logging.Logger) -> None:
25+
"""
26+
Initializes the CS3Client class with configuration and logger.
27+
:param config: Dictionary containing configuration parameters.
28+
:param config_category: Category of the configuration parameters.
29+
:param log: Logger instance for logging.
30+
"""
31+
32+
self._config: Config = Config(config, config_category)
33+
self._log: logging.Logger = log
34+
35+
try:
36+
self.channel: grpc.Channel = self._create_channel()
37+
grpc.channel_ready_future(self.channel).result(timeout=self._config.grpc_timeout)
38+
except grpc.FutureTimeoutError as e:
39+
log.error(f'msg="Failed to connect to Reva via GRPC" error="{e}"')
40+
raise TimeoutError("Failed to connect to Reva via GRPC")
41+
self._gateway: cs3gw_grpc.GatewayAPIStub = cs3gw_grpc.GatewayAPIStub(self.channel)
42+
self.auth = Auth(self._config, self._log, self._gateway)
43+
self.file = File(self._config, self._log, self._gateway, self.auth)
44+
45+
def _create_channel(self) -> grpc.Channel:
46+
"""
47+
create_channel creates a gRPC channel to the specified host.
48+
49+
:return: gRPC channel to the specified host.
50+
"""
51+
52+
if self._config.ssl_enabled:
53+
54+
credentials = grpc.ssl_channel_credentials(
55+
root_certificates=self._config.ssl_ca_cert,
56+
private_key=self._config.ssl_client_key,
57+
certificate_chain=self._config.ssl_client_cert,
58+
)
59+
channel = grpc.secure_channel(self._config.host, credentials)
60+
else:
61+
channel = grpc.insecure_channel(self._config.host)
62+
return channel

0 commit comments

Comments
 (0)