Adding support for FibreChannelConnector for PPC64
For PPC64 architecture there is a different behavior to discover the host-devices and scsi disk rescan. Adding implementation for the same. Change-Id: Id2283195d2b6002175079070a0ff0a137a9d6806
This commit is contained in:
@@ -31,12 +31,15 @@ MULTIPATH_PATH_CHECK_REGEX = re.compile("\s+\d+:\d+:\d+:\d+\s+")
|
|||||||
PLATFORM_ALL = 'ALL'
|
PLATFORM_ALL = 'ALL'
|
||||||
PLATFORM_x86 = 'X86'
|
PLATFORM_x86 = 'X86'
|
||||||
PLATFORM_S390 = 'S390'
|
PLATFORM_S390 = 'S390'
|
||||||
|
PLATFORM_PPC64 = 'PPC64'
|
||||||
OS_TYPE_ALL = 'ALL'
|
OS_TYPE_ALL = 'ALL'
|
||||||
OS_TYPE_LINUX = 'LINUX'
|
OS_TYPE_LINUX = 'LINUX'
|
||||||
OS_TYPE_WINDOWS = 'WIN'
|
OS_TYPE_WINDOWS = 'WIN'
|
||||||
|
|
||||||
S390X = "s390x"
|
S390X = "s390x"
|
||||||
S390 = "s390"
|
S390 = "s390"
|
||||||
|
PPC64 = "ppc64"
|
||||||
|
PPC64LE = "ppc64le"
|
||||||
|
|
||||||
ISCSI = "ISCSI"
|
ISCSI = "ISCSI"
|
||||||
ISER = "ISER"
|
ISER = "ISER"
|
||||||
|
@@ -49,12 +49,15 @@ MULTIPATH_PATH_CHECK_REGEX = re.compile("\s+\d+:\d+:\d+:\d+\s+")
|
|||||||
PLATFORM_ALL = 'ALL'
|
PLATFORM_ALL = 'ALL'
|
||||||
PLATFORM_x86 = 'X86'
|
PLATFORM_x86 = 'X86'
|
||||||
PLATFORM_S390 = 'S390'
|
PLATFORM_S390 = 'S390'
|
||||||
|
PLATFORM_PPC64 = 'PPC64'
|
||||||
OS_TYPE_ALL = 'ALL'
|
OS_TYPE_ALL = 'ALL'
|
||||||
OS_TYPE_LINUX = 'LINUX'
|
OS_TYPE_LINUX = 'LINUX'
|
||||||
OS_TYPE_WINDOWS = 'WIN'
|
OS_TYPE_WINDOWS = 'WIN'
|
||||||
|
|
||||||
S390X = "s390x"
|
S390X = "s390x"
|
||||||
S390 = "s390"
|
S390 = "s390"
|
||||||
|
PPC64 = "ppc64"
|
||||||
|
PPC64LE = "ppc64le"
|
||||||
|
|
||||||
ISCSI = "ISCSI"
|
ISCSI = "ISCSI"
|
||||||
ISER = "ISER"
|
ISER = "ISER"
|
||||||
@@ -83,6 +86,8 @@ connector_list = [
|
|||||||
'os_brick.initiator.connectors.fibre_channel.FibreChannelConnector',
|
'os_brick.initiator.connectors.fibre_channel.FibreChannelConnector',
|
||||||
('os_brick.initiator.connectors.fibre_channel_s390x.'
|
('os_brick.initiator.connectors.fibre_channel_s390x.'
|
||||||
'FibreChannelConnectorS390X'),
|
'FibreChannelConnectorS390X'),
|
||||||
|
('os_brick.initiator.connectors.fibre_channel_ppc64.'
|
||||||
|
'FibreChannelConnectorPPC64'),
|
||||||
'os_brick.initiator.connectors.aoe.AoEConnector',
|
'os_brick.initiator.connectors.aoe.AoEConnector',
|
||||||
'os_brick.initiator.connectors.remotefs.RemoteFsConnector',
|
'os_brick.initiator.connectors.remotefs.RemoteFsConnector',
|
||||||
'os_brick.initiator.connectors.rbd.RBDConnector',
|
'os_brick.initiator.connectors.rbd.RBDConnector',
|
||||||
@@ -167,6 +172,13 @@ _connector_mapping_linux_s390x = {
|
|||||||
'os_brick.initiator.connectors.gpfs.GPFSConnector',
|
'os_brick.initiator.connectors.gpfs.GPFSConnector',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Mapping for the PPC64 platform
|
||||||
|
_connector_mapping_linux_ppc64 = {
|
||||||
|
initiator.FIBRE_CHANNEL:
|
||||||
|
('os_brick.initiator.connectors.fibre_channel_ppc64.'
|
||||||
|
'FibreChannelConnectorPPC64'),
|
||||||
|
}
|
||||||
|
|
||||||
# Mapping for the windows connectors
|
# Mapping for the windows connectors
|
||||||
_connector_mapping_windows = {
|
_connector_mapping_windows = {
|
||||||
initiator.ISCSI:
|
initiator.ISCSI:
|
||||||
@@ -257,6 +269,9 @@ class InitiatorConnector(object):
|
|||||||
_mapping = _connector_mapping_windows
|
_mapping = _connector_mapping_windows
|
||||||
elif arch in (initiator.S390, initiator.S390X):
|
elif arch in (initiator.S390, initiator.S390X):
|
||||||
_mapping = _connector_mapping_linux_s390x
|
_mapping = _connector_mapping_linux_s390x
|
||||||
|
elif arch in (initiator.PPC64, initiator.PPC64LE):
|
||||||
|
_mapping = _connector_mapping_linux_ppc64
|
||||||
|
|
||||||
else:
|
else:
|
||||||
_mapping = _connector_mapping_linux
|
_mapping = _connector_mapping_linux
|
||||||
|
|
||||||
|
65
os_brick/initiator/connectors/fibre_channel_ppc64.py
Normal file
65
os_brick/initiator/connectors/fibre_channel_ppc64.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# 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 initiator
|
||||||
|
from os_brick.initiator.connectors import fibre_channel
|
||||||
|
from os_brick.initiator import linuxfc
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class FibreChannelConnectorPPC64(fibre_channel.FibreChannelConnector):
|
||||||
|
"""Connector class to attach/detach Fibre Channel volumes on PPC64 arch."""
|
||||||
|
|
||||||
|
platform = initiator.PLATFORM_PPC64
|
||||||
|
|
||||||
|
def __init__(self, root_helper, driver=None,
|
||||||
|
execute=None, use_multipath=False,
|
||||||
|
device_scan_attempts=initiator.DEVICE_SCAN_ATTEMPTS_DEFAULT,
|
||||||
|
*args, **kwargs):
|
||||||
|
super(FibreChannelConnectorPPC64, self).__init__(
|
||||||
|
root_helper,
|
||||||
|
driver=driver,
|
||||||
|
execute=execute,
|
||||||
|
device_scan_attempts=device_scan_attempts,
|
||||||
|
*args, **kwargs)
|
||||||
|
self._linuxfc = linuxfc.LinuxFibreChannelPPC64(root_helper, execute)
|
||||||
|
self.use_multipath = use_multipath
|
||||||
|
|
||||||
|
def set_execute(self, execute):
|
||||||
|
super(FibreChannelConnectorPPC64, self).set_execute(execute)
|
||||||
|
self._linuxscsi.set_execute(execute)
|
||||||
|
self._linuxfc.set_execute(execute)
|
||||||
|
|
||||||
|
def _get_host_devices(self, possible_devs, lun):
|
||||||
|
host_devices = []
|
||||||
|
for pci_num, target_wwn in possible_devs:
|
||||||
|
host_device = "/dev/disk/by-path/fc-%s-lun-%s" % (
|
||||||
|
target_wwn,
|
||||||
|
self._linuxscsi.process_lun_id(lun))
|
||||||
|
host_devices.append(host_device)
|
||||||
|
return host_devices
|
||||||
|
|
||||||
|
def _get_possible_volume_paths(self, connection_properties, hbas):
|
||||||
|
ports = connection_properties['target_wwn']
|
||||||
|
it_map = connection_properties['initiator_target_map']
|
||||||
|
for hba in hbas:
|
||||||
|
if hba['node_name'] in it_map.keys():
|
||||||
|
hba['target_wwn'] = it_map.get(hba['node_name'])
|
||||||
|
possible_devs = self._get_possible_devices(hbas, ports)
|
||||||
|
lun = connection_properties.get('target_lun', 0)
|
||||||
|
host_paths = self._get_host_devices(possible_devs, lun)
|
||||||
|
return host_paths
|
@@ -265,3 +265,51 @@ class LinuxFibreChannelS390X(LinuxFibreChannel):
|
|||||||
LOG.warning("unit_remove call for s390 failed exit %(code)s, "
|
LOG.warning("unit_remove call for s390 failed exit %(code)s, "
|
||||||
"stderr %(stderr)s",
|
"stderr %(stderr)s",
|
||||||
{'code': exc.exit_code, 'stderr': exc.stderr})
|
{'code': exc.exit_code, 'stderr': exc.stderr})
|
||||||
|
|
||||||
|
|
||||||
|
class LinuxFibreChannelPPC64(LinuxFibreChannel):
|
||||||
|
|
||||||
|
def _get_hba_channel_scsi_target(self, hba, wwpn):
|
||||||
|
"""Try to get the HBA channel and SCSI target for an HBA.
|
||||||
|
|
||||||
|
This method works for Fibre Channel targets iterating over all the
|
||||||
|
target wwpn port and finding the c, t, l. so caller should expect us to
|
||||||
|
return either None or an empty list.
|
||||||
|
"""
|
||||||
|
# Leave only the number from the host_device field (ie: host6)
|
||||||
|
host_device = hba['host_device']
|
||||||
|
if host_device and len(host_device) > 4:
|
||||||
|
host_device = host_device[4:]
|
||||||
|
path = '/sys/class/fc_transport/target%s:' % host_device
|
||||||
|
cmd = 'grep -l %(wwpn)s %(path)s*/port_name' % {'wwpn': wwpn,
|
||||||
|
'path': path}
|
||||||
|
try:
|
||||||
|
out, _err = self._execute(cmd, shell=True)
|
||||||
|
return [line.split('/')[4].split(':')[1:]
|
||||||
|
for line in out.split('\n') if line.startswith(path)]
|
||||||
|
except Exception as exc:
|
||||||
|
LOG.error("Could not get HBA channel and SCSI target ID, "
|
||||||
|
"reason: %s", exc)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def rescan_hosts(self, hbas, target_lun):
|
||||||
|
for hba in hbas:
|
||||||
|
# Try to get HBA channel and SCSI target to use as filters
|
||||||
|
for wwpn in hba['target_wwn']:
|
||||||
|
cts = self._get_hba_channel_scsi_target(hba, wwpn)
|
||||||
|
# If we couldn't get the channel and target use wildcards
|
||||||
|
if not cts:
|
||||||
|
cts = [('-', '-')]
|
||||||
|
for hba_channel, target_id in cts:
|
||||||
|
LOG.debug('Scanning host %(host)s (wwpn: %(wwpn)s, c: '
|
||||||
|
'%(channel)s, t: %(target)s, l: %(lun)s)',
|
||||||
|
{'host': hba['host_device'],
|
||||||
|
'wwpn': hba['target_wwn'],
|
||||||
|
'channel': hba_channel,
|
||||||
|
'target': target_id,
|
||||||
|
'lun': target_lun})
|
||||||
|
self.echo_scsi_command(
|
||||||
|
"/sys/class/scsi_host/%s/scan" % hba['host_device'],
|
||||||
|
"%(c)s %(t)s %(l)s" % {'c': hba_channel,
|
||||||
|
't': target_id,
|
||||||
|
'l': target_lun})
|
||||||
|
@@ -0,0 +1,43 @@
|
|||||||
|
# (c) Copyright 2013 IBM Company
|
||||||
|
#
|
||||||
|
# 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 mock
|
||||||
|
|
||||||
|
from os_brick.initiator.connectors import fibre_channel_ppc64
|
||||||
|
from os_brick.initiator import linuxscsi
|
||||||
|
from os_brick.tests.initiator import test_connector
|
||||||
|
|
||||||
|
|
||||||
|
class FibreChannelConnectorPPC64TestCase(test_connector.ConnectorTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(FibreChannelConnectorPPC64TestCase, self).setUp()
|
||||||
|
self.connector = fibre_channel_ppc64.FibreChannelConnectorPPC64(
|
||||||
|
None, execute=self.fake_execute, use_multipath=False)
|
||||||
|
self.assertIsNotNone(self.connector)
|
||||||
|
self.assertIsNotNone(self.connector._linuxfc)
|
||||||
|
self.assertEqual(self.connector._linuxfc.__class__.__name__,
|
||||||
|
"LinuxFibreChannelPPC64")
|
||||||
|
self.assertIsNotNone(self.connector._linuxscsi)
|
||||||
|
|
||||||
|
@mock.patch.object(linuxscsi.LinuxSCSI, 'process_lun_id', return_value='2')
|
||||||
|
def test_get_host_devices(self, mock_process_lun_id):
|
||||||
|
lun = 2
|
||||||
|
possible_devs = [(3, "0x5005076802232ade"),
|
||||||
|
(3, "0x5005076802332ade"), ]
|
||||||
|
devices = self.connector._get_host_devices(possible_devs, lun)
|
||||||
|
self.assertEqual(2, len(devices))
|
||||||
|
device_path = "/dev/disk/by-path/fc-0x5005076802232ade-lun-2"
|
||||||
|
self.assertEqual(devices[0], device_path)
|
||||||
|
device_path = "/dev/disk/by-path/fc-0x5005076802332ade-lun-2"
|
||||||
|
self.assertEqual(devices[1], device_path)
|
Reference in New Issue
Block a user