Shared filesystem management project for OpenStack.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

4685 lines
191 KiB

# Copyright (c) 2014 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.
"""Unit tests for the Huawei nas driver module."""
import os
import requests
import shutil
import six
import tempfile
import time
import xml.dom.minidom
import ddt
import mock
from oslo_serialization import jsonutils
from xml.etree import ElementTree as ET
from manila.common import constants as common_constants
from manila import context
from manila.data import utils as data_utils
from manila import db
from manila import exception
from manila import rpc
from manila.share import configuration as conf
from manila.share.drivers.huawei import constants
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.share.drivers.huawei.v3 import replication
from manila.share.drivers.huawei.v3 import rpcapi
from manila.share.drivers.huawei.v3 import smartx
from manila import test
from manila import utils
def fake_sleep(time):
pass
def data_session(url):
if url == "/xx/sessions":
data = """{"error":{"code":0},
"data":{"username":"admin",
"iBaseToken":"2001031430",
"deviceid":"210235G7J20000000000"}}"""
if url == "sessions":
data = '{"error":{"code":0},"data":{"ID":11}}'
return data
def filesystem(method, data, fs_status_flag):
extend_share_flag = False
shrink_share_flag = False
if method == "PUT":
if data == """{"CAPACITY": 10485760}""":
data = """{"error":{"code":0},
"data":{"ID":"4",
"CAPACITY":"8388608"}}"""
extend_share_flag = True
elif data == """{"CAPACITY": 2097152}""":
data = """{"error":{"code":0},
"data":{"ID":"4",
"CAPACITY":"2097152"}}"""
shrink_share_flag = True
elif data == """{"NAME": "share_fake_manage_uuid"}""":
data = """{"error":{"code":0},
"data":{"ID":"4",
"CAPACITY":"8388608"}}"""
elif data == jsonutils.dumps({"ENABLEDEDUP": True,
"ENABLECOMPRESSION": True}):
data = """{"error":{"code":0},
"data":{"ID":"4",
"CAPACITY":"8388608"}}"""
elif data == jsonutils.dumps({"ENABLEDEDUP": False,
"ENABLECOMPRESSION": False}):
data = """{"error":{"code":0},
"data":{"ID":"4",
"CAPACITY":"8388608"}}"""
elif data == """{"IOPRIORITY": "3"}""":
data = """{"error":{"code":0}}"""
elif method == "DELETE":
data = """{"error":{"code":0}}"""
elif method == "GET":
if fs_status_flag:
data = """{"error":{"code":0},
"data":{"HEALTHSTATUS":"1",
"RUNNINGSTATUS":"27",
"ALLOCTYPE":"1",
"CAPACITY":"8388608",
"PARENTNAME":"OpenStack_Pool",
"ENABLECOMPRESSION":"false",
"ENABLEDEDUP":"false",
"CACHEPARTITIONID":"",
"SMARTCACHEPARTITIONID":"",
"IOCLASSID":"11"}}"""
else:
data = """{"error":{"code":0},
"data":{"HEALTHSTATUS":"0",
"RUNNINGSTATUS":"27",
"ALLOCTYPE":"0",
"CAPACITY":"8388608",
"PARENTNAME":"OpenStack_Pool",
"ENABLECOMPRESSION":"false",
"ENABLEDEDUP":"false",
"CACHEPARTITIONID":"",
"SMARTCACHEPARTITIONID":"",
"IOCLASSID":"11"}}"""
else:
data = '{"error":{"code":31755596}}'
return (data, extend_share_flag, shrink_share_flag)
def filesystem_thick(method, data, fs_status_flag):
extend_share_flag = False
shrink_share_flag = False
if method == "PUT":
if data == """{"CAPACITY": 10485760}""":
data = """{"error":{"code":0},
"data":{"ID":"5",
"CAPACITY":"8388608"}}"""
extend_share_flag = True
elif data == """{"CAPACITY": 2097152}""":
data = """{"error":{"code":0},
"data":{"ID":"5",
"CAPACITY":"2097152"}}"""
shrink_share_flag = True
elif data == """{"NAME": "share_fake_uuid_thickfs"}""":
data = """{"error":{"code":0},
"data":{"ID":"5",
"CAPACITY":"8388608"}}"""
elif data == jsonutils.dumps({"ENABLEDEDUP": False,
"ENABLECOMPRESSION": False}):
data = """{"error":{"code":0},
"data":{"ID":"5",
"CAPACITY":"8388608"}}"""
elif method == "DELETE":
data = """{"error":{"code":0}}"""
elif method == "GET":
if fs_status_flag:
data = """{"error":{"code":0},
"data":{"HEALTHSTATUS":"1",
"RUNNINGSTATUS":"27",
"ALLOCTYPE":"0",
"CAPACITY":"8388608",
"PARENTNAME":"OpenStack_Pool_Thick",
"ENABLECOMPRESSION":"false",
"ENABLEDEDUP":"false",
"CACHEPARTITIONID":"",
"SMARTCACHEPARTITIONID":"",
"IOCLASSID":"11"}}"""
else:
data = """{"error":{"code":0},
"data":{"HEALTHSTATUS":"0",
"RUNNINGSTATUS":"27",
"ALLOCTYPE":"0",
"CAPACITY":"8388608",
"PARENTNAME":"OpenStack_Pool_Thick",
"ENABLECOMPRESSION":"false",
"ENABLEDEDUP":"false",
"CACHEPARTITIONID":"",
"SMARTCACHEPARTITIONID":"",
"IOCLASSID":"11"}}"""
else:
data = '{"error":{"code":31755596}}'
return (data, extend_share_flag, shrink_share_flag)
def filesystem_inpartition(method, data, fs_status_flag):
extend_share_flag = False
shrink_share_flag = False
if method == "PUT":
if data == """{"CAPACITY": 10485760}""":
data = """{"error":{"code":0},
"data":{"ID":"6",
"CAPACITY":"8388608"}}"""
extend_share_flag = True
elif data == """{"CAPACITY": 2097152}""":
data = """{"error":{"code":0},
"data":{"ID":"6",
"CAPACITY":"2097152"}}"""
shrink_share_flag = True
elif data == """{"NAME": "share_fake_manage_uuid"}""":
data = """{"error":{"code":0},
"data":{"ID":"6",
"CAPACITY":"8388608"}}"""
elif data == """{"NAME": "share_fake_uuid_inpartition"}""":
data = """{"error":{"code":0},
"data":{"ID":"6",
"CAPACITY":"8388608"}}"""
elif data == jsonutils.dumps({"ENABLEDEDUP": True,
"ENABLECOMPRESSION": True}):
data = """{"error":{"code":0},
"data":{"ID":"6",
"CAPACITY":"8388608"}}"""
elif data == jsonutils.dumps({"ENABLEDEDUP": False,
"ENABLECOMPRESSION": False}):
data = """{"error":{"code":0},
"data":{"ID":"6",
"CAPACITY":"8388608"}}"""
elif method == "DELETE":
data = """{"error":{"code":0}}"""
elif method == "GET":
if fs_status_flag:
data = """{"error":{"code":0},
"data":{"HEALTHSTATUS":"1",
"RUNNINGSTATUS":"27",
"ALLOCTYPE":"1",
"CAPACITY":"8388608",
"PARENTNAME":"OpenStack_Pool",
"ENABLECOMPRESSION":"false",
"ENABLEDEDUP":"false",
"CACHEPARTITIONID":"1",
"SMARTCACHEPARTITIONID":"1",
"IOCLASSID":"11"}}"""
else:
data = """{"error":{"code":0},
"data":{"HEALTHSTATUS":"0",
"RUNNINGSTATUS":"27",
"ALLOCTYPE":"0",
"CAPACITY":"8388608",
"PARENTNAME":"OpenStack_Pool",
"ENABLECOMPRESSION":"false",
"ENABLEDEDUP":"false",
"CACHEPARTITIONID":"1",
"SMARTCACHEPARTITIONID":"1",
"IOCLASSID":"11"}}"""
else:
data = '{"error":{"code":31755596}}'
return (data, extend_share_flag, shrink_share_flag)
def allow_access(type, method, data):
allow_ro_flag = False
allow_rw_flag = False
request_data = jsonutils.loads(data)
success_data = """{"error":{"code":0}}"""
fail_data = """{"error":{"code":1077939723}}"""
ret = None
if type == "NFS":
if request_data['ACCESSVAL'] == '0':
allow_ro_flag = True
ret = success_data
elif request_data['ACCESSVAL'] == '1':
allow_rw_flag = True
ret = success_data
elif type == "CIFS":
if request_data['PERMISSION'] == '0':
allow_ro_flag = True
ret = success_data
elif request_data['PERMISSION'] == '1':
allow_rw_flag = True
ret = success_data
# Group name should start with '@'.
if ('group' in request_data['NAME']
and not request_data['NAME'].startswith('@')):
ret = fail_data
if ret is None:
ret = fail_data
return (ret, allow_ro_flag, allow_rw_flag)
def dec_driver_handles_share_servers(func):
def wrapper(*args, **kw):
self = args[0]
self.configuration.driver_handles_share_servers = True
self.recreate_fake_conf_file(logical_port='CTE0.A.H0')
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
self.driver.plugin.helper.login()
return func(*args, **kw)
return wrapper
def QoS_response(method):
if method == "GET":
data = """{"error":{"code":0},
"data":{"NAME": "OpenStack_Fake_QoS", "MAXIOPS": "100",
"FSLIST": "4", "LUNLIST": "", "RUNNINGSTATUS": "2"}}"""
elif method == "PUT":
data = """{"error":{"code":0}}"""
else:
data = """{"error":{"code":0},
"data":{"ID": "11"}}"""
return data
class FakeHuaweiNasHelper(helper.RestHelper):
def __init__(self, *args, **kwargs):
helper.RestHelper.__init__(self, *args, **kwargs)
self.test_normal = True
self.deviceid = None
self.delete_flag = False
self.allow_flag = False
self.deny_flag = False
self.create_snapflag = False
self.setupserver_flag = False
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
self.allow_ro_flag = False
self.allow_rw_flag = False
self.extend_share_flag = False
self.shrink_share_flag = False
self.add_fs_to_partition_flag = False
self.add_fs_to_cache_flag = False
self.test_multi_url_flag = 0
self.cache_exist = True
self.partition_exist = True
self.alloc_type = None
self.custom_results = {}
def _change_file_mode(self, filepath):
pass
def do_call(self, url, data, method, calltimeout=4):
url = url.replace('http://100.115.10.69:8082/deviceManager/rest', '')
url = url.replace('/210235G7J20000000000/', '')
if self.custom_results and self.custom_results.get(url):
result = self.custom_results[url]
if isinstance(result, six.string_types):
return jsonutils.loads(result)
if isinstance(result, dict) and result.get(method):
return jsonutils.loads(result[method])
if self.test_normal:
if self.test_multi_url_flag == 1:
data = '{"error":{"code":-403}}'
res_json = jsonutils.loads(data)
return res_json
elif self.test_multi_url_flag == 2:
if ('http://100.115.10.70:8082/deviceManager/rest/xx/'
'sessions' == url):
self.url = url
data = data_session("/xx/sessions")
res_json = jsonutils.loads(data)
return res_json
elif (('/xx/sessions' == url) or (self.url is not None
and 'http://100.115.10.69:8082/deviceManager/rest'
in self.url)):
data = '{"error":{"code":-403}}'
res_json = jsonutils.loads(data)
return res_json
if url == "/xx/sessions" or url == "/sessions":
data = data_session(url)
if url == "/storagepool":
data = """{"error":{"code":0},
"data":[{"USERFREECAPACITY":"2097152",
"ID":"1",
"NAME":"OpenStack_Pool",
"USERTOTALCAPACITY":"4194304",
"USAGETYPE":"2",
"USERCONSUMEDCAPACITY":"2097152",
"TIER0CAPACITY":"100",
"TIER1CAPACITY":"0",
"TIER2CAPACITY":"0"},
{"USERFREECAPACITY":"2097152",
"ID":"2",
"NAME":"OpenStack_Pool_Thick",
"USERTOTALCAPACITY":"4194304",
"USAGETYPE":"2",
"USERCONSUMEDCAPACITY":"2097152",
"TIER0CAPACITY":"100",
"TIER1CAPACITY":"0",
"TIER2CAPACITY":"0"}]}"""
if url == "/filesystem":
request_data = jsonutils.loads(data)
self.alloc_type = request_data.get('ALLOCTYPE')
data = """{"error":{"code":0},"data":{
"ID":"4"}}"""
if url == "/system/":
data = """{"error":{"code":0},
"data":{"PRODUCTVERSION": "V300R003C10",
"wwn": "fake_wwn"}}"""
if url == "/remote_device":
data = """{"error":{"code":0},
"data":[{"ID": "0",
"NAME": "fake_name",
"WWN": "fake_wwn"}]}"""
if url == "/ioclass" or url == "/ioclass/11":
data = QoS_response(method)
if url == "/ioclass/active/11":
data = """{"error":{"code":0},
"data":[{"ID": "11", "MAXIOPS": "100",
"FSLIST": ""}]}"""
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]":
if self.share_exist:
data = """{"error":{"code":0},
"data":[{"ID":"1",
"FSID":"4",
"NAME":"test",
"SHAREPATH":"/share_fake_uuid/"},
{"ID":"2",
"FSID":"5",
"NAME":"test",
"SHAREPATH":"/share_fake_uuid_thickfs/"},
{"ID":"3",
"FSID":"6",
"NAME":"test",
"SHAREPATH":"/share_fake_uuid_inpartition/"}]}"""
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},
"data":[{"ID":"2",
"FSID":"4",
"NAME":"test",
"SHAREPATH":"/share_fake_uuid/"}]}"""
if url == "/NFSHARE?range=[0-100]":
data = """{"error":{"code":0},
"data":[{"ID":"1",
"FSID":"4",
"NAME":"test_fail",
"SHAREPATH":"/share_fake_uuid_fail/"}]}"""
if url == "/CIFSHARE?range=[0-100]":
data = """{"error":{"code":0},
"data":[{"ID":"2",
"FSID":"4",
"NAME":"test_fail",
"SHAREPATH":"/share_fake_uuid_fail/"}]}"""
if url == "/NFSHARE/1" or url == "/CIFSHARE/2":
data = """{"error":{"code":0}}"""
self.delete_flag = True
if url == "/FSSNAPSHOT":
data = """{"error":{"code":0},"data":{
"ID":"3"}}"""
self.create_snapflag = True
if url == "/FSSNAPSHOT/4@share_snapshot_fake_snapshot_uuid":
if self.snapshot_flag:
data = """{"error":{"code":0},
"data":{"ID":"4@share_snapshot_fake_snapshot_uuid"}}"""
else:
data = '{"error":{"code":1073754118}}'
self.delete_flag = True
if url == "/FSSNAPSHOT/4@fake_storage_snapshot_name":
if self.snapshot_flag:
data = """{"error":{"code":0},
"data":{"ID":"4@share_snapshot_fake_snapshot_uuid",
"NAME":"share_snapshot_fake_snapshot_uuid",
"HEALTHSTATUS":"1"}}"""
else:
data = '{"error":{"code":1073754118}}'
if url == "/FSSNAPSHOT/3":
data = """{"error":{"code":0}}"""
self.delete_flag = True
if url == "/NFS_SHARE_AUTH_CLIENT":
data, self.allow_ro_flag, self.allow_rw_flag = (
allow_access('NFS', method, data))
self.allow_flag = True
if url == "/CIFS_SHARE_AUTH_CLIENT":
data, self.allow_ro_flag, self.allow_rw_flag = (
allow_access('CIFS', method, data))
self.allow_flag = True
if url == ("/FSSNAPSHOT?TYPE=48&PARENTID=4"
"&&sortby=TIMESTAMP,d&range=[0-2000]"):
data = """{"error":{"code":0},
"data":[{"ID":"3",
"NAME":"share_snapshot_fake_snapshot_uuid"}]}"""
self.delete_flag = True
if url == ("/NFS_SHARE_AUTH_CLIENT?"
"filter=PARENTID::1&range=[0-100]"):
data = """{"error":{"code":0},
"data":[{"ID":"0",
"NAME":"100.112.0.1_fail"}]}"""
if url == ("/CIFS_SHARE_AUTH_CLIENT?"
"filter=PARENTID::2&range=[0-100]"):
data = """{"error":{"code":0},
"data":[{"ID":"0",
"NAME":"user_name_fail"}]}"""
if url == ("/NFS_SHARE_AUTH_CLIENT?"
"filter=PARENTID::1&range=[100-200]"):
data = """{"error":{"code":0},
"data":[{"ID":"5",
"NAME":"100.112.0.2"}]}"""
if url == ("/CIFS_SHARE_AUTH_CLIENT?"
"filter=PARENTID::2&range=[100-200]"):
data = """{"error":{"code":0},
"data":[{"ID":"6",
"NAME":"user_exist"}]}"""
if url in ("/NFS_SHARE_AUTH_CLIENT/0",
"/NFS_SHARE_AUTH_CLIENT/5",
"/CIFS_SHARE_AUTH_CLIENT/0",
"/CIFS_SHARE_AUTH_CLIENT/6"):
if method == "DELETE":
data = """{"error":{"code":0}}"""
self.deny_flag = True
elif method == "GET":
if 'CIFS' in url:
data = """{"error":{"code":0},
"data":{"'PERMISSION'":"0"}}"""
else:
data = """{"error":{"code":0},
"data":{"ACCESSVAL":"0"}}"""
else:
data = """{"error":{"code":0}}"""
self.allow_rw_flagg = True
if url == "/NFSHARE/count" or url == "/CIFSHARE/count":
data = """{"error":{"code":0},"data":{
"COUNT":"196"}}"""
if (url == "/NFS_SHARE_AUTH_CLIENT/count?filter=PARENTID::1"
or url == ("/CIFS_SHARE_AUTH_CLIENT/count?filter="
"PARENTID::2")):
data = """{"error":{"code":0},"data":{
"COUNT":"196"}}"""
if url == "/CIFSSERVICE":
if self.service_status_flag:
data = """{"error":{"code":0},"data":{
"RUNNINGSTATUS":"2"}}"""
else:
data = """{"error":{"code":0},"data":{
"RUNNINGSTATUS":"1"}}"""
if url == "/NFSSERVICE":
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 "/FILESYSTEM?filter=NAME::" in url:
data = """{"error":{"code":0},
"data":[{"ID":"4",
"NAME":"share_fake_uuid"},
{"ID":"8",
"NAME":"share_fake_new_uuid"}]}"""
if url == "/filesystem/4":
data, self.extend_share_flag, self.shrink_share_flag = (
filesystem(method, data, self.fs_status_flag))
self.delete_flag = True
if url == "/filesystem/5":
data, self.extend_share_flag, self.shrink_share_flag = (
filesystem_thick(method, data, self.fs_status_flag))
self.delete_flag = True
if url == "/filesystem/6":
data, self.extend_share_flag, self.shrink_share_flag = (
filesystem_inpartition(method, data, self.fs_status_flag))
self.delete_flag = True
if url == "/cachepartition":
if self.partition_exist:
data = """{"error":{"code":0},
"data":[{"ID":"7",
"NAME":"test_partition_name"}]}"""
else:
data = """{"error":{"code":0},
"data":[{"ID":"7",
"NAME":"test_partition_name_fail"}]}"""
if url == "/cachepartition/1":
if self.partition_exist:
data = """{"error":{"code":0},
"data":{"ID":"7",
"NAME":"test_partition_name"}}"""
else:
data = """{"error":{"code":0},
"data":{"ID":"7",
"NAME":"test_partition_name_fail"}}"""
if url == "/SMARTCACHEPARTITION":
if self.cache_exist:
data = """{"error":{"code":0},
"data":[{"ID":"8",
"NAME":"test_cache_name"}]}"""
else:
data = """{"error":{"code":0},
"data":[{"ID":"8",
"NAME":"test_cache_name_fail"}]}"""
if url == "/SMARTCACHEPARTITION/1":
if self.cache_exist:
data = """{"error":{"code":0},
"data":{"ID":"8",
"NAME":"test_cache_name"}}"""
else:
data = """{"error":{"code":0},
"data":{"ID":"8",
"NAME":"test_cache_name_fail"}}"""
if url == "/filesystem/associate/cachepartition":
data = """{"error":{"code":0}}"""
self.add_fs_to_partition_flag = True
if url == "/SMARTCACHEPARTITION/CREATE_ASSOCIATE":
data = """{"error":{"code":0}}"""
self.add_fs_to_cache_flag = True
if url == "/SMARTCACHEPARTITION/REMOVE_ASSOCIATE":
data = """{"error":{"code":0}}"""
if url == "/smartPartition/removeFs":
data = """{"error":{"code":0}}"""
if url == "/ETH_PORT":
data = """{"error":{"code":0},
"data":[{"ID": "4",
"LOCATION":"CTE0.A.H0",
"IPV4ADDR":"",
"BONDNAME":"",
"BONDID":"",
"RUNNINGSTATUS":"10"},
{"ID": "6",
"LOCATION":"CTE0.A.H1",
"IPV4ADDR":"",
"BONDNAME":"fake_bond",
"BONDID":"5",
"RUNNINGSTATUS":"10"}]}"""
if url == "/ETH_PORT/6":
data = """{"error":{"code":0},
"data":{"ID": "6",
"LOCATION":"CTE0.A.H1",
"IPV4ADDR":"",
"BONDNAME":"fake_bond",
"BONDID":"5",
"RUNNINGSTATUS":"10"}}"""
if url == "/BOND_PORT":
data = "{\"error\":{\"code\":0},\
\"data\":[{\"ID\": \"5\",\
\"NAME\":\"fake_bond\",\
\"PORTIDLIST\": \"[\\\"6\\\"]\",\
\"RUNNINGSTATUS\":\"10\"}]}"
if url == "/vlan":
if method == "GET":
data = """{"error":{"code":0}}"""
else:
data = """{"error":{"code":0},"data":{
"ID":"4"}}"""
if url == "/LIF":
if method == "GET":
data = """{"error":{"code":0}}"""
else:
data = """{"error":{"code":0},"data":{
"ID":"4"}}"""
if url == "/DNS_Server":
if method == "GET":
data = "{\"error\":{\"code\":0},\"data\":{\
\"ADDRESS\":\"[\\\"\\\"]\"}}"
else:
data = """{"error":{"code":0}}"""
if url == "/AD_CONFIG":
if method == "GET":
data = """{"error":{"code":0},"data":{
"DOMAINSTATUS":"1",
"FULLDOMAINNAME":"huawei.com"}}"""
else:
data = """{"error":{"code":0}}"""
if url == "/LDAP_CONFIG":
if method == "GET":
data = """{"error":{"code":0},"data":{
"BASEDN":"dc=huawei,dc=com",
"LDAPSERVER": "100.97.5.87"}}"""
else:
data = """{"error":{"code":0}}"""
if url == "/REPLICATIONPAIR":
data = """{"error":{"code":0},"data":{
"ID":"fake_pair_id"}}"""
if url == "/REPLICATIONPAIR/sync":
data = """{"error":{"code":0}}"""
if url == "/REPLICATIONPAIR/switch":
data = """{"error":{"code":0}}"""
if url == "/REPLICATIONPAIR/split":
data = """{"error":{"code":0}}"""
if url == "/REPLICATIONPAIR/CANCEL_SECODARY_WRITE_LOCK":
data = """{"error":{"code":0}}"""
if url == "/REPLICATIONPAIR/SET_SECODARY_WRITE_LOCK":
data = """{"error":{"code":0}}"""
if url == "/REPLICATIONPAIR/fake_pair_id":
data = """{"error":{"code":0},"data":{
"ID": "fake_pair_id",
"HEALTHSTATUS": "1",
"SECRESDATASTATUS": "1",
"ISPRIMARY": "false",
"SECRESACCESS": "1",
"RUNNINGSTATUS": "1"}}"""
else:
data = '{"error":{"code":31755596}}'
res_json = jsonutils.loads(data)
return res_json
class FakeRpcClient(rpcapi.HuaweiV3API):
def __init__(self, helper):
super(FakeRpcClient, self).__init__()
self.replica_mgr = replication.ReplicaPairManager(helper)
class fake_call_context(object):
def __init__(self, replica_mgr):
self.replica_mgr = replica_mgr
def call(self, context, func_name, **kwargs):
if func_name == 'create_replica_pair':
return self.replica_mgr.create_replica_pair(
context, **kwargs)
def create_replica_pair(self, context, host, local_share_info,
remote_device_wwn, remote_fs_id):
self.client.prepare = mock.Mock(
return_value=self.fake_call_context(self.replica_mgr))
return super(FakeRpcClient, self).create_replica_pair(
context, host, local_share_info,
remote_device_wwn, remote_fs_id)
class FakeRpcServer(object):
def start(self):
pass
class FakePrivateStorage(object):
def __init__(self):
self.map = {}
def get(self, entity_id, key=None, default=None):
if self.map.get(entity_id):
return self.map[entity_id].get(key, default)
return default
def update(self, entity_id, details, delete_existing=False):
self.map[entity_id] = details
def delete(self, entity_id, key=None):
self.map.pop(entity_id)
class FakeHuaweiNasDriver(huawei_nas.HuaweiNasDriver):
"""Fake HuaweiNasDriver."""
def __init__(self, *args, **kwargs):
huawei_nas.HuaweiNasDriver.__init__(self, *args, **kwargs)
self.plugin = connection.V3StorageConnection(self.configuration)
self.plugin.helper = FakeHuaweiNasHelper(self.configuration)
self.plugin.replica_mgr = replication.ReplicaPairManager(
self.plugin.helper)
self.plugin.rpc_client = FakeRpcClient(self.plugin.helper)
self.plugin.private_storage = FakePrivateStorage()
class FakeConfigParseTree(object):
class FakeNode(object):
def __init__(self, text):
self._text = text
@property
def text(self):
return self._text
@text.setter
def text(self, text):
self._text = text
class FakeRoot(object):
def __init__(self):
self._node_map = {}
def findtext(self, path, default=None):
if path in self._node_map:
return self._node_map[path].text
return default
def find(self, path):
if path in self._node_map:
return self._node_map[path]
return None
def __init__(self, path_value):
self.root = self.FakeRoot()
for k in path_value:
self.root._node_map[k] = self.FakeNode(path_value[k])
def getroot(self):
return self.root
def write(self, filename, format):
pass
@ddt.ddt
class HuaweiShareDriverTestCase(test.TestCase):
"""Tests GenericShareDriver."""
def setUp(self):
super(HuaweiShareDriverTestCase, self).setUp()
self._context = context.get_admin_context()
def _safe_get(opt):
return getattr(self.configuration, opt)
self.configuration = mock.Mock(spec=conf.Configuration)
self.configuration.safe_get = mock.Mock(side_effect=_safe_get)
self.configuration.network_config_group = 'fake_network_config_group'
self.configuration.admin_network_config_group = (
'fake_admin_network_config_group')
self.configuration.config_group = 'fake_share_backend_name'
self.configuration.share_backend_name = 'fake_share_backend_name'
self.configuration.huawei_share_backend = 'V3'
self.configuration.max_over_subscription_ratio = 1
self.configuration.driver_handles_share_servers = False
self.configuration.replication_domain = None
self.configuration.filter_function = None
self.configuration.goodness_function = None
self.tmp_dir = tempfile.mkdtemp()
self.fake_conf_file = self.tmp_dir + '/manila_huawei_conf.xml'
self.addCleanup(shutil.rmtree, self.tmp_dir)
self.create_fake_conf_file(self.fake_conf_file)
self.addCleanup(os.remove, self.fake_conf_file)
self.configuration.manila_huawei_conf_file = self.fake_conf_file
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)
self.driver = FakeHuaweiNasDriver(configuration=self.configuration)
self.driver.plugin.helper.test_normal = True
self.share_nfs = {
'id': 'fake_uuid',
'share_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',
'export_locations': [
{'path': '100.115.10.68:/share_fake_uuid'},
],
'host': 'fake_host@fake_backend#OpenStack_Pool',
'share_type_id': 'fake_id',
}
self.share_nfs_thick = {
'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_Pool_Thick',
'export_locations': [
{'path': '100.115.10.68:/share_fake_uuid'},
],
'share_type_id': 'fake_id',
}
self.share_nfs_thickfs = {
'id': 'fake_uuid',
'project_id': 'fake_tenant_id',
'display_name': 'fake',
'name': 'share-fake-uuid-thickfs',
'size': 1,
'share_proto': 'NFS',
'share_network_id': 'fake_net_id',
'share_server_id': 'fake-share-srv-id',
'host': 'fake_host@fake_backend#OpenStack_Pool',
'export_locations': [
{'path': '100.115.10.68:/share_fake_uuid_thickfs'},
],
'share_type_id': 'fake_id',
}
self.share_nfs_thick_thickfs = {
'id': 'fake_uuid',
'project_id': 'fake_tenant_id',
'display_name': 'fake',
'name': 'share-fake-uuid-thickfs',
'size': 1,
'share_proto': 'NFS',
'share_network_id': 'fake_net_id',
'share_server_id': 'fake-share-srv-id',
'host': 'fake_host@fake_backend#OpenStack_Pool_Thick',
'export_locations': [
{'path': '100.115.10.68:/share_fake_uuid_thickfs'},
],
'share_type_id': 'fake_id',
}
self.share_nfs_inpartition = {
'id': 'fake_uuid',
'project_id': 'fake_tenant_id',
'display_name': 'fake',
'name': 'share-fake-uuid-inpartition',
'size': 1,
'share_proto': 'NFS',
'share_network_id': 'fake_net_id',
'share_server_id': 'fake-share-srv-id',
'host': 'fake_host@fake_backend#OpenStack_Pool',
'export_locations': [
{'path': '100.115.10.68:/share_fake_uuid_inpartition'},
],
'share_type_id': 'fake_id',
}
self.share_manage_nfs = {
'id': 'fake_uuid',
'project_id': 'fake_tenant_id',
'display_name': 'fake',
'name': 'share-fake-manage-uuid',
'size': 1,
'share_proto': 'NFS',
'share_network_id': 'fake_net_id',
'share_server_id': 'fake-share-srv-id',
'export_locations': [
{'path': '100.115.10.68:/share_fake_uuid'},
],
'host': 'fake_host@fake_backend#OpenStack_Pool',
'share_type_id': 'fake_id',
}
self.share_pool_name_not_match = {
'id': 'fake_uuid',
'project_id': 'fake_tenant_id',
'display_name': 'fake',
'name': 'share-fake-manage-uuid',
'size': 1,
'share_proto': 'NFS',
'share_network_id': 'fake_net_id',
'share_server_id': 'fake-share-srv-id',
'export_locations': [
{'path': '100.115.10.68:/share_fake_uuid'},
],
'host': 'fake_host@fake_backend#OpenStack_Pool_not_match',
'share_type_id': 'fake_id',
}
self.share_proto_fail = {
'id': 'fake_uuid',
'project_id': 'fake_tenant_id',
'display_name': 'fake',
'name': 'share-fake-uuid',
'size': 1,
'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 = {
'id': 'fake_uuid',
'share_id': 'fake_uuid',
'project_id': 'fake_tenant_id',
'display_name': 'fake',
'name': 'share-fake-uuid',
'size': 1,
'share_proto': 'CIFS',
'share_network_id': 'fake_net_id',
'share_server_id': 'fake-share-srv-id',
'export_locations': [
{'path': 'share_fake_uuid'},
],
'host': 'fake_host@fake_backend#OpenStack_Pool',
'share_type_id': 'fake_id',
}
self.share_manage_cifs = {
'id': 'fake_uuid',
'project_id': 'fake_tenant_id',
'display_name': 'fake',
'name': 'share-fake-manage-uuid',
'size': 1,
'share_proto': 'CIFS',
'share_network_id': 'fake_net_id',
'share_server_id': 'fake-share-srv-id',
'export_locations': [
{'path': '\\\\100.115.10.68\\share_fake_uuid'},
],
'host': 'fake_host@fake_backend#OpenStack_Pool',
'share_type_id': 'fake_id',
}
self.nfs_snapshot = {
'id': 'fake_snapshot_uuid',
'snapshot_id': 'fake_snapshot_uuid',
'display_name': 'snapshot',
'name': 'fake_snapshot_name',
'size': 1,
'share_name': 'share_fake_uuid',
'share_id': 'fake_uuid',
'share': {
'share_name': 'share_fake_uuid',
'share_id': 'fake_uuid',
'share_size': 1,
'share_proto': 'NFS',
},
}
self.cifs_snapshot = {
'id': 'fake_snapshot_uuid',
'snapshot_id': 'fake_snapshot_uuid',
'display_name': 'snapshot',
'name': 'fake_snapshot_name',
'size': 1,
'share_name': 'share_fake_uuid',
'share_id': 'fake_uuid',
'share': {
'share_name': 'share_fake_uuid',
'share_id': 'fake_uuid',
'share_size': 1,
'share_proto': 'CIFS',
},
}
self.storage_nfs_snapshot = {
'id': 'fake_snapshot_uuid',
'snapshot_id': 'fake_snapshot_uuid',
'display_name': 'snapshot',
'name': 'fake_snapshot_name',
'provider_location': 'fake_storage_snapshot_name',
'size': 1,
'share_name': 'share_fake_uuid',
'share_id': 'fake_uuid',
'share': {
'share_name': 'share_fake_uuid',
'share_id': 'fake_uuid',
'share_size': 1,
'share_proto': 'NFS',
},
}
self.storage_cifs_snapshot = {
'id': 'fake_snapshot_uuid',
'snapshot_id': 'fake_snapshot_uuid',
'display_name': 'snapshot',
'name': 'fake_snapshot_name',
'provider_location': 'fake_storage_snapshot_name',
'size': 1,
'share_name': 'share_fake_uuid',
'share_id': 'fake_uuid',
'share': {
'share_name': 'share_fake_uuid',
'share_id': 'fake_uuid',
'share_size': 1,
'share_proto': 'CIFS',
},
}
self.security_service = {
'id': 'fake_id',
'domain': 'FAKE',
'server': 'fake_server',
'user': 'fake_user',
'password': 'fake_password',
}
self.access_ip = {
'access_type': 'ip',
'access_to': '100.112.0.1',
'access_level': 'rw',
}
self.access_ip_exist = {
'access_type': 'ip',
'access_to': '100.112.0.2',
'access_level': 'rw',
}
self.access_user = {
'access_type': 'user',
'access_to': 'user_name',
'access_level': 'rw',
}
self.access_user_exist = {
'access_type': 'user',
'access_to': 'user_exist',
'access_level': 'rw',
}
self.access_group = {
'access_type': 'user',
'access_to': 'group_name',
'access_level': 'rw',
}
self.access_cert = {
'access_type': 'cert',
'access_to': 'fake_cert',
'access_level': 'rw',
}
self.driver_options = {
'volume_id': 'fake',
}
self.share_server = None
self.driver._licenses = ['fake']
self.fake_network_allocations = [{
'id': 'fake_network_allocation_id',
'ip_address': '111.111.111.109',
}]
self.fake_network_info = {
'server_id': '0',
'segmentation_id': '2',
'cidr': '111.111.111.0/24',
'neutron_net_id': 'fake_neutron_net_id',
'neutron_subnet_id': 'fake_neutron_subnet_id',
'security_services': '',
'network_allocations': self.fake_network_allocations,
'network_type': 'vlan',
}
self.fake_active_directory = {
'type': 'active_directory',
'dns_ip': '100.97.5.5',
'user': 'ad_user',
'password': 'ad_password',
'domain': 'huawei.com'
}
self.fake_ldap = {
'type': 'ldap',
'server': '100.97.5.87',
'domain': 'dc=huawei,dc=com'
}
fake_share_type_id_not_extra = 'fake_id'
self.fake_type_not_extra = {
'test_with_extra': {
'created_at': 'fake_time',
'deleted': '0',
'deleted_at': None,
'extra_specs': {},
'required_extra_specs': {},
'id': fake_share_type_id_not_extra,
'name': 'test_with_extra',
'updated_at': None
}
}
fake_extra_specs = {
'capabilities:dedupe': '<is> True',
'capabilities:compression': '<is> True',
'capabilities:huawei_smartcache': '<is> True',
'huawei_smartcache:cachename': 'test_cache_name',
'capabilities:huawei_smartpartition': '<is> True',
'huawei_smartpartition:partitionname': 'test_partition_name',
'capabilities:thin_provisioning': '<is> True',
'test:test:test': 'test',
}
fake_share_type_id = 'fooid-2'
self.fake_type_w_extra = {
'test_with_extra': {
'created_at': 'fake_time',
'deleted': '0',
'deleted_at': None,
'extra_specs': fake_extra_specs,
'required_extra_specs': {},
'id': fake_share_type_id,
'name': 'test_with_extra',
'updated_at': None
}
}
fake_extra_specs = {
'capabilities:dedupe': '<is> True',
'capabilities:compression': '<is> True',
'capabilities:huawei_smartcache': '<is> False',
'huawei_smartcache:cachename': None,
'capabilities:huawei_smartpartition': '<is> False',
'huawei_smartpartition:partitionname': None,
'capabilities:thin_provisioning': '<is> True',
'test:test:test': 'test',
}
fake_share_type_id = 'fooid-3'
self.fake_type_fake_extra = {
'test_with_extra': {
'created_at': 'fake_time',
'deleted': '0',
'deleted_at': None,
'extra_specs': fake_extra_specs,
'required_extra_specs': {},
'id': fake_share_type_id,
'name': 'test_with_extra',
'updated_at': None
}
}
fake_extra_specs = {
'capabilities:dedupe': '<is> True',
'capabilities:compression': '<is> True',
'capabilities:huawei_smartcache': '<is> False',
'huawei_smartcache:cachename': None,
'capabilities:huawei_smartpartition': '<is> False',
'huawei_smartpartition:partitionname': None,
'capabilities:thin_provisioning': '<is> False',
'test:test:test': 'test',
}
fake_share_type_id = 'fooid-4'
self.fake_type_thin_extra = {
'test_with_extra': {
'created_at': 'fake_time',
'deleted': '0',
'deleted_at': None,
'extra_specs': fake_extra_specs,
'required_extra_specs': {},
'id': fake_share_type_id,
'name': 'test_with_extra',
'updated_at': None
}
}
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',
}
fake_extra_specs = {
'driver_handles_share_servers': 'False',
}
fake_share_type_id = 'fake_id'
self.fake_type_extra = {
'test_with_extra': {
'created_at': 'fake_time',
'deleted': '0',
'deleted_at': None,
'extra_specs': fake_extra_specs,
'required_extra_specs': {},
'id': fake_share_type_id,
'name': 'test_with_extra',
'updated_at': None
}
}
self.active_replica = {
'id': 'fake_active_replica_id',
'share_id': 'fake_share_id',
'name': 'share_fake_uuid',
'host': 'hostname1@backend_name1#OpenStack_Pool',
'size': 5,
'share_proto': 'NFS',
'replica_state': common_constants.REPLICA_STATE_ACTIVE,
}
self.new_replica = {
'id': 'fake_new_replica_id',
'share_id': 'fake_share_id',
'name': 'share_fake_new_uuid',
'host': 'hostname2@backend_name2#OpenStack_Pool',
'size': 5,
'share_proto': 'NFS',
'replica_state': common_constants.REPLICA_STATE_OUT_OF_SYNC,
'share_type_id': 'fake_id',
}
def _get_share_by_proto(self, share_proto):
if share_proto == "NFS":
share = self.share_nfs
elif share_proto == "CIFS":
share = self.share_cifs
else:
share = None
return share
def mock_share_type(self, share_type):
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
def test_no_configuration(self):
self.mock_object(huawei_nas.HuaweiNasDriver,
'driver_handles_share_servers',
True)
self.assertRaises(exception.InvalidInput,
huawei_nas.HuaweiNasDriver)
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_conf_logical_ip_fail(self):
self.configuration.driver_handles_share_servers = True
self.recreate_fake_conf_file(logical_port="fake_port")
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
self.configuration.driver_handles_share_servers = False
self.assertRaises(exception.InvalidInput,
self.driver.plugin.check_conf_file)
def test_conf_snapshot_replication_conflict(self):
self.recreate_fake_conf_file(snapshot_support=True,
replication_support=True)
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
self.driver.plugin._setup_conf()
self.assertRaises(exception.BadConfigurationException,
self.driver.plugin.check_conf_file)
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_storagepool_not_exist(self):
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidHost,
self.driver.create_share,
self._context,
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):
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_success(self):
FakeRpcServer.start = mock.Mock()
rpc.get_server = mock.Mock(return_value=FakeRpcServer())
self.driver.plugin.connect()
FakeRpcServer.start.assert_called_once()
def test_connect_fail(self):
self.driver.plugin.helper.test_multi_url_flag = 1
self.assertRaises(exception.InvalidShare,
self.driver.plugin.connect)
def test_login_success(self):
deviceid = self.driver.plugin.helper.login()
self.assertEqual("210235G7J20000000000", deviceid)
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_no_extra(self):
share_type = self.fake_type_not_extra['test_with_extra']
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
location = self.driver.create_share(self._context, self.share_nfs,
self.share_server)
self.assertEqual("100.115.10.68:/share_fake_uuid", location)
self.assertEqual(constants.ALLOC_TYPE_THIN_FLAG,
self.driver.plugin.helper.alloc_type)
def test_create_share_with_extra_thin(self):
share_type = {
'extra_specs': {
'capabilities:thin_provisioning': '<is> True'
},
}
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
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)
self.assertEqual(constants.ALLOC_TYPE_THIN_FLAG,
self.driver.plugin.helper.alloc_type)
def test_create_share_with_extra_thick(self):
share_type = {
'extra_specs': {
'capabilities:thin_provisioning': '<is> False'
},
}
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
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)
self.assertEqual(constants.ALLOC_TYPE_THICK_FLAG,
self.driver.plugin.helper.alloc_type)
@ddt.data(*constants.VALID_SECTOR_SIZES)
def test_create_share_with_sectorsize_in_type(self, sectorsize):
share_type = {
'extra_specs': {
'capabilities:huawei_sectorsize': "<is> true",
'huawei_sectorsize:sectorsize': sectorsize,
},
}
self.mock_share_type(share_type)
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)
self.assertTrue(db.share_type_get.called)
@ddt.data('128', 'xx', 'None', ' ')
def test_create_share_with_illegal_sectorsize_in_type(self, sectorsize):
share_type = {
'extra_specs': {
'capabilities:huawei_sectorsize': "<is> true",
'huawei_sectorsize:sectorsize': sectorsize,
},
}
self.mock_share_type(share_type)
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
self.share_nfs,
self.share_server)
@ddt.data({'extra_specs': {'capabilities:huawei_sectorsize': "<is> false",
'huawei_sectorsize:sectorsize': '0'}, 'xmlvalue': '4'},
{'extra_specs': {'capabilities:huawei_sectorsize': "<is> False",
'huawei_sectorsize:sectorsize': '128'}, 'xmlvalue': '8'},
{'extra_specs': {'capabilities:huawei_sectorsize': "false",
'huawei_sectorsize:sectorsize': 'a'}, 'xmlvalue': '16'},
{'extra_specs': {'capabilities:huawei_sectorsize': "False",
'huawei_sectorsize:sectorsize': 'xx'}, 'xmlvalue': '32'},
{'extra_specs': {'capabilities:huawei_sectorsize': "true",
'huawei_sectorsize:sectorsize': 'None'}, 'xmlvalue': '64'},
{'extra_specs': {'capabilities:huawei_sectorsize': "True",
'huawei_sectorsize:sectorsize': ' '}, 'xmlvalue': ' '},
{'extra_specs': {'capabilities:huawei_sectorsize': "True",
'huawei_sectorsize:sectorsize': ''}, 'xmlvalue': ''})
@ddt.unpack
def test_create_share_with_invalid_type_valid_xml(self, extra_specs,
xmlvalue):
fake_share_type = {}
fake_share_type['extra_specs'] = extra_specs
self.mock_share_type(fake_share_type)
self.recreate_fake_conf_file(sectorsize_value=xmlvalue)
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
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)
self.assertTrue(db.share_type_get.called)
@ddt.data({'extra_specs': {'capabilities:huawei_sectorsize': "<is> false",
'huawei_sectorsize:sectorsize': '4'}, 'xmlvalue': '0'},
{'extra_specs': {'capabilities:huawei_sectorsize': "<is> False",
'huawei_sectorsize:sectorsize': '8'}, 'xmlvalue': '128'},
{'extra_specs': {'capabilities:huawei_sectorsize': "false",
'huawei_sectorsize:sectorsize': '16'}, 'xmlvalue': 'a'},
{'extra_specs': {'capabilities:huawei_sectorsize': "False",
'huawei_sectorsize:sectorsize': '32'}, 'xmlvalue': 'xx'},
{'extra_specs': {'capabilities:huawei_sectorsize': "true",
'huawei_sectorsize:sectorsize': '64'}, 'xmlvalue': 'None'})
@ddt.unpack
def test_create_share_with_invalid_type_illegal_xml(self, extra_specs,
xmlvalue):
fake_share_type = {}
fake_share_type['extra_specs'] = extra_specs
self.mock_share_type(fake_share_type)
self.recreate_fake_conf_file(sectorsize_value=xmlvalue)
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_shrink_share_success(self):
self.driver.plugin.helper.shrink_share_flag = False
self.driver.plugin.helper.login()
self.driver.shrink_share(self.share_nfs, 1,
self.share_server)
self.assertTrue(self.driver.plugin.helper.shrink_share_flag)
def test_shrink_share_fail(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.shrink_share,
self.share_nfs,
1,
self.share_server)
def test_shrink_share_size_fail(self):
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidShare,
self.driver.shrink_share,
self.share_nfs,
5,
self.share_server)
def test_shrink_share_alloctype_fail(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.fs_status_flag = False
self.assertRaises(exception.InvalidShare,
self.driver.shrink_share,
self.share_nfs,
1,
self.share_server)
def test_shrink_share_not_exist(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.share_exist = False
self.assertRaises(exception.InvalidShare,
self.driver.shrink_share,
self.share_nfs,
1,
self.share_server)
def test_extend_share_success(self):
self.driver.plugin.helper.extend_share_flag = False
self.driver.plugin.helper.login()
self.driver.extend_share(self.share_nfs, 5,
self.share_server)
self.assertTrue(self.driver.plugin.helper.extend_share_flag)
def test_extend_share_fail(self):
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidInput,
self.driver.extend_share,
self.share_nfs,
3,
self.share_server)
def test_extend_share_not_exist(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.share_exist = False
self.assertRaises(exception.InvalidShareAccess,
self.driver.extend_share,
self.share_nfs,
4,
self.share_server)
def test_create_share_nfs_success(self):
share_type = self.fake_type_not_extra['test_with_extra']
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
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):
share_type = self.fake_type_not_extra['test_with_extra']
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
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_create_share_with_extra(self):
self.driver.plugin.helper.add_fs_to_partition_flag = False
self.driver.plugin.helper.add_fs_to_cache_flag = False
share_type = self.fake_type_w_extra['test_with_extra']
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
location = self.driver.create_share(self._context, self.share_nfs,
self.share_server)
self.assertEqual("100.115.10.68:/share_fake_uuid", location)
self.assertTrue(self.driver.plugin.helper.add_fs_to_partition_flag)
self.assertTrue(self.driver.plugin.helper.add_fs_to_cache_flag)
@ddt.data({'capabilities:dedupe': '<is> True',
'capabilities:thin_provisioning': '<is> False'},
{'capabilities:dedupe': '<is> True',
'capabilities:compression': '<is> True',
'capabilities:thin_provisioning': '<is> False'},
{'capabilities:huawei_smartcache': '<is> True',
'huawei_smartcache:cachename': None},
{'capabilities:huawei_smartpartition': '<is> True',
'huawei_smartpartition:partitionname': None},
{'capabilities:huawei_smartcache': '<is> True'},
{'capabilities:huawei_smartpartition': '<is> True'})
def test_create_share_with_extra_error(self, fake_extra_specs):
fake_share_type_id = 'fooid-2'
fake_type_error_extra = {
'test_with_extra': {
'created_at': 'fake_time',
'deleted': '0',
'deleted_at': None,
'extra_specs': fake_extra_specs,
'required_extra_specs': {},
'id': fake_share_type_id,
'name': 'test_with_extra',
'updated_at': None
}
}
share_type = fake_type_error_extra['test_with_extra']
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
self.share_nfs_thick,
self.share_server)
@ddt.data({"fake_extra_specs_qos": {"qos:maxIOPS": "100",
"qos:maxBandWidth": "50",
"qos:IOType": "0"},
"fake_qos_info": {"MAXIOPS": "100",
"MAXBANDWIDTH": "50",
"IOTYPE": "0",
"LATENCY": "0",
"NAME": "OpenStack_fake_qos"}},
{"fake_extra_specs_qos": {"qos:maxIOPS": "100",
"qos:IOType": "1"},
"fake_qos_info": {"NAME": "fake_qos",
"MAXIOPS": "100",
"IOTYPE": "1",
"LATENCY": "0"}},
{"fake_extra_specs_qos": {"qos:minIOPS": "100",
"qos:minBandWidth": "50",
'qos:latency': "50",
"qos:IOType": "0"},
"fake_qos_info": {"MINIOPS": "100",
"MINBANDWIDTH": "50",
"IOTYPE": "0",
"LATENCY": "50",
"NAME": "OpenStack_fake_qos"}})
@ddt.unpack
def test_create_share_with_qos(self, fake_extra_specs_qos, fake_qos_info):
fake_share_type_id = 'fooid-2'
fake_extra_specs = {"capabilities:qos": "<is> True"}
fake_extra_specs.update(fake_extra_specs_qos)
fake_type_error_extra = {
'test_with_extra': {
'created_at': 'fake_time',
'deleted': '0',
'deleted_at': None,
'extra_specs': fake_extra_specs,
'required_extra_specs': {},
'id': fake_share_type_id,
'name': 'test_with_extra',
'updated_at': None
}
}
fake_qos_info_respons = {
"error": {
"code": 0
},
"data": [{
"ID": "11",
"FSLIST": u'["1", "2", "3", "4"]',
"LUNLIST": '[""]',
"RUNNINGSTATUS": "2",
}]
}
fake_qos_info_respons["data"][0].update(fake_qos_info)
share_type = fake_type_error_extra['test_with_extra']
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
self.mock_object(helper.RestHelper,
'get_qos',
mock.Mock(return_value=fake_qos_info_respons))
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
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)
@ddt.data({'capabilities:qos': '<is> True',
'qos:maxIOPS': -1},
{'capabilities:qos': '<is> True',
'qos:IOTYPE': 4},
{'capabilities:qos': '<is> True',
'qos:IOTYPE': 100},
{'capabilities:qos': '<is> True',
'qos:maxIOPS': 0},
{'capabilities:qos': '<is> True',
'qos:minIOPS': 0},
{'capabilities:qos': '<is> True',
'qos:minBandWidth': 0},
{'capabilities:qos': '<is> True',
'qos:maxBandWidth': 0},
{'capabilities:qos': '<is> True',
'qos:latency': 0},
{'capabilities:qos': '<is> True',
'qos:maxIOPS': 100},
{'capabilities:qos': '<is> True',
'qos:maxIOPS': 100,
'qos:minBandWidth': 100,
'qos:IOType': '0'})
def test_create_share_with_invalid_qos(self, fake_extra_specs):
fake_share_type_id = 'fooid-2'
fake_type_error_extra = {
'test_with_extra': {
'created_at': 'fake_time',
'deleted': '0',
'deleted_at': None,
'extra_specs': fake_extra_specs,
'required_extra_specs': {},
'id': fake_share_type_id,
'name': 'test_with_extra',
'updated_at': None
}
}
share_type = fake_type_error_extra['test_with_extra']
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
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_cache_not_exist(self):
self.driver.plugin.helper.cache_exist = False
share_type = self.fake_type_w_extra['test_with_extra']
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
self.share_nfs,
self.share_server)
def test_add_share_to_cache_fail(self):
opts = dict(
huawei_smartcache='true',
cachename=None,
)
fsid = 4
smartcache = smartx.SmartCache(self.driver.plugin.helper)
self.assertRaises(exception.InvalidInput, smartcache.add,
opts, fsid)
def test_create_share_partition_not_exist(self):
self.driver.plugin.helper.partition_exist = False
share_type = self.fake_type_w_extra['test_with_extra']
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
self.share_nfs,
self.share_server)
def test_add_share_to_partition_fail(self):
opts = dict(
huawei_smartpartition='true',
partitionname=None,
)
fsid = 4
smartpartition = smartx.SmartPartition(self.driver.plugin.helper)
self.assertRaises(exception.InvalidInput, smartpartition.add,
opts, fsid)
def test_login_fail(self):
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.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
self.share_nfs,
self.share_server)
def test_create_share_nfs_status_fail(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.fs_status_flag = False
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
self.share_nfs,
self.share_server)
def test_create_share_cifs_fs_fail(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
self.share_cifs,
self.share_server)
def test_create_share_cifs_fail(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.create_share_flag = True
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
self.share_cifs,
self.share_server)
def test_create_share_nfs_fail(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.create_share_flag = True
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
self.share_nfs,
self.share_server)
@ddt.data({"share_proto": "NFS",
"fake_qos_info_respons": {"ID": "11", "MAXIOPS": "100",
"IOType": "2",
"FSLIST": u'["0", "1", "4"]'}},
{"share_proto": "CIFS",
"fake_qos_info_respons": {"ID": "11", "MAXIOPS": "100",
"IOType": "2", "FSLIST": u'["4"]',
"RUNNINGSTATUS": "2"}})
@ddt.unpack
def test_delete_share_success(self, share_proto, fake_qos_info_respons):
self.driver.plugin.helper.login()
self.driver.plugin.helper.delete_flag = False
if share_proto == 'NFS':
share = self.share_nfs
else:
share = self.share_cifs
with mock.patch.object(helper.RestHelper, 'get_qos_info',
return_value=fake_qos_info_respons):
self.driver.delete_share(self._context,
share, self.share_server)
self.assertTrue(self.driver.plugin.helper.delete_flag)
def test_delete_share_withoutqos_success(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.delete_flag = False
self.driver.plugin.qos_support = True
self.driver.delete_share(self._context,
self.share_nfs, self.share_server)
self.assertTrue(self.driver.plugin.helper.delete_flag)
def test_check_snapshot_id_exist_fail(self):
snapshot_id = "4@share_snapshot_not_exist"
self.driver.plugin.helper.login()
self.driver.plugin.helper.test_normal = False
snapshot_info = self.driver.plugin.helper._get_snapshot_by_id(
snapshot_id)
self.assertRaises(exception.InvalidShareSnapshot,
self.driver.plugin.helper._check_snapshot_id_exist,
snapshot_info)
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.plugin.helper.delete_flag = False
fake_qos_info_respons = {
"ID": "11",
"FSLIST": u'["1", "2", "3", "4"]',
"LUNLIST": '[""]',
"RUNNINGSTATUS": "2",
}
self.mock_object(helper.RestHelper,
'get_qos_info',
mock.Mock(return_value=fake_qos_info_respons))
self.driver.plugin.helper.login()
self.driver.delete_share(self._context, self.share_cifs,
self.share_server)
self.assertTrue(self.driver.plugin.helper.delete_flag)
def test_get_network_allocations_number_dhss_true(self):
self.configuration.driver_handles_share_servers = True
number = self.driver.get_network_allocations_number()
self.assertEqual(1, number)
def test_get_network_allocations_number_dhss_false(self):
self.configuration.driver_handles_share_servers = False
number = self.driver.get_network_allocations_number()
self.assertEqual(0, number)
def test_create_nfsshare_from_nfssnapshot_success(self):
share_type = self.fake_type_not_extra['test_with_extra']
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
self.mock_object(self.driver.plugin,
'mount_share_to_host',
mock.Mock(return_value={}))
self.mock_object(self.driver.plugin,
'copy_snapshot_data',
mock.Mock(return_value=True))
self.mock_object(self.driver.plugin,
'umount_share_from_host',
mock.Mock(return_value={}))
self.driver.plugin.helper.login()
self.driver.plugin.helper.snapshot_flag = True
location = self.driver.create_share_from_snapshot(self._context,
self.share_nfs,
self.nfs_snapshot,
self.share_server)
self.assertTrue(db.share_type_get.called)
self.assertEqual(2, self.driver.plugin.
mount_share_to_host.call_count)
self.assertTrue(self.driver.plugin.
copy_snapshot_data.called)
self.assertEqual(2, self.driver.plugin.
umount_share_from_host.call_count)
self.assertEqual("100.115.10.68:/share_fake_uuid", location)
def test_create_cifsshare_from_cifssnapshot_success(self):
share_type = self.fake_type_not_extra['test_with_extra']
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
self.mock_object(self.driver.plugin,
'mount_share_to_host',
mock.Mock(return_value={}))
self.mock_object(self.driver.plugin,
'copy_snapshot_data',
mock.Mock(return_value=True))
self.mock_object(self.driver.plugin,
'umount_share_from_host',
mock.Mock(return_value={}))
self.driver.plugin.helper.login()
self.driver.plugin.helper.snapshot_flag = True
location = self.driver.create_share_from_snapshot(self._context,
self.share_cifs,
self.cifs_snapshot,
self.share_server)
self.assertTrue(db.share_type_get.called)
self.assertEqual(2, self.driver.plugin.
mount_share_to_host.call_count)
self.assertTrue(self.driver.plugin.
copy_snapshot_data.called)
self.assertEqual(2, self.driver.plugin.
umount_share_from_host.call_count)
self.assertEqual("\\\\100.115.10.68\\share_fake_uuid", location)
def test_create_nfsshare_from_cifssnapshot_success(self):
share_type = self.fake_type_not_extra['test_with_extra']
self.mock_object(db,
'share_type_get',
mock