Merge "Huawei driver support storage pools"

This commit is contained in:
Jenkins 2015-07-22 01:36:31 +00:00 committed by Gerrit Code Review
commit 51a2bbefe1
5 changed files with 156 additions and 50 deletions

View File

@ -59,5 +59,9 @@ class HuaweiBase(object):
def get_network_allocations_number(self):
"""Get number of network interfaces to be created."""
@abc.abstractmethod
def get_pool(self, share):
"""Return pool name where the share resides on."""
def update_share_stats(self, stats_dict):
"""Retrieve stats info from share group."""

View File

@ -139,6 +139,11 @@ class HuaweiNasDriver(driver.ShareDriver):
self.plugin.deny_access(share, access, share_server)
def get_pool(self, share):
"""Return pool name where the share resides on."""
LOG.debug("Get pool.")
return self.plugin.get_pool(share)
def get_network_allocations_number(self):
"""Get number of network interfaces to be created."""
LOG.debug("Get network allocations number.")
@ -151,7 +156,9 @@ class HuaweiNasDriver(driver.ShareDriver):
data = dict(
share_backend_name=backend_name or 'HUAWEI_NAS_Driver',
vendor_name='Huawei',
storage_protocol='NFS_CIFS')
storage_protocol='NFS_CIFS',
total_capacity_gb=0.0,
free_capacity_gb=0.0)
self.plugin.update_share_stats(data)
super(HuaweiNasDriver, self)._update_share_stats(data)

View File

@ -24,6 +24,7 @@ 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
from manila.share import utils as share_utils
LOG = log.getLogger(__name__)
@ -47,13 +48,25 @@ class V3StorageConnection(driver.HuaweiBase):
share_name = share['name']
share_proto = share['share_proto']
pool_name = share_utils.extract_host(share['host'], level='pool')
if not pool_name:
msg = _("Pool is not available in the share host field.")
raise exception.InvalidHost(reason=msg)
result = self.helper._find_all_pool_info()
poolinfo = self.helper._find_pool_info(pool_name, result)
if not poolinfo:
msg = (_("Can not find pool info by pool name: %s") % pool_name)
raise exception.InvalidHost(reason=msg)
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_id = self.allocate_container(share, poolinfo)
fs = self.helper._get_fs_info_by_id(fs_id)
end_time = time.time() + timeout
@ -162,18 +175,30 @@ class V3StorageConnection(driver.HuaweiBase):
def update_share_stats(self, stats_dict):
"""Retrieve status info from share group."""
capacity = self._get_capacity()
root = self.helper._read_xml()
pool_name_list = root.findtext('Filesystem/StoragePool')
if not pool_name_list:
err_msg = _("The StoragePool is None.")
LOG.error(err_msg)
raise exception.InvalidInput(err_msg)
pool_name_list = pool_name_list.split(";")
result = self.helper._find_all_pool_info()
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)
for pool_name in pool_name_list:
pool_name = pool_name.strip().strip('\n')
capacity = self._get_capacity(pool_name, result)
if capacity:
pool = dict(
pool_name=pool_name,
total_capacity_gb=capacity['TOTALCAPACITY'],
free_capacity_gb=capacity['CAPACITY'],
allocated_capacity_gb=capacity['CONSUMEDCAPACITY'],
QoS_support=False,
reserved_percentage=0,
)
stats_dict["pools"].append(pool)
def delete_share(self, share, share_server=None):
"""Delete share."""
@ -206,23 +231,24 @@ class V3StorageConnection(driver.HuaweiBase):
"""Get number of network interfaces to be created."""
return constants.IP_ALLOCATIONS
def _get_capacity(self):
def _get_capacity(self, pool_name, result):
"""Get free capacity and total capacity of the pools."""
poolinfo = self.helper._find_pool_info()
poolinfo = self.helper._find_pool_info(pool_name, result)
if poolinfo:
total = int(poolinfo['TOTALCAPACITY']) / units.Mi / 2
free = int(poolinfo['CAPACITY']) / units.Mi / 2
consumed = int(poolinfo['CONSUMEDCAPACITY']) / units.Mi / 2
poolinfo['TOTALCAPACITY'] = total
poolinfo['CAPACITY'] = free
poolinfo['CONSUMEDCAPACITY'] = consumed
return poolinfo
def _init_filesys_para(self, share):
def _init_filesys_para(self, share, poolinfo):
"""Init basic filesystem parameters."""
name = share['name']
size = share['size'] * units.Mi * 2
poolinfo = self.helper._find_pool_info()
fileparam = {
"NAME": name.replace("-", "_"),
"DESCRIPTION": "",
@ -335,9 +361,24 @@ class V3StorageConnection(driver.HuaweiBase):
self.helper._allow_access_rest(share_id, access_to,
share_proto, access_level)
def allocate_container(self, share):
def get_pool(self, share):
pool_name = share_utils.extract_host(share['host'], level='pool')
if pool_name:
return pool_name
share_name = share['name']
share_url_type = self.helper._get_share_url_type(share['share_proto'])
share = self.helper._get_share_by_name(share_name, share_url_type)
pool_name = None
if share:
pool = self.helper._get_fs_info_by_id(share['FSID'])
pool_name = pool['POOLNAME']
return pool_name
def allocate_container(self, share, poolinfo):
"""Creates filesystem associated to share by name."""
fileParam = self._init_filesys_para(share)
fileParam = self._init_filesys_para(share, poolinfo)
fsid = self.helper._create_filesystem(fileParam)
return fsid

View File

@ -323,30 +323,33 @@ class RestHelper(object):
self._assert_rest_result(result, 'Start CIFS service error.')
def _find_pool_info(self):
root = self._read_xml()
pool_name = root.findtext('Filesystem/StoragePool')
if not pool_name:
err_msg = (_("Invalid resource pool: %s.") % pool_name)
LOG.error(err_msg)
raise exception.InvalidInput(err_msg)
url = self.url + "/storagepool"
result = self.call(url, None)
self._assert_rest_result(result, 'Query resource pool error.')
def _find_pool_info(self, pool_name, result):
if pool_name is None:
return
poolinfo = {}
pool_name = pool_name.strip()
for item in result.get('data', []):
if pool_name == item['NAME']:
if pool_name == item['NAME'] and '2' == item['USAGETYPE']:
poolinfo['name'] = pool_name
poolinfo['ID'] = item['ID']
poolinfo['CAPACITY'] = item['USERFREECAPACITY']
poolinfo['TOTALCAPACITY'] = item['USERTOTALCAPACITY']
poolinfo['CONSUMEDCAPACITY'] = item['USERCONSUMEDCAPACITY']
break
return poolinfo
def _find_all_pool_info(self):
url = self.url + "/storagepool"
result = self.call(url, None)
msg = "Query resource pool error."
self._assert_rest_result(result, msg)
self._assert_data_in_result(result, msg)
return result
def _read_xml(self):
"""Open xml file and parse the content."""
filename = self.configuration.manila_huawei_conf_file
@ -580,6 +583,7 @@ class RestHelper(object):
fs = {}
fs['HEALTHSTATUS'] = result['data']['HEALTHSTATUS']
fs['RUNNINGSTATUS'] = result['data']['RUNNINGSTATUS']
fs['POOLNAME'] = result['data']['PARENTNAME']
return fs
def _get_share_path(self, share_name):

View File

@ -64,11 +64,13 @@ def filesystem(method, data, fs_status_flag):
if fs_status_flag:
data = """{"error":{"code":0},
"data":{"HEALTHSTATUS":"1",
"RUNNINGSTATUS":"27"}}"""
"RUNNINGSTATUS":"27",
"PARENTNAME":"OpenStack_Pool"}}"""
else:
data = """{"error":{"code":0},
"data":{"HEALTHSTATUS":"0",
"RUNNINGSTATUS":"27"}}"""
"RUNNINGSTATUS":"27",
"PARENTNAME":"OpenStack_Pool"}}"""
else:
data = '{"error":{"code":31755596}}'
return (data, extend_share_flag)
@ -171,7 +173,9 @@ class FakeHuaweiNasHelper(helper.RestHelper):
"data":[{"USERFREECAPACITY":"2097152",
"ID":"1",
"NAME":"OpenStack_Pool",
"USERTOTALCAPACITY":"4194304"}]}"""
"USERTOTALCAPACITY":"4194304",
"USAGETYPE":"2",
"USERCONSUMEDCAPACITY":"2097152"}]}"""
if url == "filesystem":
data = """{"error":{"code":0},"data":{
@ -196,7 +200,7 @@ class FakeHuaweiNasHelper(helper.RestHelper):
else:
data = """{"error":{"code":0},
"data":[{"ID":"1",
"FSID":"4",
"FSID":"",
"NAME":"test",
"SHAREPATH":"/share_fake_uuid_fail/"}]}"""
@ -393,6 +397,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
'share_proto': 'NFS',
'share_network_id': 'fake_net_id',
'share_server_id': 'fake-share-srv-id',
'host': 'fake_host@fake_backend#OpenStack_Pool',
}
self.share_proto_fail = {
@ -404,6 +409,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
'share_proto': 'proto_fail',
'share_network_id': 'fake_net_id',
'share_server_id': 'fake-share-srv-id',
'host': 'fake_host@fake_backend#OpenStack_Pool',
}
self.share_cifs = {
@ -415,6 +421,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
'share_proto': 'CIFS',
'share_network_id': 'fake_net_id',
'share_server_id': 'fake-share-srv-id',
'host': 'fake_host@fake_backend#OpenStack_Pool',
}
self.nfs_snapshot = {
@ -473,6 +480,30 @@ class HuaweiShareDriverTestCase(test.TestCase):
],
}
self.share_nfs_host_not_exist = {
'id': 'fake_uuid',
'project_id': 'fake_tenant_id',
'display_name': 'fake',
'name': 'share-fake-uuid',
'size': 1,
'share_proto': 'NFS',
'share_network_id': 'fake_net_id',
'share_server_id': 'fake-share-srv-id',
'host': 'fake_host@fake_backend#',
}
self.share_nfs_storagepool_fail = {
'id': 'fake_uuid',
'project_id': 'fake_tenant_id',
'display_name': 'fake',
'name': 'share-fake-uuid',
'size': 1,
'share_proto': 'NFS',
'share_network_id': 'fake_net_id',
'share_server_id': 'fake-share-srv-id',
'host': 'fake_host@fake_backend#OpenStack_Pool2',
}
def test_conf_product_fail(self):
self.recreate_fake_conf_file(product_flag=False)
self.driver.plugin.configuration.manila_huawei_conf_file = (
@ -533,15 +564,20 @@ class HuaweiShareDriverTestCase(test.TestCase):
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)
def test_create_share_storagepool_not_exist(self):
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidShare,
self.assertRaises(exception.InvalidHost,
self.driver.create_share,
self._context,
self.share_nfs,
self.share_nfs_host_not_exist,
self.share_server)
def test_create_share_nfs_storagepool_fail(self):
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidHost,
self.driver.create_share,
self._context,
self.share_nfs_storagepool_fail,
self.share_server)
def test_create_share_nfs_no_data_fail(self):
@ -725,6 +761,14 @@ class HuaweiShareDriverTestCase(test.TestCase):
self._context, self.share_nfs, self.nfs_snapshot,
self.share_server)
def test_get_share_stats_refresh_pool_not_exist(self):
self.driver.plugin.helper.login()
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._update_share_stats)
def test_get_share_stats_refresh(self):
self.driver.plugin.helper.login()
self.driver._update_share_stats()
@ -736,8 +780,8 @@ class HuaweiShareDriverTestCase(test.TestCase):
expected["driver_version"] = '1.0'
expected["storage_protocol"] = 'NFS_CIFS'
expected['reserved_percentage'] = 0
expected['total_capacity_gb'] = 'infinite'
expected['free_capacity_gb'] = 'infinite'
expected['total_capacity_gb'] = 0.0
expected['free_capacity_gb'] = 0.0
expected['QoS_support'] = False
expected["pools"] = []
pool = {}
@ -745,19 +789,14 @@ class HuaweiShareDriverTestCase(test.TestCase):
pool_name='OpenStack_Pool',
total_capacity_gb=2,
free_capacity_gb=1,
allocated_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.plugin.helper.login()
capacity = {}
capacity = self.driver.plugin._get_capacity()
self.assertEqual(2, capacity['TOTALCAPACITY'])
self.assertEqual(1, capacity['CAPACITY'])
def test_allow_access_proto_fail(self):
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidInput,
@ -995,6 +1034,17 @@ class HuaweiShareDriverTestCase(test.TestCase):
self.driver.delete_snapshot, self._context,
self.cifs_snapshot, self.share_server)
def test_get_pool_success(self):
self.driver.plugin.helper.login()
pool_name = self.driver.get_pool(self.share_nfs_host_not_exist)
self.assertEqual('OpenStack_Pool', pool_name)
def test_get_pool_fail(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.share_exist = False
pool_name = self.driver.get_pool(self.share_nfs_host_not_exist)
self.assertEqual(None, pool_name)
def test_multi_resturls_success(self):
self.recreate_fake_conf_file(multi_url=True)
self.driver.plugin.configuration.manila_huawei_conf_file = (
@ -1074,7 +1124,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
storagepool = doc.createElement('StoragePool')
if pool_node_flag:
pool_text = doc.createTextNode('OpenStack_Pool')
pool_text = doc.createTextNode('OpenStack_Pool;OpenStack_Pool2; ;')
else:
pool_text = doc.createTextNode('')
storagepool.appendChild(pool_text)