Merge "Huawei manila driver code refactoring"

This commit is contained in:
Jenkins 2015-06-03 20:04:53 +00:00 committed by Gerrit Code Review
commit dfed9c66a8
6 changed files with 871 additions and 475 deletions

View File

@ -0,0 +1,59 @@
# Copyright (c) 2015 Huawei Technologies Co., Ltd.
# 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.
"""Abstract base class to work with share."""
import abc
import six
@six.add_metaclass(abc.ABCMeta)
class HuaweiBase(object):
"""Interface to work with share."""
def __init__(self, configuration):
"""Do initialization."""
self.configuration = configuration
@abc.abstractmethod
def create_share(self, share, share_server):
"""Is called to create share."""
@abc.abstractmethod
def create_snapshot(self, snapshot, share_server):
"""Is called to create snapshot."""
@abc.abstractmethod
def delete_share(self, share, share_server):
"""Is called to remove share."""
@abc.abstractmethod
def delete_snapshot(self, snapshot, share_server):
"""Is called to remove snapshot."""
@abc.abstractmethod
def allow_access(self, share, access, share_server):
"""Allow access to the share."""
@abc.abstractmethod
def deny_access(self, share, access, share_server):
"""Deny access to the share."""
@abc.abstractmethod
def get_network_allocations_number(self):
"""Get number of network interfaces to be created."""
def update_share_stats(self, stats_dict):
"""Retrieve stats info from share group."""

View File

@ -13,20 +13,21 @@
# License for the specific language governing permissions and limitations
# under the License.
"""Huawei Nas Driver for Huawei OceanStor V3 storage arrays."""
import time
"""Huawei Nas Driver for Huawei storage arrays."""
from xml.etree import ElementTree as ET
from oslo_config import cfg
from oslo_log import log
from oslo_utils import excutils
from oslo_utils import units
from oslo_utils import importutils
from manila import exception
from manila.i18n import _, _LI, _LW
from manila.openstack.common import loopingcall
from manila.i18n import _
from manila.share import driver
from manila.share.drivers.huawei import constants
from manila.share.drivers.huawei import huawei_helper
HUAWEI_UNIFIED_DRIVER_REGISTRY = {
'V3': 'manila.share.drivers.huawei.v3.connection.V3StorageConnection', }
huawei_opts = [
cfg.StrOpt('manila_huawei_conf_file',
@ -54,56 +55,47 @@ class HuaweiNasDriver(driver.ShareDriver):
self.configuration = kwargs.get('configuration', None)
if self.configuration:
self.configuration.append_config_values(huawei_opts)
self.helper = huawei_helper.RestHelper(self.configuration)
backend_driver = self.get_backend_driver()
self.plugin = importutils.import_object(backend_driver,
self.configuration)
else:
raise exception.InvalidShare(_("Huawei configuration missing."))
def check_for_setup_error(self):
"""Returns an error if prerequisites aren't met."""
self.helper._check_conf_file()
self.helper._check_service()
self.plugin.check_conf_file()
self.plugin.check_service()
def get_backend_driver(self):
filename = self.configuration.manila_huawei_conf_file
try:
tree = ET.parse(filename)
root = tree.getroot()
except Exception as err:
message = (_('Read Huawei config file(%(filename)s)'
' for Manila error: %(err)s')
% {'filename': filename,
'err': err})
LOG.error(message)
raise exception.InvalidInput(reason=message)
product = root.findtext('Storage/Product')
backend_driver = HUAWEI_UNIFIED_DRIVER_REGISTRY.get(product)
if backend_driver is None:
raise exception.InvalidInput(
reason=_('Storage %s is not supported.') % product)
return backend_driver
def do_setup(self, context):
"""Any initialization the huawei nas driver does while starting."""
LOG.debug("Do setup the plugin.")
return self.helper.login()
self.plugin.connect()
def create_share(self, context, share, share_server=None):
"""Create a share."""
LOG.debug("Create a share.")
share_name = share['name']
share_proto = share['share_proto']
size = share['size'] * units.Mi * 2
fs_id = None
# We sleep here to ensure the newly created filesystem can be read.
wait_interval = self._get_wait_interval()
try:
fs_id = self.helper.allocate_container(share_name, size)
def _create_share_complete():
fs = self.helper._get_fs_info_by_id(fs_id)
if fs['HEALTHSTATUS'] == constants.STATUS_FS_HEALTH\
and fs['RUNNINGSTATUS'] == constants.STATUS_FS_RUNNING:
return True
else:
return False
self._wait_for_condition(_create_share_complete,
int(wait_interval))
except Exception:
with excutils.save_and_reraise_exception():
if fs_id is not None:
self.helper._delete_fs(fs_id)
raise exception.InvalidShare('The status of filesystem error.')
try:
self.helper._create_share(share_name, fs_id, share_proto)
except Exception:
with excutils.save_and_reraise_exception():
if fs_id is not None:
self.helper._delete_fs(fs_id)
location = self.helper._get_location_path(share_name, share_proto)
location = self.plugin.create_share(share, share_server)
return location
def create_share_from_snapshot(self, context, share, snapshot,
@ -116,48 +108,16 @@ class HuaweiNasDriver(driver.ShareDriver):
"""Delete a share."""
LOG.debug("Delete a share.")
self.helper._delete_share(share['name'], share['share_proto'])
self.plugin.delete_share(share, share_server)
def create_snapshot(self, context, snapshot, share_server=None):
"""Create a snapshot."""
snap_name = snapshot['id']
share_proto = snapshot['share_proto']
share_name = self.helper._get_share_name_by_id(snapshot['share_id'])
share_type = self.helper._get_share_type(share_proto)
share = self.helper._get_share_by_name(share_name, share_type)
if not share:
err_msg = (_("Create a snapshot,share fs id is empty."))
LOG.error(err_msg)
raise exception.InvalidInput(reason=err_msg)
sharefsid = share['FSID']
snapshot_name = "share_snapshot_" + snap_name
snap_id = self.helper._create_snapshot(sharefsid,
snapshot_name)
LOG.info(_LI('Creating snapshot id %s.'), snap_id)
self.plugin.create_snapshot(snapshot, share_server)
def delete_snapshot(self, context, snapshot, share_server=None):
"""Delete a snapshot."""
LOG.debug("Delete a snapshot.")
snap_name = snapshot['id']
share_name = self.helper._get_share_name_by_id(snapshot['share_id'])
sharefsid = self.helper._get_fsid_by_name(share_name)
if sharefsid is None:
LOG.warn(_LW('Delete snapshot share id %s fs has been deleted.'),
snap_name)
return
snapshot_id = self.helper._get_snapshot_id(sharefsid, snap_name)
snapshot_flag = self.helper._check_snapshot_id_exist(snapshot_id)
if snapshot_flag is True:
self.helper._delete_snapshot(snapshot_id)
else:
LOG.warn(_LW("Can not find snapshot %s in array."), snap_name)
self.plugin.delete_snapshot(snapshot, share_server)
def ensure_share(self, context, share, share_server=None):
"""Ensure that storages are mounted and exported."""
@ -167,80 +127,27 @@ class HuaweiNasDriver(driver.ShareDriver):
"""Allow access to the share."""
LOG.debug("Allow access.")
self.helper._allow_access(share['name'], access, share['share_proto'])
self.plugin.allow_access(share, access, share_server)
def deny_access(self, context, share, access, share_server=None):
"""Deny access to the share."""
LOG.debug("Deny access.")
self.helper._deny_access(share['name'], access, share['share_proto'])
self.plugin.deny_access(share, access, share_server)
def get_network_allocations_number(self):
"""Get number of network interfaces to be created."""
LOG.debug("Get network allocations number.")
return constants.IP_ALLOCATIONS
return self.plugin.get_network_allocations_number()
def _update_share_stats(self):
"""Retrieve status info from share group."""
backend_name = self.configuration.safe_get('share_backend_name')
capacity = self.helper._get_capacity()
data = dict(
share_backend_name=backend_name or 'HUAWEI_NAS_Driver',
vendor_name='Huawei',
storage_protocol='NFS_CIFS',
total_capacity_gb=capacity['total_capacity'],
free_capacity_gb=capacity['free_capacity'])
storage_protocol='NFS_CIFS')
self.plugin.update_share_stats(data)
super(HuaweiNasDriver, self)._update_share_stats(data)
def _get_wait_interval(self):
"""Get wait interval from huawei conf file."""
root = self.helper._read_xml()
wait_interval = root.findtext('Filesystem/WaitInterval')
if wait_interval:
return wait_interval
else:
LOG.info(_LI(
"Wait interval is not configured in huawei "
"conf file. Use default: %(default_wait_interval)d."),
{"default_wait_interval": constants.DEFAULT_WAIT_INTERVAL})
return constants.DEFAULT_WAIT_INTERVAL
def _get_timeout(self):
"""Get timeout from huawei conf file."""
root = self.helper._read_xml()
timeout = root.findtext('Filesystem/Timeout')
if timeout:
return timeout
else:
LOG.info(_LI(
"Timeout is not configured in huawei conf file. "
"Use default: %(default_timeout)d."),
{"default_timeout": constants.DEFAULT_TIMEOUT})
return constants.DEFAULT_TIMEOUT
def _wait_for_condition(self, func, interval, timeout=None):
start_time = time.time()
if timeout is None:
timeout = self._get_timeout()
def _inner():
try:
res = func()
except Exception as ex:
res = False
LOG.debug('_wait_for_condition: %(func_name)s '
'failed for %(exception)s.',
{'func_name': func.__name__,
'exception': ex.message})
if res:
raise loopingcall.LoopingCallDone()
if int(time.time()) - int(start_time) > int(timeout):
msg = (_('_wait_for_condition: %s timed out.')
% func.__name__)
LOG.error(msg)
raise exception.InvalidShare(data=msg)
timer = loopingcall.FixedIntervalLoopingCall(_inner)
timer.start(interval=interval).wait()

View File

@ -0,0 +1,388 @@
# Copyright (c) 2015 Huawei Technologies Co., Ltd.
# 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.
import time
from oslo_log import log
from oslo_utils import units
from manila import exception
from manila.i18n import _, _LI, _LW
from manila.share.drivers.huawei import base as driver
from manila.share.drivers.huawei import constants
from manila.share.drivers.huawei.v3 import helper
LOG = log.getLogger(__name__)
class V3StorageConnection(driver.HuaweiBase):
"""Helper class for Huawei OceanStor V3 storage system."""
def __init__(self, configuration):
super(V3StorageConnection, self).__init__(configuration)
def connect(self):
"""Try to connect to V3 server."""
if self.configuration:
self.helper = helper.RestHelper(self.configuration)
else:
raise exception.InvalidInput(_("Huawei configuration missing."))
self.helper.login()
def create_share(self, share, share_server=None):
"""Create a share."""
share_name = share['name']
share_proto = share['share_proto']
fs_id = None
# We sleep here to ensure the newly created filesystem can be read.
wait_interval = self._get_wait_interval()
timeout = self._get_timeout()
try:
fs_id = self.allocate_container(share)
fs = self.helper._get_fs_info_by_id(fs_id)
end_time = time.time() + timeout
while not (self.check_fs_status(fs['HEALTHSTATUS'],
fs['RUNNINGSTATUS'])
or time.time() > end_time):
time.sleep(wait_interval)
fs = self.helper._get_fs_info_by_id(fs_id)
if not self.check_fs_status(fs['HEALTHSTATUS'],
fs['RUNNINGSTATUS']):
raise exception.InvalidShare(
reason=(_('Invalid status of filesystem: %(health)s '
'%(running)s.')
% {'health': fs['HEALTHSTATUS'],
'running': fs['RUNNINGSTATUS']}))
except Exception as err:
if fs_id is not None:
self.helper._delete_fs(fs_id)
message = (_('Failed to create share %(name)s.'
'Reason: %(err)s.')
% {'name': share_name,
'err': err})
raise exception.InvalidShare(reason=message)
try:
self.helper._create_share(share_name, fs_id, share_proto)
except Exception as err:
if fs_id is not None:
self.helper._delete_fs(fs_id)
raise exception.InvalidShare(
reason=(_('Failed to create share %(name)s.'
'Reason: %(err)s.')
% {'name': share_name,
'err': err}))
location = self._get_location_path(share_name, share_proto)
return location
def check_fs_status(self, health_status, running_status):
if (health_status == constants.STATUS_FS_HEALTH
and running_status == constants.STATUS_FS_RUNNING):
return True
else:
return False
def create_snapshot(self, snapshot, share_server=None):
"""Create a snapshot."""
snap_name = snapshot['id']
share_proto = snapshot['share_proto']
share_name = self.helper._get_share_name_by_id(snapshot['share_id'])
share_type = self.helper._get_share_type(share_proto)
share = self.helper._get_share_by_name(share_name, share_type)
if not share:
err_msg = _('Can not create snapshot,'
' because share_id is not provided.')
LOG.error(err_msg)
raise exception.InvalidInput(reason=err_msg)
sharefsid = share['FSID']
snapshot_name = "share_snapshot_" + snap_name
snap_id = self.helper._create_snapshot(sharefsid,
snapshot_name)
LOG.info(_LI('Creating snapshot id %s.'), snap_id)
def delete_snapshot(self, snapshot, share_server=None):
"""Delete a snapshot."""
LOG.debug("Delete a snapshot.")
snap_name = snapshot['id']
share_name = self.helper._get_share_name_by_id(snapshot['share_id'])
sharefsid = self.helper._get_fsid_by_name(share_name)
if sharefsid is None:
LOG.warning(_LW('Delete snapshot share id %s fs has been '
'deleted.'), snap_name)
return
snapshot_id = self.helper._get_snapshot_id(sharefsid, snap_name)
snapshot_flag = self.helper._check_snapshot_id_exist(snapshot_id)
if snapshot_flag:
self.helper._delete_snapshot(snapshot_id)
else:
LOG.warning(_LW("Can not find snapshot %s in array."), snap_name)
def update_share_stats(self, stats_dict):
"""Retrieve status info from share group."""
capacity = self._get_capacity()
stats_dict["pools"] = []
pool = {}
pool.update(dict(
pool_name=capacity['name'],
total_capacity_gb=capacity['TOTALCAPACITY'],
free_capacity_gb=capacity['CAPACITY'],
QoS_support=False,
reserved_percentage=0,
))
stats_dict["pools"].append(pool)
def delete_share(self, share, share_server=None):
"""Delete share."""
share_name = share['name']
share_proto = self.helper._get_share_type(share['share_proto'])
share = self.helper._get_share_by_name(share_name, share_proto)
if not share:
LOG.warning(_LW('The share was not found. Share name:%s'),
share_name)
fsid = self.helper._get_fsid_by_name(share_name)
if fsid:
self.helper._delete_fs(fsid)
return
LOG.warning(_LW('The filesystem was not found.'))
return
share_id = share['ID']
share_fs_id = share['FSID']
if share_id:
self.helper._delete_share_by_id(share_id, share_proto)
if share_fs_id:
self.helper._delete_fs(share_fs_id)
return share
def get_network_allocations_number(self):
"""Get number of network interfaces to be created."""
return constants.IP_ALLOCATIONS
def _get_capacity(self):
"""Get free capacity and total capacity of the pools."""
poolinfo = self.helper._find_pool_info()
if poolinfo:
total = int(poolinfo['TOTALCAPACITY']) / units.Mi / 2
free = int(poolinfo['CAPACITY']) / units.Mi / 2
poolinfo['TOTALCAPACITY'] = total
poolinfo['CAPACITY'] = free
return poolinfo
def _init_filesys_para(self, share):
"""Init basic filesystem parameters."""
name = share['name']
size = share['size'] * units.Mi * 2
poolinfo = self.helper._find_pool_info()
fileparam = {
"NAME": name.replace("-", "_"),
"DESCRIPTION": "",
"ALLOCTYPE": 1,
"CAPACITY": size,
"PARENTID": poolinfo['ID'],
"INITIALALLOCCAPACITY": units.Ki * 20,
"PARENTTYPE": 216,
"SNAPSHOTRESERVEPER": 20,
"INITIALDISTRIBUTEPOLICY": 0,
"ISSHOWSNAPDIR": True,
"RECYCLESWITCH": 0,
"RECYCLEHOLDTIME": 15,
"RECYCLETHRESHOLD": 0,
"RECYCLEAUTOCLEANSWITCH": 0,
"ENABLEDEDUP": False,
"ENABLECOMPRESSION": False,
}
root = self.helper._read_xml()
fstype = root.findtext('Filesystem/AllocType')
if fstype:
fstype = fstype.strip()
if fstype == 'Thin':
fileparam['ALLOCTYPE'] = 1
elif fstype == 'Thick':
fileparam['ALLOCTYPE'] = 0
else:
err_msg = (_(
'Config file is wrong. Filesystem type must be "Thin"'
' or "Thick". AllocType:%(fetchtype)s') %
{'fetchtype': fstype})
LOG.error(err_msg)
raise exception.InvalidShare(reason=err_msg)
return fileparam
def deny_access(self, share, access, share_server=None):
"""Deny access to share."""
share_proto = share['share_proto']
share_name = share['name']
share_type = self.helper._get_share_type(share_proto)
share_client_type = self.helper._get_share_client_type(share_proto)
access_type = access['access_type']
if share_proto == 'NFS' and access_type != 'ip':
LOG.warning(_LW('Only IP access type is allowed for NFS shares.'))
return
elif share_proto == 'CIFS' and access_type != 'user':
LOG.warning(_LW('Only USER access type is allowed for'
' CIFS shares.'))
return
access_to = access['access_to']
share = self.helper._get_share_by_name(share_name, share_type)
if not share:
LOG.warning(_LW('Can not get share. share_name: %s'), share_name)
return
access_id = self.helper._get_access_from_share(share['ID'], access_to,
share_client_type)
if not access_id:
LOG.warning(_LW('Can not get access id from share. '
'share_name: %s'), share_name)
return
self.helper._remove_access_from_share(access_id, share_client_type)
def allow_access(self, share, access, share_server=None):
"""Allow access to the share."""
share_proto = share['share_proto']
share_name = share['name']
share_type = self.helper._get_share_type(share_proto)
access_type = access['access_type']
if share_proto == 'NFS' and access_type != 'ip':
message = _('Only IP access type is allowed for NFS shares.')
raise exception.InvalidShareAccess(reason=message)
elif share_proto == 'CIFS' and access_type != 'user':
message = _('Only USER access type is allowed for CIFS shares.')
raise exception.InvalidShareAccess(reason=message)
access_to = access['access_to']
share = self.helper._get_share_by_name(share_name, share_type)
if not share:
err_msg = (_("Can not get share ID by share %s.")
% share_name)
LOG.error(err_msg)
raise exception.InvalidShareAccess(reason=err_msg)
share_id = share['ID']
self.helper._allow_access_rest(share_id, access_to, share_proto)
def allocate_container(self, share):
"""Creates filesystem associated to share by name."""
fileParam = self._init_filesys_para(share)
fsid = self.helper._create_filesystem(fileParam)
return fsid
def _get_location_path(self, share_name, share_proto):
root = self.helper._read_xml()
target_ip = root.findtext('Storage/LogicalPortIP').strip()
location = None
if share_proto == 'NFS':
location = '%s:/%s' % (target_ip,
share_name.replace("-", "_"))
elif share_proto == 'CIFS':
location = '\\\\%s\\%s' % (target_ip,
share_name.replace("-", "_"))
else:
raise exception.InvalidShareAccess(
reason=(_('Invalid NAS protocol supplied: %s.')
% share_proto))
return location
def _get_wait_interval(self):
"""Get wait interval from huawei conf file."""
root = self.helper._read_xml()
wait_interval = root.findtext('Filesystem/WaitInterval')
if wait_interval:
return int(wait_interval)
else:
LOG.info(_LI(
"Wait interval is not configured in huawei "
"conf file. Use default: %(default_wait_interval)d."),
{"default_wait_interval": constants.DEFAULT_WAIT_INTERVAL})
return constants.DEFAULT_WAIT_INTERVAL
def _get_timeout(self):
"""Get timeout from huawei conf file."""
root = self.helper._read_xml()
timeout = root.findtext('Filesystem/Timeout')
if timeout:
return int(timeout)
else:
LOG.info(_LI(
"Timeout is not configured in huawei conf file. "
"Use default: %(default_timeout)d."),
{"default_timeout": constants.DEFAULT_TIMEOUT})
return constants.DEFAULT_TIMEOUT
def check_conf_file(self):
"""Check the config file, make sure the essential items are set."""
root = self.helper._read_xml()
resturl = root.findtext('Storage/RestURL')
username = root.findtext('Storage/UserName')
pwd = root.findtext('Storage/UserPassword')
product = root.findtext('Storage/Product')
pool_node = root.findtext('Filesystem/StoragePool')
if product != "V3":
err_msg = (_(
'_check_conf_file: Config file invalid. '
'Product must be set to V3.'))
LOG.error(err_msg)
raise exception.InvalidInput(err_msg)
if not (resturl and username and pwd):
err_msg = (_(
'_check_conf_file: Config file invalid. RestURL,'
' UserName and UserPassword must be set.'))
LOG.error(err_msg)
raise exception.InvalidInput(err_msg)
if not pool_node:
err_msg = (_(
'_check_conf_file: Config file invalid. '
'StoragePool must be set.'))
LOG.error(err_msg)
raise exception.InvalidInput(err_msg)
def check_service(self):
running_status = self.helper._get_cifs_service_status()
if running_status != constants.STATUS_SERVICE_RUNNING:
self.helper._start_cifs_service_status()
service = self.helper._get_nfs_service_status()
if ((service['RUNNINGSTATUS'] != constants.STATUS_SERVICE_RUNNING) or
(service['SUPPORTV3'] == 'false') or
(service['SUPPORTV4'] == 'false')):
self.helper._start_nfs_service_status()

View File

@ -18,20 +18,20 @@ from xml.etree import ElementTree as ET
from oslo_log import log
from oslo_serialization import jsonutils
from oslo_utils import units
import six
from six.moves import http_cookiejar
from six.moves.urllib import request as urlreq # pylint: disable=E0611
from manila import exception
from manila.i18n import _, _LE, _LW
from manila.i18n import _
from manila.i18n import _LE
from manila.share.drivers.huawei import constants
from manila import utils
LOG = log.getLogger(__name__)
class RestHelper():
class RestHelper(object):
"""Helper class for Huawei OceanStor V3 storage system."""
def __init__(self, configuration):
@ -203,31 +203,6 @@ class RestHelper():
return result['data']['ID']
def _delete_share(self, share_name, share_proto):
"""Delete share."""
share_type = self._get_share_type(share_proto)
share = self._get_share_by_name(share_name, share_type)
if not share:
LOG.warn(_LW('The share was not found. share_name:%s'), share_name)
fsid = self._get_fsid_by_name(share_name)
if fsid:
self._delete_fs(fsid)
return
LOG.warn(_LW('The filesystem was not found.'))
return
share_id = share['ID']
share_fs_id = share['FSID']
if share_id:
self._delete_share_by_id(share_id, share_type)
if share_fs_id:
self._delete_fs(share_fs_id)
return share
def _delete_share_by_id(self, share_id, share_type):
"""Delete share by share id."""
url = self.url + "/" + share_type + "/" + share_id
@ -317,32 +292,16 @@ class RestHelper():
poolinfo = {}
pool_name = pool_name.strip()
if "data" in result:
for item in result['data']:
if pool_name == item['NAME']:
poolinfo['ID'] = item['ID']
poolinfo['CAPACITY'] = item['USERFREECAPACITY']
poolinfo['TOTALCAPACITY'] = item['USERTOTALCAPACITY']
break
for item in result.get('data', []):
if pool_name == item['NAME']:
poolinfo['name'] = pool_name
poolinfo['ID'] = item['ID']
poolinfo['CAPACITY'] = item['USERFREECAPACITY']
poolinfo['TOTALCAPACITY'] = item['USERTOTALCAPACITY']
break
return poolinfo
def _get_capacity(self):
"""Get free capacity and total capacity of the pools."""
poolinfo = self._find_pool_info()
pool_capacity = {
'total_capacity': 0.0,
'free_capacity': 0.0
}
if poolinfo:
total = int(poolinfo['TOTALCAPACITY']) / units.Mi / 2
free = int(poolinfo['CAPACITY']) / units.Mi / 2
pool_capacity['total_capacity'] = total
pool_capacity['free_capacity'] = free
return pool_capacity
def _read_xml(self):
"""Open xml file and parse the content."""
filename = self.configuration.manila_huawei_conf_file
@ -350,78 +309,14 @@ class RestHelper():
tree = ET.parse(filename)
root = tree.getroot()
except Exception as err:
LOG.error(_LE('Read Huawei config file(%(filename)s)'
' for Manila error: %(err)s') %
{'filename': filename,
'err': err})
raise err
message = (_('Read Huawei config file(%(filename)s)'
' for Manila error: %(err)s')
% {'filename': filename,
'err': err})
LOG.error(message)
raise exception.InvalidInput(reason=message)
return root
def _init_filesys_para(self, name, size):
"""Init basic filesystem parameters."""
poolinfo = self._find_pool_info()
fileparam = {
"NAME": name.replace("-", "_"),
"DESCRIPTION": "",
"ALLOCTYPE": 1,
"CAPACITY": size,
"PARENTID": poolinfo['ID'],
"INITIALALLOCCAPACITY": units.Ki * 20,
"PARENTTYPE": 216,
"SNAPSHOTRESERVEPER": 20,
"INITIALDISTRIBUTEPOLICY": 0,
"ISSHOWSNAPDIR": 'true',
"RECYCLESWITCH": 0,
"RECYCLEHOLDTIME": 15,
"RECYCLETHRESHOLD": 0,
"RECYCLEAUTOCLEANSWITCH": 0,
}
root = self._read_xml()
fstype = root.findtext('Filesystem/AllocType')
if fstype:
fstype = fstype.strip()
if fstype == 'Thin':
fileparam['ALLOCTYPE'] = 1
elif fstype == 'Thick':
fileparam['ALLOCTYPE'] = 0
else:
err_msg = (_(
'Config file is wrong. Filesystem type must be "Thin"'
' or "Thick". AllocType:%(fetchtype)s') %
{'fetchtype': fstype})
LOG.error(err_msg)
raise exception.InvalidShare(reason=err_msg)
return fileparam
def _deny_access(self, share_name, access, share_proto):
"""Deny access to share."""
share_type = self._get_share_type(share_proto)
share_client_type = self._get_share_client_type(share_proto)
access_type = access['access_type']
if share_proto == 'NFS' and access_type != 'ip':
LOG.warn(_LW('Only ip access type allowed.'))
return
if share_proto == 'CIFS' and access_type != 'user':
LOG.warn(_LW('Only user access type allowed.'))
return
access_to = access['access_to']
share = self._get_share_by_name(share_name, share_type)
if not share:
LOG.warn(_LW('Can not get share. share_name: %s'), share_name)
return
access_id = self._get_access_from_share(share['ID'], access_to,
share_client_type)
if not access_id:
LOG.warn(_LW('Can not get access id from share. share_name: %s'),
share_name)
return
self._remove_access_from_share(access_id, share_client_type)
def _remove_access_from_share(self, access_id, access_type):
url = self.url + "/" + access_type + "/" + access_id
result = self.call(url, None, "DELETE")
@ -467,34 +362,9 @@ class RestHelper():
result = self.call(url, None, "GET")
self._assert_rest_result(result, 'Get access id by share error!')
if "data" in result:
for item in result['data']:
if access_to == item['NAME']:
return item['ID']
def _allow_access(self, share_name, access, share_proto):
"""Allow access to the share."""
share_type = self._get_share_type(share_proto)
access_type = access['access_type']
if share_proto == 'NFS' and access_type != 'ip':
message = _('Only IP access type is allowed for NFS shares.')
raise exception.InvalidShareAccess(reason=message)
if share_proto == 'CIFS' and access_type != 'user':
message = _('Only USER access type is allowed for CIFS shares.')
raise exception.InvalidShareAccess(reason=message)
access_to = access['access_to']
share = self._get_share_by_name(share_name, share_type)
if not share:
err_msg = (_('Can not get share.'))
LOG.error(err_msg)
raise exception.InvalidShareAccess(reason=err_msg)
share_id = share['ID']
self._allow_access_rest(share_id, access_to, share_proto)
for item in result.get('data', []):
if access_to == item['NAME']:
return item['ID']
def _allow_access_rest(self, share_id, access_to, share_proto):
"""Allow access to the share."""
@ -532,7 +402,7 @@ class RestHelper():
elif share_proto == 'CIFS':
share_client_type = "CIFS_SHARE_AUTH_CLIENT"
else:
raise exception.InvalidShare(
raise exception.InvalidInput(
reason=(_('Invalid NAS protocol supplied: %s.')
% share_proto))
@ -622,12 +492,11 @@ class RestHelper():
share_path = self._get_share_path(share_name)
share = {}
if "data" in result:
for item in result['data']:
if share_path == item['SHAREPATH']:
share['ID'] = item['ID']
share['FSID'] = item['FSID']
break
for item in result.get('data', []):
if share_path == item['SHAREPATH']:
share['ID'] = item['ID']
share['FSID'] = item['FSID']
break
return share
@ -638,7 +507,7 @@ class RestHelper():
elif share_proto == 'CIFS':
share_type = "CIFSHARE"
else:
raise exception.InvalidShare(
raise exception.InvalidInput(
reason=(_('Invalid NAS protocol supplied: %s.')
% share_proto))
@ -650,10 +519,9 @@ class RestHelper():
self._assert_rest_result(result, 'Get filesystem by name error!')
sharename = share_name.replace("-", "_")
if "data" in result:
for item in result['data']:
if sharename == item['NAME']:
return item['ID']
for item in result.get('data', []):
if sharename == item['NAME']:
return item['ID']
def _get_fs_info_by_id(self, fsid):
url = self.url + "/filesystem/%s" % fsid
@ -668,64 +536,10 @@ class RestHelper():
fs['RUNNINGSTATUS'] = result['data']['RUNNINGSTATUS']
return fs
def allocate_container(self, share_name, size):
"""Creates filesystem associated to share by name."""
fileParam = self._init_filesys_para(share_name, size)
fsid = self._create_filesystem(fileParam)
return fsid
def _check_conf_file(self):
"""Check the config file, make sure the essential items are set."""
root = self._read_xml()
resturl = root.findtext('Storage/RestURL')
username = root.findtext('Storage/UserName')
pwd = root.findtext('Storage/UserPassword')
product = root.findtext('Storage/Product')
pool_node = root.findall('Filesystem/StoragePool')
if product != "V3":
err_msg = (_(
'_check_conf_file: Config file invalid. '
'Product must be set to V3.'))
LOG.error(err_msg)
raise exception.InvalidInput(err_msg)
if (not resturl) or (not username) or (not pwd):
err_msg = (_(
'_check_conf_file: Config file invalid. RestURL,'
' UserName and UserPassword must be set.'))
LOG.error(err_msg)
raise exception.InvalidInput(err_msg)
if not pool_node:
err_msg = (_(
'_check_conf_file: Config file invalid. '
'StoragePool must be set.'))
LOG.error(err_msg)
raise exception.InvalidInput(err_msg)
def _get_share_path(self, share_name):
share_path = "/" + share_name.replace("-", "_") + "/"
return share_path
def _get_location_path(self, share_name, share_proto):
root = self._read_xml()
target_ip = root.findtext('Storage/LogicalPortIP').strip()
location = None
if share_proto == 'NFS':
location = '%s:/%s' % (target_ip,
share_name.replace("-", "_"))
elif share_proto == 'CIFS':
location = '\\\\%s\\%s' % (target_ip,
share_name.replace("-", "_"))
else:
raise exception.InvalidShare(
reason=(_('Invalid NAS protocol supplied: %s.')
% share_proto))
return location
def _get_share_name_by_id(self, share_id):
share_name = "share_" + share_id
return share_name
@ -734,14 +548,3 @@ class RestHelper():
snapshot_id = (fs_id + "@" + "share_snapshot_"
+ snap_name.replace("-", "_"))
return snapshot_id
def _check_service(self):
running_status = self._get_cifs_service_status()
if running_status != constants.STATUS_SERVICE_RUNNING:
self._start_cifs_service_status()
service = self._get_nfs_service_status()
if ((service['RUNNINGSTATUS'] != constants.STATUS_SERVICE_RUNNING) or
(service['SUPPORTV3'] == 'false') or
(service['SUPPORTV4'] == 'false')):
self._start_nfs_service_status()

View File

@ -28,8 +28,9 @@ from oslo_serialization import jsonutils
from manila import context
from manila import exception
from manila.share import configuration as conf
from manila.share.drivers.huawei import huawei_helper
from manila.share.drivers.huawei import huawei_nas
from manila.share.drivers.huawei.v3 import connection
from manila.share.drivers.huawei.v3 import helper
from manila import test
@ -64,18 +65,10 @@ def filesystem(method, fs_status_flag):
return data
class FakeHuaweiNasDriver(huawei_nas.HuaweiNasDriver):
"""Fake Huawei Storage, Rewrite some methods of HuaweiNasDriver."""
class FakeHuaweiNasHelper(helper.RestHelper):
def __init__(self, *args, **kwargs):
huawei_nas.HuaweiNasDriver.__init__(self, *args, **kwargs)
self.helper = FakeHuaweiNasHelper(self.configuration)
class FakeHuaweiNasHelper(huawei_helper.RestHelper):
def __init__(self, *args, **kwargs):
huawei_helper.RestHelper.__init__(self, *args, **kwargs)
helper.RestHelper.__init__(self, *args, **kwargs)
self.test_normal = True
self.deviceid = None
self.delete_flag = False
@ -86,12 +79,15 @@ class FakeHuaweiNasHelper(huawei_helper.RestHelper):
self.fs_status_flag = True
self.create_share_flag = False
self.snapshot_flag = True
self.service_status_flag = True
self.share_exist = True
self.service_nfs_status_flag = True
self.create_share_data_flag = False
def _change_file_mode(self, filepath):
pass
def call(self, url, data=None, method=None):
url = url.replace('http://100.115.10.69:8082/deviceManager/rest', '')
url = url.replace('/210235G7J20000000000/', '')
data = None
@ -114,16 +110,25 @@ class FakeHuaweiNasHelper(huawei_helper.RestHelper):
if url == "NFSHARE" or url == "CIFSHARE":
if self.create_share_flag:
data = '{"error":{"code":31755596}}'
elif self.create_share_data_flag:
data = '{"error":{"code":0}}'
else:
data = """{"error":{"code":0},"data":{
"ID":"10"}}"""
if url == "NFSHARE?range=[100-200]":
data = """{"error":{"code":0},
"data":[{"ID":"1",
"FSID":"4",
"NAME":"test",
"SHAREPATH":"/share_fake_uuid/"}]}"""
if self.share_exist:
data = """{"error":{"code":0},
"data":[{"ID":"1",
"FSID":"4",
"NAME":"test",
"SHAREPATH":"/share_fake_uuid/"}]}"""
else:
data = """{"error":{"code":0},
"data":[{"ID":"1",
"FSID":"4",
"NAME":"test",
"SHAREPATH":"/share_fake_uuid_fail/"}]}"""
if url == "CIFSHARE?range=[100-200]":
data = """{"error":{"code":0},
@ -218,14 +223,24 @@ class FakeHuaweiNasHelper(huawei_helper.RestHelper):
"COUNT":"196"}}"""
if url == "CIFSSERVICE":
data = """{"error":{"code":0},"data":{
"RUNNINGSTATUS":"2"}}"""
if self.service_status_flag:
data = """{"error":{"code":0},"data":{
"RUNNINGSTATUS":"2"}}"""
else:
data = """{"error":{"code":0},"data":{
"RUNNINGSTATUS":"1"}}"""
if url == "NFSSERVICE":
data = """{"error":{"code":0},
"data":{"RUNNINGSTATUS":"2",
"SUPPORTV3":"true",
"SUPPORTV4":"true"}}"""
if self.service_nfs_status_flag:
data = """{"error":{"code":0},
"data":{"RUNNINGSTATUS":"2",
"SUPPORTV3":"true",
"SUPPORTV4":"true"}}"""
else:
data = """{"error":{"code":0},
"data":{"RUNNINGSTATUS":"1",
"SUPPORTV3":"true",
"SUPPORTV4":"true"}}"""
self.setupserver_flag = True
if url == "FILESYSTEM?range=[0-8191]":
@ -244,12 +259,28 @@ class FakeHuaweiNasHelper(huawei_helper.RestHelper):
return res_json
class FakeHuaweiNasDriver(huawei_nas.HuaweiNasDriver):
"""Fake HuaweiNasDriver."""
def __init__(self, *args, **kwargs):
huawei_nas.HuaweiNasDriver.__init__(self, *args, **kwargs)
self.plugin = FakeV3StorageConnection(self.configuration)
class FakeV3StorageConnection(connection.V3StorageConnection):
"""Fake V3StorageConnection."""
def __init__(self, configuration):
connection.V3StorageConnection.__init__(self, configuration)
self.configuration = configuration
self.helper = FakeHuaweiNasHelper(self.configuration)
class HuaweiShareDriverTestCase(test.TestCase):
"""Tests GenericShareDriver."""
def setUp(self):
super(HuaweiShareDriverTestCase, self).setUp()
self._context = context.get_admin_context()
self.tmp_dir = tempfile.mkdtemp()
self.fake_conf_file = self.tmp_dir + '/manila_huawei_conf.xml'
@ -264,12 +295,17 @@ class HuaweiShareDriverTestCase(test.TestCase):
self.configuration.safe_get = mock.Mock(side_effect=_safe_get)
self.configuration.network_config_group = 'fake_network_config_group'
self.configuration.share_backend_name = 'fake_share_backend_name'
self.configuration.driver_handles_share_servers = False
self.configuration.huawei_share_backend = 'V3'
self.configuration.manila_huawei_conf_file = self.fake_conf_file
self.configuration.driver_handles_share_servers = False
self._helper_fake = mock.Mock()
self.mock_object(huawei_nas.importutils, 'import_object',
mock.Mock(return_value=self._helper_fake))
self.mock_object(time, 'sleep', fake_sleep)
driver = FakeHuaweiNasDriver(configuration=self.configuration)
self.driver = driver
self.driver.helper.test_normal = True
self.driver = FakeHuaweiNasDriver(configuration=self.configuration)
self.driver.plugin.helper.test_normal = True
self.share_nfs = {
'id': 'fake_uuid',
@ -334,8 +370,6 @@ class HuaweiShareDriverTestCase(test.TestCase):
}
self.share_server = None
self.helper = mock.Mock()
self.driver._helpers = {'FAKE': self.helper}
self.driver._licenses = ['fake']
self.network_info = {
@ -349,38 +383,151 @@ class HuaweiShareDriverTestCase(test.TestCase):
],
}
def test_conf_product_fail(self):
self.recreate_fake_conf_file(product_flag=False)
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
self.assertRaises(exception.InvalidInput,
self.driver.plugin.check_conf_file)
def test_conf_pool_node_fail(self):
self.recreate_fake_conf_file(pool_node_flag=False)
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
self.assertRaises(exception.InvalidInput,
self.driver.plugin.check_conf_file)
def test_conf_username_fail(self):
self.recreate_fake_conf_file(username_flag=False)
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
self.assertRaises(exception.InvalidInput,
self.driver.plugin.check_conf_file)
def test_conf_timeout_fail(self):
self.recreate_fake_conf_file(timeout_flag=False)
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
timeout = self.driver.plugin._get_timeout()
self.assertEqual(60, timeout)
def test_conf_wait_interval_fail(self):
self.recreate_fake_conf_file(wait_interval_flag=False)
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
wait_interval = self.driver.plugin._get_wait_interval()
self.assertEqual(3, wait_interval)
def test_get_backend_driver_fail(self):
test_fake_conf_file = None
self.driver.plugin.configuration.manila_huawei_conf_file = (
test_fake_conf_file)
self.assertRaises(exception.InvalidInput,
self.driver.get_backend_driver)
def test_get_backend_driver_fail_driver_none(self):
self.recreate_fake_conf_file(product_flag=False)
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
self.assertRaises(exception.InvalidInput,
self.driver.get_backend_driver)
def test_create_share_nfs_alloctype_fail(self):
self.recreate_fake_conf_file(alloctype_value='alloctype_fail')
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
self.share_nfs,
self.share_server)
def test_create_share_nfs_storagepool_fail(self):
self.recreate_fake_conf_file(pool_node_flag=False)
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
self.share_nfs,
self.share_server)
def test_create_share_nfs_no_data_fail(self):
self.driver.plugin.helper.create_share_data_flag = True
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
self.share_nfs,
self.share_server)
def test_read_xml_fail(self):
test_fake_conf_file = None
self.driver.plugin.configuration.manila_huawei_conf_file = (
test_fake_conf_file)
self.assertRaises(exception.InvalidInput,
self.driver.plugin.helper._read_xml)
def test_connect_fail(self):
self.driver.plugin.configuration = None
self.assertRaises(exception.InvalidInput,
self.driver.plugin.connect)
def test_login_success(self):
deviceid = self.driver.helper.login()
deviceid = self.driver.plugin.helper.login()
self.assertEqual("210235G7J20000000000", deviceid)
def test_create_share_nfs_alloctype_thick_success(self):
self.recreate_fake_conf_file(alloctype_value='Thick')
self.driver.helper.configuration.manila_huawei_conf_file = (
def test_check_for_setup_success(self):
self.driver.plugin.helper.login()
self.driver.check_for_setup_error()
def test_check_for_setup_service_down(self):
self.driver.plugin.helper.service_status_flag = False
self.driver.plugin.helper.login()
self.driver.check_for_setup_error()
def test_check_for_setup_nfs_down(self):
self.driver.plugin.helper.service_nfs_status_flag = False
self.driver.plugin.helper.login()
self.driver.check_for_setup_error()
def test_check_for_setup_service_false(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.check_for_setup_error)
def test_create_share_nfs_alloctype_thin_success(self):
self.recreate_fake_conf_file(alloctype_value='Thin')
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
self.driver.helper.login()
self.driver.plugin.helper.login()
location = self.driver.create_share(self._context, self.share_nfs,
self.share_server)
self.assertEqual("100.115.10.68:/share_fake_uuid", location)
def test_create_share_nfs_success(self):
self.driver.helper.login()
self.driver.plugin.helper.login()
location = self.driver.create_share(self._context, self.share_nfs,
self.share_server)
self.assertEqual("100.115.10.68:/share_fake_uuid", location)
def test_create_share_cifs_success(self):
self.driver.helper.login()
self.driver.plugin.helper.login()
location = self.driver.create_share(self._context, self.share_cifs,
self.share_server)
self.assertEqual("\\\\100.115.10.68\\share_fake_uuid", location)
def test_login_fail(self):
self.driver.helper.test_normal = False
self.assertRaises(exception.InvalidShare, self.driver.helper.login)
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.plugin.helper.login)
def test_create_share_nfs_fs_fail(self):
self.driver.helper.login()
self.driver.helper.test_normal = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
@ -388,8 +535,8 @@ class HuaweiShareDriverTestCase(test.TestCase):
self.share_server)
def test_create_share_nfs_status_fail(self):
self.driver.helper.login()
self.driver.helper.fs_status_flag = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.fs_status_flag = False
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
@ -397,8 +544,8 @@ class HuaweiShareDriverTestCase(test.TestCase):
self.share_server)
def test_create_share_cifs_fs_fail(self):
self.driver.helper.login()
self.driver.helper.test_normal = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
@ -406,8 +553,8 @@ class HuaweiShareDriverTestCase(test.TestCase):
self.share_server)
def test_create_share_cifs_fail(self):
self.driver.helper.login()
self.driver.helper.create_share_flag = True
self.driver.plugin.helper.login()
self.driver.plugin.helper.create_share_flag = True
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
@ -415,8 +562,8 @@ class HuaweiShareDriverTestCase(test.TestCase):
self.share_server)
def test_create_share_nfs_fail(self):
self.driver.helper.login()
self.driver.helper.create_share_flag = True
self.driver.plugin.helper.login()
self.driver.plugin.helper.create_share_flag = True
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
@ -424,29 +571,48 @@ class HuaweiShareDriverTestCase(test.TestCase):
self.share_server)
def test_delete_share_nfs_success(self):
self.driver.helper.login()
self.driver.helper.delete_flag = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.delete_flag = False
self.driver.delete_share(self._context,
self.share_nfs, self.share_server)
self.assertTrue(self.driver.helper.delete_flag)
self.assertTrue(self.driver.plugin.helper.delete_flag)
def test_check_snapshot_id_exist_fail(self):
snapshot_id = "4"
self.driver.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.plugin.helper._check_snapshot_id_exist,
snapshot_id)
def test_delete_share_nfs_fail_not_exist(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.delete_flag = False
self.driver.plugin.helper.share_exist = False
self.driver.delete_share(self._context,
self.share_nfs, self.share_server)
self.assertTrue(self.driver.plugin.helper.delete_flag)
def test_delete_share_cifs_success(self):
self.driver.helper.login()
self.driver.helper.delete_flag = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.delete_flag = False
self.driver.delete_share(self._context, self.share_cifs,
self.share_server)
self.assertTrue(self.driver.helper.delete_flag)
self.assertTrue(self.driver.plugin.helper.delete_flag)
def test_get_share_stats_refresh_false(self):
self.driver._stats = {'fake_key': 'fake_value'}
def test_get_network_allocations_number(self):
number = self.driver.get_network_allocations_number()
self.assertEqual(0, number)
result = self.driver.get_share_stats(False)
def test_create_share_from_snapshot(self):
self.assertRaises(NotImplementedError,
self.driver.create_share_from_snapshot,
self._context, self.share_nfs, self.nfs_snapshot,
self.share_server)
self.assertEqual(self.driver._stats, result)
def test_get_share_stats_refresh_true(self):
self.driver.helper.login()
data = self.driver.get_share_stats(True)
def test_get_share_stats_refresh(self):
self.driver.plugin.helper.login()
self.driver._update_share_stats()
expected = {}
expected["share_backend_name"] = "fake_share_backend_name"
@ -454,131 +620,204 @@ class HuaweiShareDriverTestCase(test.TestCase):
expected["vendor_name"] = 'Huawei'
expected["driver_version"] = '1.0'
expected["storage_protocol"] = 'NFS_CIFS'
expected['total_capacity_gb'] = 2
expected['free_capacity_gb'] = 1
expected['reserved_percentage'] = 0
expected['total_capacity_gb'] = 'infinite'
expected['free_capacity_gb'] = 'infinite'
expected['QoS_support'] = False
self.assertDictMatch(expected, data)
expected["pools"] = []
pool = {}
pool.update(dict(
pool_name='OpenStack_Pool',
total_capacity_gb=2,
free_capacity_gb=1,
QoS_support=False,
reserved_percentage=0,
))
expected["pools"].append(pool)
self.assertEqual(expected, self.driver._stats)
def test_get_capacity_success(self):
self.driver.helper.login()
self.driver.plugin.helper.login()
capacity = {}
capacity = self.driver.helper._get_capacity()
self.assertEqual(2, capacity['total_capacity'])
self.assertEqual(1, capacity['free_capacity'])
capacity = self.driver.plugin._get_capacity()
self.assertEqual(2, capacity['TOTALCAPACITY'])
self.assertEqual(1, capacity['CAPACITY'])
def test_allow_access_ip_success(self):
self.driver.helper.login()
self.driver.plugin.helper.login()
self.allow_flag = False
self.driver.allow_access(self._context,
self.share_nfs,
self.access_ip,
self.share_server)
self.assertTrue(self.driver.helper.allow_flag)
self.assertTrue(self.driver.plugin.helper.allow_flag)
def test_allow_access_user_success(self):
self.driver.helper.login()
self.driver.plugin.helper.login()
self.allow_flag = False
self.driver.allow_access(self._context, self.share_cifs,
self.access_user, self.share_server)
self.assertTrue(self.driver.helper.allow_flag)
self.assertTrue(self.driver.plugin.helper.allow_flag)
def test_get_share_client_type_fail(self):
share_proto = 'fake_proto'
self.assertRaises(exception.InvalidInput,
self.driver.plugin.helper._get_share_client_type,
share_proto)
def test_get_share_type_fail(self):
share_proto = 'fake_proto'
self.assertRaises(exception.InvalidInput,
self.driver.plugin.helper._get_share_type,
share_proto)
def test_get_location_path_fail(self):
share_name = 'share-fake-uuid'
share_proto = 'fake_proto'
self.assertRaises(exception.InvalidShareAccess,
self.driver.plugin._get_location_path, share_name,
share_proto)
def test_allow_access_ip_proto_fail(self):
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidShareAccess,
self.driver.allow_access, self._context,
self.share_nfs, self.access_user, self.share_server)
def test_allow_access_user_proto_fail(self):
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidShareAccess,
self.driver.allow_access, self._context,
self.share_cifs, self.access_ip, self.share_server)
def test_deny_access_ip_proto_fail(self):
self.driver.plugin.helper.login()
result = self.driver.deny_access(self._context, self.share_nfs,
self.access_user, self.share_server)
self.assertEqual(None, result)
def test_deny_access_user_proto_fail(self):
self.driver.plugin.helper.login()
result = self.driver.deny_access(self._context, self.share_cifs,
self.access_ip, self.share_server)
self.assertEqual(None, result)
def test_allow_access_ip_share_not_exist(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.share_exist = False
self.assertRaises(exception.InvalidShareAccess,
self.driver.allow_access, self._context,
self.share_nfs, self.access_ip, self.share_server)
def test_deny_access_ip_share_not_exist(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.share_exist = False
self.driver.deny_access(self._context, self.share_nfs,
self.access_ip, self.share_server)
def test_allow_access_ip_fail(self):
self.driver.helper.login()
self.driver.helper.test_normal = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.allow_access, self._context,
self.share_nfs, self.access_ip, self.share_server)
def test_allow_access_user_fail(self):
self.driver.helper.login()
self.driver.helper.test_normal = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.allow_access, self._context,
self.share_cifs, self.access_user, self.share_server)
def test_deny_access_ip_success(self):
self.driver.helper.login()
self.driver.plugin.helper.login()
self.deny_flag = False
self.driver.deny_access(self._context, self.share_nfs,
self.access_ip, self.share_server)
self.assertTrue(self.driver.helper.deny_flag)
self.assertTrue(self.driver.plugin.helper.deny_flag)
def test_deny_access_user_success(self):
self.driver.helper.login()
self.driver.plugin.helper.login()
self.deny_flag = False
self.driver.deny_access(self._context, self.share_cifs,
self.access_user, self.share_server)
self.assertTrue(self.driver.helper.deny_flag)
self.assertTrue(self.driver.plugin.helper.deny_flag)
def test_deny_access_ip_fail(self):
self.driver.helper.login()
self.driver.helper.test_normal = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.deny_access, self._context,
self.share_nfs, self.access_ip, self.share_server)
def test_deny_access_user_fail(self):
self.driver.helper.login()
self.driver.helper.test_normal = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.deny_access, self._context,
self.share_cifs, self.access_user, self.share_server)
def test_create_nfs_snapshot_success(self):
self.driver.helper.login()
self.driver.helper.create_snapflag = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.create_snapflag = False
self.driver.create_snapshot(self._context, self.nfs_snapshot,
self.share_server)
self.assertTrue(self.driver.helper.create_snapflag)
self.assertTrue(self.driver.plugin.helper.create_snapflag)
def test_create_nfs_snapshot_share_not_exist(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.share_exist = False
self.assertRaises(exception.InvalidInput,
self.driver.create_snapshot, self._context,
self.nfs_snapshot, self.share_server)
def test_create_cifs_snapshot_success(self):
self.driver.helper.login()
self.driver.helper.create_snapflag = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.create_snapflag = False
self.driver.create_snapshot(self._context, self.cifs_snapshot,
self.share_server)
self.assertTrue(self.driver.helper.create_snapflag)
self.assertTrue(self.driver.plugin.helper.create_snapflag)
def test_delete_snapshot_success(self):
self.driver.helper.login()
self.driver.helper.delete_flag = False
self.driver.helper.snapshot_flag = True
self.driver.plugin.helper.login()
self.driver.plugin.helper.delete_flag = False
self.driver.plugin.helper.snapshot_flag = True
self.driver.delete_snapshot(self._context, self.nfs_snapshot,
self.share_server)
self.assertTrue(self.driver.helper.delete_flag)
self.assertTrue(self.driver.plugin.helper.delete_flag)
def test_delete_snapshot_not_exist_success(self):
self.driver.helper.login()
self.driver.helper.delete_flag = False
self.driver.helper.snapshot_flag = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.delete_flag = False
self.driver.plugin.helper.snapshot_flag = False
self.driver.delete_snapshot(self._context, self.nfs_snapshot,
self.share_server)
self.assertTrue(self.driver.helper.delete_flag)
self.assertTrue(self.driver.plugin.helper.delete_flag)
def test_create_nfs_snapshot_fail(self):
self.driver.helper.login()
self.driver.helper.test_normal = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.create_snapshot, self._context,
self.nfs_snapshot, self.share_server)
def test_create_cifs_snapshot_fail(self):
self.driver.helper.login()
self.driver.helper.test_normal = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.create_snapshot, self._context,
self.cifs_snapshot, self.share_server)
def test_delete_nfs_snapshot_fail(self):
self.driver.helper.login()
self.driver.helper.test_normal = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.delete_snapshot, self._context,
self.nfs_snapshot, self.share_server)
def test_delete_cifs_snapshot_fail(self):
self.driver.helper.login()
self.driver.helper.test_normal = False
self.driver.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.delete_snapshot, self._context,
self.cifs_snapshot, self.share_server)
@ -641,14 +880,14 @@ class HuaweiShareDriverTestCase(test.TestCase):
timeout = doc.createElement('Timeout')
if timeout_flag:
timeout_text = doc.createTextNode('1')
timeout_text = doc.createTextNode('0')
else:
timeout_text = doc.createTextNode('')
timeout.appendChild(timeout_text)
waitinterval = doc.createElement('WaitInterval')
if wait_interval_flag:
waitinterval_text = doc.createTextNode('1')
waitinterval_text = doc.createTextNode('0')
else:
waitinterval_text = doc.createTextNode('')
waitinterval.appendChild(waitinterval_text)