27
27
from .typelets import ExcType , ExcValue , ExcTraceback
28
28
29
29
_RADOSModule = typing .Any
30
+ _RADOSObject = typing .Any
30
31
31
32
_CHUNK_SIZE = 4 * 1024
32
33
@@ -35,43 +36,60 @@ class RADOSUnsupported(Exception):
35
36
pass
36
37
37
38
39
+ class _RADOSInterface :
40
+ api : _RADOSModule
41
+ client_name : str
42
+ full_name : bool
43
+
44
+ def Rados (self ) -> _RADOSObject :
45
+ name = rados_id = ""
46
+ if self .full_name :
47
+ name = self .client_name
48
+ else :
49
+ rados_id = self .client_name
50
+ return self .api .Rados (
51
+ name = name ,
52
+ rados_id = rados_id ,
53
+ conffile = self .api .Rados .DEFAULT_CONF_FILES ,
54
+ )
55
+
56
+
38
57
class _RADOSHandler (urllib .request .BaseHandler ):
39
- _rados_api : typing .Optional [_RADOSModule ] = None
58
+ _interface : typing .Optional [_RADOSInterface ] = None
40
59
41
60
def rados_open (self , req : urllib .request .Request ) -> typing .IO :
42
- if self ._rados_api is None :
61
+ if self ._interface is None :
43
62
raise RADOSUnsupported ()
44
63
if req .selector .startswith ("mon-config-key:" ):
45
64
return _get_mon_config_key (
46
- self ._rados_api , req .selector .split (":" , 1 )[1 ]
65
+ self ._interface , req .selector .split (":" , 1 )[1 ]
47
66
)
48
67
sel = req .selector .lstrip ("/" )
49
68
if req .host :
50
69
pool = req .host
51
70
ns , key = sel .split ("/" , 1 )
52
71
else :
53
72
pool , ns , key = sel .split ("/" , 2 )
54
- return _RADOSResponse (self ._rados_api , pool , ns , key )
73
+ return _RADOSResponse (self ._interface , pool , ns , key )
55
74
56
75
57
76
# it's quite annoying to have a read-only typing.IO we're forced to
58
77
# have so many stub methods. Go's much more granular io interfaces for
59
78
# readers/writers is much nicer for this.
60
79
class _RADOSResponse (typing .IO ):
61
80
def __init__ (
62
- self , rados_api : _RADOSModule , pool : str , ns : str , key : str
81
+ self , interface : _RADOSInterface , pool : str , ns : str , key : str
63
82
) -> None :
64
83
self ._pool = pool
65
84
self ._ns = ns
66
85
self ._key = key
67
86
68
- self ._open (rados_api )
87
+ self ._open (interface )
69
88
self ._test ()
70
89
71
- def _open (self , rados_api : _RADOSModule ) -> None :
90
+ def _open (self , interface : _RADOSInterface ) -> None :
72
91
# TODO: connection caching
73
- self ._conn = rados_api .Rados ()
74
- self ._conn .conf_read_file ()
92
+ self ._conn = interface .Rados ()
75
93
self ._conn .connect ()
76
94
self ._connected = True
77
95
self ._ioctx = self ._conn .open_ioctx (self ._pool )
@@ -177,14 +195,14 @@ def writelines(self, ls: typing.Iterable[typing.Any]) -> None:
177
195
raise NotImplementedError ()
178
196
179
197
180
- def _get_mon_config_key (rados_api : _RADOSModule , key : str ) -> io .BytesIO :
198
+ def _get_mon_config_key (interface : _RADOSInterface , key : str ) -> io .BytesIO :
181
199
mcmd = json .dumps (
182
200
{
183
201
"prefix" : "config-key get" ,
184
202
"key" : str (key ),
185
203
}
186
204
)
187
- with rados_api .Rados (conffile = rados_api . Rados . DEFAULT_CONF_FILES ) as rc :
205
+ with interface .Rados () as rc :
188
206
ret , out , err = rc .mon_command (mcmd , b"" )
189
207
if ret == 0 :
190
208
# We need to return a file like object. Since we are handed just
@@ -196,7 +214,12 @@ def _get_mon_config_key(rados_api: _RADOSModule, key: str) -> io.BytesIO:
196
214
raise OSError (ret , msg )
197
215
198
216
199
- def enable_rados_url_opener (cls : typing .Type [url_opener .URLOpener ]) -> None :
217
+ def enable_rados_url_opener (
218
+ cls : typing .Type [url_opener .URLOpener ],
219
+ * ,
220
+ client_name : str = "" ,
221
+ full_name : bool = False ,
222
+ ) -> None :
200
223
"""Extend the URLOpener type to support pseudo-URLs for rados
201
224
object storage. If rados libraries are not found the function
202
225
does nothing.
@@ -211,5 +234,10 @@ def enable_rados_url_opener(cls: typing.Type[url_opener.URLOpener]) -> None:
211
234
except ImportError :
212
235
return
213
236
214
- _RADOSHandler ._rados_api = rados
237
+ rados_interface = _RADOSInterface ()
238
+ rados_interface .api = rados
239
+ rados_interface .client_name = client_name
240
+ rados_interface .full_name = full_name
241
+
242
+ _RADOSHandler ._interface = rados_interface
215
243
cls ._handlers .append (_RADOSHandler )
0 commit comments