Skip to content

Commit f7f7cbd

Browse files
committed
feat(LinstorSR): improve DB volume robustness
- Use specific DRBD options to detect failures in a small delay. - Use these options to control quorum with drbd-reactor. - Provide a better compromise in terms of availability. Signed-off-by: Ronan Abhamon <ronan.abhamon@vates.tech>
1 parent f72cb09 commit f7f7cbd

2 files changed

Lines changed: 41 additions & 36 deletions

File tree

drivers/LinstorSR.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from linstorvolumemanager import get_controller_node_name
2626
from linstorvolumemanager import LinstorVolumeManager
2727
from linstorvolumemanager import LinstorVolumeManagerError
28+
from linstorvolumemanager import DATABASE_VOLUME_NAME
2829
from linstorvolumemanager import PERSISTENT_PREFIX
2930

3031
LINSTOR_AVAILABLE = True
@@ -618,7 +619,6 @@ def create(self, uuid, size) -> None:
618619
ips,
619620
self._redundancy,
620621
thin_provisioning=self._provisioning == 'thin',
621-
auto_quorum=self._monitor_db_quorum,
622622
logger=util.SMlog
623623
)
624624
self._vhdutil = LinstorVhdUtil(self.session, self._linstor)
@@ -677,6 +677,8 @@ def delete(self, uuid) -> None:
677677
)
678678

679679
try:
680+
if self._monitor_db_quorum:
681+
self._linstor.set_drbd_ha_properties(DATABASE_VOLUME_NAME, enabled=False)
680682
self._update_drbd_reactor_on_all_hosts(
681683
controller_node_name=node_name, enabled=False
682684
)
@@ -692,6 +694,8 @@ def delete(self, uuid) -> None:
692694
self._update_drbd_reactor_on_all_hosts(
693695
controller_node_name=node_name, enabled=True
694696
)
697+
if self._monitor_db_quorum:
698+
self._linstor.set_drbd_ha_properties(DATABASE_VOLUME_NAME, enabled=True)
695699
except Exception as e2:
696700
util.SMlog(
697701
'Failed to restart drbd-reactor after destroy fail: {}'
@@ -741,6 +745,9 @@ def attach(self, uuid) -> None:
741745
opterr='no such group: {}'.format(self._group_name)
742746
)
743747

748+
if self._monitor_db_quorum and self.is_master():
749+
self._linstor.set_drbd_ha_properties(DATABASE_VOLUME_NAME)
750+
744751
@override
745752
@_locked_load
746753
def detach(self, uuid) -> None:

drivers/linstorvolumemanager.py

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -927,6 +927,34 @@ def set_auto_promote_timeout(self, volume_uuid, timeout):
927927
.format(volume_uuid, error_str)
928928
)
929929

930+
def set_drbd_ha_properties(self, volume_name, enabled=True):
931+
"""
932+
Set or not HA DRBD properties required by drbd-reactor and
933+
by specific volumes.
934+
:param str volume_name: The volume to modify.
935+
:param bool enabled: Enable or disable HA properties.
936+
"""
937+
938+
properties = {
939+
'DrbdOptions/auto-quorum': 'disabled',
940+
'DrbdOptions/Resource/auto-promote': 'no',
941+
'DrbdOptions/Resource/on-no-data-accessible': 'io-error',
942+
'DrbdOptions/Resource/on-no-quorum': 'io-error',
943+
'DrbdOptions/Resource/on-suspended-primary-outdated': 'force-secondary',
944+
'DrbdOptions/Resource/quorum': 'majority'
945+
}
946+
if enabled:
947+
result = self._linstor.resource_dfn_modify(volume_name, properties)
948+
else:
949+
result = self._linstor.resource_dfn_modify(volume_name, {}, delete_props=list(properties.keys()))
950+
951+
error_str = self._get_error_str(result)
952+
if error_str:
953+
raise LinstorVolumeManagerError(
954+
'Could not modify HA DRBD properties on volume `{}`: {}'
955+
.format(volume_name, error_str)
956+
)
957+
930958
def get_volume_info(self, volume_uuid):
931959
"""
932960
Get the volume info of a particular volume.
@@ -1735,33 +1763,21 @@ def get_all_group_names(cls, base_name):
17351763
return [cls._build_group_name(base_name), cls._build_ha_group_name(base_name)]
17361764

17371765
@classmethod
1738-
def create_sr(
1739-
cls, group_name, ips, redundancy,
1740-
thin_provisioning, auto_quorum,
1741-
logger=default_logger.__func__
1742-
):
1766+
def create_sr(cls, group_name, ips, redundancy, thin_provisioning, logger=default_logger.__func__):
17431767
"""
17441768
Create a new SR on the given nodes.
17451769
:param str group_name: The SR group_name to use.
17461770
:param set(str) ips: Node ips.
17471771
:param int redundancy: How many copy of volumes should we store?
17481772
:param bool thin_provisioning: Use thin or thick provisioning.
1749-
:param bool auto_quorum: DB quorum is monitored by LINSTOR.
17501773
:param function logger: Function to log messages.
17511774
:return: A new LinstorSr instance.
17521775
:rtype: LinstorSr
17531776
"""
17541777

17551778
try:
17561779
cls._start_controller(start=True)
1757-
sr = cls._create_sr(
1758-
group_name,
1759-
ips,
1760-
redundancy,
1761-
thin_provisioning,
1762-
auto_quorum,
1763-
logger
1764-
)
1780+
sr = cls._create_sr(group_name, ips, redundancy, thin_provisioning, logger)
17651781
finally:
17661782
# Controller must be stopped and volume unmounted because
17671783
# it is the role of the drbd-reactor daemon to do the right
@@ -1775,11 +1791,7 @@ def create_sr(
17751791
return sr
17761792

17771793
@classmethod
1778-
def _create_sr(
1779-
cls, group_name, ips, redundancy,
1780-
thin_provisioning, auto_quorum,
1781-
logger=default_logger.__func__
1782-
):
1794+
def _create_sr(cls, group_name, ips, redundancy, thin_provisioning, logger=default_logger.__func__):
17831795
# 1. Check if SR already exists.
17841796
uri = 'linstor://localhost'
17851797

@@ -1921,7 +1933,7 @@ def _create_sr(
19211933
try:
19221934
logger('Creating database volume...')
19231935
volume_path = cls._create_database_volume(
1924-
lin, ha_group_name, storage_pool_name, node_names, redundancy, auto_quorum
1936+
lin, ha_group_name, storage_pool_name, node_names, redundancy
19251937
)
19261938
except LinstorVolumeManagerError as e:
19271939
if e.code != LinstorVolumeManagerError.ERR_VOLUME_EXISTS:
@@ -2695,7 +2707,7 @@ def _request_database_path(cls, lin, activate=False):
26952707

26962708
@classmethod
26972709
def _create_database_volume(
2698-
cls, lin, group_name, storage_pool_name, node_names, redundancy, auto_quorum
2710+
cls, lin, group_name, storage_pool_name, node_names, redundancy
26992711
):
27002712
try:
27012713
dfns = lin.resource_dfn_list_raise().resource_definitions
@@ -2779,20 +2791,6 @@ def _create_database_volume(
27792791
)
27802792
)
27812793

2782-
# We must modify the quorum. Otherwise we can't use correctly the
2783-
# drbd-reactor daemon.
2784-
if auto_quorum:
2785-
result = lin.resource_dfn_modify(DATABASE_VOLUME_NAME, {
2786-
'DrbdOptions/auto-quorum': 'disabled',
2787-
'DrbdOptions/Resource/quorum': 'majority'
2788-
})
2789-
error_str = cls._get_error_str(result)
2790-
if error_str:
2791-
raise LinstorVolumeManagerError(
2792-
'Could not activate quorum on database volume: {}'
2793-
.format(error_str)
2794-
)
2795-
27962794
# Create database and ensure path exists locally and
27972795
# on replicated devices.
27982796
current_device_path = cls._request_database_path(lin, activate=True)

0 commit comments

Comments
 (0)