diff --git a/manila/share/drivers/netapp/common.py b/manila/share/drivers/netapp/common.py
index 36ff021f1b..1a1a554f0d 100644
--- a/manila/share/drivers/netapp/common.py
+++ b/manila/share/drivers/netapp/common.py
@@ -67,7 +67,6 @@ class NetAppDriver(object):
config.append_config_values(driver.share_opts)
config.append_config_values(options.netapp_proxy_opts)
na_utils.check_flags(NetAppDriver.REQUIRED_FLAGS, config)
- na_utils.check_netapp_lib()
app_version = na_utils.OpenStackInfo().info()
LOG.info(_LI('OpenStack OS Version Info: %s'), app_version)
diff --git a/manila/share/drivers/netapp/dataontap/client/api.py b/manila/share/drivers/netapp/dataontap/client/api.py
new file mode 100644
index 0000000000..caa8bcdfc2
--- /dev/null
+++ b/manila/share/drivers/netapp/dataontap/client/api.py
@@ -0,0 +1,623 @@
+# Copyright (c) 2014 Navneet Singh. All rights reserved.
+# Copyright (c) 2014 Clinton Knight. 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.
+"""
+NetApp API for Data ONTAP and OnCommand DFM.
+
+Contains classes required to issue API calls to Data ONTAP and OnCommand DFM.
+"""
+
+import copy
+
+from lxml import etree
+from oslo_log import log
+import six
+from six.moves import urllib
+
+from manila import exception
+from manila.i18n import _
+
+
+LOG = log.getLogger(__name__)
+
+EONTAPI_EINVAL = '22'
+EAPIERROR = '13001'
+EAPINOTFOUND = '13005'
+ESNAPSHOTNOTALLOWED = '13023'
+EVOLUMEOFFLINE = '13042'
+EINTERNALERROR = '13114'
+EDUPLICATEENTRY = '13130'
+EVOLNOTCLONE = '13170'
+EVOL_NOT_MOUNTED = '14716'
+ESIS_CLONE_NOT_LICENSED = '14956'
+EOBJECTNOTFOUND = '15661'
+E_VIFMGR_PORT_ALREADY_ASSIGNED_TO_BROADCAST_DOMAIN = '18605'
+
+
+class NaServer(object):
+ """Encapsulates server connection logic."""
+
+ TRANSPORT_TYPE_HTTP = 'http'
+ TRANSPORT_TYPE_HTTPS = 'https'
+ SERVER_TYPE_FILER = 'filer'
+ SERVER_TYPE_DFM = 'dfm'
+ URL_FILER = 'servlets/netapp.servlets.admin.XMLrequest_filer'
+ URL_DFM = 'apis/XMLrequest'
+ NETAPP_NS = 'http://www.netapp.com/filer/admin'
+ STYLE_LOGIN_PASSWORD = 'basic_auth'
+ STYLE_CERTIFICATE = 'certificate_auth'
+
+ def __init__(self, host, server_type=SERVER_TYPE_FILER,
+ transport_type=TRANSPORT_TYPE_HTTP,
+ style=STYLE_LOGIN_PASSWORD, username=None,
+ password=None, port=None, trace=False):
+ self._host = host
+ self.set_server_type(server_type)
+ self.set_transport_type(transport_type)
+ self.set_style(style)
+ if port:
+ self.set_port(port)
+ self._username = username
+ self._password = password
+ self._trace = trace
+ self._refresh_conn = True
+ self._trace = trace
+
+ LOG.debug('Using NetApp controller: %s', self._host)
+
+ def get_transport_type(self):
+ """Get the transport type protocol."""
+ return self._protocol
+
+ def set_transport_type(self, transport_type):
+ """Set the transport type protocol for API.
+
+ Supports http and https transport types.
+ """
+ if transport_type.lower() not in (
+ NaServer.TRANSPORT_TYPE_HTTP,
+ NaServer.TRANSPORT_TYPE_HTTPS):
+ raise ValueError('Unsupported transport type')
+ self._protocol = transport_type.lower()
+ if self._protocol == NaServer.TRANSPORT_TYPE_HTTP:
+ if self._server_type == NaServer.SERVER_TYPE_FILER:
+ self.set_port(80)
+ else:
+ self.set_port(8088)
+ else:
+ if self._server_type == NaServer.SERVER_TYPE_FILER:
+ self.set_port(443)
+ else:
+ self.set_port(8488)
+ self._refresh_conn = True
+
+ def get_style(self):
+ """Get the authorization style for communicating with the server."""
+ return self._auth_style
+
+ def set_style(self, style):
+ """Set the authorization style for communicating with the server.
+
+ Supports basic_auth for now. Certificate_auth mode to be done.
+ """
+ if style.lower() not in (NaServer.STYLE_LOGIN_PASSWORD,
+ NaServer.STYLE_CERTIFICATE):
+ raise ValueError('Unsupported authentication style')
+ self._auth_style = style.lower()
+
+ def get_server_type(self):
+ """Get the target server type."""
+ return self._server_type
+
+ def set_server_type(self, server_type):
+ """Set the target server type.
+
+ Supports filer and dfm server types.
+ """
+ if server_type.lower() not in (NaServer.SERVER_TYPE_FILER,
+ NaServer.SERVER_TYPE_DFM):
+ raise ValueError('Unsupported server type')
+ self._server_type = server_type.lower()
+ if self._server_type == NaServer.SERVER_TYPE_FILER:
+ self._url = NaServer.URL_FILER
+ else:
+ self._url = NaServer.URL_DFM
+ self._ns = NaServer.NETAPP_NS
+ self._refresh_conn = True
+
+ def set_api_version(self, major, minor):
+ """Set the API version."""
+ try:
+ self._api_major_version = int(major)
+ self._api_minor_version = int(minor)
+ self._api_version = six.text_type(major) + "." + \
+ six.text_type(minor)
+ except ValueError:
+ raise ValueError('Major and minor versions must be integers')
+ self._refresh_conn = True
+
+ def get_api_version(self):
+ """Gets the API version tuple."""
+ if hasattr(self, '_api_version'):
+ return (self._api_major_version, self._api_minor_version)
+ return None
+
+ def set_port(self, port):
+ """Set the server communication port."""
+ try:
+ int(port)
+ except ValueError:
+ raise ValueError('Port must be integer')
+ self._port = six.text_type(port)
+ self._refresh_conn = True
+
+ def get_port(self):
+ """Get the server communication port."""
+ return self._port
+
+ def set_timeout(self, seconds):
+ """Sets the timeout in seconds."""
+ try:
+ self._timeout = int(seconds)
+ except ValueError:
+ raise ValueError('timeout in seconds must be integer')
+
+ def get_timeout(self):
+ """Gets the timeout in seconds if set."""
+ if hasattr(self, '_timeout'):
+ return self._timeout
+ return None
+
+ def get_vfiler(self):
+ """Get the vfiler to use in tunneling."""
+ return self._vfiler
+
+ def set_vfiler(self, vfiler):
+ """Set the vfiler to use if tunneling gets enabled."""
+ self._vfiler = vfiler
+
+ def get_vserver(self):
+ """Get the vserver to use in tunneling."""
+ return self._vserver
+
+ def set_vserver(self, vserver):
+ """Set the vserver to use if tunneling gets enabled."""
+ self._vserver = vserver
+
+ def set_username(self, username):
+ """Set the user name for authentication."""
+ self._username = username
+ self._refresh_conn = True
+
+ def set_password(self, password):
+ """Set the password for authentication."""
+ self._password = password
+ self._refresh_conn = True
+
+ def set_trace(self, trace=True):
+ """Enable or disable the API tracing facility."""
+ self._trace = trace
+
+ def invoke_elem(self, na_element, enable_tunneling=False):
+ """Invoke the API on the server."""
+ if na_element and not isinstance(na_element, NaElement):
+ ValueError('NaElement must be supplied to invoke API')
+
+ request, request_element = self._create_request(na_element,
+ enable_tunneling)
+
+ if self._trace:
+ LOG.debug("Request: %s", request_element.to_string(pretty=True))
+
+ if not hasattr(self, '_opener') or not self._opener \
+ or self._refresh_conn:
+ self._build_opener()
+ try:
+ if hasattr(self, '_timeout'):
+ response = self._opener.open(request, timeout=self._timeout)
+ else:
+ response = self._opener.open(request)
+ except urllib.error.HTTPError as e:
+ raise NaApiError(e.code, e.msg)
+ except Exception as e:
+ raise NaApiError('Unexpected error', e)
+
+ response_xml = response.read()
+ response_element = self._get_result(response_xml)
+
+ if self._trace:
+ LOG.debug("Response: %s", response_element.to_string(pretty=True))
+
+ return response_element
+
+ def invoke_successfully(self, na_element, enable_tunneling=False):
+ """Invokes API and checks execution status as success.
+
+ Need to set enable_tunneling to True explicitly to achieve it.
+ This helps to use same connection instance to enable or disable
+ tunneling. The vserver or vfiler should be set before this call
+ otherwise tunneling remains disabled.
+ """
+ result = self.invoke_elem(na_element, enable_tunneling)
+ if result.has_attr('status') and result.get_attr('status') == 'passed':
+ return result
+ code = result.get_attr('errno')\
+ or result.get_child_content('errorno')\
+ or 'ESTATUSFAILED'
+ if code == ESIS_CLONE_NOT_LICENSED:
+ msg = 'Clone operation failed: FlexClone not licensed.'
+ else:
+ msg = result.get_attr('reason')\
+ or result.get_child_content('reason')\
+ or 'Execution status is failed due to unknown reason'
+ raise NaApiError(code, msg)
+
+ def _create_request(self, na_element, enable_tunneling=False):
+ """Creates request in the desired format."""
+ netapp_elem = NaElement('netapp')
+ netapp_elem.add_attr('xmlns', self._ns)
+ if hasattr(self, '_api_version'):
+ netapp_elem.add_attr('version', self._api_version)
+ if enable_tunneling:
+ self._enable_tunnel_request(netapp_elem)
+ netapp_elem.add_child_elem(na_element)
+ request_d = netapp_elem.to_string()
+ request = urllib.request.Request(
+ self._get_url(), data=request_d,
+ headers={'Content-Type': 'text/xml', 'charset': 'utf-8'})
+ return request, netapp_elem
+
+ def _enable_tunnel_request(self, netapp_elem):
+ """Enables vserver or vfiler tunneling."""
+ if hasattr(self, '_vfiler') and self._vfiler:
+ if hasattr(self, '_api_major_version') and \
+ hasattr(self, '_api_minor_version') and \
+ self._api_major_version >= 1 and \
+ self._api_minor_version >= 7:
+ netapp_elem.add_attr('vfiler', self._vfiler)
+ else:
+ raise ValueError('ontapi version has to be atleast 1.7'
+ ' to send request to vfiler')
+ if hasattr(self, '_vserver') and self._vserver:
+ if hasattr(self, '_api_major_version') and \
+ hasattr(self, '_api_minor_version') and \
+ self._api_major_version >= 1 and \
+ self._api_minor_version >= 15:
+ netapp_elem.add_attr('vfiler', self._vserver)
+ else:
+ raise ValueError('ontapi version has to be atleast 1.15'
+ ' to send request to vserver')
+
+ def _parse_response(self, response):
+ """Get the NaElement for the response."""
+ if not response:
+ raise NaApiError('No response received')
+ xml = etree.XML(response)
+ return NaElement(xml)
+
+ def _get_result(self, response):
+ """Gets the call result."""
+ processed_response = self._parse_response(response)
+ return processed_response.get_child_by_name('results')
+
+ def _get_url(self):
+ return '%s://%s:%s/%s' % (self._protocol, self._host, self._port,
+ self._url)
+
+ def _build_opener(self):
+ if self._auth_style == NaServer.STYLE_LOGIN_PASSWORD:
+ auth_handler = self._create_basic_auth_handler()
+ else:
+ auth_handler = self._create_certificate_auth_handler()
+ opener = urllib.request.build_opener(auth_handler)
+ self._opener = opener
+
+ def _create_basic_auth_handler(self):
+ password_man = urllib.request.HTTPPasswordMgrWithDefaultRealm()
+ password_man.add_password(None, self._get_url(), self._username,
+ self._password)
+ auth_handler = urllib.request.HTTPBasicAuthHandler(password_man)
+ return auth_handler
+
+ def _create_certificate_auth_handler(self):
+ raise NotImplementedError()
+
+ def __str__(self):
+ return "server: %s" % (self._host)
+
+
+class NaElement(object):
+ """Class wraps basic building block for NetApp API request."""
+
+ def __init__(self, name):
+ """Name of the element or etree.Element."""
+ if isinstance(name, etree._Element):
+ self._element = name
+ else:
+ self._element = etree.Element(name)
+
+ def get_name(self):
+ """Returns the tag name of the element."""
+ return self._element.tag
+
+ def set_content(self, text):
+ """Set the text string for the element."""
+ self._element.text = text
+
+ def get_content(self):
+ """Get the text for the element."""
+ return self._element.text
+
+ def add_attr(self, name, value):
+ """Add the attribute to the element."""
+ self._element.set(name, value)
+
+ def add_attrs(self, **attrs):
+ """Add multiple attributes to the element."""
+ for attr in attrs.keys():
+ self._element.set(attr, attrs.get(attr))
+
+ def add_child_elem(self, na_element):
+ """Add the child element to the element."""
+ if isinstance(na_element, NaElement):
+ self._element.append(na_element._element)
+ return
+ raise
+
+ def get_child_by_name(self, name):
+ """Get the child element by the tag name."""
+ for child in self._element.iterchildren():
+ if child.tag == name or etree.QName(child.tag).localname == name:
+ return NaElement(child)
+ return None
+
+ def get_child_content(self, name):
+ """Get the content of the child."""
+ for child in self._element.iterchildren():
+ if child.tag == name or etree.QName(child.tag).localname == name:
+ return child.text
+ return None
+
+ def get_children(self):
+ """Get the children for the element."""
+ return [NaElement(el) for el in self._element.iterchildren()]
+
+ def has_attr(self, name):
+ """Checks whether element has attribute."""
+ attributes = self._element.attrib or {}
+ return name in attributes.keys()
+
+ def get_attr(self, name):
+ """Get the attribute with the given name."""
+ attributes = self._element.attrib or {}
+ return attributes.get(name)
+
+ def get_attr_names(self):
+ """Returns the list of attribute names."""
+ attributes = self._element.attrib or {}
+ return attributes.keys()
+
+ def add_new_child(self, name, content, convert=False):
+ """Add child with tag name and context.
+
+ Convert replaces entity refs to chars.
+ """
+ child = NaElement(name)
+ if convert:
+ content = NaElement._convert_entity_refs(content)
+ child.set_content(content)
+ self.add_child_elem(child)
+
+ @staticmethod
+ def _convert_entity_refs(text):
+ """Converts entity refs to chars to handle etree auto conversions."""
+ text = text.replace("<", "<")
+ text = text.replace(">", ">")
+ return text
+
+ @staticmethod
+ def create_node_with_children(node, **children):
+ """Creates and returns named node with children."""
+ parent = NaElement(node)
+ for child in children.keys():
+ parent.add_new_child(child, children.get(child, None))
+ return parent
+
+ def add_node_with_children(self, node, **children):
+ """Creates named node with children."""
+ parent = NaElement.create_node_with_children(node, **children)
+ self.add_child_elem(parent)
+
+ def to_string(self, pretty=False, method='xml', encoding='UTF-8'):
+ """Prints the element to string."""
+ return etree.tostring(self._element, method=method, encoding=encoding,
+ pretty_print=pretty)
+
+ def __getitem__(self, key):
+ """Dict getter method for NaElement.
+
+ Returns NaElement list if present,
+ text value in case no NaElement node
+ children or attribute value if present.
+ """
+
+ child = self.get_child_by_name(key)
+ if child:
+ if child.get_children():
+ return child
+ else:
+ return child.get_content()
+ elif self.has_attr(key):
+ return self.get_attr(key)
+ raise KeyError(_('No element by given name %s.') % (key))
+
+ def __setitem__(self, key, value):
+ """Dict setter method for NaElement.
+
+ Accepts dict, list, tuple, str, int, float and long as valid value.
+ """
+ if key:
+ if value:
+ if isinstance(value, NaElement):
+ child = NaElement(key)
+ child.add_child_elem(value)
+ self.add_child_elem(child)
+ elif isinstance(
+ value,
+ six.string_types + six.integer_types + (float, )):
+ self.add_new_child(key, six.text_type(value))
+ elif isinstance(value, (list, tuple, dict)):
+ child = NaElement(key)
+ child.translate_struct(value)
+ self.add_child_elem(child)
+ else:
+ raise TypeError(_('Not a valid value for NaElement.'))
+ else:
+ self.add_child_elem(NaElement(key))
+ else:
+ raise KeyError(_('NaElement name cannot be null.'))
+
+ def translate_struct(self, data_struct):
+ """Convert list, tuple, dict to NaElement and appends.
+
+ Example usage:
+ 1.
+
+ vl1
+ vl2
+ vl3
+
+ The above can be achieved by doing
+ root = NaElement('root')
+ root.translate_struct({'elem1': 'vl1', 'elem2': 'vl2',
+ 'elem3': 'vl3'})
+ 2.
+
+ vl1
+ vl2
+ vl3
+
+ The above can be achieved by doing
+ root = NaElement('root')
+ root.translate_struct([{'elem1': 'vl1', 'elem2': 'vl2'},
+ {'elem1': 'vl3'}])
+ """
+ if isinstance(data_struct, (list, tuple)):
+ for el in data_struct:
+ if isinstance(el, (list, tuple, dict)):
+ self.translate_struct(el)
+ else:
+ self.add_child_elem(NaElement(el))
+ elif isinstance(data_struct, dict):
+ for k in data_struct.keys():
+ child = NaElement(k)
+ if isinstance(data_struct[k], (dict, list, tuple)):
+ child.translate_struct(data_struct[k])
+ else:
+ if data_struct[k]:
+ child.set_content(six.text_type(data_struct[k]))
+ self.add_child_elem(child)
+ else:
+ raise ValueError(_('Type cannot be converted into NaElement.'))
+
+
+class NaApiError(Exception):
+ """Base exception class for NetApp API errors."""
+
+ def __init__(self, code='unknown', message='unknown'):
+ self.code = code
+ self.message = message
+
+ def __str__(self, *args, **kwargs):
+ return 'NetApp API failed. Reason - %s:%s' % (self.code, self.message)
+
+
+def invoke_api(na_server, api_name, api_family='cm', query=None,
+ des_result=None, additional_elems=None,
+ is_iter=False, records=0, tag=None,
+ timeout=0, tunnel=None):
+ """Invokes any given API call to a NetApp server.
+
+ :param na_server: na_server instance
+ :param api_name: API name string
+ :param api_family: cm or 7m
+ :param query: API query as dict
+ :param des_result: desired result as dict
+ :param additional_elems: dict other than query and des_result
+ :param is_iter: is iterator API
+ :param records: limit for records, 0 for infinite
+ :param timeout: timeout seconds
+ :param tunnel: tunnel entity, vserver or vfiler name
+ """
+ record_step = 50
+ if not (na_server or isinstance(na_server, NaServer)):
+ msg = _("Requires an NaServer instance.")
+ raise exception.InvalidInput(reason=msg)
+ server = copy.copy(na_server)
+ if api_family == 'cm':
+ server.set_vserver(tunnel)
+ else:
+ server.set_vfiler(tunnel)
+ if timeout > 0:
+ server.set_timeout(timeout)
+ iter_records = 0
+ cond = True
+ while cond:
+ na_element = create_api_request(
+ api_name, query, des_result, additional_elems,
+ is_iter, record_step, tag)
+ result = server.invoke_successfully(na_element, True)
+ if is_iter:
+ if records > 0:
+ iter_records = iter_records + record_step
+ if iter_records >= records:
+ cond = False
+ tag_el = result.get_child_by_name('next-tag')
+ tag = tag_el.get_content() if tag_el else None
+ if not tag:
+ cond = False
+ else:
+ cond = False
+ yield result
+
+
+def create_api_request(api_name, query=None, des_result=None,
+ additional_elems=None, is_iter=False,
+ record_step=50, tag=None):
+ """Creates a NetApp API request.
+
+ :param api_name: API name string
+ :param query: API query as dict
+ :param des_result: desired result as dict
+ :param additional_elems: dict other than query and des_result
+ :param is_iter: is iterator API
+ :param record_step: records at a time for iter API
+ :param tag: next tag for iter API
+ """
+ api_el = NaElement(api_name)
+ if query:
+ query_el = NaElement('query')
+ query_el.translate_struct(query)
+ api_el.add_child_elem(query_el)
+ if des_result:
+ res_el = NaElement('desired-attributes')
+ res_el.translate_struct(des_result)
+ api_el.add_child_elem(res_el)
+ if additional_elems:
+ api_el.translate_struct(additional_elems)
+ if is_iter:
+ api_el.add_new_child('max-records', six.text_type(record_step))
+ if tag:
+ api_el.add_new_child('tag', tag, True)
+ return api_el
diff --git a/manila/share/drivers/netapp/dataontap/client/client_base.py b/manila/share/drivers/netapp/dataontap/client/client_base.py
index eb3530c441..4982a694b5 100644
--- a/manila/share/drivers/netapp/dataontap/client/client_base.py
+++ b/manila/share/drivers/netapp/dataontap/client/client_base.py
@@ -15,15 +15,11 @@
from oslo_log import log
from oslo_utils import excutils
-from oslo_utils import importutils
from manila.i18n import _LE
+from manila.share.drivers.netapp.dataontap.client import api as netapp_api
from manila.share.drivers.netapp import utils as na_utils
-netapp_lib = importutils.try_import('netapp_lib')
-if netapp_lib:
- from netapp_lib.api.zapi import zapi as netapp_api
-
LOG = log.getLogger(__name__)
diff --git a/manila/share/drivers/netapp/dataontap/client/client_cmode.py b/manila/share/drivers/netapp/dataontap/client/client_cmode.py
index a38905484d..45314fe7bd 100644
--- a/manila/share/drivers/netapp/dataontap/client/client_cmode.py
+++ b/manila/share/drivers/netapp/dataontap/client/client_cmode.py
@@ -20,21 +20,16 @@ import hashlib
import time
from oslo_log import log
-from oslo_utils import importutils
from oslo_utils import strutils
from oslo_utils import units
import six
from manila import exception
from manila.i18n import _, _LE, _LW
+from manila.share.drivers.netapp.dataontap.client import api as netapp_api
from manila.share.drivers.netapp.dataontap.client import client_base
from manila.share.drivers.netapp import utils as na_utils
-netapp_lib = importutils.try_import('netapp_lib')
-if netapp_lib:
- from netapp_lib.api.zapi import errors as netapp_error
- from netapp_lib.api.zapi import zapi as netapp_api
-
LOG = log.getLogger(__name__)
DELETED_PREFIX = 'deleted_manila_'
@@ -217,7 +212,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
try:
vserver_client.offline_volume(root_volume_name)
except netapp_api.NaApiError as e:
- if e.code == netapp_error.EVOLUMEOFFLINE:
+ if e.code == netapp_api.EVOLUMEOFFLINE:
LOG.error(_LE("Volume %s is already offline."),
root_volume_name)
else:
@@ -246,7 +241,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
try:
vserver_client.send_request('cifs-server-delete', api_args)
except netapp_api.NaApiError as e:
- if e.code == netapp_error.EOBJECTNOTFOUND:
+ if e.code == netapp_api.EOBJECTNOTFOUND:
LOG.error(_LE('CIFS server does not exist for '
'Vserver %s.'), vserver_name)
else:
@@ -408,7 +403,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
}
self.send_request('net-vlan-create', api_args)
except netapp_api.NaApiError as e:
- if e.code == netapp_error.EDUPLICATEENTRY:
+ if e.code == netapp_api.EDUPLICATEENTRY:
LOG.debug('VLAN %(vlan)s already exists on port %(port)s',
{'vlan': vlan, 'port': port})
else:
@@ -501,7 +496,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
}
self.send_request('net-port-broadcast-domain-add-ports', api_args)
except netapp_api.NaApiError as e:
- if e.code == (netapp_error.
+ if e.code == (netapp_api.
E_VIFMGR_PORT_ALREADY_ASSIGNED_TO_BROADCAST_DOMAIN):
LOG.debug('Port %(port)s already exists in broadcast domain '
'%(domain)s', {'port': port, 'domain': domain})
@@ -623,7 +618,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
aggrs = self._get_aggregates(aggregate_names=[aggregate_name],
desired_attributes=desired_attributes)
except netapp_api.NaApiError as e:
- if e.code == netapp_error.EAPINOTFOUND:
+ if e.code == netapp_api.EAPINOTFOUND:
return None
else:
raise e
@@ -861,7 +856,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
try:
self.send_request('kerberos-realm-create', api_args)
except netapp_api.NaApiError as e:
- if e.code == netapp_error.EDUPLICATEENTRY:
+ if e.code == netapp_api.EDUPLICATEENTRY:
LOG.debug('Kerberos realm config already exists.')
else:
msg = _('Failed to create Kerberos realm. %s')
@@ -911,7 +906,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
try:
self.send_request('net-dns-create', api_args)
except netapp_api.NaApiError as e:
- if e.code == netapp_error.EDUPLICATEENTRY:
+ if e.code == netapp_api.EDUPLICATEENTRY:
LOG.error(_LE("DNS exists for Vserver."))
else:
msg = _("Failed to configure DNS. %s")
@@ -1389,7 +1384,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
try:
self.send_request('volume-offline', {'name': volume_name})
except netapp_api.NaApiError as e:
- if e.code == netapp_error.EVOLUMEOFFLINE:
+ if e.code == netapp_api.EVOLUMEOFFLINE:
return
raise
@@ -1403,7 +1398,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
try:
self.send_request('volume-unmount', api_args)
except netapp_api.NaApiError as e:
- if e.code == netapp_error.EVOL_NOT_MOUNTED:
+ if e.code == netapp_api.EVOL_NOT_MOUNTED:
return
raise
@@ -1430,7 +1425,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
LOG.debug('Volume %s unmounted.', volume_name)
return
except netapp_api.NaApiError as e:
- if e.code == netapp_error.EAPIERROR and 'job ID' in e.message:
+ if e.code == netapp_api.EAPIERROR and 'job ID' in e.message:
msg = _LW('Could not unmount volume %(volume)s due to '
'ongoing volume operation: %(exception)s')
msg_args = {'volume': volume_name, 'exception': e}
@@ -1494,7 +1489,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
'code': error_code,
'reason': error_reason
}
- if error_code == netapp_error.ESNAPSHOTNOTALLOWED:
+ if error_code == netapp_api.ESNAPSHOTNOTALLOWED:
raise exception.SnapshotUnavailable(msg % msg_args)
else:
raise exception.NetAppException(msg % msg_args)
@@ -1674,7 +1669,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
try:
self.send_request('export-rule-destroy', api_args)
except netapp_api.NaApiError as e:
- if e.code != netapp_error.EOBJECTNOTFOUND:
+ if e.code != netapp_api.EOBJECTNOTFOUND:
raise
@na_utils.trace
@@ -1744,7 +1739,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
try:
self.send_request('export-policy-create', api_args)
except netapp_api.NaApiError as e:
- if e.code != netapp_error.EDUPLICATEENTRY:
+ if e.code != netapp_api.EDUPLICATEENTRY:
raise
@na_utils.trace
@@ -1763,7 +1758,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
try:
self.send_request('export-policy-destroy', api_args)
except netapp_api.NaApiError as e:
- if e.code == netapp_error.EOBJECTNOTFOUND:
+ if e.code == netapp_api.EOBJECTNOTFOUND:
return
raise
@@ -1932,7 +1927,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
# API succeeded, so definitely a cluster management LIF
return True
except netapp_api.NaApiError as e:
- if e.code == netapp_error.EAPINOTFOUND:
+ if e.code == netapp_api.EAPINOTFOUND:
LOG.debug('Not connected to cluster management LIF.')
return False
else:
diff --git a/manila/share/drivers/netapp/dataontap/protocols/cifs_cmode.py b/manila/share/drivers/netapp/dataontap/protocols/cifs_cmode.py
index 8f4b8e6a9e..9f022d44de 100644
--- a/manila/share/drivers/netapp/dataontap/protocols/cifs_cmode.py
+++ b/manila/share/drivers/netapp/dataontap/protocols/cifs_cmode.py
@@ -18,17 +18,13 @@ NetApp CIFS protocol helper class.
import re
from oslo_log import log
-from oslo_utils import importutils
from manila import exception
from manila.i18n import _, _LE
+from manila.share.drivers.netapp.dataontap.client import api as netapp_api
from manila.share.drivers.netapp.dataontap.protocols import base
from manila.share.drivers.netapp import utils as na_utils
-netapp_lib = importutils.try_import('netapp_lib')
-if netapp_lib:
- from netapp_lib.api.zapi import errors as netapp_error
- from netapp_lib.api.zapi import zapi as netapp_api
LOG = log.getLogger(__name__)
@@ -62,7 +58,7 @@ class NetAppCmodeCIFSHelper(base.NetAppBaseHelper):
try:
self._client.add_cifs_share_access(share_name, access['access_to'])
except netapp_api.NaApiError as e:
- if e.code == netapp_error.EDUPLICATEENTRY:
+ if e.code == netapp_api.EDUPLICATEENTRY:
# Duplicate entry, so use specific exception.
raise exception.ShareAccessExists(
access_type=access['access_type'], access=access)
@@ -76,9 +72,9 @@ class NetAppCmodeCIFSHelper(base.NetAppBaseHelper):
try:
self._client.remove_cifs_share_access(share_name, user_name)
except netapp_api.NaApiError as e:
- if e.code == netapp_error.EONTAPI_EINVAL:
+ if e.code == netapp_api.EONTAPI_EINVAL:
LOG.error(_LE("User %s does not exist."), user_name)
- elif e.code == netapp_error.EOBJECTNOTFOUND:
+ elif e.code == netapp_api.EOBJECTNOTFOUND:
LOG.error(_LE("Rule %s does not exist."), user_name)
else:
raise e
diff --git a/manila/share/drivers/netapp/utils.py b/manila/share/drivers/netapp/utils.py
index 95022eb14d..90bc30aa0c 100644
--- a/manila/share/drivers/netapp/utils.py
+++ b/manila/share/drivers/netapp/utils.py
@@ -21,7 +21,6 @@ import platform
from oslo_concurrency import processutils as putils
from oslo_log import log
-from oslo_utils import importutils
import six
from manila import exception
@@ -103,14 +102,6 @@ def convert_to_list(value):
return [value]
-def check_netapp_lib():
- if not importutils.try_import('netapp_lib'):
- msg = ('You have not installed the NetApp API Library for OpenStack. '
- 'Please install it using "sudo pip install netapp-lib" and '
- 'restart this service!')
- raise exception.NetAppException(msg)
-
-
class OpenStackInfo(object):
"""OS/distribution, release, and version.
diff --git a/manila/tests/share/drivers/netapp/dataontap/client/fake_api.py b/manila/tests/share/drivers/netapp/dataontap/client/fake_api.py
deleted file mode 100644
index 4576452e9d..0000000000
--- a/manila/tests/share/drivers/netapp/dataontap/client/fake_api.py
+++ /dev/null
@@ -1,232 +0,0 @@
-# Copyright (c) 2015 Clinton Knight. 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 sys
-
-from lxml import etree
-import mock
-import six
-
-from manila import exception
-
-
-EONTAPI_EINVAL = '22'
-EAPIERROR = '13001'
-EAPINOTFOUND = '13005'
-ESNAPSHOTNOTALLOWED = '13023'
-EVOLUMEOFFLINE = '13042'
-EINTERNALERROR = '13114'
-EDUPLICATEENTRY = '13130'
-EVOLNOTCLONE = '13170'
-EVOL_NOT_MOUNTED = '14716'
-ESIS_CLONE_NOT_LICENSED = '14956'
-EOBJECTNOTFOUND = '15661'
-E_VIFMGR_PORT_ALREADY_ASSIGNED_TO_BROADCAST_DOMAIN = '18605'
-
-
-def mock_netapp_lib(modules):
- """Inject fake netapp_lib module classes."""
-
- netapp_lib = mock.Mock()
- netapp_lib.api.zapi.zapi.NaElement = NaElement
- netapp_lib.api.zapi.zapi.NaApiError = NaApiError
- netapp_lib.api.zapi.zapi.NaServer = mock.Mock()
- netapp_lib.api.zapi.errors = sys.modules[__name__]
- for module in modules:
- setattr(module, 'netapp_api', netapp_lib.api.zapi.zapi)
- setattr(module, 'netapp_error', netapp_lib.api.zapi.errors)
-
-
-class NaApiError(exception.ManilaException):
- """Fake NetApi API invocation error."""
-
- def __init__(self, code=None, message=None):
- if not code:
- code = 'unknown'
- if not message:
- message = 'unknown'
- self.code = code
- self.message = message
- super(NaApiError, self).__init__(message=message)
-
-
-class NaElement(object):
- """Fake XML wrapper class for NetApp API."""
-
- def __init__(self, name):
- """Name of the element or etree.Element."""
- if isinstance(name, etree._Element):
- self._element = name
- else:
- self._element = etree.Element(name)
-
- def get_name(self):
- """Returns the tag name of the element."""
- return self._element.tag
-
- def set_content(self, text):
- """Set the text string for the element."""
- self._element.text = text
-
- def get_content(self):
- """Get the text for the element."""
- return self._element.text
-
- def add_attr(self, name, value):
- """Add the attribute to the element."""
- self._element.set(name, value)
-
- def add_attrs(self, **attrs):
- """Add multiple attributes to the element."""
- for attr in attrs.keys():
- self._element.set(attr, attrs.get(attr))
-
- def add_child_elem(self, na_element):
- """Add the child element to the element."""
- if isinstance(na_element, NaElement):
- self._element.append(na_element._element)
- return
- raise
-
- def get_child_by_name(self, name):
- """Get the child element by the tag name."""
- for child in self._element.iterchildren():
- if child.tag == name or etree.QName(child.tag).localname == name:
- return NaElement(child)
- return None
-
- def get_child_content(self, name):
- """Get the content of the child."""
- for child in self._element.iterchildren():
- if child.tag == name or etree.QName(child.tag).localname == name:
- return child.text
- return None
-
- def get_children(self):
- """Get the children for the element."""
- return [NaElement(el) for el in self._element.iterchildren()]
-
- def has_attr(self, name):
- """Checks whether element has attribute."""
- attributes = self._element.attrib or {}
- return name in attributes.keys()
-
- def get_attr(self, name):
- """Get the attribute with the given name."""
- attributes = self._element.attrib or {}
- return attributes.get(name)
-
- def get_attr_names(self):
- """Returns the list of attribute names."""
- attributes = self._element.attrib or {}
- return attributes.keys()
-
- def add_new_child(self, name, content, convert=False):
- """Add child with tag name and context.
-
- Convert replaces entity refs to chars.
- """
- child = NaElement(name)
- if convert:
- content = NaElement._convert_entity_refs(content)
- child.set_content(content)
- self.add_child_elem(child)
-
- @staticmethod
- def _convert_entity_refs(text):
- """Converts entity refs to chars to handle etree auto conversions."""
- text = text.replace("<", "<")
- text = text.replace(">", ">")
- return text
-
- @staticmethod
- def create_node_with_children(node, **children):
- """Creates and returns named node with children."""
- parent = NaElement(node)
- for child in children.keys():
- parent.add_new_child(child, children.get(child, None))
- return parent
-
- def add_node_with_children(self, node, **children):
- """Creates named node with children."""
- parent = NaElement.create_node_with_children(node, **children)
- self.add_child_elem(parent)
-
- def to_string(self, pretty=False, method='xml', encoding='UTF-8'):
- """Prints the element to string."""
- return etree.tostring(self._element, method=method, encoding=encoding,
- pretty_print=pretty)
-
- def __getitem__(self, key):
- """Dict getter method for NaElement.
-
- Returns NaElement list if present,
- text value in case no NaElement node
- children or attribute value if present.
- """
-
- child = self.get_child_by_name(key)
- if child:
- if child.get_children():
- return child
- else:
- return child.get_content()
- elif self.has_attr(key):
- return self.get_attr(key)
- raise KeyError('No element by given name %s.' % key)
-
- def __setitem__(self, key, value):
- """Dict setter method for NaElement.
-
- Accepts dict, list, tuple, str, int, float and long as valid value.
- """
- if key:
- if value:
- if isinstance(value, NaElement):
- child = NaElement(key)
- child.add_child_elem(value)
- self.add_child_elem(child)
- elif isinstance(value, (str, int, float, long)):
- self.add_new_child(key, six.text_type(value))
- elif isinstance(value, (list, tuple, dict)):
- child = NaElement(key)
- child.translate_struct(value)
- self.add_child_elem(child)
- else:
- raise TypeError('Not a valid value for NaElement.')
- else:
- self.add_child_elem(NaElement(key))
- else:
- raise KeyError('NaElement name cannot be null.')
-
- def translate_struct(self, data_struct):
- """Convert list, tuple, dict to NaElement and appends."""
-
- if isinstance(data_struct, (list, tuple)):
- for el in data_struct:
- if isinstance(el, (list, tuple, dict)):
- self.translate_struct(el)
- else:
- self.add_child_elem(NaElement(el))
- elif isinstance(data_struct, dict):
- for k in data_struct.keys():
- child = NaElement(k)
- if isinstance(data_struct[k], (dict, list, tuple)):
- child.translate_struct(data_struct[k])
- else:
- if data_struct[k]:
- child.set_content(six.text_type(data_struct[k]))
- self.add_child_elem(child)
- else:
- raise ValueError('Type cannot be converted into NaElement.')
diff --git a/manila/tests/share/drivers/netapp/dataontap/client/test_api.py b/manila/tests/share/drivers/netapp/dataontap/client/test_api.py
new file mode 100644
index 0000000000..1051e79cdc
--- /dev/null
+++ b/manila/tests/share/drivers/netapp/dataontap/client/test_api.py
@@ -0,0 +1,156 @@
+# Copyright (c) 2014 Ben Swartzlander. All rights reserved.
+# Copyright (c) 2014 Navneet Singh. All rights reserved.
+# Copyright (c) 2014 Clinton Knight. All rights reserved.
+# Copyright (c) 2014 Alex Meade. All rights reserved.
+# Copyright (c) 2014 Bob Callaway. 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.
+"""
+Tests for NetApp API layer
+"""
+
+from manila.share.drivers.netapp.dataontap.client import api
+from manila import test
+
+
+class NetAppApiElementTransTests(test.TestCase):
+ """Test case for NetApp API element translations."""
+
+ def test_translate_struct_dict_unique_key(self):
+ """Tests if dict gets properly converted to NaElements."""
+ root = api.NaElement('root')
+ child = {'e1': 'v1', 'e2': 'v2', 'e3': 'v3'}
+
+ root.translate_struct(child)
+
+ self.assertEqual(3, len(root.get_children()))
+ for key, value in child.items():
+ self.assertEqual(value, root.get_child_content(key))
+
+ def test_translate_struct_dict_nonunique_key(self):
+ """Tests if list/dict gets properly converted to NaElements."""
+ root = api.NaElement('root')
+ child = [{'e1': 'v1', 'e2': 'v2'}, {'e1': 'v3'}]
+
+ root.translate_struct(child)
+
+ children = root.get_children()
+ self.assertEqual(3, len(children))
+ for c in children:
+ if c.get_name() == 'e1':
+ self.assertIn(c.get_content(), ['v1', 'v3'])
+ else:
+ self.assertEqual('v2', c.get_content())
+
+ def test_translate_struct_list(self):
+ """Tests if list gets properly converted to NaElements."""
+ root = api.NaElement('root')
+ child = ['e1', 'e2']
+
+ root.translate_struct(child)
+
+ self.assertEqual(2, len(root.get_children()))
+ self.assertIsNone(root.get_child_content('e1'))
+ self.assertIsNone(root.get_child_content('e2'))
+
+ def test_translate_struct_tuple(self):
+ """Tests if tuple gets properly converted to NaElements."""
+ root = api.NaElement('root')
+ child = ('e1', 'e2')
+
+ root.translate_struct(child)
+
+ self.assertEqual(2, len(root.get_children()))
+ self.assertIsNone(root.get_child_content('e1'))
+ self.assertIsNone(root.get_child_content('e2'))
+
+ def test_translate_invalid_struct(self):
+ """Tests if invalid data structure raises exception."""
+ root = api.NaElement('root')
+ child = 'random child element'
+ self.assertRaises(ValueError, root.translate_struct, child)
+
+ def test_setter_builtin_types(self):
+ """Tests str, int, float get converted to NaElement."""
+ update = dict(e1='v1', e2='1', e3='2.0', e4='8')
+ root = api.NaElement('root')
+
+ for key, value in update.items():
+ root[key] = value
+
+ for key, value in update.items():
+ self.assertEqual(value, root.get_child_content(key))
+
+ def test_setter_na_element(self):
+ """Tests na_element gets appended as child."""
+ root = api.NaElement('root')
+ root['e1'] = api.NaElement('nested')
+ self.assertEqual(1, len(root.get_children()))
+ e1 = root.get_child_by_name('e1')
+ self.assertIsInstance(e1, api.NaElement)
+ self.assertIsInstance(e1.get_child_by_name('nested'), api.NaElement)
+
+ def test_setter_child_dict(self):
+ """Tests dict is appended as child to root."""
+ root = api.NaElement('root')
+ root['d'] = {'e1': 'v1', 'e2': 'v2'}
+ e1 = root.get_child_by_name('d')
+ self.assertIsInstance(e1, api.NaElement)
+ sub_ch = e1.get_children()
+ self.assertEqual(2, len(sub_ch))
+ for c in sub_ch:
+ self.assertIn(c.get_name(), ['e1', 'e2'])
+ if c.get_name() == 'e1':
+ self.assertEqual('v1', c.get_content())
+ else:
+ self.assertEqual('v2', c.get_content())
+
+ def test_setter_child_list_tuple(self):
+ """Tests list/tuple are appended as child to root."""
+ root = api.NaElement('root')
+
+ root['l'] = ['l1', 'l2']
+ root['t'] = ('t1', 't2')
+
+ l = root.get_child_by_name('l')
+ self.assertIsInstance(l, api.NaElement)
+ t = root.get_child_by_name('t')
+ self.assertIsInstance(t, api.NaElement)
+
+ self.assertEqual(2, len(l.get_children()))
+ for le in l.get_children():
+ self.assertIn(le.get_name(), ['l1', 'l2'])
+
+ self.assertEqual(2, len(t.get_children()))
+ for te in t.get_children():
+ self.assertIn(te.get_name(), ['t1', 't2'])
+
+ def test_setter_no_value(self):
+ """Tests key with None value."""
+ root = api.NaElement('root')
+ root['k'] = None
+ self.assertIsNone(root.get_child_content('k'))
+
+ def test_setter_invalid_value(self):
+ """Tests invalid value raises exception."""
+ self.assertRaises(TypeError,
+ api.NaElement('root').__setitem__,
+ 'k',
+ api.NaServer('localhost'))
+
+ def test_setter_invalid_key(self):
+ """Tests invalid value raises exception."""
+ self.assertRaises(KeyError,
+ api.NaElement('root').__setitem__,
+ None,
+ 'value')
diff --git a/manila/tests/share/drivers/netapp/dataontap/client/test_client_base.py b/manila/tests/share/drivers/netapp/dataontap/client/test_client_base.py
index 9be521bcee..3ed8fbc9e6 100644
--- a/manila/tests/share/drivers/netapp/dataontap/client/test_client_base.py
+++ b/manila/tests/share/drivers/netapp/dataontap/client/test_client_base.py
@@ -17,10 +17,9 @@ import ddt
import mock
from oslo_log import log
+from manila.share.drivers.netapp.dataontap.client import api as netapp_api
from manila.share.drivers.netapp.dataontap.client import client_base
from manila import test
-from manila.tests.share.drivers.netapp.dataontap.client import fake_api \
- as netapp_api
from manila.tests.share.drivers.netapp.dataontap.client import fakes as fake
@@ -35,9 +34,6 @@ class NetAppBaseClientTestCase(test.TestCase):
'error',
mock.Mock(side_effect=mock_logger.error))
- # Inject fake netapp_lib module classes.
- netapp_api.mock_netapp_lib([client_base])
-
self.client = client_base.NetAppBaseClient(**fake.CONNECTION_INFO)
self.client.connection = mock.MagicMock()
self.connection = self.client.connection
diff --git a/manila/tests/share/drivers/netapp/dataontap/client/test_client_cmode.py b/manila/tests/share/drivers/netapp/dataontap/client/test_client_cmode.py
index db0984704b..cea0d27a10 100644
--- a/manila/tests/share/drivers/netapp/dataontap/client/test_client_cmode.py
+++ b/manila/tests/share/drivers/netapp/dataontap/client/test_client_cmode.py
@@ -24,11 +24,10 @@ from oslo_log import log
import six
from manila import exception
+from manila.share.drivers.netapp.dataontap.client import api as netapp_api
from manila.share.drivers.netapp.dataontap.client import client_base
from manila.share.drivers.netapp.dataontap.client import client_cmode
from manila import test
-from manila.tests.share.drivers.netapp.dataontap.client import fake_api \
- as netapp_api
from manila.tests.share.drivers.netapp.dataontap.client import fakes as fake
@@ -54,9 +53,6 @@ class NetAppClientCmodeTestCase(test.TestCase):
'get_ontapi_version',
mock.Mock(return_value=(1, 20)))
- # Inject fake netapp_lib module classes.
- netapp_api.mock_netapp_lib([client_base, client_cmode])
-
self.client = client_cmode.NetAppCmodeClient(**fake.CONNECTION_INFO)
self.client.connection = mock.MagicMock()
diff --git a/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_multi_svm.py b/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_multi_svm.py
index 705d1a9c13..4b664f86f7 100644
--- a/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_multi_svm.py
+++ b/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_multi_svm.py
@@ -23,12 +23,11 @@ from oslo_log import log
from manila import context
from manila import exception
+from manila.share.drivers.netapp.dataontap.client import api as netapp_api
from manila.share.drivers.netapp.dataontap.cluster_mode import lib_base
from manila.share.drivers.netapp.dataontap.cluster_mode import lib_multi_svm
from manila.share.drivers.netapp import utils as na_utils
from manila import test
-from manila.tests.share.drivers.netapp.dataontap.client \
- import fake_api as netapp_api
from manila.tests.share.drivers.netapp.dataontap import fakes as fake
@@ -55,9 +54,6 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
'app_version': fake.APP_VERSION
}
- # Inject fake netapp_lib module classes.
- netapp_api.mock_netapp_lib([lib_multi_svm])
-
self.library = lib_multi_svm.NetAppCmodeMultiSVMFileStorageLibrary(
fake.DRIVER_NAME, **kwargs)
self.library._client = mock.Mock()
diff --git a/manila/tests/share/drivers/netapp/dataontap/protocols/test_cifs_cmode.py b/manila/tests/share/drivers/netapp/dataontap/protocols/test_cifs_cmode.py
index 26fb731b18..84eadba298 100644
--- a/manila/tests/share/drivers/netapp/dataontap/protocols/test_cifs_cmode.py
+++ b/manila/tests/share/drivers/netapp/dataontap/protocols/test_cifs_cmode.py
@@ -20,10 +20,9 @@ import mock
from oslo_log import log
from manila import exception
+from manila.share.drivers.netapp.dataontap.client import api as netapp_api
from manila.share.drivers.netapp.dataontap.protocols import cifs_cmode
from manila import test
-from manila.tests.share.drivers.netapp.dataontap.client \
- import fake_api as netapp_api
from manila.tests.share.drivers.netapp.dataontap.protocols \
import fakes as fake
@@ -42,9 +41,6 @@ class NetAppClusteredCIFSHelperTestCase(test.TestCase):
self.mock_context = mock.Mock()
- # Inject fake netapp_lib module classes.
- netapp_api.mock_netapp_lib([cifs_cmode])
-
self.mock_client = mock.Mock()
self.helper = cifs_cmode.NetAppCmodeCIFSHelper()
self.helper.set_client(self.mock_client)
diff --git a/manila/tests/share/drivers/netapp/test_common.py b/manila/tests/share/drivers/netapp/test_common.py
index 8cf0cf0f77..ce250e4f69 100644
--- a/manila/tests/share/drivers/netapp/test_common.py
+++ b/manila/tests/share/drivers/netapp/test_common.py
@@ -37,8 +37,6 @@ class NetAppDriverFactoryTestCase(test.TestCase):
mock.Mock(return_value='fake_mode'))
mock_create_driver = self.mock_object(na_common.NetAppDriver,
'_create_driver')
- mock_check_netapp_lib = self.mock_object(na_utils,
- 'check_netapp_lib')
config = na_fakes.create_configuration()
config.netapp_storage_family = 'fake_family'
@@ -51,7 +49,6 @@ class NetAppDriverFactoryTestCase(test.TestCase):
mock_get_driver_mode.assert_called_once_with('fake_family', True)
mock_create_driver.assert_called_once_with('fake_family', 'fake_mode',
*(), **kwargs)
- mock_check_netapp_lib.assert_called_once_with()
def test_new_missing_config(self):
diff --git a/manila/tests/share/drivers/netapp/test_utils.py b/manila/tests/share/drivers/netapp/test_utils.py
index dba8491d1b..03c812d829 100644
--- a/manila/tests/share/drivers/netapp/test_utils.py
+++ b/manila/tests/share/drivers/netapp/test_utils.py
@@ -21,7 +21,6 @@ import platform
import mock
from oslo_concurrency import processutils as putils
from oslo_log import log
-from oslo_utils import importutils
from manila import exception
from manila.share.drivers.netapp import utils as na_utils
@@ -131,21 +130,6 @@ class NetAppDriverUtilsTestCase(test.TestCase):
sorted(na_utils.convert_to_list({'key1': 'value1',
'key2': 'value2'})))
- def test_check_netapp_lib(self):
- mock_try_import = self.mock_object(importutils, 'try_import')
-
- na_utils.check_netapp_lib()
-
- mock_try_import.assert_called_once_with('netapp_lib')
-
- def test_check_netapp_lib_not_found(self):
- self.mock_object(importutils,
- 'try_import',
- mock.Mock(return_value=None))
-
- self.assertRaises(exception.NetAppException,
- na_utils.check_netapp_lib)
-
class OpenstackInfoTestCase(test.TestCase):