Merge "Fix Brcd lookup service to use defined southbound protocol"
This commit is contained in:
commit
5ad5809c8c
@ -1,4 +1,4 @@
|
||||
# (c) Copyright 2014 Brocade Communications Systems Inc.
|
||||
# (c) Copyright 2016 Brocade Communications Systems Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
@ -18,16 +18,13 @@
|
||||
"""Unit tests for brcd fc san lookup service."""
|
||||
|
||||
import mock
|
||||
from oslo_concurrency import processutils as putils
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import importutils
|
||||
|
||||
from cinder import exception
|
||||
from cinder import ssh_utils
|
||||
from cinder import test
|
||||
from cinder.volume import configuration as conf
|
||||
import cinder.zonemanager.drivers.brocade.brcd_fc_san_lookup_service \
|
||||
as brcd_lookup
|
||||
from cinder.zonemanager.drivers.brocade import fc_zone_constants
|
||||
|
||||
|
||||
parsed_switch_port_wwns = ['20:1a:00:05:1e:e8:e3:29',
|
||||
@ -76,6 +73,10 @@ class TestBrcdFCSanLookupService(brcd_lookup.BrcdFCSanLookupService,
|
||||
self.configuration.set_default('fc_fabric_names', 'BRCD_FAB_2',
|
||||
'fc-zone-manager')
|
||||
self.configuration.fc_fabric_names = 'BRCD_FAB_2'
|
||||
self.configuration.brcd_sb_connector = ('cinder.tests.unit.zonemanager'
|
||||
'.test_brcd_fc_san_lookup_'
|
||||
'service'
|
||||
'.FakeBrcdFCZoneClientCLI')
|
||||
self.create_configuration()
|
||||
|
||||
# override some of the functions
|
||||
@ -98,46 +99,57 @@ class TestBrcdFCSanLookupService(brcd_lookup.BrcdFCSanLookupService,
|
||||
config = conf.Configuration(fc_fabric_opts, 'BRCD_FAB_2')
|
||||
self.fabric_configs = {'BRCD_FAB_2': config}
|
||||
|
||||
def get_client(self, protocol='HTTPS'):
|
||||
conn = ('cinder.tests.unit.zonemanager.'
|
||||
'test_brcd_fc_san_lookup_service.' +
|
||||
('FakeBrcdFCZoneClientCLI' if protocol == "CLI"
|
||||
else 'FakeBrcdHttpFCZoneClient'))
|
||||
client = importutils.import_object(
|
||||
conn,
|
||||
ipaddress="10.24.48.213",
|
||||
username="admin",
|
||||
password="password",
|
||||
key="/home/stack/.ssh/id_rsa",
|
||||
port=22,
|
||||
vfid="2",
|
||||
protocol=protocol
|
||||
)
|
||||
return client
|
||||
|
||||
@mock.patch.object(brcd_lookup.BrcdFCSanLookupService,
|
||||
'get_nameserver_info')
|
||||
@mock.patch('cinder.zonemanager.drivers.brocade.brcd_fc_san_lookup_service'
|
||||
'.ssh_utils.SSHPool')
|
||||
def test_get_device_mapping_from_network(self, mock_ssh_pool,
|
||||
get_nameserver_info_mock):
|
||||
'_get_southbound_client')
|
||||
def test_get_device_mapping_from_network(self, get_southbound_client_mock):
|
||||
initiator_list = [parsed_switch_port_wwns[1]]
|
||||
target_list = [parsed_switch_port_wwns[0], '20240002ac000a40']
|
||||
get_nameserver_info_mock.return_value = parsed_switch_port_wwns
|
||||
get_southbound_client_mock.return_value = self.get_client("HTTPS")
|
||||
device_map = self.get_device_mapping_from_network(
|
||||
initiator_list, target_list)
|
||||
self.assertDictMatch(_device_map_to_verify, device_map)
|
||||
|
||||
@mock.patch.object(brcd_lookup.BrcdFCSanLookupService, '_get_switch_data')
|
||||
def test_get_nameserver_info(self, get_switch_data_mock):
|
||||
ns_info_list = []
|
||||
|
||||
get_switch_data_mock.return_value = (switch_data)
|
||||
# get_switch_data will be called twice with the results appended
|
||||
ns_info_list_expected = (parsed_switch_port_wwns +
|
||||
parsed_switch_port_wwns)
|
||||
class FakeClient(object):
|
||||
def is_supported_firmware(self):
|
||||
return True
|
||||
|
||||
ns_info_list = self.get_nameserver_info(None)
|
||||
self.assertEqual(ns_info_list_expected, ns_info_list)
|
||||
def get_nameserver_info(self):
|
||||
ns_info_list_expected = (parsed_switch_port_wwns)
|
||||
return ns_info_list_expected
|
||||
|
||||
@mock.patch.object(putils, 'ssh_execute', return_value=(switch_data, ''))
|
||||
@mock.patch.object(ssh_utils.SSHPool, 'item')
|
||||
def test__get_switch_data(self, ssh_pool_mock, ssh_execute_mock):
|
||||
actual_switch_data = self._get_switch_data(ssh_pool_mock,
|
||||
fc_zone_constants.NS_SHOW)
|
||||
self.assertEqual(actual_switch_data, switch_data)
|
||||
ssh_execute_mock.side_effect = putils.ProcessExecutionError()
|
||||
self.assertRaises(exception.FCSanLookupServiceException,
|
||||
self._get_switch_data, ssh_pool_mock,
|
||||
fc_zone_constants.NS_SHOW)
|
||||
def close_connection(self):
|
||||
pass
|
||||
|
||||
def test__parse_ns_output(self):
|
||||
invalid_switch_data = ' N 011a00;20:1a:00:05:1e:e8:e3:29'
|
||||
return_wwn_list = []
|
||||
return_wwn_list = self._parse_ns_output(switch_data)
|
||||
self.assertEqual(parsed_switch_port_wwns, return_wwn_list)
|
||||
self.assertRaises(exception.InvalidParameterValue,
|
||||
self._parse_ns_output, invalid_switch_data)
|
||||
def cleanup(self):
|
||||
pass
|
||||
|
||||
|
||||
class FakeBrcdFCZoneClientCLI(FakeClient):
|
||||
def __init__(self, ipaddress, username,
|
||||
password, port, key, vfid, protocol):
|
||||
self.firmware_supported = True
|
||||
|
||||
|
||||
class FakeBrcdHttpFCZoneClient(FakeClient):
|
||||
|
||||
def __init__(self, ipaddress, username,
|
||||
password, port, key, vfid, protocol):
|
||||
self.firmware_supported = True
|
||||
|
@ -1,8 +1,6 @@
|
||||
# (c) Copyright 2014 Brocade Communications Systems Inc.
|
||||
# (c) Copyright 2016 Brocade Communications Systems Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Copyright 2014 OpenStack Foundation
|
||||
#
|
||||
# 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
|
||||
@ -16,17 +14,13 @@
|
||||
# under the License.
|
||||
#
|
||||
|
||||
from oslo_concurrency import processutils
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
import six
|
||||
from oslo_utils import importutils
|
||||
|
||||
from cinder import exception
|
||||
from cinder.i18n import _, _LE
|
||||
from cinder import ssh_utils
|
||||
from cinder import utils
|
||||
from cinder.zonemanager.drivers.brocade import brcd_fabric_opts as fabric_opts
|
||||
import cinder.zonemanager.drivers.brocade.fc_zone_constants as zone_constant
|
||||
from cinder.zonemanager import fc_san_lookup_service as fc_service
|
||||
from cinder.zonemanager import utils as fczm_utils
|
||||
|
||||
@ -38,10 +32,11 @@ class BrcdFCSanLookupService(fc_service.FCSanLookupService):
|
||||
|
||||
Version History:
|
||||
1.0.0 - Initial version
|
||||
1.1 - Add support to use config option for switch southbound protocol
|
||||
|
||||
"""
|
||||
|
||||
VERSION = "1.0.0"
|
||||
VERSION = "1.1"
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
"""Initializing the client."""
|
||||
@ -107,15 +102,6 @@ class BrcdFCSanLookupService(fc_service.FCSanLookupService):
|
||||
for fabric_name in fabrics:
|
||||
fabric_ip = self.fabric_configs[fabric_name].safe_get(
|
||||
'fc_fabric_address')
|
||||
fabric_user = self.fabric_configs[fabric_name].safe_get(
|
||||
'fc_fabric_user')
|
||||
fabric_pwd = self.fabric_configs[fabric_name].safe_get(
|
||||
'fc_fabric_password')
|
||||
fabric_port = self.fabric_configs[fabric_name].safe_get(
|
||||
'fc_fabric_port')
|
||||
|
||||
ssh_pool = ssh_utils.SSHPool(fabric_ip, fabric_port, None,
|
||||
fabric_user, password=fabric_pwd)
|
||||
|
||||
# Get name server data from fabric and find the targets
|
||||
# logged in
|
||||
@ -123,7 +109,8 @@ class BrcdFCSanLookupService(fc_service.FCSanLookupService):
|
||||
try:
|
||||
LOG.debug("Getting name server data for "
|
||||
"fabric %s", fabric_ip)
|
||||
nsinfo = self.get_nameserver_info(ssh_pool)
|
||||
conn = self._get_southbound_client(fabric_name)
|
||||
nsinfo = conn.get_nameserver_info()
|
||||
except exception.FCSanLookupServiceException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE("Failed collecting name server info from"
|
||||
@ -172,69 +159,28 @@ class BrcdFCSanLookupService(fc_service.FCSanLookupService):
|
||||
LOG.debug("Device map for SAN context: %s", device_map)
|
||||
return device_map
|
||||
|
||||
def get_nameserver_info(self, ssh_pool):
|
||||
"""Get name server data from fabric.
|
||||
def _get_southbound_client(self, fabric):
|
||||
"""Implementation to get SouthBound Connector.
|
||||
|
||||
This method will return the connected node port wwn list(local
|
||||
and remote) for the given switch fabric
|
||||
South bound connector will be
|
||||
dynamically selected based on the configuration
|
||||
|
||||
:param ssh_pool: SSH connections for the current fabric
|
||||
:param fabric: fabric information
|
||||
"""
|
||||
cli_output = None
|
||||
nsinfo_list = []
|
||||
fabric_info = self.fabric_configs[fabric]
|
||||
fc_ip = fabric_info.safe_get('fc_fabric_address')
|
||||
sb_connector = fabric_info.safe_get('fc_southbound_protocol')
|
||||
if sb_connector is None:
|
||||
sb_connector = self.configuration.brcd_sb_connector
|
||||
try:
|
||||
cli_output = self._get_switch_data(ssh_pool,
|
||||
zone_constant.NS_SHOW)
|
||||
except exception.FCSanLookupServiceException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE("Failed collecting nsshow info for fabric"))
|
||||
if cli_output:
|
||||
nsinfo_list = self._parse_ns_output(cli_output)
|
||||
try:
|
||||
cli_output = self._get_switch_data(ssh_pool,
|
||||
zone_constant.NS_CAM_SHOW)
|
||||
|
||||
except exception.FCSanLookupServiceException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE("Failed collecting nscamshow"))
|
||||
if cli_output:
|
||||
nsinfo_list.extend(self._parse_ns_output(cli_output))
|
||||
LOG.debug("Connector returning nsinfo-%s", nsinfo_list)
|
||||
return nsinfo_list
|
||||
|
||||
def _get_switch_data(self, ssh_pool, cmd):
|
||||
utils.check_ssh_injection([cmd])
|
||||
|
||||
with ssh_pool.item() as ssh:
|
||||
try:
|
||||
switch_data, err = processutils.ssh_execute(ssh, cmd)
|
||||
except processutils.ProcessExecutionError as e:
|
||||
msg = (_("SSH Command failed with error: '%(err)s', Command: "
|
||||
"'%(command)s'") % {'err': six.text_type(e),
|
||||
'command': cmd})
|
||||
LOG.error(msg)
|
||||
raise exception.FCSanLookupServiceException(message=msg)
|
||||
|
||||
return switch_data
|
||||
|
||||
def _parse_ns_output(self, switch_data):
|
||||
"""Parses name server data.
|
||||
|
||||
Parses nameserver raw data and adds the device port wwns to the list
|
||||
|
||||
:returns: list of device port wwn from ns info
|
||||
"""
|
||||
nsinfo_list = []
|
||||
lines = switch_data.split('\n')
|
||||
for line in lines:
|
||||
if not(" NL " in line or " N " in line):
|
||||
continue
|
||||
linesplit = line.split(';')
|
||||
if len(linesplit) > 2:
|
||||
node_port_wwn = linesplit[2].strip()
|
||||
nsinfo_list.append(node_port_wwn)
|
||||
else:
|
||||
msg = _("Malformed nameserver string: %s") % line
|
||||
LOG.error(msg)
|
||||
raise exception.InvalidParameterValue(err=msg)
|
||||
return nsinfo_list
|
||||
conn_factory = importutils.import_object(
|
||||
"cinder.zonemanager.drivers.brocade."
|
||||
"brcd_fc_zone_connector_factory."
|
||||
"BrcdFCZoneFactory")
|
||||
client = conn_factory.get_connector(fabric_info,
|
||||
sb_connector.upper())
|
||||
except Exception:
|
||||
msg = _("Failed to create south bound connector for %s.") % fc_ip
|
||||
LOG.exception(msg)
|
||||
raise exception.FCZoneDriverException(msg)
|
||||
return client
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- Support for use of 'fc_southbound_protocol'
|
||||
configuration setting in the Brocade FC SAN
|
||||
lookup service.
|
Loading…
Reference in New Issue
Block a user