os-brick/os_brick/initiator/connectors/base.py

130 lines
4.9 KiB
Python

# 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 glob
import os
from oslo_concurrency import processutils as putils
from oslo_log import log as logging
from os_brick import exception
from os_brick import initiator
from os_brick.i18n import _LE, _LW
from os_brick.initiator import host_driver
from os_brick.initiator import initiator_connector
from os_brick.initiator import linuxscsi
LOG = logging.getLogger(__name__)
class BaseLinuxConnector(initiator_connector.InitiatorConnector):
os_type = initiator.OS_TYPE_LINUX
def __init__(self, root_helper, driver=None, execute=None,
*args, **kwargs):
self._linuxscsi = linuxscsi.LinuxSCSI(root_helper, execute=execute)
if not driver:
driver = host_driver.HostDriver()
self.set_driver(driver)
super(BaseLinuxConnector, self).__init__(root_helper, execute=execute,
*args, **kwargs)
@staticmethod
def get_connector_properties(root_helper, *args, **kwargs):
"""The generic connector properties."""
multipath = kwargs['multipath']
enforce_multipath = kwargs['enforce_multipath']
props = {}
props['multipath'] = (multipath and
linuxscsi.LinuxSCSI.is_multipath_running(
enforce_multipath, root_helper,
execute=kwargs.get('execute')))
return props
def check_valid_device(self, path, run_as_root=True):
cmd = ('dd', 'if=%(path)s' % {"path": path},
'of=/dev/null', 'count=1')
out, info = None, None
try:
out, info = self._execute(*cmd, run_as_root=run_as_root,
root_helper=self._root_helper)
except putils.ProcessExecutionError as e:
LOG.error(_LE("Failed to access the device on the path "
"%(path)s: %(error)s."),
{"path": path, "error": e.stderr})
return False
# If the info is none, the path does not exist.
if info is None:
return False
return True
def get_all_available_volumes(self, connection_properties=None):
volumes = []
path = self.get_search_path()
if path:
# now find all entries in the search path
if os.path.isdir(path):
path_items = [path, '/*']
file_filter = ''.join(path_items)
volumes = glob.glob(file_filter)
return volumes
def _discover_mpath_device(self, device_wwn, connection_properties,
device_name):
"""This method discovers a multipath device.
Discover a multipath device based on a defined connection_property
and a device_wwn and return the multipath_id and path of the multipath
enabled device if there is one.
"""
path = self._linuxscsi.find_multipath_device_path(device_wwn)
device_path = None
multipath_id = None
if path is None:
# find_multipath_device only accept realpath not symbolic path
device_realpath = os.path.realpath(device_name)
mpath_info = self._linuxscsi.find_multipath_device(
device_realpath)
if mpath_info:
device_path = mpath_info['device']
multipath_id = device_wwn
else:
# we didn't find a multipath device.
# so we assume the kernel only sees 1 device
device_path = device_name
LOG.debug("Unable to find multipath device name for "
"volume. Using path %(device)s for volume.",
{'device': device_path})
else:
device_path = path
multipath_id = device_wwn
if connection_properties.get('access_mode', '') != 'ro':
try:
# Sometimes the multipath devices will show up as read only
# initially and need additional time/rescans to get to RW.
self._linuxscsi.wait_for_rw(device_wwn, device_path)
except exception.BlockDeviceReadOnly:
LOG.warning(_LW('Block device %s is still read-only. '
'Continuing anyway.'), device_path)
return device_path, multipath_id