os-brick/os_brick/initiator/utils.py
Gorka Eguileor 71a1e22418 Context manager to handle shared_targets
We introduced "shared_targets" and "service_uuid" fields in volumes to
allow volume consumers to protect themselves from unintended leftover
devices when handling iSCSI connections with shared targets.

The way they protect themselves from the automatic scans that happen on
detach/map race conditions is by locking and only allowing one attach or
one detach operation for each server to happen at a given time.

When using an up to date Open iSCSI initiator we don't need to use
locks, as it has the possibility to disable automatic LUN scans (which
are the real cause of the leftover devices), and OS-Brick already
supports this feature.

This is currently not the case, since Nova is blindly locking whenever
"shared_targets" is set to True.

Thanks to the context manager introduced in this patch we can improve
our separation of concerns (Nova doesn't have to care when we have to
lock), and we can fine tune the locking to only lock when the iSCSI
initiator doesn't support disabling automatic scans.

The context manager "guard_connection" lives in
"os_brick.initiator.utils" and needs a cinder volume.  The volume can be
passed as a dictionary or OVO instance.

Change-Id: I4970363301d5d1f4e7d0f07e09b34d15ee6884c3
Related-Bug: #1800515
2018-10-30 16:55:01 +01:00

47 lines
1.4 KiB
Python

# Copyright 2018 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import contextlib
import os
from oslo_concurrency import lockutils
from oslo_concurrency import processutils as putils
def check_manual_scan():
if os.name == 'nt':
return False
try:
putils.execute('grep', '-F', 'node.session.scan', '/sbin/iscsiadm')
except putils.ProcessExecutionError:
return False
return True
ISCSI_SUPPORTS_MANUAL_SCAN = check_manual_scan()
@contextlib.contextmanager
def guard_connection(device):
"""Context Manager handling locks for attach/detach operations."""
if ISCSI_SUPPORTS_MANUAL_SCAN or not device.get('shared_targets'):
yield
else:
# Cinder passes an OVO, but Nova passes a dictionary, so we use dict
# key access that works with both.
with lockutils.lock(device['service_uuid'], 'os-brick-'):
yield