128 lines
4.5 KiB
Python
128 lines
4.5 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.
|
|
|
|
from oslo_log import log as logging
|
|
|
|
from os_brick import exception
|
|
from os_brick.i18n import _
|
|
from os_brick import initiator
|
|
from os_brick.initiator.connectors import base
|
|
from os_brick.initiator import linuxsheepdog
|
|
from os_brick import utils
|
|
|
|
DEVICE_SCAN_ATTEMPTS_DEFAULT = 3
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class SheepdogConnector(base.BaseLinuxConnector):
|
|
""""Connector class to attach/detach sheepdog volumes."""
|
|
|
|
def __init__(self, root_helper, driver=None, use_multipath=False,
|
|
device_scan_attempts=initiator.DEVICE_SCAN_ATTEMPTS_DEFAULT,
|
|
*args, **kwargs):
|
|
|
|
super(SheepdogConnector, self).__init__(root_helper, driver=driver,
|
|
device_scan_attempts=
|
|
device_scan_attempts,
|
|
*args, **kwargs)
|
|
|
|
@staticmethod
|
|
def get_connector_properties(root_helper, *args, **kwargs):
|
|
"""The Sheepdog connector properties."""
|
|
return {}
|
|
|
|
def get_volume_paths(self, connection_properties):
|
|
# TODO(lixiaoy1): don't know where the connector
|
|
# looks for sheepdog volumes.
|
|
return []
|
|
|
|
def get_search_path(self):
|
|
# TODO(lixiaoy1): don't know where the connector
|
|
# looks for sheepdog volumes.
|
|
return None
|
|
|
|
def get_all_available_volumes(self, connection_properties=None):
|
|
# TODO(lixiaoy1): not sure what to return here for sheepdog
|
|
return []
|
|
|
|
def _get_sheepdog_handle(self, connection_properties):
|
|
try:
|
|
host = connection_properties['hosts'][0]
|
|
name = connection_properties['name']
|
|
port = connection_properties['ports'][0]
|
|
except IndexError:
|
|
msg = _("Connect volume failed, malformed connection properties")
|
|
raise exception.BrickException(msg=msg)
|
|
|
|
sheepdog_handle = linuxsheepdog.SheepdogVolumeIOWrapper(
|
|
host, port, name)
|
|
return sheepdog_handle
|
|
|
|
@utils.trace
|
|
def connect_volume(self, connection_properties):
|
|
"""Connect to a volume.
|
|
|
|
:param connection_properties: The dictionary that describes all
|
|
of the target volume attributes.
|
|
:type connection_properties: dict
|
|
:returns: dict
|
|
"""
|
|
|
|
sheepdog_handle = self._get_sheepdog_handle(connection_properties)
|
|
return {'path': sheepdog_handle}
|
|
|
|
@utils.trace
|
|
def disconnect_volume(self, connection_properties, device_info,
|
|
force=False, ignore_errors=False):
|
|
"""Disconnect a volume.
|
|
|
|
:param connection_properties: The dictionary that describes all
|
|
of the target volume attributes.
|
|
:type connection_properties: dict
|
|
:param device_info: historical difference, but same as connection_props
|
|
:type device_info: dict
|
|
"""
|
|
if device_info:
|
|
sheepdog_handle = device_info.get('path', None)
|
|
self.check_IO_handle_valid(sheepdog_handle,
|
|
linuxsheepdog.SheepdogVolumeIOWrapper,
|
|
'Sheepdog')
|
|
if sheepdog_handle is not None:
|
|
sheepdog_handle.close()
|
|
|
|
def check_valid_device(self, path, run_as_root=True):
|
|
"""Verify an existing sheepdog handle is connected and valid."""
|
|
sheepdog_handle = path
|
|
|
|
if sheepdog_handle is None:
|
|
return False
|
|
|
|
original_offset = sheepdog_handle.tell()
|
|
|
|
try:
|
|
sheepdog_handle.read(4096)
|
|
except Exception as e:
|
|
LOG.error("Failed to access sheepdog device "
|
|
"handle: %(error)s",
|
|
{"error": e})
|
|
return False
|
|
finally:
|
|
sheepdog_handle.seek(original_offset, 0)
|
|
|
|
return True
|
|
|
|
def extend_volume(self, connection_properties):
|
|
# TODO(lixiaoy1): is this possible?
|
|
raise NotImplementedError
|