Merge "Remove ZTE volume driver"

This commit is contained in:
Jenkins 2017-10-08 16:33:46 +00:00 committed by Gerrit Code Review
commit 1ec94c301a
9 changed files with 1 additions and 1690 deletions

View File

@ -181,7 +181,6 @@ from cinder.volume.drivers.zfssa import zfssaiscsi as \
cinder_volume_drivers_zfssa_zfssaiscsi
from cinder.volume.drivers.zfssa import zfssanfs as \
cinder_volume_drivers_zfssa_zfssanfs
from cinder.volume.drivers.zte import zte_ks as cinder_volume_drivers_zte_zteks
from cinder.volume import manager as cinder_volume_manager
from cinder.wsgi import eventlet_server as cinder_wsgi_eventletserver
from cinder.zonemanager.drivers.brocade import brcd_fabric_opts as \
@ -372,7 +371,6 @@ def list_opts():
cinder_volume_drivers_zadara.zadara_opts,
cinder_volume_drivers_zfssa_zfssaiscsi.ZFSSA_OPTS,
cinder_volume_drivers_zfssa_zfssanfs.ZFSSA_OPTS,
cinder_volume_drivers_zte_zteks.zte_opts,
cinder_volume_manager.volume_backend_opts,
)),
('nova',

View File

@ -1,424 +0,0 @@
# Copyright 2016 ZTE Corporation. All rights reserved
# 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.
#
"""
Self test for ZTE Storage Driver platform.
"""
from oslo_config import cfg
from cinder import exception
from cinder import test
from cinder.volume import configuration as conf
from cinder.volume.drivers.zte import zte_ks
from cinder.volume.drivers.zte import zte_pub
session_id = 'kfomqdnoetjcjlva'
volume_paras = {'name': 'volume-21ec7341-9256-497b-97d9-ef48edcf0635',
'size': 2,
'volume_name': 'vol1',
'id': '21ec7341-9256-497b-97d9-ef48edcf0635',
'volume_id': '21ec7341-9256-497b-97d9-ef48edcf0635',
'provider_auth': None,
'project_id': 'project',
'display_name': 'vol1',
'source_volid': None,
'volume_metadata': [],
'display_description': 'test volume',
'volume_type_id': None}
volume_clone = {'name': 'volume-ee317512-f6a6-4284-a94e-5f4ac8783169',
'size': 4,
'volume_name': 'vol1',
'id': 'ee317512-f6a6-4284-a94e-5f4ac8783169',
'volume_id': 'ee317512-f6a6-4284-a94e-5f4ac8783169',
'provider_auth': None,
'project_id': 'project',
'display_name': 'clone_vol1',
'source_volid': None,
'volume_metadata': [],
'display_description': 'test clone volume',
'volume_type_id': None}
snapvolume_paras = {'name': 'volume-21ec7341-9256-497b-97d9-ef48edcf0635',
'size': 2,
'volume_size': 2,
'volume_name': 'vol1',
'id': '21ec7341-9256-497b-97d9-ef48edcf0635',
'volume_id': '21ec7341-9256-497b-97d9-ef48edcf0635',
'provider_auth': None,
'project_id': 'project',
'display_name': 'vol1',
'source_volid': None,
'volume_metadata': [],
'display_description': 'test volume',
'volume_type_id': None}
connector = {'ip': '10.0.0.0',
'initiator': 'iqn.1993-08.org.debian:01:222'}
fcconnector = {'ip': '10.0.0.0',
'wwpns': [1, 2, 3, 4, 5, 6, 7, 8]}
fake_opt = [
cfg.StrOpt('fake_opt', default='fake', help='fake opts')
]
VolFlowLimitAttr_paras = {'sqwWriteFlowLimit': 0,
'cVolName': 'OpenCos_5072124445952515861',
'sqwTotalFlowLimit': 500,
'sqwWriteIoCount': 0,
'sqwTotalIoCount': 0,
'sqwReadFlowLimit': 0,
'sqwReadIoCount': 0}
volume_name = 'OpenCos_8359669312515962256'
return_success = {'returncode': zte_pub.ZTE_SUCCESS, 'data': {}}
return_error = {'returncode': zte_pub.ZTE_ERR_LUNDEV_NOT_EXIST, 'data': {}}
return_port_error = (
{'returncode': zte_pub.ZTE_ERR_PORT_EXIST_INOTHER, 'data': {}})
return_host_error = (
{'returncode': zte_pub.ZTE_ERR_HOST_EXIST_INOTHER, 'data': {}})
MAP_TO_RESPONSE = {}
signin_info = {'sessionID': session_id}
MAP_TO_RESPONSE['plat.session.signin'] = {'returncode': zte_pub.ZTE_SUCCESS,
'data': signin_info}
MAP_TO_RESPONSE['plat.session.heartbeat'] = return_success
pool_info = {'sdwState': 1, 'qwTotalCapacity': 1024560,
'qwFreeCapacity': 102456}
MAP_TO_RESPONSE['GetPoolInfo'] = {'returncode': zte_pub.ZTE_SUCCESS,
'data': pool_info}
MAP_TO_RESPONSE['CreateVolOnPool'] = return_success
MAP_TO_RESPONSE['DelCvol'] = return_success
MAP_TO_RESPONSE['GetCvolNamesOnVol'] = {
'returncode': zte_pub.ZTE_SUCCESS,
'data': {'sdwCvolNum': 2, 'scCvolNames': [{'scCvolName': 'clone1'},
{'scCvolName': 'clone2'}]}}
MAP_TO_RESPONSE['CreateSvol'] = return_success
MAP_TO_RESPONSE['DelSvol'] = return_success
MAP_TO_RESPONSE['ExpandVolOnPool'] = return_success
MAP_TO_RESPONSE['CreateCvol'] = return_success
cVolName_from_vol_name = "OpenCos_9fbc232bf71ee2fa8bd"
grp_info = {'sdwHostNum': 1,
'tHostInfo': [{'ucHostName': 'host1'}],
'sdwLunNum': 5,
'cMapGrpName': 'group_cjf',
'tLunInfo': [{'sdwLunState': 0, 'sdwBlockSize': 0,
'sdwAccessAttr': 0, 'sdwLunId': 0,
'cVolName': 'vol1'},
{'sdwLunState': 0, 'sdwBlockSize': 0,
'sdwAccessAttr': 0, 'sdwLunId': 1,
'cVolName': volume_name},
{'sdwLunState': 0, 'sdwBlockSize': 0,
'sdwAccessAttr': 0, 'sdwLunId': 2,
'cVolName': 'vol3'},
{'sdwLunState': 0, 'sdwBlockSize': 0,
'sdwAccessAttr': 0, 'sdwLunId': 3,
'cVolName': cVolName_from_vol_name},
{'sdwLunState': 0, 'sdwBlockSize': 0,
'sdwAccessAttr': 0, 'sdwLunId': 5,
'cVolName': 'vol4'}]}
MAP_TO_RESPONSE['GetMapGrpInfo'] = (
{'returncode': zte_pub.ZTE_SUCCESS, 'data': grp_info})
MAP_TO_RESPONSE['DelMapGrp'] = return_success
simple_grp_info = {'sdwMapGrpNum': 0,
'tMapGrpSimpleInfo': [{'sdwHostNum': 0,
'sdwLunNum': 0,
'cMapGrpName': session_id},
{'sdwHostNum': 1,
'sdwLunNum': 1,
'cMapGrpName': ''}]}
MAP_TO_RESPONSE['GetGrpSimpleInfoList'] = {'returncode': zte_pub.ZTE_SUCCESS,
'data': simple_grp_info}
luninfo = {'sdwLunId': 3}
MAP_TO_RESPONSE['AddVolToGrp'] = {'returncode': zte_pub.ZTE_SUCCESS,
'data': luninfo}
sys_info = {'cVendor': 'ZTE', 'cVersionName': 'V1.0',
'storage_protocol': 'iSCSI'}
MAP_TO_RESPONSE['GetSysInfo'] = {'returncode': zte_pub.ZTE_SUCCESS,
'data': sys_info}
cfg_info = {'sdwDeviceNum': 4,
'tSystemNetCfg': [
{'udwCtrlId': 0, 'udwRoleType': 0,
'udwPortType': 1, 'udwDeviceId': 123,
'cIpAddr': '198.51.100.20'},
{'udwCtrlId': 0, 'udwRoleType': 0,
'udwPortType': 1, 'udwDeviceId': 123,
'cIpAddr': '198.51.100.21'},
{'udwCtrlId': 0, 'udwRoleType': 0,
'udwPortType': 1, 'udwDeviceId': 123,
'cIpAddr': '198.51.100.22'},
{'udwCtrlId': 0, 'udwRoleType': 0,
'udwPortType': 1, 'udwDeviceId': 123,
'cIpAddr': '198.51.100.23'}]}
MAP_TO_RESPONSE['GetSystemNetCfg'] = {'returncode': zte_pub.ZTE_SUCCESS,
'data': cfg_info}
iscsi_target = {
'tIscsiTargetInfo': [
{'udwCtrlId': 0,
'cTgtName': 'iqn.2099-01.cn.com.zte:usp.spr11-00:00:22:15'},
{'udwCtrlId': 0,
'cTgtName': 'iqn.2099-01.cn.com.zte:usp.spr11-00:00:22:25'}],
'udwCtrlCount': 2}
MAP_TO_RESPONSE['GetIscsiTargetName'] = {'returncode': zte_pub.ZTE_SUCCESS,
'data': iscsi_target}
MAP_TO_RESPONSE['CreateMapGrp'] = return_success
grp_info_forsearch = {'cVolName': 'vol1',
'sdwMapGrpNum': 1,
'cMapGrpNames': ['grp1'],
'sdwLunLocalId': [1]}
MAP_TO_RESPONSE['GetGrpNamesOfVol'] = (
{'returncode': zte_pub.ZTE_SUCCESS, 'data': grp_info_forsearch})
MAP_TO_RESPONSE['CreateHost'] = return_success
MAP_TO_RESPONSE['AddPortToHost'] = return_success
MAP_TO_RESPONSE['AddHostToGrp'] = return_success
MAP_TO_RESPONSE['DelVolFromGrp'] = return_success
MAP_TO_RESPONSE['DelHostFromGrp'] = return_success
host_info = {'sdwPortNum': 2,
'tPort': [{'cPortName': 'port1'},
{'cPortName': 'port2'}]}
MAP_TO_RESPONSE['GetHost'] = {'returncode': zte_pub.ZTE_SUCCESS,
'data': host_info}
MAP_TO_RESPONSE['DelPortFromHost'] = return_success
MAP_TO_RESPONSE['DelHost'] = return_success
class FakeZteISCSIDriver(zte_ks.ZteISCSIDriver):
def __init__(self, configuration):
self.configuration = configuration
super(FakeZteISCSIDriver, self).__init__(
configuration=self.configuration)
self.result = zte_pub.ZTE_SUCCESS
self.test_flag = True
self.portexist_flag = False
self.portexistother_flag = False
self.hostexist_flag = False
self.hostexistother_flag = False
def _call(self, sessionid='', method='', params=None):
return_data = return_success
if method in MAP_TO_RESPONSE.keys():
return_data = MAP_TO_RESPONSE[method]
if not self.test_flag:
return_data = return_error
if self.portexistother_flag:
return_data = return_port_error
if self.hostexistother_flag:
return_data = return_host_error
return return_data
def _check_conf_file(self):
pass
def _get_iscsi_info(self):
iscsi_info = {'DefaultTargetIPs': ["198.51.100.20"]}
return iscsi_info
class ZteBaseDriverTestCase(object):
def test_create_volume_success(self):
self.driver.test_flag = True
self.driver.create_volume(volume_paras)
self.assertEqual(zte_pub.ZTE_SUCCESS, self.driver.result)
def test_create_volume_fail(self):
self.driver.test_flag = False
self.assertRaises(exception.CinderException,
self.driver.create_volume, volume_paras)
def test_delete_volume_success(self):
self.driver.test_flag = True
self.driver.delete_volume(volume_paras)
self.assertEqual(zte_pub.ZTE_SUCCESS, self.driver.result)
def test_delete_volume_fail(self):
self.driver.test_flag = False
self.assertRaises(exception.CinderException,
self.driver.delete_volume, volume_paras)
def test_delete_cloned_volume_success(self):
self.driver.test_flag = True
vol = {'name': 'volume-21ec7341-9256-497b-97d9-ef48edcf0635',
'source_volid': '68a52c1e-ecbe-4f6c-954c-9f551347ff3f'}
self.driver.delete_volume(vol)
self.assertEqual(zte_pub.ZTE_SUCCESS, self.driver.result)
def test_delete_cloned_volume_fail(self):
self.driver.test_flag = False
vol = {'name': 'volume-21ec7341-9256-497b-97d9-ef48edcf0635',
'source_volid': '68a52c1e-ecbe-4f6c-954c-9f551347ff3f'}
self.assertRaises(exception.CinderException,
self.driver.delete_volume, vol)
def test_create_snapshot_success(self):
self.driver.test_flag = True
snap_vol = {'name': 'snapshot-2b9b982a-8b56-46e3-9d4f-6392e8a72e6e',
'volume_name':
'volume-21ec7341-9256-497b-97d9-ef48edcf0635',
'volume_size': 2}
self.driver.create_snapshot(snap_vol)
self.assertEqual(zte_pub.ZTE_SUCCESS, self.driver.result)
def test_create_snapshot_fail(self):
self.driver.test_flag = False
snap_vol = {'name': 'snapshot-2b9b982a-8b56-46e3-9d4f-6392e8a72e6e',
'volume_name':
'volume-21ec7341-9256-497b-97d9-ef48edcf0635',
'volume_size': 2}
self.assertRaises(exception.CinderException,
self.driver.create_snapshot, snap_vol)
def test_delete_snapshot_success(self):
self.driver.test_flag = True
snap_vol = {'name': 'snapshot-2b9b982a-8b56-46e3-9d4f-6392e8a72e6e'}
self.driver.delete_snapshot(snap_vol)
self.assertEqual(zte_pub.ZTE_SUCCESS, self.driver.result)
def test_delete_snapshot_fail(self):
self.driver.test_flag = False
snap_vol = {'name': 'snapshot-2b9b982a-8b56-46e3-9d4f-6392e8a72e6e'}
self.assertRaises(exception.CinderException,
self.driver.delete_snapshot, snap_vol)
def test_extend_volume_success(self):
self.driver.test_flag = True
self.driver.extend_volume(volume_paras, 4)
self.assertEqual(zte_pub.ZTE_SUCCESS, self.driver.result)
def test_extend_volume_fail(self):
self.driver.test_flag = False
self.assertRaises(exception.CinderException,
self.driver.extend_volume, volume_paras, 4)
def test_create_cloned_volume_success(self):
self.driver.test_flag = True
self.driver.create_cloned_volume(volume_clone, volume_paras)
self.assertEqual(zte_pub.ZTE_SUCCESS, self.driver.result)
def test_create_cloned_volume_fail(self):
self.driver.test_flag = False
self.assertRaises(exception.CinderException,
self.driver.create_cloned_volume,
volume_clone, volume_paras)
def test_create_volume_from_snapshot_success(self):
self.driver.test_flag = True
self.driver.create_volume_from_snapshot(volume_clone, snapvolume_paras)
self.assertEqual(zte_pub.ZTE_SUCCESS, self.driver.result)
def test_create_volume_from_snapshot_fail(self):
self.driver.test_flag = False
self.assertRaises(exception.CinderException,
self.driver.create_cloned_volume,
volume_clone, volume_paras)
class ZteISCSIDriverTestCase(ZteBaseDriverTestCase, test.TestCase):
"""Test ZTE iSCSI volume driver."""
def __init__(self, *args, **kwargs):
super(ZteISCSIDriverTestCase, self).__init__(*args, **kwargs)
def setUp(self):
super(ZteISCSIDriverTestCase, self).setUp()
configuration = conf.Configuration(None)
self.configuration = configuration
self.configuration.zteControllerIP0 = '192.0.2.2'
self.configuration.zteLocalIP = '192.0.2.8'
self.configuration.zteUserName = 'root'
self.configuration.zteUserPassword = 'root'
self.configuration.zteChunkSize = 64
self.configuration.zteAheadReadSize = 8
self.configuration.zteCachePolicy = 65535
self.configuration.zteSSDCacheSwitch = 0
self.configuration.zteStoragePool = 'pool1,pool2,pool3'
self.configuration.ztePoolVolAllocPolicy = 0
self.configuration.ztePoolVolMovePolicy = 0
self.configuration.ztePoolVolIsThin = 0
self.configuration.ztePoolVolInitAllocedCapacity = 0
self.configuration.ztePoolVolAlarmThreshold = 0
self.configuration.ztePoolVolAlarmStopAllocFlag = 0
self.driver = FakeZteISCSIDriver(configuration=self.configuration)
self.driver.do_setup({})
def test_get_volume_stats(self):
stats = self.driver.get_volume_stats(True)
self.assertEqual("ZTE", stats["vendor_name"])
self.assertEqual("iSCSI", stats["storage_protocol"])
self.assertEqual("V1.0", stats["driver_version"])
self.assertLess(0, stats["total_capacity_gb"])
def test_initialize_connection_success(self):
self.driver.test_flag = True
data = self.driver.initialize_connection(volume_paras, connector)
properties = data['data']
self.assertEqual("iscsi", data["driver_volume_type"])
self.assertEqual('iqn.2099-01.cn.com.zte:usp.spr11-00:00:22:15',
properties["target_iqn"])
self.assertEqual(3, properties["target_lun"])
self.assertEqual('198.51.100.20:3260', properties["target_portal"])
def test_initialize_connection_portexist(self):
self.driver.portexist_flag = True
data = self.driver.initialize_connection(volume_paras, connector)
properties = data['data']
self.assertEqual("iscsi", data["driver_volume_type"])
self.assertEqual('iqn.2099-01.cn.com.zte:usp.spr11-00:00:22:15',
properties["target_iqn"])
self.assertEqual(3, properties["target_lun"])
self.assertEqual('198.51.100.20:3260', properties["target_portal"])
def test_initialize_connection_hostexist(self):
self.driver.hostexist_flag = True
data = self.driver.initialize_connection(volume_paras, connector)
properties = data['data']
self.assertEqual("iscsi", data["driver_volume_type"])
self.assertEqual('iqn.2099-01.cn.com.zte:usp.spr11-00:00:22:15',
properties["target_iqn"])
self.assertEqual(3, properties["target_lun"])
self.assertEqual('198.51.100.20:3260', properties["target_portal"])
def test_initialize_connection_portexistother(self):
self.driver.portexistother_flag = True
self.assertRaises(exception.CinderException,
self.driver.initialize_connection,
volume_paras, connector)
def test_initialize_connection_hostexistother(self):
self.driver.hostexistother_flag = True
self.assertRaises(exception.CinderException,
self.driver.initialize_connection,
volume_paras, connector)
def test_initialize_connection_fail(self):
self.driver.test_flag = False
self.assertRaises(exception.CinderException,
self.driver.initialize_connection,
volume_paras, connector)
def test_terminate_connection_success(self):
self.driver.test_flag = True
vol = {'name': 'volume-ee317512-f6a6-4284-a94e-5f4ac8783169'}
self.driver.terminate_connection(vol, connector)
self.assertEqual(zte_pub.ZTE_SUCCESS, self.driver.result)
def test_terminate_connection_fail(self):
self.driver.test_flag = False
vol = {'name': 'volume-ee317512-f6a6-4284-a94e-5f4ac8783169'}
self.assertRaises(exception.CinderException,
self.driver.terminate_connection, vol, connector)

View File

@ -1,994 +0,0 @@
# Copyright 2016 ZTE Corporation. All rights reserved
# 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.
"""
Volume driver for ZTE storage systems.
"""
import hashlib
import json
from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import units
import six
from six.moves import urllib
from cinder import exception
from cinder.i18n import _
from cinder import interface
from cinder import utils
from cinder.volume import configuration
from cinder.volume import driver
from cinder.volume.drivers.zte import zte_pub
LOG = logging.getLogger(__name__)
zte_opts = [
cfg.IPOpt('zteControllerIP0', default=None,
help='Main controller IP.'),
cfg.IPOpt('zteControllerIP1', default=None,
help='Slave controller IP.'),
cfg.IPOpt('zteLocalIP', default=None, help='Local IP.'),
cfg.StrOpt('zteUserName', default=None, help='User name.'),
cfg.StrOpt('zteUserPassword', default=None, secret=True,
help='User password.'),
cfg.IntOpt('zteChunkSize', default=4,
help='Virtual block size of pool. '
'Unit : KB. '
'Valid value : 4, 8, 16, 32, 64, 128, 256, 512. '),
cfg.IntOpt('zteAheadReadSize', default=8, help='Cache readahead size.'),
cfg.IntOpt('zteCachePolicy', default=1,
help='Cache policy. '
'0, Write Back; 1, Write Through.'),
cfg.IntOpt('zteSSDCacheSwitch', default=1,
help='SSD cache switch. '
'0, OFF; 1, ON.'),
cfg.ListOpt('zteStoragePool', default=[], help='Pool name list.'),
cfg.IntOpt('ztePoolVoAllocatedPolicy', default=0,
help='Pool volume allocated policy. '
'0, Auto; '
'1, High Performance Tier First; '
'2, Performance Tier First; '
'3, Capacity Tier First.'),
cfg.IntOpt('ztePoolVolMovePolicy', default=0,
help='Pool volume move policy.'
'0, Auto; '
'1, Highest Available; '
'2, Lowest Available; '
'3, No Relocation.'),
cfg.BoolOpt('ztePoolVolIsThin', default=False,
help='Whether it is a thin volume.'),
cfg.IntOpt('ztePoolVolInitAllocatedCapacity', default=0,
help='Pool volume init allocated Capacity.'
'Unit : KB. '),
cfg.IntOpt('ztePoolVolAlarmThreshold', default=0,
help='Pool volume alarm threshold. [0, 100]'),
cfg.IntOpt('ztePoolVolAlarmStopAllocatedFlag', default=0,
help='Pool volume alarm stop allocated flag.')
]
CONF = cfg.CONF
CONF.register_opts(zte_opts, group=configuration.SHARED_CONF_GROUP)
class ZTEVolumeDriver(driver.VolumeDriver):
VERSION = "1.0.0"
# ThirdPartySystems wiki page
CI_WIKI_NAME = "ZTE_cinder2_CI"
def __init__(self, *args, **kwargs):
super(ZTEVolumeDriver, self).__init__(*args, **kwargs)
self.configuration.append_config_values(zte_opts)
self.url = ''
self.login_info = {}
self.session_id = ''
def _get_md5(self, src_string):
md5obj = hashlib.md5()
md5obj.update(src_string.encode('UTF-8'))
md5_string = md5obj.hexdigest()
md5_string = md5_string[0:19]
return md5_string
def _call_method(self, method='', params=None):
sid = self._get_sessionid()
return self._call(sid, method, params)
def _call(self, sessin_id='', method='', params=None):
try:
params = params or {}
data = ("sessionID=" + sessin_id + "&method=" +
method + "&params=" + json.dumps(params))
LOG.debug('Req Data: method %(method)s data %(data)s.',
{'method': method, 'data': data})
headers = {"Connection": "keep-alive",
"Content-Type": "application/x-www-form-urlencoded"}
req = urllib.request.Request(self.url, data, headers)
req.get_method = lambda: 'POST'
# self.url used for req is coded to always use the HTTPS scheme
response = urllib.request.urlopen(req, # nosec
timeout=
zte_pub.ZTE_DEFAULT_TIMEOUT
).read()
LOG.debug('Response Data: method %(method)s res %(res)s.',
{'method': method, 'res': response})
except Exception:
LOG.exception('Bad response from server.')
msg = (_('_call failed.'))
raise exception.VolumeBackendAPIException(data=msg)
res_json = json.loads(response)
return res_json
def _get_server(self):
controller_ip = (self.login_info['ControllerIP0']
or self.login_info['ControllerIP1'] or '')
self.url = 'https://' + controller_ip + '/phpclient/client.php'
LOG.debug('Set ZTE server is %s.', self.url)
def _change_server(self):
if (self.login_info['ControllerIP0'] and
self.login_info['ControllerIP1']):
controller_ip = (self.login_info['ControllerIP1']
if self.login_info['ControllerIP0'] in self.url
else self.login_info['ControllerIP0'])
self.url = 'https://' + controller_ip + '/phpclient/client.php'
def _user_login(self):
loginfo = {'UserName': self.login_info['UserName'],
'UserPassword': self.login_info['UserPassword'],
'LocalIP': self.login_info['LocalIP'],
'LoginType': zte_pub.ZTE_WEB_LOGIN_TYPE}
result = self._call('""', 'plat.session.signin', loginfo)
if result['returncode'] in [zte_pub.ZTE_SUCCESS,
zte_pub.ZTE_SESSION_EXIST]:
self.session_id = result['data']['sessionID']
return self.session_id
else:
err_msg = (
_('Failed to login. Return code: %(ret)s.') % {
'ret': result['returncode']})
raise exception.VolumeBackendAPIException(
data=err_msg)
def do_setup(self, context):
"""Any initialization the volume driver does while starting."""
self.login_info = {
'ControllerIP0': self.configuration.zteControllerIP0,
'ControllerIP1': self.configuration.zteControllerIP1,
'LocalIP': self.configuration.zteLocalIP,
'UserName': self.configuration.zteUserName,
'UserPassword': self.configuration.zteUserPassword}
self._get_server()
try:
self.session_id = self._user_login()
except exception.VolumeBackendAPIException:
self._change_server()
self.session_id = self._user_login()
def check_for_setup_error(self):
zteControllerIP0 = self.configuration.zteControllerIP0
if zteControllerIP0 is None:
msg = (_("Controller IP is missing for ZTE driver."))
raise exception.VolumeBackendAPIException(data=msg)
zteUserName = self.configuration.zteUserName
if zteUserName is None:
msg = (_("User Name is missing for ZTE driver."))
raise exception.VolumeBackendAPIException(data=msg)
zteUserPassword = self.configuration.zteUserPassword
if zteUserPassword is None:
msg = (_("User Password is missing for ZTE driver."))
raise exception.VolumeBackendAPIException(data=msg)
def _get_sessionid(self):
try:
sid = self.session_id
ret = self._call(sid, 'plat.session.heartbeat')
if ret['returncode'] == zte_pub.ZTE_SUCCESS:
return sid
else:
LOG.info('heartbeat failed. Return code: %(ret)s.',
{'ret': ret['returncode']})
except Exception:
LOG.exception('_get_sessionid error.')
self._change_server()
return self._user_login()
def _get_pool_list(self):
pool_info_list = []
for pool_name in self.configuration.zteStoragePool:
if pool_name:
ret = self._call_method(
'GetPoolInfo', {
'scPoolName': pool_name})
pool_info = {'name': pool_name}
if ((ret['returncode'] == zte_pub.ZTE_SUCCESS) and
(ret['data']['sdwState'] == zte_pub.ZTE_STATUS_OK)):
total_capacity = ret['data']['qwTotalCapacity']
free_capacitity = ret['data']['qwFreeCapacity']
pool_info['total'] = (
float(total_capacity) / units.Ki)
pool_info['free'] = (
float(free_capacitity) / units.Ki)
pool_info_list.append(pool_info)
if not pool_info_list:
err_msg = (_('No pool available.'))
raise exception.VolumeBackendAPIException(data=err_msg)
return pool_info_list
def _find_pool_to_create_volume(self):
pool_list = self._get_pool_list()
pool = max(pool_list, key=lambda arg: arg['free'])
return pool['name']
def _create_volume_in_pool(self, volume_name, volume_size, pool_name):
vol = {
'scPoolName': pool_name,
'scVolName': volume_name,
'sdwStripeDepth': self.configuration.zteChunkSize,
'qwCapacity': float(volume_size),
'sdwCtrlPrefer': 0xFFFF,
'sdwCachePolicy': self.configuration.zteCachePolicy,
'sdwAheadReadSize': self.configuration.zteAheadReadSize,
'sdwAllocPolicy': self.configuration.ztePoolVoAllocatedPolicy,
'sdwMovePolicy': self.configuration.ztePoolVolMovePolicy,
'udwIsThinVol': self.configuration.ztePoolVolIsThin,
'uqwInitAllocedCapacity':
self.configuration.ztePoolVolInitAllocatedCapacity,
'sdwAlarmThreshold':
self.configuration.ztePoolVolAlarmThreshold,
'sdwAlarmStopAllocFlag':
self.configuration.ztePoolVolAlarmStopAllocatedFlag,
'dwSSDCacheSwitch': self.configuration.zteSSDCacheSwitch}
ret = self._call_method('CreateVolOnPool', vol)
if ret['returncode'] not in [zte_pub.ZTE_ERR_OBJECT_EXIST,
zte_pub.ZTE_SUCCESS]:
err_msg = (
_('Create volume failed. Volume name: %(name)s. '
'Return code: %(ret)s.') %
{'name': volume_name,
'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(
data=err_msg)
def _create_volume(self, volume_name, volume_size):
pool_name = self._find_pool_to_create_volume()
if pool_name:
self._create_volume_in_pool(volume_name, volume_size, pool_name)
else:
msg = _('No pool available.')
raise exception.VolumeDriverException(message=msg)
def create_volume(self, volume):
"""Create a new volume."""
volume_name = self._translate_volume_name(volume['name'])
volume_size = float(volume['size'] * units.Mi)
self._create_volume(volume_name, volume_size)
def _delete_clone_volume(self, cloned_name):
cloned_name += zte_pub.ZTE_CLONE_SUFFIX
cvol_name = {'scCvolName': cloned_name}
ret = self._call_method('DelCvol', cvol_name)
if ret['returncode'] not in [zte_pub.ZTE_ERR_CLONE_OR_SNAP_NOT_EXIST,
zte_pub.ZTE_ERR_VAS_OBJECT_NOT_EXIST,
zte_pub.ZTE_SUCCESS]:
err_msg = (_('Delete volume failed. Clone name: %(name)s. '
'Return code: %(ret)s.') %
{'name': cloned_name,
'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)
def _remove_volume_from_group(self, volume):
ret = self._call_method('GetGrpNamesOfVol', {'cVolName': volume})
if ret['returncode'] == zte_pub.ZTE_SUCCESS:
group_num = int(ret['data']['sdwMapGrpNum'])
for index in range(0, group_num):
group_name = ret['data']['cMapGrpNames'][index]
lun_ID = ret['data']['sdwLunLocalId'][index]
self._map_delete_lun(lun_ID, group_name)
def _delete_volume(self, volume_name):
vol_name = {'cVolName': volume_name}
ret = self._call_method('DelVol', vol_name)
if ret['returncode'] not in [zte_pub.ZTE_ERR_VOLUME_NOT_EXIST,
zte_pub.ZTE_ERR_LUNDEV_NOT_EXIST,
zte_pub.ZTE_SUCCESS]:
err_msg = (_('Delete volume failed. Volume name: %(name)s.'
'Return code: %(ret)s.') %
{'name': volume_name,
'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)
def delete_volume(self, volume):
"""Delete a volume."""
volume_name = self._translate_volume_name(volume['name'])
LOG.debug('delete_volume: volume name: %s.', volume_name)
self._delete_clone_relation_by_volname(volume_name, False)
self._remove_volume_from_group(volume_name)
self._delete_volume(volume_name)
def _delete_cvol(self, cloned_name, issnapshot):
cvol_name = {'scCvolName': cloned_name}
ret = self._call_method('SyncForceDelCvol', cvol_name)
if ret['returncode'] not in [zte_pub.ZTE_ERR_CLONE_OR_SNAP_NOT_EXIST,
zte_pub.ZTE_ERR_VAS_OBJECT_NOT_EXIST,
zte_pub.ZTE_SUCCESS]:
err_msg = (_('_delete_cvol: Failed to delete clone vol. '
'cloned name: %(name)s with Return code: '
'%(ret)s.') %
{'name': cloned_name, 'ret': ret['returncode']})
if ret['returncode'] == zte_pub.ZTE_VOLUME_TASK_NOT_FINISHED:
if issnapshot:
raise exception.SnapshotIsBusy(snapshot_name=cloned_name)
else:
raise exception.VolumeIsBusy(volume_name=cloned_name)
else:
raise exception.VolumeBackendAPIException(data=err_msg)
def _delete_clone_relation_by_volname(self, volname, issnapshot):
svol_name = {'scVolName': volname}
LOG.debug('GetCvolNamesOnVol: volume name: %s.', volname)
ret = self._call_method('GetCvolNamesOnVol', svol_name)
data_info = ret['data']
if ret['returncode'] == zte_pub.ZTE_SUCCESS:
sccvolnames = data_info['scCvolNames']
for i in range(0, ret['data']['sdwCvolNum']):
cloned_name = sccvolnames[i]['scCvolName']
self._delete_cvol(cloned_name, issnapshot)
cloned_name = volname + zte_pub.ZTE_CLONE_SUFFIX
self._delete_cvol(cloned_name, False)
def _create_snapshot(
self,
snapshot_name,
src_vol,
src_vol_size,
snapshot_mode):
svol_paras = {
'scVolName': src_vol,
'scSnapName': snapshot_name,
'sdwSnapType': 1,
'swRepoSpaceAlarm': 60,
'swRepoOverflowPolicy': 0,
'sqwRepoCapacity': float(src_vol_size * units.Mi),
'ucIsAgent': 0,
'ucSnapMode': snapshot_mode,
'is_private': 0,
'ucIsAuto': 0}
ret = self._call_method('CreateSvol', svol_paras)
if ret['returncode'] != zte_pub.ZTE_SUCCESS:
err_msg = (_('Failed to create snap.snap name: %(snapname)s,'
'srvol name :%(srv)s with Return code: %(ret)s. ') %
{'snapname': snapshot_name,
'srv': src_vol,
'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)
def create_snapshot(self, snapshot):
"""create a snapshot from volume"""
snapshot_name = self._translate_volume_name(snapshot['name'])
volume_name = self._translate_volume_name(snapshot['volume_name'])
volume_size = snapshot['volume_size']
self._create_snapshot(snapshot_name,
volume_name,
volume_size,
zte_pub.ZTE_SNAPSHOT_MODE_RW)
def _delete_snapshot(self, snapshot_name):
svol_name = {'scSnapName': snapshot_name}
ret = self._call_method('DelSvol', svol_name)
if ret['returncode'] not in [zte_pub.ZTE_ERR_CLONE_OR_SNAP_NOT_EXIST,
zte_pub.ZTE_ERR_VAS_OBJECT_NOT_EXIST,
zte_pub.ZTE_SUCCESS]:
err_msg = (_('_delete_snapshot:Failed to delete snap.'
'snap name: %(snapname)s with Return code: '
'%(ret)s.') %
{'snapname': snapshot_name,
'ret': ret['returncode']})
if ret['returncode'] == zte_pub.ZTE_ERR_SNAP_EXIST_CLONE:
raise exception.SnapshotIsBusy(snapshot_name=snapshot_name)
else:
raise exception.VolumeBackendAPIException(data=err_msg)
def delete_snapshot(self, snapshot):
"""delete a snapshot volume"""
snapshot_name = self._translate_volume_name(snapshot['name'])
self._delete_clone_relation_by_volname(snapshot_name, True)
self._delete_snapshot(snapshot_name)
def _extend_volume(self, volume_name, inc_size):
ext_vol_paras = {'scVolName': volume_name,
'qwExpandCapacity':
float(inc_size * units.Ki)}
ret = self._call_method('ExpandVolOnPool', ext_vol_paras)
if ret['returncode'] != zte_pub.ZTE_SUCCESS:
err_msg = (_('_extend_volume:Failed to extend vol.vol name:'
'%(name)s with Return code: %(ret)s.') %
{'name': volume_name, 'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)
def extend_volume(self, volume, new_size):
"""extend volume size"""
size_increase = (int(new_size)) - volume['size']
volume_name = self._translate_volume_name(volume['name'])
self._extend_volume(volume_name, size_increase)
def _cloned_volume(self, cloned_name, src_name, vol_size, vol_type):
self._create_volume(cloned_name, vol_size)
cvol_paras = {
'scCvolName': cloned_name + zte_pub.ZTE_CLONE_SUFFIX,
'scBvolName': src_name,
'scTargetName': cloned_name,
'sdwInitSync': 1,
'sdwProtectRestore': 0,
'sdwPri': 0,
'sdwPolicy': 0,
'sdwBvolType': vol_type}
ret = self._call_method('CreateCvol', cvol_paras)
if ret['returncode'] != zte_pub.ZTE_SUCCESS:
self._delete_volume(cloned_name)
err_msg = (_('_cloned_volume: Failed to clone vol. '
'vol name: %(name)s with Return code: %(ret)s. ') %
{'name': src_name,
'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)
def create_cloned_volume(self, volume, src_vref):
"""clone a volume"""
bvol_name = self._translate_volume_name(src_vref['name'])
cvol_name = self._translate_volume_name(volume['name'])
if volume['size'] < src_vref['size']:
err_msg = (_('Cloned volume size invalid. '
'Clone size: %(cloned_size)s. '
'Src volume size: %(volume_size)s.') %
{'cloned_size': volume['size'],
'volume_size': src_vref['size']})
raise exception.VolumeDriverException(message=err_msg)
else:
volume_size = float(
volume['size'] * units.Mi)
try:
self._cloned_volume(
cvol_name,
bvol_name,
volume_size,
zte_pub.ZTE_VOLUME)
except Exception:
self._delete_clone_relation_by_volname(bvol_name, False)
self._cloned_volume(
cvol_name,
bvol_name,
volume_size,
zte_pub.ZTE_VOLUME)
def create_volume_from_snapshot(self, volume, snapshot):
"""Create volume from snapshot """
bvol_name = self._translate_volume_name(snapshot['name'])
cvol_name = self._translate_volume_name(volume['name'])
if volume['size'] < snapshot['volume_size']:
err_msg = (
_('Cloned volume size invalid. '
'Clone size: %(cloned_size)s. '
'Src volume size: %(volume_size)s.') %
{'cloned_size': volume['size'],
'volume_size': snapshot['volume_size']})
raise exception.VolumeDriverException(message=err_msg)
else:
volume_size = float(
volume['size'] * units.Mi)
try:
self._cloned_volume(
cvol_name,
bvol_name,
volume_size,
zte_pub.ZTE_SNAPSHOT)
except Exception:
self._delete_clone_relation_by_volname(bvol_name, False)
self._cloned_volume(
cvol_name,
bvol_name,
volume_size,
zte_pub.ZTE_SNAPSHOT)
def create_export(self, context, volume, connector):
"""Exports the volume """
pass
def ensure_export(self, context, volume):
"""Driver entry point to get the export info for an existing volume."""
pass
def remove_export(self, context, volume_id):
"""Driver entry point to remove an export for a volume."""
pass
def get_volume_stats(self, refresh=False):
"""Get volume status."""
if refresh:
self._update_volume_status()
return self._stats
def _translate_host_name(self, host_name):
new_name = 'host_' + six.text_type(self._get_md5(host_name))
new_name = new_name.replace('-', 'R')
LOG.debug('_translate_host_name: Name in cinder: %(old)s, '
'new name in storage system: %(new)s.',
{'old': host_name, 'new': new_name})
return new_name
def _translate_volume_name(self, vol_name):
new_name = zte_pub.ZTE_VOL_NAME_PREFIX_NEW + six.text_type(
self._get_md5(vol_name))
new_name = new_name.replace('-', 'R')
LOG.debug('_translate_volume_name: Name in cinder: %(old)s, '
'new name in storage system: %(new)s.',
{'old': vol_name, 'new': new_name})
return new_name
def _get_lunid_from_vol(self, volume_name, map_group_name):
map_grp_info = {'cMapGrpName': map_group_name}
ret = self._call_method('GetMapGrpInfo', map_grp_info)
if ret['returncode'] == zte_pub.ZTE_SUCCESS:
lun_num = int(ret['data']['sdwLunNum'])
lun_info = ret['data']['tLunInfo']
for count in range(0, lun_num):
if volume_name == lun_info[count]['cVolName']:
return lun_info[count]['sdwLunId']
return None
elif ret['returncode'] == zte_pub.ZTE_ERR_GROUP_NOT_EXIST:
return None
else:
err_msg = (_('_get_lunid_from_vol:Get lunid from vol fail. '
'Group name:%(name)s vol:%(vol)s '
'with Return code: %(ret)s.') %
{'name': map_group_name,
'vol': volume_name,
'ret': ret['returncode']})
raise exception.VolumeDriverException(message=err_msg)
def _get_group_lunnum(self, map_group_name):
map_grp_info = {'cMapGrpName': map_group_name}
ret = self._call_method('GetMapGrpInfo', map_grp_info)
if ret['returncode'] == zte_pub.ZTE_SUCCESS:
lun_num = ret['data']['sdwLunNum']
return int(lun_num)
elif ret['returncode'] == zte_pub.ZTE_ERR_GROUP_NOT_EXIST:
return -1
else:
err_msg = (_('_get_group_lunnum:Get group info fail. '
'Group name:%(name)s with Return code: %(ret)s.') %
{'name': map_group_name, 'ret': ret['returncode']})
raise exception.VolumeDriverException(message=err_msg)
def _delete_group(self, map_group_name):
# before delete the group, we must delete the hosts in group
self._map_delete_host(map_group_name)
map_grp_info = {'cMapGrpName': map_group_name}
ret = self._call_method('DelMapGrp', map_grp_info)
if ret['returncode'] not in [zte_pub.ZTE_SUCCESS,
zte_pub.ZTE_ERR_GROUP_NOT_EXIST]:
err_msg = (_('_delete_group:Del group fail. '
'Group name:%(name)s with Return code: %(ret)s.') %
{'name': map_group_name, 'ret': ret['returncode']})
raise exception.VolumeDriverException(message=err_msg)
def _map_add_lun(self, volume_name, map_group_name):
add_vol_to_grp = {
'cMapGrpName': map_group_name,
'sdwLunId': 0,
'cVolName': volume_name}
ret = self._call_method('AddVolToGrp', add_vol_to_grp)
if ret['returncode'] in [zte_pub.ZTE_SUCCESS,
zte_pub.ZTE_VOLUME_IN_GROUP,
zte_pub.ZTE_ERR_VOL_EXISTS]:
return self._get_lunid_from_vol(volume_name, map_group_name)
err_msg = (
_(
'_map_add_lun:fail to add vol to grp. group name:%(name)s'
' lunid:%(lun)s '
'vol:%(vol)s with Return code: %(ret)s') %
{'name': map_group_name,
'lun': 0,
'vol': volume_name,
'ret': ret['returncode']})
raise exception.VolumeDriverException(message=err_msg)
def _update_volume_group_info(self):
pool_list = self._get_pool_list()
pool_info = {'total': 0, 'free': 0}
for item in pool_list:
pool_info['total'] += item['total']
pool_info['free'] += item['free']
return pool_info
def _get_sysinfo(self):
ret = self._call_method('GetSysInfo')
if ret['returncode'] != zte_pub.ZTE_SUCCESS:
err_msg = (_('_get_sysinfo:get sys info failed. Return code: '
'%(ret)s.'),
{'ret': ret['returncode']})
raise exception.VolumeDriverException(message=err_msg)
return ret['data']
def _update_volume_status(self):
LOG.debug("Updating volume status")
sys_info = self._get_sysinfo()
backend_name = self.configuration.safe_get('volume_backend_name')
pool_info = self._update_volume_group_info()
data = {
"volume_backend_name": backend_name or 'ZteISCSIDriver',
'vendor_name': sys_info['cVendor'],
'driver_version': sys_info['cVersionName'],
'storage_protocol': 'iSCSI',
'multiattach': False,
'total_capacity_gb': pool_info['total'],
'free_capacity_gb': pool_info['free'],
'reserved_percentage': 0,
'QoS_support': False}
self._stats = data
def _create_group(self, initiator_name, map_group_name):
pass
def _map_delete_host(self, map_group_name):
pass
def _map_delete_lun(self, lunid, initiator_name):
pass
@interface.volumedriver
class ZteISCSIDriver(ZTEVolumeDriver, driver.ISCSIDriver):
"""Zte iSCSI volume driver."""
# ThirdPartySystems wiki page
WIKI_CI_NAME = "ZTE_cinder2_CI"
# TODO(smcginnis) Remove driver in Queens if CI issues not fixed
SUPPORTED = False
def __init__(self, *args, **kwargs):
super(ZteISCSIDriver, self).__init__(*args, **kwargs)
def _map_lun(self, initiator_name, volume_name, map_group_name):
self._create_group(initiator_name, map_group_name)
return self._map_add_lun(volume_name, map_group_name)
def _get_net_cfg_ips(self):
ret = self._call_method('GetSystemNetCfg')
if ret['returncode'] != zte_pub.ZTE_SUCCESS:
err_msg = (_('get_Net_Cfg failed. Return code: %(ret)s.') %
{'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)
targetips = []
net_cfg_info = ret['data']['tSystemNetCfg']
for item in range(ret['data']['sdwDeviceNum']):
if (net_cfg_info[item]['udwRoleType'] == 0 and
net_cfg_info[item]['cIpAddr']):
targetips.append(net_cfg_info[item]['cIpAddr'])
return targetips
@utils.synchronized('zte_locked_initialize_connection')
def initialize_connection(self, volume, connector):
"""Map a volume to a host and return target iSCSI information."""
initiator_name = connector['initiator']
volume_name = self._translate_volume_name(volume['name'])
LOG.debug('initialize_connection: Volume name: %(volume)s. '
'Initiator name: %(ini)s.',
{'volume': volume_name,
'ini': initiator_name})
iscsi_conf = self._get_iscsi_info()
target_ips = iscsi_conf['DefaultTargetIPs']
target_portals = {}
target_iqns = []
for ip in target_ips:
iqn = self._get_tgt_iqn(ip)
if iqn:
if iqn not in target_iqns:
target_iqns.append(iqn)
target_portals[iqn] = ['%s:%s' % (ip, '3260')]
else:
target_portals[iqn].append('%s:%s' % (ip, '3260'))
if not target_iqns:
msg = (_('Failed to get target ip or iqn '
'for initiator %(ini)s, please check config file.') %
{'ini': initiator_name})
raise exception.VolumeDriverException(message=msg)
map_group_name = self._translate_grp_name(initiator_name)
lunid = self._map_lun(initiator_name, volume_name, map_group_name)
# Return iSCSI properties.
properties = {
'target_discovered': False,
'target_portal': target_portals[
target_iqns[0]][0],
'target_iqn': target_iqns[0],
'target_lun': lunid,
'volume_id': volume['id']}
if target_iqns and target_portals:
properties['target_portals'] = target_portals
properties['target_iqns'] = target_iqns
return {'driver_volume_type': 'iscsi', 'data': properties}
@utils.synchronized('zte_locked_initialize_connection')
def terminate_connection(self, volume, connector, **kwargs):
"""Delete map between a volume and a host."""
initiator_name = connector['initiator']
volume_name = self._translate_volume_name(volume['name'])
LOG.debug('volume name: %(volume)s, initiator name: %(ini)s.',
{'volume': volume_name,
'ini': initiator_name})
map_group_name = self._translate_grp_name(initiator_name)
lunid = self._get_lunid_from_vol(volume_name, map_group_name)
self._map_delete_lun(lunid, initiator_name)
def _get_iscsi_info(self):
iscsi_info = {}
try:
iscsi_info['DefaultTargetIPs'] = self._get_net_cfg_ips()
if not iscsi_info['DefaultTargetIPs']:
err_msg = _('Can not get target ip address. ')
raise exception.VolumeBackendAPIException(data=err_msg)
initiator_list = []
iscsi_info['Initiator'] = initiator_list
except Exception:
LOG.exception('_get_iscsi_info error.')
raise
return iscsi_info
def _translate_grp_name(self, grp_name):
new_name = zte_pub.ZTE_HOST_GROUP_NAME_PREFIX + six.text_type(
self._get_md5(grp_name))
new_name = new_name.replace('-', 'R')
LOG.debug('_translate_grp_name:Name in cinder: %(old)s, '
'new name in storage system: %(new)s.',
{'old': grp_name,
'new': new_name})
return new_name
def _get_target_ip_ctrl(self, target_ip):
LOG.debug('_get_target_ip_ctrl:target IP is %s.', target_ip)
ret = self._call_method('GetSystemNetCfg')
if ret['returncode'] != zte_pub.ZTE_SUCCESS:
err_msg = (_('_get_target_ip_ctrl:get iscsi port list fail. '
'with Return code: %(ret)s.') %
{'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)
count = ret['data']['sdwDeviceNum']
for index in range(0, count):
systemnetcfg = ret['data']['tSystemNetCfg'][index]
if target_ip == systemnetcfg['cIpAddr']:
return systemnetcfg['udwCtrlId']
return None
def _get_tgt_iqn(self, iscsiip):
# as the given iscsiip,we need to find it's ctrl number
ip_ctrl = self._get_target_ip_ctrl(iscsiip)
if ip_ctrl is None:
LOG.exception('_get_tgt_iqn:get iscsi ip ctrl fail, '
'IP is %s.', iscsiip)
return None
# get the ctrl iqn
ret = self._call_method('GetIscsiTargetName')
if ret['returncode'] != zte_pub.ZTE_SUCCESS:
return None
target_info = ret['data']['tIscsiTargetInfo']
ctrl_count = ret['data']['udwCtrlCount']
for index in range(0, ctrl_count):
if ip_ctrl == target_info[index]['udwCtrlId']:
return target_info[index]['cTgtName']
return None
def _create_group(self, initiator_name, map_group_name):
map_grp_info = {'cMapGrpName': map_group_name}
ret = self._call_method('CreateMapGrp', map_grp_info)
if ((ret['returncode'] == zte_pub.ZTE_SUCCESS) or
(ret['returncode'] == zte_pub.ZTE_ERR_GROUP_EXIST)):
host_name = self._translate_host_name(initiator_name)
host_info = {'cHostAlias': host_name, 'ucOs': 1, 'ucType': 1,
'cPortName': initiator_name,
'sdwMultiPathMode': 1, 'cMulChapPass': ''}
# create host
ret = self._call_method('CreateHost', host_info)
if ret['returncode'] not in [zte_pub.ZTE_SUCCESS,
zte_pub.ZTE_ERR_HOSTNAME_EXIST,
zte_pub.ZTE_ERR_PORT_EXIST,
zte_pub.ZTE_ERR_PORT_EXIST_OLD]:
err_msg = (
_('create host failed. Host name:%(name)s '
'with Return code: %(ret)s.') %
{'name': host_name, 'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)
# If port deleted by user, add it.
port_info = {
'cHostAlias': host_name,
'ucType': 1,
'cPortName': initiator_name,
'sdwMultiPathMode': 1,
'cMulChapPass': ''}
ret = self._call_method('AddPortToHost', port_info)
if ret['returncode'] not in [zte_pub.ZTE_SUCCESS,
zte_pub.ZTE_ERR_PORT_EXIST,
zte_pub.ZTE_ERR_PORT_EXIST_OLD]:
err_msg = (_('_create_group:add port failed. Port name: '
'%(name)s with Return code: %(ret)s.') %
{'name': initiator_name,
'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)
host_in_grp = {
'ucInitName': host_name,
'cMapGrpName': map_group_name}
ret = self._call_method('AddHostToGrp', host_in_grp)
if ret['returncode'] not in [zte_pub.ZTE_SUCCESS,
zte_pub.ZTE_ERR_HOST_EXIST,
zte_pub.ZTE_ERR_HOST_EXIST_OLD]:
self._delete_group(map_group_name)
err_msg = (_('_create_group:add host to group failed. '
'group name:%(name)s init name :%(init)s '
'with Return code: %(ret)s.') %
{'name': map_group_name,
'init': host_name,
'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)
else:
err_msg = (_('create group failed. Group name:%(name)s '
'with Return code: %(ret)s.') %
{'name': map_group_name,
'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)
def _map_delete_lun(self, lunid, initiator_name):
map_group_name = self._translate_grp_name(initiator_name)
# lun not exist, no need to delete
if (lunid != zte_pub.ZTE_LUNID_NULL
and lunid is not None):
del_vol_from_grp = {
'cMapGrpName': map_group_name,
'sdwLunId': lunid}
ret = self._call_method('DelVolFromGrp', del_vol_from_grp)
if ret['returncode'] != zte_pub.ZTE_SUCCESS:
err_msg = (_('_map_lun:delete lunid from group failed. '
'group name:%(name)s lunid : %(lun)s '
'with Return code: %(ret)s.') %
{'name': map_group_name, 'lun': lunid,
'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)
# if no lun in group,then we will delete this group
lun_num = self._get_group_lunnum(map_group_name)
if lun_num == 0:
self._delete_group(map_group_name)
def _map_delete_host(self, map_group_name):
map_grp_info = {'cMapGrpName': map_group_name}
ret = self._call_method('GetMapGrpInfo', map_grp_info)
if ret['returncode'] != zte_pub.ZTE_SUCCESS:
err_msg = (_('_map_delete_host:get map group info failed. '
'group name:%(name)s with Return code: %(ret)s.') %
{'name': map_group_name, 'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)
sdwhostnum = ret['data']['sdwHostNum']
if sdwhostnum > 0:
thostinfo = ret['data']['tHostInfo']
for hostindex in range(0, int(sdwhostnum)):
initiator_name = thostinfo[hostindex]['ucHostName']
host_in_grp = {
'ucInitName': initiator_name,
'cMapGrpName': map_group_name}
ret = self._call_method('DelHostFromGrp', host_in_grp)
if ret['returncode'] == zte_pub.ZTE_ERR_GROUP_NOT_EXIST:
continue
if ret['returncode'] not in [zte_pub.ZTE_SUCCESS,
zte_pub.ZTE_ERR_HOST_NOT_EXIST]:
msg = _('delete host from group failed. ')
raise exception.VolumeDriverException(message=msg)
ret = self._call_method(
'GetHost', {"cHostAlias": initiator_name})
if ret['returncode'] != zte_pub.ZTE_SUCCESS:
err_msg = (_('_map_delete_host:get host info failed. '
'host name:%(name)s with Return code: '
'%(ret)s.') %
{'name': initiator_name,
'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)
return_data = ret['data']
portnum = return_data['sdwPortNum']
for portindex in range(0, int(portnum)):
port_host_info = {}
port_info = return_data['tPort']
port_name = port_info[portindex]['cPortName']
port_host_info['cPortName'] = port_name
port_host_info['cHostAlias'] = initiator_name
ret = self._call_method('DelPortFromHost', port_host_info)
if ret['returncode'] != zte_pub.ZTE_SUCCESS:
err_msg = (_('delete port from host failed. '
'host name:%(name)s, port name:%(port)s '
'with Return code: %(ret)s.') %
{'name': initiator_name,
'port': port_name,
'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)
ret = self._call_method(
'DelHost', {"cHostAlias": initiator_name})
if (ret['returncode'] not
in [zte_pub.ZTE_SUCCESS,
zte_pub.ZTE_ERR_HOSTNAME_NOT_EXIST]):
err_msg = (_('_map_delete_host: delete host failed. '
'host name:%(name)s with Return code: '
'%(ret)s') %
{'name': initiator_name,
'ret': ret['returncode']})
raise exception.VolumeBackendAPIException(data=err_msg)

View File

@ -1,59 +0,0 @@
# Copyright 2016 ZTE Corporation. All rights reserved
# 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.
"""
Constants used in ZTE Volume driver.
"""
ZTE_HOST_GROUP_NAME_PREFIX = 'HostGroup_'
ZTE_VOL_AND_SNAP_NAME_PREFIX = 'OpenStack_'
ZTE_VOL_NAME_PREFIX_NEW = 'OpenCos_'
ZTE_CLONE_SUFFIX = 'c'
ZTE_GROUP_MAX_LUN = 255
ZTE_SUCCESS = 0
ZTE_VOLUME_IN_GROUP = 16917029
ZTE_WEB_LOGIN_TYPE = 5
ZTE_ERR_GROUP_NOT_EXIST = 16916997
ZTE_ERR_GROUP_EXIST = 16916994
ZTE_ERR_HOSTNAME_EXIST = 16918785
ZTE_ERR_HOSTNAME_NOT_EXIST = 16918786
ZTE_ERR_PORT_EXIST_OLD = 16918787
ZTE_ERR_PORT_EXIST = 16918798
ZTE_ERR_PORT_EXIST_INOTHER = 16918799
ZTE_ERR_HOST_NOT_EXIST = 16917004
ZTE_ERR_HOST_EXIST_OLD = 16917002
ZTE_ERR_HOST_EXIST = 16917015
ZTE_ERR_HOST_EXIST_INOTHER = 16917016
ZTE_ERR_VOLUME_NOT_EXIST = 17108999
ZTE_ERR_OBJECT_EXIST = 16917159
ZTE_ERR_CLONE_OR_SNAP_NOT_EXIST = 16917040
ZTE_ERR_VOL_EXISTS = 16917000
ZTE_ERR_LUNDEV_NOT_EXIST = 16973826
ZTE_ERR_VAS_OBJECT_NOT_EXIST = 17436681
ZTE_VOLUME_TASK_NOT_FINISHED = 17436959
ZTE_ERR_SNAP_EXIST_CLONE = 16917163
ZTE_SESSION_EXIST = 1495
ZTE_STATUS_OK = 1
ZTE_VOLUME = 0
ZTE_SNAPSHOT = 1
ZTE_LUNID_NULL = -1
ZTE_VOLUME_ALLOCATION_RATIO = 20
ZTE_VOLUME_SNAPSHOT_PERCENT = 50
ZTE_DEFAULT_TIMEOUT = 720
ZTE_SNAPSHOT_MODE_READ_ONLY = 0
ZTE_SNAPSHOT_MODE_RW = 1

View File

@ -1,158 +0,0 @@
==================
ZTE volume drivers
==================
The ZTE volume drivers allow ZTE KS3200 or KU5200 arrays
to be used for Block Storage in OpenStack deployments.
System requirements
~~~~~~~~~~~~~~~~~~~
To use the ZTE drivers, the following prerequisites:
- ZTE KS3200 or KU5200 array with:
- iSCSI or FC interfaces
- 30B2 firmware or later
- Network connectivity between the OpenStack host and the array
management interfaces
- HTTPS or HTTP must be enabled on the array
Supported operations
~~~~~~~~~~~~~~~~~~~~
- Create, delete, attach, and detach volumes.
- Create, list, and delete volume snapshots.
- Create a volume from a snapshot.
- Copy an image to a volume.
- Copy a volume to an image.
- Clone a volume.
- Extend a volume.
- Migrate a volume with back-end assistance.
- Retype a volume.
- Manage and unmanage a volume.
Configuring the array
~~~~~~~~~~~~~~~~~~~~~
#. Verify that the array can be managed using an HTTPS connection. HTTP can
also be used if ``zte_api_protocol=http`` is placed into the
appropriate sections of the ``cinder.conf`` file.
Confirm that virtual pools A and B are present if you plan to use
virtual pools for OpenStack storage.
#. Edit the ``cinder.conf`` file to define a storage back-end entry for
each storage pool on the array that will be managed by OpenStack. Each
entry consists of a unique section name, surrounded by square brackets,
followed by options specified in ``key=value`` format.
- The ``zte_backend_name`` value specifies the name of the storage
pool on the array.
- The ``volume_backend_name`` option value can be a unique value, if
you wish to be able to assign volumes to a specific storage pool on
the array, or a name that is shared among multiple storage pools to
let the volume scheduler choose where new volumes are allocated.
- The rest of the options will be repeated for each storage pool in a
given array: the appropriate cinder driver name, IP address or
host name of the array management interface; the username and password
of an array user account with ``manage`` privileges; and the iSCSI IP
addresses for the array if using the iSCSI transport protocol.
In the examples below, two back ends are defined, one for pool A and one
for pool B, and a common ``volume_backend_name``. Use this for a
single volume type definition can be used to allocate volumes from both
pools.
**Example: iSCSI back-end entries**
.. code-block:: ini
[pool-a]
zte_backend_name = A
volume_backend_name = zte-array
volume_driver = cinder.volume.drivers.zte.zte_iscsi.ZTEISCSIDriver
san_ip = 10.1.2.3
san_login = manage
san_password = !manage
zte_iscsi_ips = 10.2.3.4,10.2.3.5
[pool-b]
zte_backend_name = B
volume_backend_name = zte-array
volume_driver = cinder.volume.drivers.zte.zte_iscsi.ZTEISCSIDriver
san_ip = 10.1.2.3
san_login = manage
san_password = !manage
zte_iscsi_ips = 10.2.3.4,10.2.3.5
**Example: Fibre Channel back end entries**
.. code-block:: ini
[pool-a]
zte_backend_name = A
volume_backend_name = zte-array
volume_driver = cinder.volume.drivers.zte.zte_fc.ZTEFCDriver
san_ip = 10.1.2.3
san_login = manage
san_password = !manage
[pool-b]
zte_backend_name = B
volume_backend_name = zte-array
volume_driver = cinder.volume.drivers.zte.zte_fc.ZTEFCDriver
san_ip = 10.1.2.3
san_login = manage
san_password = !manage
#. If HTTPS is not enabled in the array, include
``zte_api_protocol = http`` in each of the back-end definitions.
#. If HTTPS is enabled, you can enable certificate verification with the
option ``zte_verify_certificate=True``. You may also use the
``zte_verify_certificate_path`` parameter to specify the path to a
``CA_BUNDLE`` file containing CAs other than those in the default list.
#. Modify the ``[DEFAULT]`` section of the ``cinder.conf`` file to add an
``enabled_backends`` parameter specifying the back-end entries you added,
and a ``default_volume_type`` parameter specifying the name of a volume
type that you will create in the next step.
**Example: [DEFAULT] section changes**
.. code-block:: ini
[DEFAULT]
# ...
enabled_backends = pool-a,pool-b
default_volume_type = zte
#. Create a new volume type for each distinct ``volume_backend_name`` value
that you added to the ``cinder.conf`` file. The example below
assumes that the same ``volume_backend_name=zte-array``
option was specified in all of the
entries, and specifies that the volume type ``zte`` can be used to
allocate volumes from any of them.
**Example: Creating a volume type**
.. code-block:: console
$ openstack volume type create zte
$ openstack volume type set --property volume_backend_name=zte-array zte
#. After modifying the ``cinder.conf`` file,
restart the ``cinder-volume`` service.
Driver-specific options
~~~~~~~~~~~~~~~~~~~~~~~
The following table contains the configuration options that are specific
to the ZTE drivers.
.. include:: ../../tables/cinder-zte.inc

View File

@ -58,7 +58,6 @@ Volume drivers
drivers/zadara-volume-driver.rst
drivers/zfssa-iscsi-driver.rst
drivers/zfssa-nfs-driver.rst
drivers/zte-storage-driver.rst
To use different volume drivers for the cinder-volume service, use the
parameters described in these sections.

View File

@ -1,52 +0,0 @@
..
Warning: Do not edit this file. It is automatically generated from the
software project's code and your changes will be overwritten.
The tool to generate this file lives in openstack-doc-tools repository.
Please make any changes needed in the code, then run the
autogenerate-config-doc tool from the openstack-doc-tools repository, or
ask for help on the documentation mailing list, IRC channel or meeting.
.. _cinder-zte:
.. list-table:: Description of Zte volume driver configuration options
:header-rows: 1
:class: config-ref-table
* - Configuration option = Default value
- Description
* - **[DEFAULT]**
-
* - ``zteAheadReadSize`` = ``8``
- (Integer) Cache readahead size.
* - ``zteCachePolicy`` = ``1``
- (Integer) Cache policy. 0, Write Back; 1, Write Through.
* - ``zteChunkSize`` = ``4``
- (Integer) Virtual block size of pool. Unit : KB. Valid value : 4, 8, 16, 32, 64, 128, 256, 512.
* - ``zteControllerIP0`` = ``None``
- (IP) Main controller IP.
* - ``zteControllerIP1`` = ``None``
- (IP) Slave controller IP.
* - ``zteLocalIP`` = ``None``
- (IP) Local IP.
* - ``ztePoolVoAllocatedPolicy`` = ``0``
- (Integer) Pool volume allocated policy. 0, Auto; 1, High Performance Tier First; 2, Performance Tier First; 3, Capacity Tier First.
* - ``ztePoolVolAlarmStopAllocatedFlag`` = ``0``
- (Integer) Pool volume alarm stop allocated flag.
* - ``ztePoolVolAlarmThreshold`` = ``0``
- (Integer) Pool volume alarm threshold. [0, 100]
* - ``ztePoolVolInitAllocatedCapacity`` = ``0``
- (Integer) Pool volume init allocated Capacity.Unit : KB.
* - ``ztePoolVolIsThin`` = ``False``
- (Integer) Whether it is a thin volume.
* - ``ztePoolVolMovePolicy`` = ``0``
- (Integer) Pool volume move policy.0, Auto; 1, Highest Available; 2, Lowest Available; 3, No Relocation.
* - ``zteSSDCacheSwitch`` = ``1``
- (Integer) SSD cache switch. 0, OFF; 1, ON.
* - ``zteStoragePool`` =
- (List) Pool name list.
* - ``zteUserName`` = ``None``
- (String) User name.
* - ``zteUserPassword`` = ``None``
- (String) User password.

View File

@ -13,4 +13,5 @@ upgrade:
* Reduxio
* Violin
* X-IO
* ZTE