-
Notifications
You must be signed in to change notification settings - Fork 7
feat(linstorvolumemanager): cache controller uri in a file #83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 3.2.12-8.3
Are you sure you want to change the base?
Changes from all commits
bcb21f0
c981335
81e8ec2
cb37708
81355f5
fbf38e1
6f57a6b
8d46a87
99f90e6
674cca7
abffda5
f32542e
64a8e15
945dc64
4e0d68d
1dbb248
9760980
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,7 @@ | |
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
from linstorvolumemanager import write_controller_uri_cache | ||
from sm_typing import Optional, override | ||
|
||
from constants import CBTLOG_TAG | ||
|
@@ -420,6 +420,7 @@ def connect(): | |
try: | ||
util.SMlog('Connecting from config to LINSTOR controller using: {}'.format(ip)) | ||
create_linstor(controller_uri, attempt_count=0) | ||
write_controller_uri_cache(controller_uri) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function might make more sense line 434. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No that's correct. This code part is only executed when we can't reuse the cached value. If you move it line 434, the write call would be executed multiple times for each on-slave call. |
||
return controller_uri | ||
except: | ||
pass | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,8 @@ | |
|
||
|
||
from linstorvolumemanager import \ | ||
get_controller_uri, LinstorVolumeManager, LinstorVolumeManagerError | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you sort the imports? If the line is too long, don't hesitate to make several. |
||
get_controller_uri, LinstorVolumeManager, LinstorVolumeManagerError, build_controller_uri_cache, \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only |
||
delete_controller_uri_cache | ||
import linstor | ||
import re | ||
import util | ||
|
@@ -160,8 +161,10 @@ def connect(uri): | |
|
||
try: | ||
return connect(uri) | ||
except (linstor.errors.LinstorNetworkError, LinstorVolumeManagerError): | ||
except LinstorVolumeManagerError: | ||
pass | ||
except linstor.errors.LinstorNetworkError: | ||
delete_controller_uri_cache() | ||
|
||
return util.retry( | ||
lambda: connect(None), | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -43,6 +43,10 @@ | |||||||||||||||||
|
||||||||||||||||||
DRBD_BY_RES_PATH = '/dev/drbd/by-res/' | ||||||||||||||||||
|
||||||||||||||||||
CONTROLLER_CACHE_DIRECTORY = os.environ.get('TMPDIR', '/tmp') + '/linstor' | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have dedicated places for nonpersistent SR related data in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I hesitated to add such a comment. But I see a problem: if we want to support multiple LINSTOR SRs, we cannot use a non-persistent directory with a specific SR UUID. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having it in |
||||||||||||||||||
CONTROLLER_CACHE_FILE = 'controller_uri' | ||||||||||||||||||
CONTROLLER_CACHE_PATH = "{}/{}".format(CONTROLLER_CACHE_DIRECTORY, CONTROLLER_CACHE_FILE) | ||||||||||||||||||
|
||||||||||||||||||
PLUGIN = 'linstor-manager' | ||||||||||||||||||
|
||||||||||||||||||
|
||||||||||||||||||
|
@@ -196,18 +200,57 @@ def _get_controller_uri(): | |||||||||||||||||
# Not found, maybe we are trying to create the SR... | ||||||||||||||||||
pass | ||||||||||||||||||
|
||||||||||||||||||
def get_controller_uri(): | ||||||||||||||||||
retries = 0 | ||||||||||||||||||
while True: | ||||||||||||||||||
|
||||||||||||||||||
def get_cached_controller_uri(): | ||||||||||||||||||
try: | ||||||||||||||||||
with open(CONTROLLER_CACHE_PATH, "r") as f: | ||||||||||||||||||
return f.read().strip() | ||||||||||||||||||
except Exception as e: | ||||||||||||||||||
util.SMlog('Unable to read controller uri cache file at {} : {}'.format( | ||||||||||||||||||
CONTROLLER_CACHE_PATH, | ||||||||||||||||||
e | ||||||||||||||||||
)) | ||||||||||||||||||
Comment on lines
+209
to
+212
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also: I'm not sure that's a good idea to log if the file is missing. Maybe it's better to log in case of a real error like a disk failure. |
||||||||||||||||||
return None | ||||||||||||||||||
|
||||||||||||||||||
def delete_controller_uri_cache(): | ||||||||||||||||||
try: | ||||||||||||||||||
os.remove(CONTROLLER_CACHE_PATH) | ||||||||||||||||||
except Exception as e: | ||||||||||||||||||
util.SMlog('Unable to write controller uri cache file at {} : {}'.format( | ||||||||||||||||||
CONTROLLER_CACHE_PATH, | ||||||||||||||||||
e | ||||||||||||||||||
)) | ||||||||||||||||||
Comment on lines
+219
to
+222
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same, don't see a reason to log if the file is not here. |
||||||||||||||||||
|
||||||||||||||||||
def write_controller_uri_cache(uri): | ||||||||||||||||||
try: | ||||||||||||||||||
if not os.path.exists(CONTROLLER_CACHE_DIRECTORY): | ||||||||||||||||||
os.makedirs(CONTROLLER_CACHE_DIRECTORY) | ||||||||||||||||||
os.chmod(CONTROLLER_CACHE_DIRECTORY, 0o700) | ||||||||||||||||||
if not os.path.isdir(CONTROLLER_CACHE_DIRECTORY): | ||||||||||||||||||
raise NotADirectoryError | ||||||||||||||||||
Comment on lines
+229
to
+230
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure that's important here. You will have an error raised by the next open call if we don't manipulate a file. |
||||||||||||||||||
with open(CONTROLLER_CACHE_PATH, "w") as f: | ||||||||||||||||||
f.write(uri) | ||||||||||||||||||
except Exception as e: | ||||||||||||||||||
util.SMlog('Unable to write controller uri cache file at {} : {}'.format( | ||||||||||||||||||
CONTROLLER_CACHE_PATH, | ||||||||||||||||||
e | ||||||||||||||||||
)) | ||||||||||||||||||
Comment on lines
+234
to
+237
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||
|
||||||||||||||||||
|
||||||||||||||||||
def build_controller_uri_cache(): | ||||||||||||||||||
for _ in range(10): | ||||||||||||||||||
uri = _get_controller_uri() | ||||||||||||||||||
if uri: | ||||||||||||||||||
write_controller_uri_cache(uri) | ||||||||||||||||||
return uri | ||||||||||||||||||
|
||||||||||||||||||
retries += 1 | ||||||||||||||||||
if retries >= 10: | ||||||||||||||||||
break | ||||||||||||||||||
Comment on lines
-206
to
-208
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand the range() call here. But in the worst case you can wait 1s for nothing when the last range value is reached. |
||||||||||||||||||
time.sleep(1) | ||||||||||||||||||
return None | ||||||||||||||||||
|
||||||||||||||||||
def get_controller_uri(): | ||||||||||||||||||
uri = get_cached_controller_uri() | ||||||||||||||||||
if not uri: | ||||||||||||||||||
uri = build_controller_uri_cache() | ||||||||||||||||||
return uri | ||||||||||||||||||
|
||||||||||||||||||
def get_controller_node_name(): | ||||||||||||||||||
PLUGIN_CMD = 'hasControllerRunning' | ||||||||||||||||||
|
@@ -429,6 +472,34 @@ def __init__( | |||||||||||||||||
self._volume_info_cache_dirty = True | ||||||||||||||||||
self._build_volumes(repair=repair) | ||||||||||||||||||
|
||||||||||||||||||
@staticmethod | ||||||||||||||||||
def create_from_cache( | ||||||||||||||||||
group_name, repair=False, logger=default_logger.__func__, | ||||||||||||||||||
attempt_count=30 | ||||||||||||||||||
): | ||||||||||||||||||
""" | ||||||||||||||||||
Attempt to create a LinstorVolumeManager from cached data. | ||||||||||||||||||
If it fails, refresh the cache and retry once. | ||||||||||||||||||
|
||||||||||||||||||
:param str group_name: The SR goup name to use. | ||||||||||||||||||
:param bool repair: If true we try to remove bad volumes due to a crash | ||||||||||||||||||
or unexpected behavior. | ||||||||||||||||||
:param function logger: Function to log messages. | ||||||||||||||||||
:param int attempt_count: Number of attempts to join the controller. | ||||||||||||||||||
""" | ||||||||||||||||||
uri = get_cached_controller_uri() | ||||||||||||||||||
if not uri: | ||||||||||||||||||
uri = build_controller_uri_cache() | ||||||||||||||||||
if not uri: | ||||||||||||||||||
raise LinstorVolumeManagerError( | ||||||||||||||||||
"Unable to retrieve a valid controller URI from cache or after rebuild." | ||||||||||||||||||
) | ||||||||||||||||||
|
||||||||||||||||||
return LinstorVolumeManager( | ||||||||||||||||||
uri, group_name, repair=repair, | ||||||||||||||||||
logger=logger, attempt_count=attempt_count | ||||||||||||||||||
) | ||||||||||||||||||
|
||||||||||||||||||
@property | ||||||||||||||||||
def group_name(self): | ||||||||||||||||||
""" | ||||||||||||||||||
|
@@ -2598,7 +2669,7 @@ def _get_error_str(cls, result): | |||||||||||||||||
|
||||||||||||||||||
@classmethod | ||||||||||||||||||
def _create_linstor_instance( | ||||||||||||||||||
cls, uri, keep_uri_unmodified=False, attempt_count=30 | ||||||||||||||||||
cls, uri, keep_uri_unmodified=False, keep_cache_on_error=False, attempt_count=30 | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess you can remove this new |
||||||||||||||||||
): | ||||||||||||||||||
retry = False | ||||||||||||||||||
|
||||||||||||||||||
|
@@ -2615,8 +2686,11 @@ def connect(uri): | |||||||||||||||||
|
||||||||||||||||||
try: | ||||||||||||||||||
return connect(uri) | ||||||||||||||||||
except (linstor.errors.LinstorNetworkError, LinstorVolumeManagerError): | ||||||||||||||||||
except LinstorVolumeManagerError: | ||||||||||||||||||
pass | ||||||||||||||||||
except linstor.errors.LinstorNetworkError: | ||||||||||||||||||
if not keep_cache_on_error: | ||||||||||||||||||
build_controller_uri_cache() | ||||||||||||||||||
|
||||||||||||||||||
if not keep_uri_unmodified: | ||||||||||||||||||
uri = None | ||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anything imported from
sm_typing
should come before any other imports. This module contains everything important for typing the project.And more important: you must move this import in the try/catch below, otherwise if LINSTOR python packages are not installed, it can have serious repercussions on the XAPI driver detection.