Skip to content

Commit 3579d92

Browse files
Millefeuille42WescoeurNambrok
committed
feat: add caching functions for controller_uri
Co-authored-by: Ronan Abhamon <ronan.abhamon@vates.tech> Co-authored-by: Damien Thenot <damien.thenot@vates.tech> Signed-off-by: Mathieu Labourier <mathieu.labourier@vates.tech>
1 parent 921f385 commit 3579d92

5 files changed

Lines changed: 181 additions & 43 deletions

File tree

drivers/LinstorSR.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from linstorvolumemanager import LinstorVolumeManager
2727
from linstorvolumemanager import LinstorVolumeManagerError
2828
from linstorvolumemanager import PERSISTENT_PREFIX
29+
from linstorvolumemanager import write_controller_uri_cache
2930

3031
LINSTOR_AVAILABLE = True
3132
except ImportError:
@@ -420,6 +421,7 @@ def connect():
420421
try:
421422
util.SMlog('Connecting from config to LINSTOR controller using: {}'.format(ip))
422423
create_linstor(controller_uri, attempt_count=0)
424+
write_controller_uri_cache(controller_uri)
423425
return controller_uri
424426
except:
425427
pass

drivers/linstor-manager

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,7 @@ def detach(session, args):
350350
vdi_uuid = args['vdiUuid']
351351
group_name = args['groupName']
352352

353-
linstor = LinstorVolumeManager(
354-
get_controller_uri(),
353+
linstor = LinstorVolumeManager.create_from_cache(
355354
group_name,
356355
logger=util.SMlog
357356
)
@@ -405,8 +404,7 @@ def get_vhd_info(session, args):
405404
group_name = args['groupName']
406405
include_parent = util.strtobool(args['includeParent'])
407406

408-
linstor = LinstorVolumeManager(
409-
get_controller_uri(),
407+
linstor = LinstorVolumeManager.create_from_cache(
410408
group_name,
411409
logger=util.SMlog
412410
)
@@ -440,8 +438,7 @@ def get_parent(session, args):
440438
device_path = args['devicePath']
441439
group_name = args['groupName']
442440

443-
linstor = LinstorVolumeManager(
444-
get_controller_uri(),
441+
linstor = LinstorVolumeManager.create_from_cache(
445442
group_name,
446443
logger=util.SMlog
447444
)
@@ -594,8 +591,7 @@ def deflate(session, args):
594591
zeroize = util.strtobool(args['zeroize'])
595592
group_name = args['groupName']
596593

597-
linstor = LinstorVolumeManager(
598-
get_controller_uri(),
594+
linstor = LinstorVolumeManager.create_from_cache(
599595
group_name,
600596
logger=util.SMlog
601597
)
@@ -619,8 +615,7 @@ def lock_vdi(session, args):
619615
if locked:
620616
lock.acquire()
621617

622-
linstor = LinstorVolumeManager(
623-
get_controller_uri(),
618+
linstor = LinstorVolumeManager.create_from_cache(
624619
group_name,
625620
logger=util.SMlog
626621
)
@@ -678,8 +673,7 @@ def add_host(session, args):
678673
)
679674

680675
# 3. Ensure node doesn't exist.
681-
linstor = LinstorVolumeManager(
682-
get_controller_uri(),
676+
linstor = LinstorVolumeManager.create_from_cache(
683677
group_name,
684678
logger=util.SMlog
685679
)
@@ -781,8 +775,7 @@ def remove_host(session, args):
781775
pbds[pbd_ref] = pbd
782776

783777
# 2. Remove node.
784-
linstor = LinstorVolumeManager(
785-
get_controller_uri(),
778+
linstor = LinstorVolumeManager.create_from_cache(
786779
group_name,
787780
logger=util.SMlog
788781
)
@@ -1127,8 +1120,7 @@ def create_node_interface(session, args):
11271120

11281121
ip_addr = get_ip_addr_of_pif(session, pif_uuid)
11291122

1130-
linstor = LinstorVolumeManager(
1131-
get_controller_uri(),
1123+
linstor = LinstorVolumeManager.create_from_cache(
11321124
group_name,
11331125
logger=util.SMlog
11341126
)
@@ -1144,8 +1136,7 @@ def destroy_node_interface(session, args):
11441136
hostname = args['hostname']
11451137
name = args['name']
11461138

1147-
linstor = LinstorVolumeManager(
1148-
get_controller_uri(),
1139+
linstor = LinstorVolumeManager.create_from_cache(
11491140
group_name,
11501141
logger=util.SMlog
11511142
)
@@ -1164,8 +1155,7 @@ def modify_node_interface(session, args):
11641155

11651156
ip_addr = get_ip_addr_of_pif(session, pif_uuid)
11661157

1167-
linstor = LinstorVolumeManager(
1168-
get_controller_uri(),
1158+
linstor = LinstorVolumeManager.create_from_cache(
11691159
group_name,
11701160
logger=util.SMlog
11711161
)
@@ -1180,8 +1170,7 @@ def list_node_interfaces(session, args):
11801170
group_name = args['groupName']
11811171
hostname = args['hostname']
11821172

1183-
linstor = LinstorVolumeManager(
1184-
get_controller_uri(),
1173+
linstor = LinstorVolumeManager.create_from_cache(
11851174
group_name,
11861175
logger=util.SMlog
11871176
)
@@ -1195,8 +1184,7 @@ def get_node_preferred_interface(session, args):
11951184
group_name = args['groupName']
11961185
hostname = args['hostname']
11971186

1198-
linstor = LinstorVolumeManager(
1199-
get_controller_uri(),
1187+
linstor = LinstorVolumeManager.create_from_cache(
12001188
group_name,
12011189
logger=util.SMlog
12021190
)
@@ -1211,8 +1199,7 @@ def set_node_preferred_interface(session, args):
12111199
hostname = args['hostname']
12121200
name = args['name']
12131201

1214-
linstor = LinstorVolumeManager(
1215-
get_controller_uri(),
1202+
linstor = LinstorVolumeManager.create_from_cache(
12161203
group_name,
12171204
logger=util.SMlog
12181205
)

drivers/linstorjournaler.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@
1616
#
1717

1818

19-
from linstorvolumemanager import \
20-
get_controller_uri, LinstorVolumeManager, LinstorVolumeManagerError
19+
from linstorvolumemanager import (
20+
delete_controller_uri_cache,
21+
get_controller_uri,
22+
LinstorVolumeManager,
23+
LinstorVolumeManagerError,
24+
)
25+
2126
import linstor
2227
import re
2328
import util
@@ -160,8 +165,10 @@ def connect(uri):
160165

161166
try:
162167
return connect(uri)
163-
except (linstor.errors.LinstorNetworkError, LinstorVolumeManagerError):
168+
except LinstorVolumeManagerError:
164169
pass
170+
except linstor.errors.LinstorNetworkError:
171+
delete_controller_uri_cache(uri)
165172

166173
return util.retry(
167174
lambda: connect(None),

drivers/linstorvolumemanager.py

Lines changed: 154 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717

1818
from sm_typing import override
1919

20+
import contextlib
2021
import errno
22+
import flock
2123
import json
2224
import linstor
2325
import os.path
@@ -43,6 +45,10 @@
4345

4446
DRBD_BY_RES_PATH = '/dev/drbd/by-res/'
4547

48+
CONTROLLER_CACHE_DIRECTORY = os.environ.get('TMPDIR', '/tmp') + '/linstor'
49+
CONTROLLER_CACHE_FILE = 'controller_uri'
50+
CONTROLLER_CACHE_PATH = "{}/{}".format(CONTROLLER_CACHE_DIRECTORY, CONTROLLER_CACHE_FILE)
51+
4652
PLUGIN = 'linstor-manager'
4753

4854

@@ -196,17 +202,123 @@ def _get_controller_uri():
196202
# Not found, maybe we are trying to create the SR...
197203
pass
198204

199-
def get_controller_uri():
200-
retries = 0
201-
while True:
202-
uri = _get_controller_uri()
203-
if uri:
204-
return uri
205205

206-
retries += 1
207-
if retries >= 10:
208-
break
209-
time.sleep(1)
206+
@contextlib.contextmanager
207+
def shared_reader(path):
208+
with open(path, 'r') as f:
209+
lock = flock.ReadLock(f.fileno())
210+
lock.lock()
211+
try:
212+
yield f
213+
finally:
214+
lock.unlock()
215+
216+
217+
@contextlib.contextmanager
218+
def excl_writer(path):
219+
with open(path, 'r+') as f:
220+
lock = flock.WriteLock(f.fileno())
221+
lock.lock()
222+
try:
223+
yield f
224+
finally:
225+
lock.unlock()
226+
227+
228+
def _read_controller_uri_from_file(f):
229+
try:
230+
return f.read().strip()
231+
except Exception as e:
232+
util.SMlog('Unable to read controller URI cache file at `{}`: {}'.format(CONTROLLER_CACHE_PATH, e))
233+
234+
235+
def _write_controller_uri_to_file(uri, f):
236+
try:
237+
f.seek(0)
238+
f.write(uri)
239+
f.truncate()
240+
except Exception as e:
241+
util.SMlog('Unable to write URI cache file at `{}` : {}'.format(CONTROLLER_CACHE_PATH, e))
242+
243+
244+
def _delete_controller_uri_from_file(f):
245+
try:
246+
f.seek(0)
247+
f.truncate()
248+
except Exception as e:
249+
util.SMlog('Unable to delete URI cache file at `{}` : {}'.format(CONTROLLER_CACHE_PATH, e))
250+
251+
252+
def read_controller_uri_cache():
253+
try:
254+
with shared_reader(CONTROLLER_CACHE_PATH) as f:
255+
return _read_controller_uri_from_file(f)
256+
except FileNotFoundError:
257+
pass
258+
except Exception as e:
259+
util.SMlog('Unable to read controller URI cache file at `{}`: {}'.format(CONTROLLER_CACHE_PATH, e))
260+
261+
262+
def write_controller_uri_cache(uri):
263+
try:
264+
with excl_writer(CONTROLLER_CACHE_PATH) as f:
265+
_write_controller_uri_to_file(uri, f)
266+
except FileNotFoundError:
267+
if os.path.exists(CONTROLLER_CACHE_DIRECTORY):
268+
raise
269+
os.makedirs(CONTROLLER_CACHE_DIRECTORY)
270+
os.chmod(CONTROLLER_CACHE_DIRECTORY, 0o700)
271+
return write_controller_uri_cache(uri)
272+
except Exception as e:
273+
util.SMlog('Unable to write URI cache file at `{}` : {}'.format(CONTROLLER_CACHE_PATH, e))
274+
275+
276+
def delete_controller_uri_cache(uri=None):
277+
try:
278+
with excl_writer(CONTROLLER_CACHE_PATH) as f:
279+
if uri and uri != _read_controller_uri_from_file(f):
280+
return
281+
f.seek(0)
282+
f.truncate()
283+
except FileNotFoundError:
284+
pass
285+
except Exception as e:
286+
util.SMlog('Unable to delete URI cache file at `{}` : {}'.format(CONTROLLER_CACHE_PATH, e))
287+
288+
289+
def build_controller_uri_cache():
290+
uri = ''
291+
try:
292+
with excl_writer(CONTROLLER_CACHE_PATH) as f:
293+
uri = _read_controller_uri_from_file(f)
294+
if uri:
295+
return uri
296+
uri = _get_controller_uri()
297+
if not uri:
298+
for retries in range(9):
299+
time.sleep(1)
300+
uri = _get_controller_uri()
301+
if uri:
302+
break
303+
if uri:
304+
_write_controller_uri_to_file(uri, f)
305+
except FileNotFoundError:
306+
if os.path.exists(CONTROLLER_CACHE_DIRECTORY):
307+
raise
308+
os.makedirs(CONTROLLER_CACHE_DIRECTORY)
309+
os.chmod(CONTROLLER_CACHE_DIRECTORY, 0o700)
310+
return build_controller_uri_cache()
311+
except Exception as e:
312+
util.SMlog('Unable to write URI cache file at `{}` : {}'.format(CONTROLLER_CACHE_PATH, e))
313+
314+
return uri
315+
316+
317+
def get_controller_uri():
318+
uri = read_controller_uri_cache()
319+
if not uri:
320+
uri = build_controller_uri_cache()
321+
return uri
210322

211323

212324
def get_controller_node_name():
@@ -429,6 +541,34 @@ def __init__(
429541
self._volume_info_cache_dirty = True
430542
self._build_volumes(repair=repair)
431543

544+
@staticmethod
545+
def create_from_cache(
546+
group_name, repair=False, logger=default_logger.__func__,
547+
attempt_count=30
548+
):
549+
"""
550+
Attempt to create a LinstorVolumeManager from cached data.
551+
If it fails, refresh the cache and retry once.
552+
553+
:param str group_name: The SR goup name to use.
554+
:param bool repair: If true we try to remove bad volumes due to a crash
555+
or unexpected behavior.
556+
:param function logger: Function to log messages.
557+
:param int attempt_count: Number of attempts to join the controller.
558+
"""
559+
uri = read_controller_uri_cache()
560+
if not uri:
561+
uri = build_controller_uri_cache()
562+
if not uri:
563+
raise LinstorVolumeManagerError(
564+
"Unable to retrieve a valid controller URI from cache or after rebuild."
565+
)
566+
567+
return LinstorVolumeManager(
568+
uri, group_name, repair=repair,
569+
logger=logger, attempt_count=attempt_count
570+
)
571+
432572
@property
433573
def group_name(self):
434574
"""
@@ -1772,6 +1912,7 @@ def create_sr(
17721912
DATABASE_PATH,
17731913
mount=False
17741914
)
1915+
delete_controller_uri_cache()
17751916
return sr
17761917

17771918
@classmethod
@@ -2615,8 +2756,10 @@ def connect(uri):
26152756

26162757
try:
26172758
return connect(uri)
2618-
except (linstor.errors.LinstorNetworkError, LinstorVolumeManagerError):
2759+
except LinstorVolumeManagerError:
26192760
pass
2761+
except linstor.errors.LinstorNetworkError:
2762+
delete_controller_uri_cache(uri)
26202763

26212764
if not keep_uri_unmodified:
26222765
uri = None

0 commit comments

Comments
 (0)