Add cinder volume drivers for NEC V series Storage

VStorageISCSIDriver is an iSCSI driver.
VStorageFCDriver is a Fibre Channel driver.
These drivers import Hitachi driver, and parameters are customized for
NEC.

Implements: blueprint nec-v-volume-driver
Change-Id: I7e7ebea51f8c3c80df99eb85a8327e5b8d1b63c6
This commit is contained in:
Naoki Saito 2021-10-27 09:46:18 +00:00
parent 4082ed3bea
commit c4f5564d99
12 changed files with 1419 additions and 0 deletions

View File

@ -138,6 +138,8 @@ from cinder.volume.drivers import linstordrv as \
from cinder.volume.drivers import lvm as cinder_volume_drivers_lvm
from cinder.volume.drivers.macrosan import driver as \
cinder_volume_drivers_macrosan_driver
from cinder.volume.drivers.nec.v import nec_v_rest as \
cinder_volume_drivers_nec_v_necvrest
from cinder.volume.drivers.netapp import options as \
cinder_volume_drivers_netapp_options
from cinder.volume.drivers.nexenta import options as \
@ -353,6 +355,9 @@ def list_opts():
cinder_volume_drivers_linstordrv.linstor_opts,
cinder_volume_drivers_lvm.volume_opts,
cinder_volume_drivers_macrosan_driver.config.macrosan_opts,
cinder_volume_drivers_nec_v_necvrest.COMMON_VOLUME_OPTS,
cinder_volume_drivers_nec_v_necvrest.REST_VOLUME_OPTS,
cinder_volume_drivers_nec_v_necvrest.FC_VOLUME_OPTS,
cinder_volume_drivers_netapp_options.netapp_proxy_opts,
cinder_volume_drivers_netapp_options.netapp_connection_opts,
cinder_volume_drivers_netapp_options.netapp_transport_opts,

View File

@ -0,0 +1,383 @@
# Copyright (C) 2021 NEC corporation
#
# 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.
#
"""Unit tests for NEC Driver."""
from unittest import mock
from oslo_config import cfg
import requests
from cinder import context as cinder_context
from cinder import db
from cinder.tests.unit import fake_volume
from cinder.tests.unit import test
from cinder.volume import configuration as conf
from cinder.volume.drivers.hitachi import hbsd_rest
from cinder.volume.drivers.hitachi import hbsd_rest_api
from cinder.volume.drivers.nec.v import nec_v_fc
from cinder.volume.drivers.nec.v import nec_v_rest
from cinder.volume import volume_utils
# Configuration parameter values
CONFIG_MAP = {
'serial': '886000123456',
'my_ip': '127.0.0.1',
'rest_server_ip_addr': '172.16.18.108',
'rest_server_ip_port': '23451',
'port_id': 'CL1-A',
'host_grp_name': 'NEC-0123456789abcdef',
'host_mode': 'LINUX/IRIX',
'host_wwn': '0123456789abcdef',
'target_wwn': '1111111123456789',
'user_id': 'user',
'user_pass': 'password',
'pool_name': 'test_pool',
'auth_user': 'auth_user',
'auth_password': 'auth_password',
}
# Dummy response
DEFAULT_CONNECTOR = {
'host': 'host',
'ip': CONFIG_MAP['my_ip'],
'wwpns': [CONFIG_MAP['host_wwn']],
'multipath': False,
}
# Dummy response for REST API
POST_SESSIONS_RESULT = {
"token": "b74777a3-f9f0-4ea8-bd8f-09847fac48d3",
"sessionId": 0,
}
GET_PORTS_RESULT = {
"data": [
{
"portId": CONFIG_MAP['port_id'],
"portType": "FIBRE",
"portAttributes": [
"TAR",
"MCU",
"RCU",
"ELUN"
],
"fabricMode": True,
"portConnection": "PtoP",
"lunSecuritySetting": True,
"wwn": CONFIG_MAP['target_wwn'],
},
],
}
GET_HOST_WWNS_RESULT = {
"data": [
{
"hostGroupNumber": 0,
"hostWwn": CONFIG_MAP['host_wwn'],
},
],
}
COMPLETED_SUCCEEDED_RESULT = {
"status": "Completed",
"state": "Succeeded",
"affectedResources": ('a/b/c/1',),
}
def _brick_get_connector_properties(multipath=False, enforce_multipath=False):
"""Return a predefined connector object."""
return DEFAULT_CONNECTOR
class FakeResponse():
def __init__(self, status_code, data=None, headers=None):
self.status_code = status_code
self.data = data
self.text = data
self.content = data
self.headers = {'Content-Type': 'json'} if headers is None else headers
def json(self):
return self.data
class VStorageRESTFCDriverTest(test.TestCase):
"""Unit test class for NEC REST interface fibre channel module."""
test_existing_ref = {'source-id': '1'}
test_existing_ref_name = {
'source-name': '15960cc7-38c9-4c5b-b4f1-365be5eeed45'}
def setUp(self):
"""Set up the test environment."""
def _set_required(opts, required):
for opt in opts:
opt.required = required
# Initialize Cinder and avoid checking driver options.
rest_required_opts = [
opt for opt in nec_v_rest.REST_VOLUME_OPTS if opt.required]
common_required_opts = [
opt for opt in nec_v_rest.COMMON_VOLUME_OPTS if opt.required]
_set_required(rest_required_opts, False)
_set_required(common_required_opts, False)
super(VStorageRESTFCDriverTest, self).setUp()
_set_required(rest_required_opts, True)
_set_required(common_required_opts, True)
self.configuration = mock.Mock(conf.Configuration)
self.ctxt = cinder_context.get_admin_context()
self._setup_config()
self._setup_driver()
def _setup_config(self):
"""Set configuration parameter values."""
self.configuration.config_group = "REST"
self.configuration.volume_backend_name = "RESTFC"
self.configuration.volume_driver = (
"cinder.volume.drivers.nec.v.nec_v_fc.VStorageFCDriver")
self.configuration.reserved_percentage = "0"
self.configuration.use_multipath_for_image_xfer = False
self.configuration.enforce_multipath_for_image_xfer = False
self.configuration.max_over_subscription_ratio = 500.0
self.configuration.driver_ssl_cert_verify = False
self.configuration.nec_v_storage_id = CONFIG_MAP['serial']
self.configuration.nec_v_pool = "30"
self.configuration.nec_v_snap_pool = None
self.configuration.nec_v_ldev_range = "0-1"
self.configuration.nec_v_target_ports = [CONFIG_MAP['port_id']]
self.configuration.nec_v_compute_target_ports = [
CONFIG_MAP['port_id']]
self.configuration.nec_v_group_create = True
self.configuration.nec_v_group_delete = True
self.configuration.nec_v_copy_speed = 3
self.configuration.nec_v_copy_check_interval = 3
self.configuration.nec_v_async_copy_check_interval = 10
self.configuration.san_login = CONFIG_MAP['user_id']
self.configuration.san_password = CONFIG_MAP['user_pass']
self.configuration.san_ip = CONFIG_MAP[
'rest_server_ip_addr']
self.configuration.san_api_port = CONFIG_MAP[
'rest_server_ip_port']
self.configuration.nec_v_rest_disable_io_wait = True
self.configuration.nec_v_rest_tcp_keepalive = True
self.configuration.nec_v_discard_zero_page = True
self.configuration.nec_v_rest_number = "0"
self.configuration.nec_v_lun_timeout = hbsd_rest._LUN_TIMEOUT
self.configuration.nec_v_lun_retry_interval = (
hbsd_rest._LUN_RETRY_INTERVAL)
self.configuration.nec_v_restore_timeout = hbsd_rest._RESTORE_TIMEOUT
self.configuration.nec_v_state_transition_timeout = (
hbsd_rest._STATE_TRANSITION_TIMEOUT)
self.configuration.nec_v_lock_timeout = hbsd_rest_api._LOCK_TIMEOUT
self.configuration.nec_v_rest_timeout = hbsd_rest_api._REST_TIMEOUT
self.configuration.nec_v_extend_timeout = (
hbsd_rest_api._EXTEND_TIMEOUT)
self.configuration.nec_v_exec_retry_interval = (
hbsd_rest_api._EXEC_RETRY_INTERVAL)
self.configuration.nec_v_rest_connect_timeout = (
hbsd_rest_api._DEFAULT_CONNECT_TIMEOUT)
self.configuration.nec_v_rest_job_api_response_timeout = (
hbsd_rest_api._JOB_API_RESPONSE_TIMEOUT)
self.configuration.nec_v_rest_get_api_response_timeout = (
hbsd_rest_api._GET_API_RESPONSE_TIMEOUT)
self.configuration.nec_v_rest_server_busy_timeout = (
hbsd_rest_api._REST_SERVER_BUSY_TIMEOUT)
self.configuration.nec_v_rest_keep_session_loop_interval = (
hbsd_rest_api._KEEP_SESSION_LOOP_INTERVAL)
self.configuration.nec_v_rest_another_ldev_mapped_retry_timeout = (
hbsd_rest_api._ANOTHER_LDEV_MAPPED_RETRY_TIMEOUT)
self.configuration.nec_v_rest_tcp_keepidle = (
hbsd_rest_api._TCP_KEEPIDLE)
self.configuration.nec_v_rest_tcp_keepintvl = (
hbsd_rest_api._TCP_KEEPINTVL)
self.configuration.nec_v_rest_tcp_keepcnt = (
hbsd_rest_api._TCP_KEEPCNT)
self.configuration.nec_v_host_mode_options = []
self.configuration.nec_v_zoning_request = False
self.configuration.san_thin_provision = True
self.configuration.san_private_key = ''
self.configuration.san_clustername = ''
self.configuration.san_ssh_port = '22'
self.configuration.san_is_local = False
self.configuration.ssh_conn_timeout = '30'
self.configuration.ssh_min_pool_conn = '1'
self.configuration.ssh_max_pool_conn = '5'
self.configuration.use_chap_auth = True
self.configuration.chap_username = CONFIG_MAP['auth_user']
self.configuration.chap_password = CONFIG_MAP['auth_password']
self.configuration.safe_get = self._fake_safe_get
CONF = cfg.CONF
CONF.my_ip = CONFIG_MAP['my_ip']
def _fake_safe_get(self, value):
"""Retrieve a configuration value avoiding throwing an exception."""
try:
val = getattr(self.configuration, value)
except AttributeError:
val = None
return val
@mock.patch.object(requests.Session, "request")
@mock.patch.object(
volume_utils, 'brick_get_connector_properties',
side_effect=_brick_get_connector_properties)
def _setup_driver(
self, brick_get_connector_properties=None, request=None):
"""Set up the driver environment."""
self.driver = nec_v_fc.VStorageFCDriver(
configuration=self.configuration, db=db)
request.side_effect = [FakeResponse(200, POST_SESSIONS_RESULT),
FakeResponse(200, GET_PORTS_RESULT),
FakeResponse(200, GET_HOST_WWNS_RESULT)]
self.driver.do_setup(None)
self.driver.check_for_setup_error()
self.driver.local_path(None)
# stop the Loopingcall within the do_setup treatment
self.driver.common.client.keep_session_loop.stop()
def tearDown(self):
self.client = None
super(VStorageRESTFCDriverTest, self).tearDown()
# API test cases
def test_configuration(self):
drv = nec_v_fc.VStorageFCDriver(
configuration=self.configuration, db=db)
self.assertEqual(drv.configuration.hitachi_storage_id,
drv.configuration.nec_v_storage_id)
self.assertEqual(drv.configuration.hitachi_pool,
drv.configuration.nec_v_pool)
self.assertEqual(drv.configuration.hitachi_snap_pool,
drv.configuration.nec_v_snap_pool)
self.assertEqual(drv.configuration.hitachi_ldev_range,
drv.configuration.nec_v_ldev_range)
self.assertEqual(drv.configuration.hitachi_target_ports,
drv.configuration.nec_v_target_ports)
self.assertEqual(drv.configuration.hitachi_compute_target_ports,
drv.configuration.nec_v_compute_target_ports)
self.assertEqual(drv.configuration.hitachi_group_create,
drv.configuration.nec_v_group_create)
self.assertEqual(drv.configuration.hitachi_group_delete,
drv.configuration.nec_v_group_delete)
self.assertEqual(drv.configuration.hitachi_copy_speed,
drv.configuration.nec_v_copy_speed)
self.assertEqual(drv.configuration.hitachi_copy_check_interval,
drv.configuration.nec_v_copy_check_interval)
self.assertEqual(drv.configuration.hitachi_async_copy_check_interval,
drv.configuration.nec_v_async_copy_check_interval)
self.assertEqual(drv.configuration.hitachi_rest_disable_io_wait,
drv.configuration.nec_v_rest_disable_io_wait)
self.assertEqual(drv.configuration.hitachi_rest_tcp_keepalive,
drv.configuration.nec_v_rest_tcp_keepalive)
self.assertEqual(drv.configuration.hitachi_discard_zero_page,
drv.configuration.nec_v_discard_zero_page)
self.assertEqual(drv.configuration.hitachi_lun_timeout,
drv.configuration.nec_v_lun_timeout)
self.assertEqual(drv.configuration.hitachi_lun_retry_interval,
drv.configuration.nec_v_lun_retry_interval)
self.assertEqual(drv.configuration.hitachi_restore_timeout,
drv.configuration.nec_v_restore_timeout)
self.assertEqual(drv.configuration.hitachi_state_transition_timeout,
drv.configuration.nec_v_state_transition_timeout)
self.assertEqual(drv.configuration.hitachi_lock_timeout,
drv.configuration.nec_v_lock_timeout)
self.assertEqual(drv.configuration.hitachi_rest_timeout,
drv.configuration.nec_v_rest_timeout)
self.assertEqual(drv.configuration.hitachi_extend_timeout,
drv.configuration.nec_v_extend_timeout)
self.assertEqual(drv.configuration.hitachi_exec_retry_interval,
drv.configuration.nec_v_exec_retry_interval)
self.assertEqual(drv.configuration.hitachi_rest_connect_timeout,
drv.configuration.nec_v_rest_connect_timeout)
self.assertEqual(
drv.configuration.hitachi_rest_job_api_response_timeout,
drv.configuration.nec_v_rest_job_api_response_timeout)
self.assertEqual(
drv.configuration.hitachi_rest_get_api_response_timeout,
drv.configuration.nec_v_rest_get_api_response_timeout)
self.assertEqual(drv.configuration.hitachi_rest_server_busy_timeout,
drv.configuration.nec_v_rest_server_busy_timeout)
self.assertEqual(
drv.configuration.hitachi_rest_keep_session_loop_interval,
drv.configuration.nec_v_rest_keep_session_loop_interval)
self.assertEqual(
drv.configuration.hitachi_rest_another_ldev_mapped_retry_timeout,
drv.configuration.nec_v_rest_another_ldev_mapped_retry_timeout)
self.assertEqual(drv.configuration.hitachi_rest_tcp_keepidle,
drv.configuration.nec_v_rest_tcp_keepidle)
self.assertEqual(drv.configuration.hitachi_rest_tcp_keepintvl,
drv.configuration.nec_v_rest_tcp_keepintvl)
self.assertEqual(drv.configuration.hitachi_rest_tcp_keepcnt,
drv.configuration.nec_v_rest_tcp_keepcnt)
self.assertEqual(drv.configuration.hitachi_host_mode_options,
drv.configuration.nec_v_host_mode_options)
self.assertEqual(drv.configuration.hitachi_zoning_request,
drv.configuration.nec_v_zoning_request)
def test_driverinfo(self):
drv = nec_v_fc.VStorageFCDriver(
configuration=self.configuration, db=db)
self.assertEqual(drv.common.driver_info['version'],
"1.0.0")
self.assertEqual(drv.common.driver_info['proto'],
"FC")
self.assertEqual(drv.common.driver_info['hba_id'],
"wwpns")
self.assertEqual(drv.common.driver_info['hba_id_type'],
"World Wide Name")
self.assertEqual(drv.common.driver_info['msg_id']['target'].msg_id,
308)
self.assertEqual(drv.common.driver_info['volume_backend_name'],
"NECFC")
self.assertEqual(drv.common.driver_info['volume_type'],
"fibre_channel")
self.assertEqual(drv.common.driver_info['param_prefix'],
"nec_v")
self.assertEqual(drv.common.driver_info['vendor_name'],
"NEC")
self.assertEqual(drv.common.driver_info['driver_prefix'],
"NEC")
self.assertEqual(drv.common.driver_info['driver_file_prefix'],
"nec")
self.assertEqual(drv.common.driver_info['target_prefix'],
"NEC-")
self.assertEqual(drv.common.driver_info['hdp_vol_attr'],
"DP")
self.assertEqual(drv.common.driver_info['hdt_vol_attr'],
"DT")
self.assertEqual(drv.common.driver_info['nvol_ldev_type'],
"DP-VOL")
self.assertEqual(drv.common.driver_info['target_iqn_suffix'],
".nec-target")
self.assertEqual(drv.common.driver_info['pair_attr'],
"SS")
@mock.patch.object(requests.Session, "request")
def test_create_volume(self, request):
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
ret = self.driver.create_volume(fake_volume.fake_volume_obj(self.ctxt))
self.assertEqual('1', ret['provider_location'])
self.assertEqual(2, request.call_count)

View File

@ -0,0 +1,403 @@
# Copyright (C) 2021 NEC corporation
#
#
# 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.
#
"""Unit tests for NEC Driver."""
from unittest import mock
from oslo_config import cfg
import requests
from cinder import context as cinder_context
from cinder import db
from cinder.tests.unit import fake_volume
from cinder.tests.unit import test
from cinder.volume import configuration as conf
from cinder.volume.drivers.hitachi import hbsd_rest
from cinder.volume.drivers.hitachi import hbsd_rest_api
from cinder.volume.drivers.nec.v import nec_v_iscsi
from cinder.volume.drivers.nec.v import nec_v_rest
from cinder.volume import volume_utils
# Configuration parameter values
CONFIG_MAP = {
'serial': '886000123456',
'my_ip': '127.0.0.1',
'rest_server_ip_addr': '172.16.18.108',
'rest_server_ip_port': '23451',
'port_id': 'CL1-A',
'host_grp_name': 'NEC-127.0.0.1',
'host_mode': 'LINUX/IRIX',
'host_iscsi_name': 'iqn.nec-test-host',
'target_iscsi_name': 'iqn.nec-test-target',
'user_id': 'user',
'user_pass': 'password',
'ipv4Address': '111.22.333.44',
'tcpPort': '5555',
'auth_user': 'auth_user',
'auth_password': 'auth_password',
}
DEFAULT_CONNECTOR = {
'host': 'host',
'ip': CONFIG_MAP['my_ip'],
'initiator': CONFIG_MAP['host_iscsi_name'],
'multipath': False,
}
# Dummy response for REST API
POST_SESSIONS_RESULT = {
"token": "b74777a3-f9f0-4ea8-bd8f-09847fac48d3",
"sessionId": 0,
}
GET_PORTS_RESULT = {
"data": [
{
"portId": CONFIG_MAP['port_id'],
"portType": "ISCSI",
"portAttributes": [
"TAR",
"MCU",
"RCU",
"ELUN"
],
"portSpeed": "AUT",
"loopId": "00",
"fabricMode": False,
"lunSecuritySetting": True,
},
],
}
GET_PORT_RESULT = {
"ipv4Address": CONFIG_MAP['ipv4Address'],
"tcpPort": CONFIG_MAP['tcpPort'],
}
GET_HOST_ISCSIS_RESULT = {
"data": [
{
"hostGroupNumber": 0,
"iscsiName": CONFIG_MAP['host_iscsi_name'],
},
],
}
GET_HOST_GROUP_RESULT = {
"hostGroupName": CONFIG_MAP['host_grp_name'],
"iscsiName": CONFIG_MAP['target_iscsi_name'],
}
GET_HOST_GROUPS_RESULT = {
"data": [
{
"hostGroupNumber": 0,
"portId": CONFIG_MAP['port_id'],
"hostGroupName": "NEC-test",
"iscsiName": CONFIG_MAP['target_iscsi_name'],
},
],
}
COMPLETED_SUCCEEDED_RESULT = {
"status": "Completed",
"state": "Succeeded",
"affectedResources": ('a/b/c/1',),
}
def _brick_get_connector_properties(multipath=False, enforce_multipath=False):
"""Return a predefined connector object."""
return DEFAULT_CONNECTOR
class FakeResponse():
def __init__(self, status_code, data=None, headers=None):
self.status_code = status_code
self.data = data
self.text = data
self.content = data
self.headers = {'Content-Type': 'json'} if headers is None else headers
def json(self):
return self.data
class VStorageRESTISCSIDriverTest(test.TestCase):
"""Unit test class for NEC REST interface iSCSI module."""
test_existing_ref = {'source-id': '1'}
test_existing_ref_name = {
'source-name': '15960cc7-38c9-4c5b-b4f1-365be5eeed45'}
def setUp(self):
"""Set up the test environment."""
def _set_required(opts, required):
for opt in opts:
opt.required = required
# Initialize Cinder and avoid checking driver options.
rest_required_opts = [
opt for opt in nec_v_rest.REST_VOLUME_OPTS if opt.required]
common_required_opts = [
opt for opt in nec_v_rest.COMMON_VOLUME_OPTS if opt.required]
_set_required(rest_required_opts, False)
_set_required(common_required_opts, False)
super(VStorageRESTISCSIDriverTest, self).setUp()
_set_required(rest_required_opts, True)
_set_required(common_required_opts, True)
self.configuration = mock.Mock(conf.Configuration)
self.ctxt = cinder_context.get_admin_context()
self._setup_config()
self._setup_driver()
def _setup_config(self):
"""Set configuration parameter values."""
self.configuration.config_group = "REST"
self.configuration.volume_backend_name = "RESTISCSI"
self.configuration.volume_driver = (
"cinder.volume.drivers.nec.v.nec_v_iscsi.VStorageISCSIDriver")
self.configuration.reserved_percentage = "0"
self.configuration.use_multipath_for_image_xfer = False
self.configuration.enforce_multipath_for_image_xfer = False
self.configuration.max_over_subscription_ratio = 500.0
self.configuration.driver_ssl_cert_verify = False
self.configuration.nec_v_storage_id = CONFIG_MAP['serial']
self.configuration.nec_v_pool = "30"
self.configuration.nec_v_snap_pool = None
self.configuration.nec_v_ldev_range = "0-1"
self.configuration.nec_v_target_ports = [CONFIG_MAP['port_id']]
self.configuration.nec_v_compute_target_ports = [
CONFIG_MAP['port_id']]
self.configuration.nec_v_group_create = True
self.configuration.nec_v_group_delete = True
self.configuration.nec_v_copy_speed = 3
self.configuration.nec_v_copy_check_interval = 3
self.configuration.nec_v_async_copy_check_interval = 10
self.configuration.san_login = CONFIG_MAP['user_id']
self.configuration.san_password = CONFIG_MAP['user_pass']
self.configuration.san_ip = CONFIG_MAP[
'rest_server_ip_addr']
self.configuration.san_api_port = CONFIG_MAP[
'rest_server_ip_port']
self.configuration.nec_v_rest_disable_io_wait = True
self.configuration.nec_v_rest_tcp_keepalive = True
self.configuration.nec_v_discard_zero_page = True
self.configuration.nec_v_rest_number = "0"
self.configuration.nec_v_lun_timeout = hbsd_rest._LUN_TIMEOUT
self.configuration.nec_v_lun_retry_interval = (
hbsd_rest._LUN_RETRY_INTERVAL)
self.configuration.nec_v_restore_timeout = hbsd_rest._RESTORE_TIMEOUT
self.configuration.nec_v_state_transition_timeout = (
hbsd_rest._STATE_TRANSITION_TIMEOUT)
self.configuration.nec_v_lock_timeout = hbsd_rest_api._LOCK_TIMEOUT
self.configuration.nec_v_rest_timeout = hbsd_rest_api._REST_TIMEOUT
self.configuration.nec_v_extend_timeout = (
hbsd_rest_api._EXTEND_TIMEOUT)
self.configuration.nec_v_exec_retry_interval = (
hbsd_rest_api._EXEC_RETRY_INTERVAL)
self.configuration.nec_v_rest_connect_timeout = (
hbsd_rest_api._DEFAULT_CONNECT_TIMEOUT)
self.configuration.nec_v_rest_job_api_response_timeout = (
hbsd_rest_api._JOB_API_RESPONSE_TIMEOUT)
self.configuration.nec_v_rest_get_api_response_timeout = (
hbsd_rest_api._GET_API_RESPONSE_TIMEOUT)
self.configuration.nec_v_rest_server_busy_timeout = (
hbsd_rest_api._REST_SERVER_BUSY_TIMEOUT)
self.configuration.nec_v_rest_keep_session_loop_interval = (
hbsd_rest_api._KEEP_SESSION_LOOP_INTERVAL)
self.configuration.nec_v_rest_another_ldev_mapped_retry_timeout = (
hbsd_rest_api._ANOTHER_LDEV_MAPPED_RETRY_TIMEOUT)
self.configuration.nec_v_rest_tcp_keepidle = (
hbsd_rest_api._TCP_KEEPIDLE)
self.configuration.nec_v_rest_tcp_keepintvl = (
hbsd_rest_api._TCP_KEEPINTVL)
self.configuration.nec_v_rest_tcp_keepcnt = (
hbsd_rest_api._TCP_KEEPCNT)
self.configuration.nec_v_host_mode_options = []
self.configuration.use_chap_auth = True
self.configuration.chap_username = CONFIG_MAP['auth_user']
self.configuration.chap_password = CONFIG_MAP['auth_password']
self.configuration.san_thin_provision = True
self.configuration.san_private_key = ''
self.configuration.san_clustername = ''
self.configuration.san_ssh_port = '22'
self.configuration.san_is_local = False
self.configuration.ssh_conn_timeout = '30'
self.configuration.ssh_min_pool_conn = '1'
self.configuration.ssh_max_pool_conn = '5'
self.configuration.safe_get = self._fake_safe_get
CONF = cfg.CONF
CONF.my_ip = CONFIG_MAP['my_ip']
def _fake_safe_get(self, value):
"""Retrieve a configuration value avoiding throwing an exception."""
try:
val = getattr(self.configuration, value)
except AttributeError:
val = None
return val
@mock.patch.object(requests.Session, "request")
@mock.patch.object(
volume_utils, 'brick_get_connector_properties',
side_effect=_brick_get_connector_properties)
def _setup_driver(
self, brick_get_connector_properties=None, request=None):
"""Set up the driver environment."""
self.driver = nec_v_iscsi.VStorageISCSIDriver(
configuration=self.configuration, db=db)
request.side_effect = [FakeResponse(200, POST_SESSIONS_RESULT),
FakeResponse(200, GET_PORTS_RESULT),
FakeResponse(200, GET_PORT_RESULT),
FakeResponse(200, GET_HOST_ISCSIS_RESULT),
FakeResponse(200, GET_HOST_GROUP_RESULT)]
self.driver.do_setup(None)
self.driver.check_for_setup_error()
self.driver.local_path(None)
# stop the Loopingcall within the do_setup treatment
self.driver.common.client.keep_session_loop.stop()
def tearDown(self):
self.client = None
super(VStorageRESTISCSIDriverTest, self).tearDown()
# API test cases
def test_configuration(self):
drv = nec_v_iscsi.VStorageISCSIDriver(
configuration=self.configuration, db=db)
self.assertEqual(drv.configuration.hitachi_storage_id,
drv.configuration.nec_v_storage_id)
self.assertEqual(drv.configuration.hitachi_pool,
drv.configuration.nec_v_pool)
self.assertEqual(drv.configuration.hitachi_snap_pool,
drv.configuration.nec_v_snap_pool)
self.assertEqual(drv.configuration.hitachi_ldev_range,
drv.configuration.nec_v_ldev_range)
self.assertEqual(drv.configuration.hitachi_target_ports,
drv.configuration.nec_v_target_ports)
self.assertEqual(drv.configuration.hitachi_compute_target_ports,
drv.configuration.nec_v_compute_target_ports)
self.assertEqual(drv.configuration.hitachi_group_create,
drv.configuration.nec_v_group_create)
self.assertEqual(drv.configuration.hitachi_group_delete,
drv.configuration.nec_v_group_delete)
self.assertEqual(drv.configuration.hitachi_copy_speed,
drv.configuration.nec_v_copy_speed)
self.assertEqual(drv.configuration.hitachi_copy_check_interval,
drv.configuration.nec_v_copy_check_interval)
self.assertEqual(drv.configuration.hitachi_async_copy_check_interval,
drv.configuration.nec_v_async_copy_check_interval)
self.assertEqual(drv.configuration.hitachi_rest_disable_io_wait,
drv.configuration.nec_v_rest_disable_io_wait)
self.assertEqual(drv.configuration.hitachi_rest_tcp_keepalive,
drv.configuration.nec_v_rest_tcp_keepalive)
self.assertEqual(drv.configuration.hitachi_discard_zero_page,
drv.configuration.nec_v_discard_zero_page)
self.assertEqual(drv.configuration.hitachi_lun_timeout,
drv.configuration.nec_v_lun_timeout)
self.assertEqual(drv.configuration.hitachi_lun_retry_interval,
drv.configuration.nec_v_lun_retry_interval)
self.assertEqual(drv.configuration.hitachi_restore_timeout,
drv.configuration.nec_v_restore_timeout)
self.assertEqual(drv.configuration.hitachi_state_transition_timeout,
drv.configuration.nec_v_state_transition_timeout)
self.assertEqual(drv.configuration.hitachi_lock_timeout,
drv.configuration.nec_v_lock_timeout)
self.assertEqual(drv.configuration.hitachi_rest_timeout,
drv.configuration.nec_v_rest_timeout)
self.assertEqual(drv.configuration.hitachi_extend_timeout,
drv.configuration.nec_v_extend_timeout)
self.assertEqual(drv.configuration.hitachi_exec_retry_interval,
drv.configuration.nec_v_exec_retry_interval)
self.assertEqual(drv.configuration.hitachi_rest_connect_timeout,
drv.configuration.nec_v_rest_connect_timeout)
self.assertEqual(
drv.configuration.hitachi_rest_job_api_response_timeout,
drv.configuration.nec_v_rest_job_api_response_timeout)
self.assertEqual(
drv.configuration.hitachi_rest_get_api_response_timeout,
drv.configuration.nec_v_rest_get_api_response_timeout)
self.assertEqual(drv.configuration.hitachi_rest_server_busy_timeout,
drv.configuration.nec_v_rest_server_busy_timeout)
self.assertEqual(
drv.configuration.hitachi_rest_keep_session_loop_interval,
drv.configuration.nec_v_rest_keep_session_loop_interval)
self.assertEqual(
drv.configuration.hitachi_rest_another_ldev_mapped_retry_timeout,
drv.configuration.nec_v_rest_another_ldev_mapped_retry_timeout)
self.assertEqual(drv.configuration.hitachi_rest_tcp_keepidle,
drv.configuration.nec_v_rest_tcp_keepidle)
self.assertEqual(drv.configuration.hitachi_rest_tcp_keepintvl,
drv.configuration.nec_v_rest_tcp_keepintvl)
self.assertEqual(drv.configuration.hitachi_rest_tcp_keepcnt,
drv.configuration.nec_v_rest_tcp_keepcnt)
self.assertEqual(drv.configuration.hitachi_host_mode_options,
drv.configuration.nec_v_host_mode_options)
def test_driverinfo(self):
drv = nec_v_iscsi.VStorageISCSIDriver(
configuration=self.configuration, db=db)
self.assertEqual(drv.common.driver_info['version'],
"1.0.0")
self.assertEqual(drv.common.driver_info['proto'],
"iSCSI")
self.assertEqual(drv.common.driver_info['hba_id'],
"initiator")
self.assertEqual(drv.common.driver_info['hba_id_type'],
"iSCSI initiator IQN")
self.assertEqual(drv.common.driver_info['msg_id']['target'].msg_id,
309)
self.assertEqual(drv.common.driver_info['volume_backend_name'],
"NECiSCSI")
self.assertEqual(drv.common.driver_info['volume_type'],
"iscsi")
self.assertEqual(drv.common.driver_info['param_prefix'],
"nec_v")
self.assertEqual(drv.common.driver_info['vendor_name'],
"NEC")
self.assertEqual(drv.common.driver_info['driver_prefix'],
"NEC")
self.assertEqual(drv.common.driver_info['driver_file_prefix'],
"nec")
self.assertEqual(drv.common.driver_info['target_prefix'],
"NEC-")
self.assertEqual(drv.common.driver_info['hdp_vol_attr'],
"DP")
self.assertEqual(drv.common.driver_info['hdt_vol_attr'],
"DT")
self.assertEqual(drv.common.driver_info['nvol_ldev_type'],
"DP-VOL")
self.assertEqual(drv.common.driver_info['target_iqn_suffix'],
".nec-target")
self.assertEqual(drv.common.driver_info['pair_attr'],
"SS")
@mock.patch.object(requests.Session, "request")
def test_create_volume(self, request):
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
ret = self.driver.create_volume(fake_volume.fake_volume_obj(self.ctxt))
self.assertEqual('1', ret['provider_location'])
self.assertEqual(2, request.call_count)

View File

View File

@ -0,0 +1,72 @@
# Copyright (C) 2021 NEC corporation
#
# 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.
#
"""Fibre channel module for NEC Driver."""
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.hitachi import hbsd_common
from cinder.volume.drivers.hitachi import hbsd_fc
from cinder.volume.drivers.hitachi import hbsd_rest
from cinder.volume.drivers.hitachi import hbsd_utils
from cinder.volume.drivers.nec.v import nec_v_rest as rest
from cinder.volume.drivers.nec.v import nec_v_utils as utils
MSG = hbsd_utils.HBSDMsg
@interface.volumedriver
class VStorageFCDriver(hbsd_fc.HBSDFCDriver):
"""Fibre channel class for NEC Driver.
Version history:
.. code-block:: none
1.0.0 - Initial driver.
"""
VERSION = utils.VERSION
# ThirdPartySystems wiki page
CI_WIKI_NAME = utils.CI_WIKI_NAME
def __init__(self, *args, **kwargs):
"""Initialize instance variables."""
super(VStorageFCDriver, self).__init__(*args, **kwargs)
self.configuration.append_config_values(rest.COMMON_VOLUME_OPTS)
self.configuration.append_config_values(rest.FC_VOLUME_OPTS)
def _init_common(self, conf, db):
utils.DRIVER_INFO['proto'] = 'FC'
utils.DRIVER_INFO['hba_id'] = 'wwpns'
utils.DRIVER_INFO['hba_id_type'] = 'World Wide Name'
utils.DRIVER_INFO['msg_id'] = {
'target': MSG.CREATE_HOST_GROUP_FAILED}
utils.DRIVER_INFO['volume_backend_name'] = '%(prefix)sFC' % {
'prefix': utils.DRIVER_PREFIX}
utils.DRIVER_INFO['volume_type'] = 'fibre_channel'
return rest.VStorageRESTFC(conf, utils.DRIVER_INFO, db)
@staticmethod
def get_driver_options():
additional_opts = driver.BaseVD._get_oslo_driver_opts(
*(hbsd_common._INHERITED_VOLUME_OPTS +
hbsd_rest._REQUIRED_REST_OPTS +
['driver_ssl_cert_verify', 'driver_ssl_cert_path',
'san_api_port']))
return (rest.COMMON_VOLUME_OPTS + rest.REST_VOLUME_OPTS +
rest.FC_VOLUME_OPTS + additional_opts)

View File

@ -0,0 +1,71 @@
# Copyright (C) 2021 NEC corporation
#
# 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.
#
"""iSCSI channel module for NEC Driver."""
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.hitachi import hbsd_common
from cinder.volume.drivers.hitachi import hbsd_iscsi
from cinder.volume.drivers.hitachi import hbsd_rest
from cinder.volume.drivers.hitachi import hbsd_utils
from cinder.volume.drivers.nec.v import nec_v_rest as rest
from cinder.volume.drivers.nec.v import nec_v_utils as utils
MSG = hbsd_utils.HBSDMsg
@interface.volumedriver
class VStorageISCSIDriver(hbsd_iscsi.HBSDISCSIDriver):
"""iSCSI class for NEC Driver.
Version history:
.. code-block:: none
1.0.0 - Initial driver.
"""
VERSION = utils.VERSION
# ThirdPartySystems wiki page
CI_WIKI_NAME = utils.CI_WIKI_NAME
def __init__(self, *args, **kwargs):
"""Initialize instance variables."""
super(VStorageISCSIDriver, self).__init__(*args, **kwargs)
self.configuration.append_config_values(rest.COMMON_VOLUME_OPTS)
def _init_common(self, conf, db):
utils.DRIVER_INFO['proto'] = 'iSCSI'
utils.DRIVER_INFO['hba_id'] = 'initiator'
utils.DRIVER_INFO['hba_id_type'] = 'iSCSI initiator IQN'
utils.DRIVER_INFO['msg_id'] = {
'target': MSG.CREATE_ISCSI_TARGET_FAILED}
utils.DRIVER_INFO['volume_backend_name'] = '%(prefix)siSCSI' % {
'prefix': utils.DRIVER_PREFIX}
utils.DRIVER_INFO['volume_type'] = 'iscsi'
return rest.VStorageRESTISCSI(conf, utils.DRIVER_INFO, db)
@staticmethod
def get_driver_options():
additional_opts = driver.BaseVD._get_oslo_driver_opts(
*(hbsd_common._INHERITED_VOLUME_OPTS +
hbsd_rest._REQUIRED_REST_OPTS +
['driver_ssl_cert_verify', 'driver_ssl_cert_path',
'san_api_port']))
return (rest.COMMON_VOLUME_OPTS + rest.REST_VOLUME_OPTS +
additional_opts)

View File

@ -0,0 +1,279 @@
# Copyright (C) 2021 NEC corporation
#
# 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.
#
"""REST interface for NEC Driver."""
from oslo_config import cfg
from cinder.volume import configuration
from cinder.volume.drivers.hitachi import hbsd_rest
from cinder.volume.drivers.hitachi import hbsd_rest_api
from cinder.volume.drivers.hitachi import hbsd_rest_fc
from cinder.volume.drivers.hitachi import hbsd_rest_iscsi
COMMON_VOLUME_OPTS = [
cfg.StrOpt(
'nec_v_storage_id',
default=None,
help='Product number of the storage system.'),
cfg.StrOpt(
'nec_v_pool',
default=None,
help='Pool number or pool name of the DP pool.'),
cfg.StrOpt(
'nec_v_snap_pool',
default=None,
help='Pool number or pool name of the snapshot pool.'),
cfg.StrOpt(
'nec_v_ldev_range',
default=None,
help='Range of the LDEV numbers in the format of \'xxxx-yyyy\' that '
'can be used by the driver. Values can be in decimal format '
'(e.g. 1000) or in colon-separated hexadecimal format '
'(e.g. 00:03:E8).'),
cfg.ListOpt(
'nec_v_target_ports',
default=[],
help='IDs of the storage ports used to attach volumes to the '
'controller node. To specify multiple ports, connect them by '
'commas (e.g. CL1-A,CL2-A).'),
cfg.ListOpt(
'nec_v_compute_target_ports',
default=[],
help='IDs of the storage ports used to attach volumes to compute '
'nodes. To specify multiple ports, connect them by commas '
'(e.g. CL1-A,CL2-A).'),
cfg.BoolOpt(
'nec_v_group_create',
default=False,
help='If True, the driver will create host groups or iSCSI targets on '
'storage ports as needed.'),
cfg.BoolOpt(
'nec_v_group_delete',
default=False,
help='If True, the driver will delete host groups or iSCSI targets on '
'storage ports as needed.'),
cfg.IntOpt(
'nec_v_copy_speed',
default=3,
min=1, max=15,
help='Copy speed of storage system. 1 or 2 indicates '
'low speed, 3 indicates middle speed, and a value between 4 and '
'15 indicates high speed.'),
cfg.IntOpt(
'nec_v_copy_check_interval',
default=3,
min=1, max=600,
help='Interval in seconds to check copying status during a volume '
'copy.'),
cfg.IntOpt(
'nec_v_async_copy_check_interval',
default=10,
min=1, max=600,
help='Interval in seconds to check asynchronous copying status during '
'a copy pair deletion or data restoration.'),
]
REST_VOLUME_OPTS = [
cfg.BoolOpt(
'nec_v_rest_disable_io_wait',
default=True,
help='It may take some time to detach volume after I/O. '
'This option will allow detaching volume to complete '
'immediately.'),
cfg.BoolOpt(
'nec_v_rest_tcp_keepalive',
default=True,
help='Enables or disables use of REST API tcp keepalive'),
cfg.BoolOpt(
'nec_v_discard_zero_page',
default=True,
help='Enable or disable zero page reclamation in a DP-VOL.'),
cfg.IntOpt(
'nec_v_lun_timeout',
default=hbsd_rest._LUN_TIMEOUT,
help='Maximum wait time in seconds for adding a LUN to complete.'),
cfg.IntOpt(
'nec_v_lun_retry_interval',
default=hbsd_rest._LUN_RETRY_INTERVAL,
help='Retry interval in seconds for REST API adding a LUN.'),
cfg.IntOpt(
'nec_v_restore_timeout',
default=hbsd_rest._RESTORE_TIMEOUT,
help='Maximum wait time in seconds for the restore operation to '
'complete.'),
cfg.IntOpt(
'nec_v_state_transition_timeout',
default=hbsd_rest._STATE_TRANSITION_TIMEOUT,
help='Maximum wait time in seconds for a volume transition to '
'complete.'),
cfg.IntOpt(
'nec_v_lock_timeout',
default=hbsd_rest_api._LOCK_TIMEOUT,
help='Maximum wait time in seconds for storage to be unlocked.'),
cfg.IntOpt(
'nec_v_rest_timeout',
default=hbsd_rest_api._REST_TIMEOUT,
help='Maximum wait time in seconds for REST API execution to '
'complete.'),
cfg.IntOpt(
'nec_v_extend_timeout',
default=hbsd_rest_api._EXTEND_TIMEOUT,
help='Maximum wait time in seconds for a volume extention to '
'complete.'),
cfg.IntOpt(
'nec_v_exec_retry_interval',
default=hbsd_rest_api._EXEC_RETRY_INTERVAL,
help='Retry interval in seconds for REST API execution.'),
cfg.IntOpt(
'nec_v_rest_connect_timeout',
default=hbsd_rest_api._DEFAULT_CONNECT_TIMEOUT,
help='Maximum wait time in seconds for REST API connection to '
'complete.'),
cfg.IntOpt(
'nec_v_rest_job_api_response_timeout',
default=hbsd_rest_api._JOB_API_RESPONSE_TIMEOUT,
help='Maximum wait time in seconds for a response from REST API.'),
cfg.IntOpt(
'nec_v_rest_get_api_response_timeout',
default=hbsd_rest_api._GET_API_RESPONSE_TIMEOUT,
help='Maximum wait time in seconds for a response against GET method '
'of REST API.'),
cfg.IntOpt(
'nec_v_rest_server_busy_timeout',
default=hbsd_rest_api._REST_SERVER_BUSY_TIMEOUT,
help='Maximum wait time in seconds when REST API returns busy.'),
cfg.IntOpt(
'nec_v_rest_keep_session_loop_interval',
default=hbsd_rest_api._KEEP_SESSION_LOOP_INTERVAL,
help='Loop interval in seconds for keeping REST API session.'),
cfg.IntOpt(
'nec_v_rest_another_ldev_mapped_retry_timeout',
default=hbsd_rest_api._ANOTHER_LDEV_MAPPED_RETRY_TIMEOUT,
help='Retry time in seconds when new LUN allocation request fails.'),
cfg.IntOpt(
'nec_v_rest_tcp_keepidle',
default=hbsd_rest_api._TCP_KEEPIDLE,
help='Wait time in seconds for sending a first TCP keepalive packet.'),
cfg.IntOpt(
'nec_v_rest_tcp_keepintvl',
default=hbsd_rest_api._TCP_KEEPINTVL,
help='Interval of transmissions in seconds for TCP keepalive packet.'),
cfg.IntOpt(
'nec_v_rest_tcp_keepcnt',
default=hbsd_rest_api._TCP_KEEPCNT,
help='Maximum number of transmissions for TCP keepalive packet.'),
cfg.ListOpt(
'nec_v_host_mode_options',
default=[],
help='Host mode option for host group or iSCSI target'),
]
FC_VOLUME_OPTS = [
cfg.BoolOpt(
'nec_v_zoning_request',
default=False,
help='If True, the driver will configure FC zoning between the server '
'and the storage system provided that FC zoning manager is '
'enabled.'),
]
CONF = cfg.CONF
CONF.register_opts(COMMON_VOLUME_OPTS, group=configuration.SHARED_CONF_GROUP)
CONF.register_opts(REST_VOLUME_OPTS, group=configuration.SHARED_CONF_GROUP)
CONF.register_opts(FC_VOLUME_OPTS, group=configuration.SHARED_CONF_GROUP)
def update_conf(conf):
# COMMON_VOLUME_OPTS
conf.hitachi_storage_id = conf.nec_v_storage_id
conf.hitachi_pool = conf.nec_v_pool
conf.hitachi_snap_pool = conf.nec_v_snap_pool
conf.hitachi_ldev_range = conf.nec_v_ldev_range
conf.hitachi_target_ports = conf.nec_v_target_ports
conf.hitachi_compute_target_ports = (
conf.nec_v_compute_target_ports)
conf.hitachi_group_create = conf.nec_v_group_create
conf.hitachi_group_delete = conf.nec_v_group_delete
conf.hitachi_copy_speed = conf.nec_v_copy_speed
conf.hitachi_copy_check_interval = (
conf.nec_v_copy_check_interval)
conf.hitachi_async_copy_check_interval = (
conf.nec_v_async_copy_check_interval)
# REST_VOLUME_OPTS
conf.hitachi_rest_disable_io_wait = (
conf.nec_v_rest_disable_io_wait)
conf.hitachi_rest_tcp_keepalive = (
conf.nec_v_rest_tcp_keepalive)
conf.hitachi_discard_zero_page = (
conf.nec_v_discard_zero_page)
conf.hitachi_lun_timeout = conf.nec_v_lun_timeout
conf.hitachi_lun_retry_interval = (
conf.nec_v_lun_retry_interval)
conf.hitachi_restore_timeout = conf.nec_v_restore_timeout
conf.hitachi_state_transition_timeout = (
conf.nec_v_state_transition_timeout)
conf.hitachi_lock_timeout = conf.nec_v_lock_timeout
conf.hitachi_rest_timeout = conf.nec_v_rest_timeout
conf.hitachi_extend_timeout = conf.nec_v_extend_timeout
conf.hitachi_exec_retry_interval = (
conf.nec_v_exec_retry_interval)
conf.hitachi_rest_connect_timeout = (
conf.nec_v_rest_connect_timeout)
conf.hitachi_rest_job_api_response_timeout = (
conf.nec_v_rest_job_api_response_timeout)
conf.hitachi_rest_get_api_response_timeout = (
conf.nec_v_rest_get_api_response_timeout)
conf.hitachi_rest_server_busy_timeout = (
conf.nec_v_rest_server_busy_timeout)
conf.hitachi_rest_keep_session_loop_interval = (
conf.nec_v_rest_keep_session_loop_interval)
conf.hitachi_rest_another_ldev_mapped_retry_timeout = (
conf.nec_v_rest_another_ldev_mapped_retry_timeout)
conf.hitachi_rest_tcp_keepidle = (
conf.nec_v_rest_tcp_keepidle)
conf.hitachi_rest_tcp_keepintvl = (
conf.nec_v_rest_tcp_keepintvl)
conf.hitachi_rest_tcp_keepcnt = (
conf.nec_v_rest_tcp_keepcnt)
conf.hitachi_host_mode_options = (
conf.nec_v_host_mode_options)
return conf
class VStorageRESTFC(hbsd_rest_fc.HBSDRESTFC):
"""REST interface fibre channel class."""
def __init__(self, conf, storage_protocol, db):
"""Initialize instance variables."""
conf.append_config_values(COMMON_VOLUME_OPTS)
conf.append_config_values(REST_VOLUME_OPTS)
conf.append_config_values(FC_VOLUME_OPTS)
super(VStorageRESTFC, self).__init__(conf, storage_protocol, db)
self.conf = update_conf(self.conf)
# FC_VOLUME_OPTS
self.conf.hitachi_zoning_request = self.conf.nec_v_zoning_request
class VStorageRESTISCSI(hbsd_rest_iscsi.HBSDRESTISCSI):
"""REST interface iSCSI channel class."""
def __init__(self, conf, storage_protocol, db):
"""Initialize instance variables."""
conf.append_config_values(COMMON_VOLUME_OPTS)
conf.append_config_values(REST_VOLUME_OPTS)
super(VStorageRESTISCSI, self).__init__(conf, storage_protocol, db)
self.conf = update_conf(self.conf)

View File

@ -0,0 +1,50 @@
# Copyright (C) 2021 NEC corporation
#
# 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.
#
"""Utility module for NEC Driver."""
VERSION = '1.0.0'
CI_WIKI_NAME = 'NEC_V_Cinder_CI'
PARAM_PREFIX = 'nec_v'
VENDOR_NAME = 'NEC'
DRIVER_PREFIX = 'NEC'
DRIVER_FILE_PREFIX = 'nec'
TARGET_PREFIX = 'NEC-'
HDP_VOL_ATTR = 'DP'
HDT_VOL_ATTR = 'DT'
NVOL_LDEV_TYPE = 'DP-VOL'
TARGET_IQN_SUFFIX = '.nec-target'
PAIR_ATTR = 'SS'
DRIVER_INFO = {
'version': VERSION,
'proto': '',
'hba_id': '',
'hba_id_type': '',
'msg_id': {
'target': '',
},
'volume_backend_name': '',
'volume_type': '',
'param_prefix': PARAM_PREFIX,
'vendor_name': VENDOR_NAME,
'driver_prefix': DRIVER_PREFIX,
'driver_file_prefix': DRIVER_FILE_PREFIX,
'target_prefix': TARGET_PREFIX,
'hdp_vol_attr': HDP_VOL_ATTR,
'hdt_vol_attr': HDT_VOL_ATTR,
'nvol_ldev_type': NVOL_LDEV_TYPE,
'target_iqn_suffix': TARGET_IQN_SUFFIX,
'pair_attr': PAIR_ATTR,
}

View File

@ -0,0 +1,139 @@
===========================
NEC Storage V series driver
===========================
NEC Storage V series driver provides Fibre Channel and iSCSI support for
NEC V series storages.
System requirements
~~~~~~~~~~~~~~~~~~~
Supported models:
+-----------------+------------------------+
| Storage model | Firmware version |
+=================+========================+
| V100, | 93-04-21 or later |
| V300 | |
+-----------------+------------------------+
Required storage licenses:
* iStorage Local Replication
Local Replication Software
Supported operations
~~~~~~~~~~~~~~~~~~~~
* Create, delete, attach, and detach volumes.
* Create, list, and delete volume snapshots.
* Create a volume from a snapshot.
* Create, list, update, and delete consistency groups.
* Create, list, and delete consistency group snapshots.
* Copy a volume to an image.
* Copy an image to a volume.
* Clone a volume.
* Extend a volume.
* Migrate a volume.
* Get volume statistics.
* Efficient non-disruptive volume backup.
* Manage and unmanage a volume.
* Attach a volume to multiple instances at once (multi-attach).
* Revert a volume to a snapshot.
.. note::
A volume with snapshots cannot be extended in this driver.
Configuration
~~~~~~~~~~~~~
Set up NEC V series storage
---------------------------
You need to specify settings as described below for storage systems. For
details about each setting, see the user's guide of the storage systems.
Common resources:
- ``All resources``
All storage resources, such as DP pools and host groups, can not have a
name including blank space in order for the driver to use them.
- ``User accounts``
Create a storage device account belonging to the Administrator User Group.
- ``DP Pool``
Create a DP pool that is used by the driver.
- ``Resource group``
If using a new resource group for exclusive use by an OpenStack system,
create a new resource group, and assign the necessary resources, such as
LDEVs, port, and host group (iSCSI target) to the created resource.
- ``Ports``
Enable Port Security for the ports used by the driver.
If you use iSCSI:
- ``Ports``
Assign an IP address and a TCP port number to the port.
Set up NEC V series storage volume driver
-----------------------------------------
Set the volume driver to NEC V series storage driver by setting the
volume_driver option in the cinder.conf file as follows:
If you use Fibre Channel:
.. code-block:: ini
[Storage1]
volume_driver = cinder.volume.drivers.nec.v.nec_v_fc.VStorageFCDriver
volume_backend_name = Storage1
san_ip = 1.2.3.4
san_api_port = 23451
san_login = userid
san_password = password
nec_v_storage_id = 123456789012
nec_v_pool = pool0
If you use iSCSI:
.. code-block:: ini
[Storage1]
volume_driver = cinder.volume.drivers.nec.v.nec_v_iscsi.VStorageISCSIDriver
volume_backend_name = Storage1
san_ip = 1.2.3.4
san_api_port = 23451
san_login = userid
san_password = password
nec_v_storage_id = 123456789012
nec_v_pool = pool0
This table shows configuration options for NEC V series storage driver.
.. config-table::
:config-target: NEC V series storage driver
cinder.volume.drivers.nec.v.nec_v_rest
Required options
----------------
- ``san_ip``
IP address of SAN controller
- ``san_login``
Username for SAN controller
- ``san_password``
Password for SAN controller
- ``nec_v_storage_id``
Product number of the storage system.
- ``nec_v_pool``
Pool number or pool name of the DP pool.

View File

@ -135,6 +135,9 @@ title=MacroSAN Storage Driver (iSCSI, FC)
[driver.nec]
title=NEC Storage M Series Driver (iSCSI, FC)
[driver.nec_v]
title=NEC Storage V Series Driver (iSCSI, FC)
[driver.netapp_ontap]
title=NetApp Data ONTAP Driver (iSCSI, NFS, FC)
@ -257,6 +260,7 @@ driver.linbit_linstor=complete
driver.lvm=complete
driver.macrosan=complete
driver.nec=complete
driver.nec_v=complete
driver.netapp_ontap=complete
driver.netapp_solidfire=complete
driver.nexenta=complete
@ -327,6 +331,7 @@ driver.linbit_linstor=complete
driver.lvm=complete
driver.macrosan=complete
driver.nec=complete
driver.nec_v=complete
driver.netapp_ontap=complete
driver.netapp_solidfire=complete
driver.nexenta=complete
@ -400,6 +405,7 @@ driver.linbit_linstor=missing
driver.lvm=missing
driver.macrosan=complete
driver.nec=complete
driver.nec_v=missing
driver.netapp_ontap=complete
driver.netapp_solidfire=complete
driver.nexenta=missing
@ -472,6 +478,7 @@ driver.linbit_linstor=missing
driver.lvm=missing
driver.macrosan=complete
driver.nec=missing
driver.nec_v=missing
driver.netapp_ontap=complete
driver.netapp_solidfire=complete
driver.nexenta=missing
@ -545,6 +552,7 @@ driver.linbit_linstor=missing
driver.lvm=missing
driver.macrosan=missing
driver.nec=missing
driver.nec_v=complete
driver.netapp_ontap=complete
driver.netapp_solidfire=complete
driver.nexenta=missing
@ -617,6 +625,7 @@ driver.linbit_linstor=missing
driver.lvm=complete
driver.macrosan=complete
driver.nec=complete
driver.nec_v=complete
driver.netapp_ontap=complete
driver.netapp_solidfire=complete
driver.nexenta=missing
@ -690,6 +699,7 @@ driver.linbit_linstor=missing
driver.lvm=missing
driver.macrosan=complete
driver.nec=complete
driver.nec_v=missing
driver.netapp_ontap=complete
driver.netapp_solidfire=complete
driver.nexenta=missing
@ -763,6 +773,7 @@ driver.linbit_linstor=missing
driver.lvm=complete
driver.macrosan=missing
driver.nec=complete
driver.nec_v=complete
driver.netapp_ontap=complete
driver.netapp_solidfire=complete
driver.nexenta=missing
@ -833,6 +844,7 @@ driver.linbit_linstor=missing
driver.lvm=complete
driver.macrosan=missing
driver.nec=complete
driver.nec_v=complete
driver.netapp_ontap=complete
driver.netapp_solidfire=complete
driver.nexenta=missing
@ -907,6 +919,7 @@ driver.linbit_linstor=missing
driver.lvm=missing
driver.macrosan=complete
driver.nec=missing
driver.nec_v=missing
driver.netapp_ontap=missing
driver.netapp_solidfire=complete
driver.nexenta=missing

View File

@ -0,0 +1,4 @@
---
features:
- |
Added backend FC and iSCSI drivers for NEC V series Storage.