Merge "Dell PowerScale: Rename Isilon to PowerScale in Manila Driver"
This commit is contained in:
1
doc/source/_extra/.htaccess
Normal file
1
doc/source/_extra/.htaccess
Normal file
@@ -0,0 +1 @@
|
|||||||
|
RedirectMatch 301 ^/drivers/emc-isilon-driver.html$ /drivers/dell-emc-powerscale-driver.html
|
@@ -14,31 +14,31 @@
|
|||||||
License for the specific language governing permissions and limitations
|
License for the specific language governing permissions and limitations
|
||||||
under the License.
|
under the License.
|
||||||
|
|
||||||
Isilon Driver
|
PowerScale Driver
|
||||||
=============
|
=================
|
||||||
|
|
||||||
The EMC manila driver framework (EMCShareDriver) utilizes EMC storage products
|
The EMC manila driver framework (EMCShareDriver) utilizes Dell storage products
|
||||||
to provide shared filesystems to OpenStack. The EMC manila driver is a plugin
|
to provide shared filesystems to OpenStack. The EMC manila driver is a plugin
|
||||||
based driver which is designed to use different plugins to manage different EMC
|
based driver which is designed to use different plugins to manage different
|
||||||
storage products.
|
Dell storage products.
|
||||||
|
|
||||||
The Isilon manila driver is a plugin for the EMC manila driver framework which
|
The PowerScale manila driver is a plugin for the EMC manila driver framework
|
||||||
allows manila to interface with an Isilon backend to provide a shared
|
which allows manila to interface with an PowerScale backend to provide a shared
|
||||||
filesystem. The EMC driver framework with the Isilon plugin is referred to as
|
filesystem. The EMC driver framework with the PowerScale plugin is referred to
|
||||||
the "Isilon Driver" in this document.
|
as the "PowerScale Driver" in this document.
|
||||||
|
|
||||||
This Isilon Driver interfaces with an Isilon cluster via the REST Isilon
|
This PowerScale Driver interfaces with an PowerScale cluster via the REST
|
||||||
Platform API (PAPI) and the RESTful Access to Namespace API (RAN).
|
PowerScale Platform API (PAPI) and the RESTful Access to Namespace API (RAN).
|
||||||
|
|
||||||
Requirements
|
Requirements
|
||||||
------------
|
------------
|
||||||
|
|
||||||
- Isilon cluster running OneFS 7.2 or higher
|
- PowerScale cluster running OneFS 9.10 or higher
|
||||||
|
|
||||||
Supported Operations
|
Supported Operations
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
The following operations are supported on an Isilon cluster:
|
The following operations are supported on an PowerScale cluster:
|
||||||
|
|
||||||
* Create CIFS/NFS Share
|
* Create CIFS/NFS Share
|
||||||
* Delete CIFS/NFS Share
|
* Delete CIFS/NFS Share
|
||||||
@@ -55,24 +55,24 @@ Backend Configuration
|
|||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
The following parameters need to be configured in the manila configuration file
|
The following parameters need to be configured in the manila configuration file
|
||||||
for the Isilon driver:
|
for the PowerScale driver:
|
||||||
|
|
||||||
* share_driver = manila.share.drivers.dell_emc.driver.EMCShareDriver
|
* share_driver = manila.share.drivers.dell_emc.driver.EMCShareDriver
|
||||||
* driver_handles_share_servers = False
|
* driver_handles_share_servers = False
|
||||||
* emc_share_backend = isilon
|
* emc_share_backend = powerscale
|
||||||
* emc_nas_server = <IP address of Isilon cluster>
|
* emc_nas_server = <IP address of PowerScale cluster>
|
||||||
* emc_nas_server_port = <port to use for Isilon cluster (optional)>
|
* emc_nas_server_port = <port to use for PowerScale cluster (optional)>
|
||||||
* emc_nas_login = <username>
|
* emc_nas_login = <username>
|
||||||
* emc_nas_password = <password>
|
* emc_nas_password = <password>
|
||||||
* emc_nas_root_dir = <root directory path to create shares (e.g./ifs/manila)>
|
* emc_nas_root_dir = <root directory path to create shares (e.g./ifs/manila)>
|
||||||
|
|
||||||
Restart of :term:`manila-share` service is needed for the configuration changes to take
|
Restart of :term:`manila-share` service is needed for the configuration changes
|
||||||
effect.
|
to take effect.
|
||||||
|
|
||||||
Restrictions
|
Restrictions
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The Isilon driver has the following restrictions:
|
The PowerScale driver has the following restrictions:
|
||||||
|
|
||||||
- Only IP access type is supported for NFS and CIFS.
|
- Only IP access type is supported for NFS and CIFS.
|
||||||
|
|
||||||
@@ -87,10 +87,10 @@ The :mod:`manila.share.drivers.dell_emc.driver` Module
|
|||||||
:undoc-members:
|
:undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
The :mod:`manila.share.drivers.dell_emc.plugins.isilon.isilon` Module
|
The :mod:`manila.share.drivers.dell_emc.plugins.powerscale.powerscale` Module
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. automodule:: manila.share.drivers.dell_emc.plugins.isilon.isilon
|
.. automodule:: manila.share.drivers.dell_emc.plugins.powerscale.powerscale
|
||||||
:noindex:
|
:noindex:
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
@@ -86,8 +86,8 @@ each back end.
|
|||||||
container_driver
|
container_driver
|
||||||
zfs_on_linux_driver
|
zfs_on_linux_driver
|
||||||
netapp_cluster_mode_driver
|
netapp_cluster_mode_driver
|
||||||
emc_isilon_driver
|
|
||||||
emc_vnx_driver
|
emc_vnx_driver
|
||||||
|
dell_emc_powerscale_driver
|
||||||
../configuration/shared-file-systems/drivers/dell-emc-unity-driver
|
../configuration/shared-file-systems/drivers/dell-emc-unity-driver
|
||||||
../configuration/shared-file-systems/drivers/dell-emc-powerstore-driver
|
../configuration/shared-file-systems/drivers/dell-emc-powerstore-driver
|
||||||
../configuration/shared-file-systems/drivers/dell-emc-powerflex-driver
|
../configuration/shared-file-systems/drivers/dell-emc-powerflex-driver
|
||||||
|
@@ -43,17 +43,17 @@ Mapping of share drivers and share features support
|
|||||||
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
||||||
| NetApp Clustered Data ONTAP | J | L | L | L | J |same pool (J), across back ends (U)| N | O | \- |
|
| NetApp Clustered Data ONTAP | J | L | L | L | J |same pool (J), across back ends (U)| N | O | \- |
|
||||||
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
||||||
| Dell EMC PowerMax | O | \- | O | \- | O | O | \- | \- | \- |
|
| Dell PowerMax | O | \- | O | \- | O | O | \- | \- | \- |
|
||||||
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
||||||
| EMC VNX | J | \- | \- | \- | J | J | \- | \- | \- |
|
| Dell VNX | J | \- | \- | \- | J | J | \- | \- | \- |
|
||||||
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
||||||
| EMC Unity | N | U | N | S | N | N | U | S | \- |
|
| Dell Unity | N | U | N | S | N | N | U | S | \- |
|
||||||
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
||||||
| EMC Isilon | K | \- | M | \- | K | K | \- | \- | \- |
|
| Dell PowerScale | K | \- | M | \- | K | K | \- | \- | \- |
|
||||||
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
||||||
| Dell EMC PowerStore | B | \- | B | B | B | B | \- | B | \- |
|
| Dell PowerStore | B | \- | B | B | B | B | \- | B | \- |
|
||||||
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
||||||
| Dell EMC PowerFlex | B | \- | B | \- | B | \- | \- | \- | \- |
|
| Dell PowerFlex | B | \- | B | \- | B | \- | \- | \- | \- |
|
||||||
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
||||||
| GlusterFS | J | \- | directory layout (T) | directory layout (T) | volume layout (L) | volume layout (L) | \- | \- | \- |
|
| GlusterFS | J | \- | directory layout (T) | directory layout (T) | volume layout (L) | volume layout (L) | \- | \- | \- |
|
||||||
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
+----------------------------------------+-----------------------+-----------------------+--------------------------+--------------------------+------------------------+-----------------------------------+--------------------------+--------------------+--------------------+
|
||||||
@@ -122,17 +122,17 @@ Mapping of share drivers and share access rules support
|
|||||||
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
||||||
| NetApp Clustered Data ONTAP | NFS (J) | NFS (Q) | CIFS (J) | \- | \- | NFS (K) | NFS (Q) | CIFS (M) | \- | \- |
|
| NetApp Clustered Data ONTAP | NFS (J) | NFS (Q) | CIFS (J) | \- | \- | NFS (K) | NFS (Q) | CIFS (M) | \- | \- |
|
||||||
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
||||||
| Dell EMC PowerMax | NFS (O) | NFS (R) | CIFS (O) | \- | \- | NFS (O) | NFS (R) | CIFS (O) | \- | \- |
|
| Dell PowerMax | NFS (O) | NFS (R) | CIFS (O) | \- | \- | NFS (O) | NFS (R) | CIFS (O) | \- | \- |
|
||||||
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
||||||
| EMC VNX | NFS (J) | NFS (Q) | CIFS (J) | \- | \- | NFS (L) | NFS (Q) | CIFS (L) | \- | \- |
|
| Dell VNX | NFS (J) | NFS (Q) | CIFS (J) | \- | \- | NFS (L) | NFS (Q) | CIFS (L) | \- | \- |
|
||||||
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
||||||
| EMC Unity | NFS (N) | NFS (Q) | CIFS (N) | \- | \- | NFS (N) | NFS (Q) | CIFS (N) | \- | \- |
|
| Dell Unity | NFS (N) | NFS (Q) | CIFS (N) | \- | \- | NFS (N) | NFS (Q) | CIFS (N) | \- | \- |
|
||||||
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
||||||
| EMC Isilon | NFS,CIFS (K) | NFS (F) | CIFS (M) | \- | \- | NFS (M) | \- | CIFS (M) | \- | \- |
|
| Dell PowerScale | NFS,CIFS (K) | \- | CIFS (M) | \- | \- | NFS (M) | \- | CIFS (M) | \- | \- |
|
||||||
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
||||||
| Dell EMC PowerStore | NFS (B) | \- | CIFS (B) | \- | \- | NFS (B) | \- | CIFS (B) | \- | \- |
|
| Dell PowerStore | NFS (B) | \- | CIFS (B) | \- | \- | NFS (B) | \- | CIFS (B) | \- | \- |
|
||||||
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
||||||
| Dell EMC PowerFlex | NFS (B) | \- | \- | \- | \- | NFS (B) | \- | \- | \- | \- |
|
| Dell PowerFlex | NFS (B) | \- | \- | \- | \- | NFS (B) | \- | \- | \- | \- |
|
||||||
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
||||||
| GlusterFS | NFS (J) | \- | \- | \- | \- | \- | \- | \- | \- | \- |
|
| GlusterFS | NFS (J) | \- | \- | \- | \- | \- | \- | \- | \- | \- |
|
||||||
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
+----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+
|
||||||
@@ -199,17 +199,17 @@ Mapping of share drivers and security services support
|
|||||||
+----------------------------------------+------------------+-----------------+------------------+
|
+----------------------------------------+------------------+-----------------+------------------+
|
||||||
| NetApp Clustered Data ONTAP | J | J | J |
|
| NetApp Clustered Data ONTAP | J | J | J |
|
||||||
+----------------------------------------+------------------+-----------------+------------------+
|
+----------------------------------------+------------------+-----------------+------------------+
|
||||||
| Dell EMC PowerMax | O | \- | \- |
|
| Dell PowerMax | O | \- | \- |
|
||||||
+----------------------------------------+------------------+-----------------+------------------+
|
+----------------------------------------+------------------+-----------------+------------------+
|
||||||
| EMC VNX | J | \- | \- |
|
| Dell VNX | J | \- | \- |
|
||||||
+----------------------------------------+------------------+-----------------+------------------+
|
+----------------------------------------+------------------+-----------------+------------------+
|
||||||
| EMC Unity | N | \- | \- |
|
| Dell Unity | N | \- | \- |
|
||||||
+----------------------------------------+------------------+-----------------+------------------+
|
+----------------------------------------+------------------+-----------------+------------------+
|
||||||
| EMC Isilon | \- | \- | \- |
|
| EMC PowerScale | \- | \- | \- |
|
||||||
+----------------------------------------+------------------+-----------------+------------------+
|
+----------------------------------------+------------------+-----------------+------------------+
|
||||||
| Dell EMC PowerStore | B | \- | \- |
|
| Dell PowerStore | B | \- | \- |
|
||||||
+----------------------------------------+------------------+-----------------+------------------+
|
+----------------------------------------+------------------+-----------------+------------------+
|
||||||
| Dell EMC PowerFlex | \- | \- | \- |
|
| Dell PowerFlex | \- | \- | \- |
|
||||||
+----------------------------------------+------------------+-----------------+------------------+
|
+----------------------------------------+------------------+-----------------+------------------+
|
||||||
| GlusterFS | \- | \- | \- |
|
| GlusterFS | \- | \- | \- |
|
||||||
+----------------------------------------+------------------+-----------------+------------------+
|
+----------------------------------------+------------------+-----------------+------------------+
|
||||||
@@ -278,17 +278,17 @@ More information: :ref:`capabilities_and_extra_specs`
|
|||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| NetApp Clustered Data ONTAP | J | K | M | M | M | L | P | J | O | \- | P | Q | \- | Y |
|
| NetApp Clustered Data ONTAP | J | K | M | M | M | L | P | J | O | \- | P | Q | \- | Y |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Dell EMC PowerMax | O | \- | \- | \- | \- | \- | \- | O | \- | \- | P | R | \- | \- |
|
| Dell PowerMax | O | \- | \- | \- | \- | \- | \- | O | \- | \- | P | R | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| EMC VNX | J | \- | \- | \- | \- | L | \- | J | \- | \- | P | Q | \- | \- |
|
| Dell VNX | J | \- | \- | \- | \- | L | \- | J | \- | \- | P | Q | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| EMC Unity | N | T | \- | \- | N | \- | \- | N | S | \- | P | Q | \- | \- |
|
| Dell Unity | N | T | \- | \- | N | \- | \- | N | S | \- | P | Q | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| EMC Isilon | \- | K | \- | \- | F | \- | \- | K | \- | \- | P | \- | \- | \- |
|
| Dell PowerScale | \- | K | \- | \- | \- | L | \- | K | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Dell EMC PowerStore | \- | B | \- | \- | B | \- | \- | B | B | \- | B | \- | \- | \- |
|
| Dell PowerStore | \- | B | \- | \- | B | \- | \- | B | B | \- | B | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Dell EMC PowerFlex | \- | B | \- | \- | B | \- | \- | \- | \- | \- | B | \- | \- | \- |
|
| Dell PowerFlex | \- | B | \- | \- | B | \- | \- | \- | \- | \- | B | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| GlusterFS | \- | J | \- | \- | \- | L | \- | volume layout (L) | \- | \- | P | \- | \- | \- |
|
| GlusterFS | \- | J | \- | \- | \- | L | \- | volume layout (L) | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
|
@@ -87,7 +87,6 @@ master_doc = 'index'
|
|||||||
# General information about the project.
|
# General information about the project.
|
||||||
copyright = '2010-present, Manila contributors'
|
copyright = '2010-present, Manila contributors'
|
||||||
|
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
# language = None
|
# language = None
|
||||||
@@ -175,6 +174,9 @@ html_theme_options = {
|
|||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
# html_static_path = ['_static']
|
# html_static_path = ['_static']
|
||||||
|
|
||||||
|
# Add any paths that contain "extra" files, such as .htaccess.
|
||||||
|
html_extra_path = ['_extra']
|
||||||
|
|
||||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||||
# using the given strftime format.
|
# using the given strftime format.
|
||||||
# html_last_updated_fmt = '%b %d, %Y'
|
# html_last_updated_fmt = '%b %d, %Y'
|
||||||
@@ -213,7 +215,6 @@ html_theme_options = {
|
|||||||
# Output file base name for HTML help builder.
|
# Output file base name for HTML help builder.
|
||||||
htmlhelp_basename = 'maniladoc'
|
htmlhelp_basename = 'maniladoc'
|
||||||
|
|
||||||
|
|
||||||
# -- Options for LaTeX output -------------------------------------------------
|
# -- Options for LaTeX output -------------------------------------------------
|
||||||
|
|
||||||
# The paper size ('letter' or 'a4').
|
# The paper size ('letter' or 'a4').
|
||||||
|
@@ -23,7 +23,7 @@ Share drivers
|
|||||||
drivers/lvm-driver.rst
|
drivers/lvm-driver.rst
|
||||||
drivers/zfs-on-linux-driver.rst
|
drivers/zfs-on-linux-driver.rst
|
||||||
drivers/zfssa-manila-driver.rst
|
drivers/zfssa-manila-driver.rst
|
||||||
drivers/emc-isilon-driver.rst
|
drivers/dell-emc-powerscale-driver.rst
|
||||||
drivers/hitachi-hnas-driver.rst
|
drivers/hitachi-hnas-driver.rst
|
||||||
drivers/hitachi-hsp-driver.rst
|
drivers/hitachi-hsp-driver.rst
|
||||||
drivers/hpe-3par-share-driver.rst
|
drivers/hpe-3par-share-driver.rst
|
||||||
|
@@ -276,7 +276,7 @@ The following parameters need to be configured in the
|
|||||||
|
|
||||||
- `emc_share_backend`
|
- `emc_share_backend`
|
||||||
The plug-in name. Set it to ``powermax`` for the PowerMax driver.
|
The plug-in name. Set it to ``powermax`` for the PowerMax driver.
|
||||||
Other values are ``isilon``, ``vnx`` and ``unity``.
|
Other values are ``powerscale``, ``vnx`` and ``unity``.
|
||||||
|
|
||||||
- `emc_nas_server`
|
- `emc_nas_server`
|
||||||
The control station IP address of the PowerMax system to be managed.
|
The control station IP address of the PowerMax system to be managed.
|
||||||
|
@@ -1,18 +1,19 @@
|
|||||||
=================
|
======================
|
||||||
EMC Isilon driver
|
Dell PowerScale driver
|
||||||
=================
|
======================
|
||||||
|
|
||||||
The EMC Shared File Systems driver framework (EMCShareDriver) utilizes
|
The EMC Shared File Systems driver framework (EMCShareDriver) utilizes
|
||||||
EMC storage products to provide shared file systems to OpenStack. The
|
Dell storage products to provide shared file systems to OpenStack. The
|
||||||
EMC driver is a plug-in based driver which is designed to use different
|
EMC driver is a plug-in based driver which is designed to use different
|
||||||
plug-ins to manage different EMC storage products.
|
plug-ins to manage different Dell storage products.
|
||||||
|
|
||||||
The Isilon driver is a plug-in for the EMC framework which allows the
|
The PowerScale driver is a plug-in for the EMC framework which allows the
|
||||||
Shared File Systems service to interface with an Isilon back end to
|
Shared File Systems service to interface with an PowerScale back end to
|
||||||
provide a shared filesystem. The EMC driver framework with the Isilon
|
provide a shared filesystem. The EMC driver framework with the PowerScale
|
||||||
plug-in is referred to as the ``Isilon Driver`` in this document.
|
plug-in is referred to as the ``PowerScale Driver`` in this document.
|
||||||
|
|
||||||
This Isilon Driver interfaces with an Isilon cluster via the REST Isilon
|
This PowerScale Driver interfaces with an PowerScale cluster via the REST
|
||||||
|
PowerScale
|
||||||
Platform API (PAPI) and the RESTful Access to Namespace API (RAN).
|
Platform API (PAPI) and the RESTful Access to Namespace API (RAN).
|
||||||
|
|
||||||
Requirements
|
Requirements
|
||||||
@@ -52,13 +53,13 @@ Back end configuration
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The following parameters need to be configured in the Shared File
|
The following parameters need to be configured in the Shared File
|
||||||
Systems service configuration file for the Isilon driver:
|
Systems service configuration file for the PowerScale driver:
|
||||||
|
|
||||||
.. code-block:: ini
|
.. code-block:: ini
|
||||||
|
|
||||||
share_driver = manila.share.drivers.emc.driver.EMCShareDriver
|
share_driver = manila.share.drivers.emc.driver.EMCShareDriver
|
||||||
emc_share_backend = isilon
|
emc_share_backend = powerscale
|
||||||
emc_nas_server = <IP address of Isilon cluster>
|
emc_nas_server = <IP address of PowerScale cluster>
|
||||||
emc_nas_login = <username>
|
emc_nas_login = <username>
|
||||||
emc_nas_password = <password>
|
emc_nas_password = <password>
|
||||||
|
|
||||||
@@ -75,7 +76,7 @@ Add the parameter below to set an advisory limit.
|
|||||||
Restrictions
|
Restrictions
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
The Isilon driver has the following restrictions:
|
The PowerScale driver has the following restrictions:
|
||||||
|
|
||||||
- Only IP access type is supported for NFS and CIFS.
|
- Only IP access type is supported for NFS and CIFS.
|
||||||
|
|
@@ -55,8 +55,8 @@ import manila.share.drivers.cephfs.driver
|
|||||||
import manila.share.drivers.container.driver
|
import manila.share.drivers.container.driver
|
||||||
import manila.share.drivers.container.storage_helper
|
import manila.share.drivers.container.storage_helper
|
||||||
import manila.share.drivers.dell_emc.driver
|
import manila.share.drivers.dell_emc.driver
|
||||||
import manila.share.drivers.dell_emc.plugins.isilon.isilon
|
|
||||||
import manila.share.drivers.dell_emc.plugins.powermax.connection
|
import manila.share.drivers.dell_emc.plugins.powermax.connection
|
||||||
|
import manila.share.drivers.dell_emc.plugins.powerscale.powerscale
|
||||||
import manila.share.drivers.generic
|
import manila.share.drivers.generic
|
||||||
import manila.share.drivers.glusterfs
|
import manila.share.drivers.glusterfs
|
||||||
import manila.share.drivers.glusterfs.common
|
import manila.share.drivers.glusterfs.common
|
||||||
@@ -95,7 +95,6 @@ import manila.volume
|
|||||||
import manila.volume.cinder
|
import manila.volume.cinder
|
||||||
import manila.wsgi.eventlet_server
|
import manila.wsgi.eventlet_server
|
||||||
|
|
||||||
|
|
||||||
# List of *all* options in [DEFAULT] namespace of manila.
|
# List of *all* options in [DEFAULT] namespace of manila.
|
||||||
# Any new option list or option needs to be registered here.
|
# Any new option list or option needs to be registered here.
|
||||||
_global_opt_lists = [
|
_global_opt_lists = [
|
||||||
|
@@ -42,7 +42,7 @@ EMC_NAS_OPTS = [
|
|||||||
help='Use secure connection to server.'),
|
help='Use secure connection to server.'),
|
||||||
cfg.StrOpt('emc_share_backend',
|
cfg.StrOpt('emc_share_backend',
|
||||||
ignore_case=True,
|
ignore_case=True,
|
||||||
choices=['isilon', 'vnx', 'unity', 'powermax',
|
choices=['powerscale', 'isilon', 'vnx', 'unity', 'powermax',
|
||||||
'powerstore', 'powerflex'],
|
'powerstore', 'powerflex'],
|
||||||
help='Share backend.'),
|
help='Share backend.'),
|
||||||
cfg.StrOpt('emc_nas_root_dir',
|
cfg.StrOpt('emc_nas_root_dir',
|
||||||
@@ -81,6 +81,11 @@ class EMCShareDriver(driver.ShareDriver):
|
|||||||
if self.backend_name == 'vnx':
|
if self.backend_name == 'vnx':
|
||||||
LOG.warning('Dell EMC VNX share driver has been deprecated and is '
|
LOG.warning('Dell EMC VNX share driver has been deprecated and is '
|
||||||
'expected to be removed in a future release.')
|
'expected to be removed in a future release.')
|
||||||
|
if self.backend_name == 'isilon':
|
||||||
|
self.backend_name = 'powerscale'
|
||||||
|
LOG.warning('Dell EMC isilon share driver has been deprecated and '
|
||||||
|
'is renamed to powerscale.It is expected'
|
||||||
|
'to be removed in a future release.')
|
||||||
self.plugin = self.plugin_manager.load_plugin(
|
self.plugin = self.plugin_manager.load_plugin(
|
||||||
self.backend_name,
|
self.backend_name,
|
||||||
configuration=self.configuration)
|
configuration=self.configuration)
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Isilon specific NAS backend plugin.
|
PowerScale specific NAS backend plugin.
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ from manila.common import constants as const
|
|||||||
from manila import exception
|
from manila import exception
|
||||||
from manila.i18n import _
|
from manila.i18n import _
|
||||||
from manila.share.drivers.dell_emc.plugins import base
|
from manila.share.drivers.dell_emc.plugins import base
|
||||||
from manila.share.drivers.dell_emc.plugins.isilon import isilon_api
|
from manila.share.drivers.dell_emc.plugins.powerscale import powerscale_api
|
||||||
|
|
||||||
"""Version history:
|
"""Version history:
|
||||||
0.1.0 - Initial version
|
0.1.0 - Initial version
|
||||||
@@ -34,8 +34,9 @@ from manila.share.drivers.dell_emc.plugins.isilon import isilon_api
|
|||||||
1.0.1 - Add support for update share stats
|
1.0.1 - Add support for update share stats
|
||||||
1.0.2 - Add support for ensure shares
|
1.0.2 - Add support for ensure shares
|
||||||
1.0.3 - Add support for thin provisioning
|
1.0.3 - Add support for thin provisioning
|
||||||
|
1.0.4 - Rename isilon to powerscale
|
||||||
"""
|
"""
|
||||||
VERSION = "1.0.3"
|
VERSION = "1.0.4"
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
@@ -53,11 +54,11 @@ POWERSCALE_OPTS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class IsilonStorageConnection(base.StorageConnection):
|
class PowerScaleStorageConnection(base.StorageConnection):
|
||||||
"""Implements Isilon specific functionality for EMC Manila driver."""
|
"""Implements PowerScale specific functionality for EMC Manila driver."""
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(IsilonStorageConnection, self).__init__(*args, **kwargs)
|
super(PowerScaleStorageConnection, self).__init__(*args, **kwargs)
|
||||||
LOG.debug('Setting up attributes for Manila '
|
LOG.debug('Setting up attributes for Manila '
|
||||||
'Dell PowerScale Driver.')
|
'Dell PowerScale Driver.')
|
||||||
if 'configuration' in kwargs:
|
if 'configuration' in kwargs:
|
||||||
@@ -75,7 +76,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
self._shares = {}
|
self._shares = {}
|
||||||
self._snapshots = {}
|
self._snapshots = {}
|
||||||
|
|
||||||
self._isilon_api = None
|
self._powerscale_api = None
|
||||||
self.driver_handles_share_servers = False
|
self.driver_handles_share_servers = False
|
||||||
self.ipv6_implemented = True
|
self.ipv6_implemented = True
|
||||||
# props for share status update
|
# props for share status update
|
||||||
@@ -104,7 +105,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
|
|
||||||
# apply directory quota based on share size
|
# apply directory quota based on share size
|
||||||
max_share_size = share['size'] * units.Gi
|
max_share_size = share['size'] * units.Gi
|
||||||
self._isilon_api.quota_create(
|
self._powerscale_api.quota_create(
|
||||||
self._get_container_path(share), 'directory', max_share_size)
|
self._get_container_path(share), 'directory', max_share_size)
|
||||||
|
|
||||||
return location
|
return location
|
||||||
@@ -118,7 +119,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
|
|
||||||
# Clone snapshot to new location
|
# Clone snapshot to new location
|
||||||
fq_target_dir = self._get_container_path(share)
|
fq_target_dir = self._get_container_path(share)
|
||||||
self._isilon_api.clone_snapshot(snapshot['name'], fq_target_dir)
|
self._powerscale_api.clone_snapshot(snapshot['name'], fq_target_dir)
|
||||||
|
|
||||||
return location
|
return location
|
||||||
|
|
||||||
@@ -129,7 +130,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
container_path = self._get_container_path(share)
|
container_path = self._get_container_path(share)
|
||||||
self._create_directory(container_path)
|
self._create_directory(container_path)
|
||||||
# Create nfs share
|
# Create nfs share
|
||||||
share_created = self._isilon_api.create_nfs_export(container_path)
|
share_created = self._powerscale_api.create_nfs_export(container_path)
|
||||||
if not share_created:
|
if not share_created:
|
||||||
message = (
|
message = (
|
||||||
_('The requested NFS share "%(share)s" was not created.') %
|
_('The requested NFS share "%(share)s" was not created.') %
|
||||||
@@ -146,7 +147,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
container_path = self._get_container_path(share)
|
container_path = self._get_container_path(share)
|
||||||
self._create_directory(container_path)
|
self._create_directory(container_path)
|
||||||
# Create smb share
|
# Create smb share
|
||||||
share_created = self._isilon_api.create_smb_share(
|
share_created = self._powerscale_api.create_smb_share(
|
||||||
share['name'], container_path)
|
share['name'], container_path)
|
||||||
if not share_created:
|
if not share_created:
|
||||||
message = (
|
message = (
|
||||||
@@ -159,7 +160,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
|
|
||||||
def _create_directory(self, path, recursive=False):
|
def _create_directory(self, path, recursive=False):
|
||||||
"""Is called to create a directory."""
|
"""Is called to create a directory."""
|
||||||
dir_created = self._isilon_api.create_directory(path, recursive)
|
dir_created = self._powerscale_api.create_directory(path, recursive)
|
||||||
if not dir_created:
|
if not dir_created:
|
||||||
message = (
|
message = (
|
||||||
_('Failed to create directory "%(dir)s".') %
|
_('Failed to create directory "%(dir)s".') %
|
||||||
@@ -171,7 +172,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
"""Is called to create snapshot."""
|
"""Is called to create snapshot."""
|
||||||
LOG.debug(f'Creating snapshot {snapshot["name"]}.')
|
LOG.debug(f'Creating snapshot {snapshot["name"]}.')
|
||||||
snapshot_path = os.path.join(self._root_dir, snapshot['share_name'])
|
snapshot_path = os.path.join(self._root_dir, snapshot['share_name'])
|
||||||
snap_created = self._isilon_api.create_snapshot(
|
snap_created = self._powerscale_api.create_snapshot(
|
||||||
snapshot['name'], snapshot_path)
|
snapshot['name'], snapshot_path)
|
||||||
if not snap_created:
|
if not snap_created:
|
||||||
message = (
|
message = (
|
||||||
@@ -201,10 +202,10 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
|
|
||||||
def _delete_quota(self, path):
|
def _delete_quota(self, path):
|
||||||
"""Is called to remove quota."""
|
"""Is called to remove quota."""
|
||||||
quota = self._isilon_api.quota_get(path, 'directory')
|
quota = self._powerscale_api.quota_get(path, 'directory')
|
||||||
if quota:
|
if quota:
|
||||||
LOG.debug(f'Removing quota {quota["id"]}')
|
LOG.debug(f'Removing quota {quota["id"]}')
|
||||||
deleted = self._isilon_api.delete_quota(quota['id'])
|
deleted = self._powerscale_api.delete_quota(quota['id'])
|
||||||
if not deleted:
|
if not deleted:
|
||||||
message = (
|
message = (
|
||||||
_('Failed to delete quota "%(quota_id)s" for '
|
_('Failed to delete quota "%(quota_id)s" for '
|
||||||
@@ -216,10 +217,10 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
|
|
||||||
def _delete_directory(self, path):
|
def _delete_directory(self, path):
|
||||||
"""Is called to remove directory."""
|
"""Is called to remove directory."""
|
||||||
path_exist = self._isilon_api.is_path_existent(path)
|
path_exist = self._powerscale_api.is_path_existent(path)
|
||||||
if path_exist:
|
if path_exist:
|
||||||
LOG.debug(f'Removing directory {path}')
|
LOG.debug(f'Removing directory {path}')
|
||||||
deleted = self._isilon_api.delete_path(path, recursive=True)
|
deleted = self._powerscale_api.delete_path(path, recursive=True)
|
||||||
if not deleted:
|
if not deleted:
|
||||||
message = (
|
message = (
|
||||||
_('Failed to delete directory "%(dir)s".') %
|
_('Failed to delete directory "%(dir)s".') %
|
||||||
@@ -230,7 +231,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
|
|
||||||
def _delete_nfs_share(self, share):
|
def _delete_nfs_share(self, share):
|
||||||
"""Is called to remove nfs share."""
|
"""Is called to remove nfs share."""
|
||||||
share_id = self._isilon_api.lookup_nfs_export(
|
share_id = self._powerscale_api.lookup_nfs_export(
|
||||||
self._get_container_path(share))
|
self._get_container_path(share))
|
||||||
|
|
||||||
if share_id is None:
|
if share_id is None:
|
||||||
@@ -239,7 +240,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
LOG.warning(lw, share['name'])
|
LOG.warning(lw, share['name'])
|
||||||
else:
|
else:
|
||||||
# attempt to delete the share
|
# attempt to delete the share
|
||||||
export_deleted = self._isilon_api.delete_nfs_share(share_id)
|
export_deleted = self._powerscale_api.delete_nfs_share(share_id)
|
||||||
if not export_deleted:
|
if not export_deleted:
|
||||||
message = _('Error deleting NFS share: %s') % share['name']
|
message = _('Error deleting NFS share: %s') % share['name']
|
||||||
LOG.error(message)
|
LOG.error(message)
|
||||||
@@ -247,13 +248,14 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
|
|
||||||
def _delete_cifs_share(self, share):
|
def _delete_cifs_share(self, share):
|
||||||
"""Is called to remove CIFS share."""
|
"""Is called to remove CIFS share."""
|
||||||
smb_share = self._isilon_api.lookup_smb_share(share['name'])
|
smb_share = self._powerscale_api.lookup_smb_share(share['name'])
|
||||||
if smb_share is None:
|
if smb_share is None:
|
||||||
lw = ('Attempted to delete CIFS Share "%s", but the share does '
|
lw = ('Attempted to delete CIFS Share "%s", but the share does '
|
||||||
'not appear to exist.')
|
'not appear to exist.')
|
||||||
LOG.warning(lw, share['name'])
|
LOG.warning(lw, share['name'])
|
||||||
else:
|
else:
|
||||||
share_deleted = self._isilon_api.delete_smb_share(share['name'])
|
share_deleted = self._powerscale_api.delete_smb_share(
|
||||||
|
share['name'])
|
||||||
if not share_deleted:
|
if not share_deleted:
|
||||||
message = _('Error deleting CIFS share: %s') % share['name']
|
message = _('Error deleting CIFS share: %s') % share['name']
|
||||||
LOG.error(message)
|
LOG.error(message)
|
||||||
@@ -262,7 +264,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
def delete_snapshot(self, context, snapshot, share_server):
|
def delete_snapshot(self, context, snapshot, share_server):
|
||||||
"""Is called to remove snapshot."""
|
"""Is called to remove snapshot."""
|
||||||
LOG.debug(f'Deleting snapshot {snapshot["name"]}')
|
LOG.debug(f'Deleting snapshot {snapshot["name"]}')
|
||||||
deleted = self._isilon_api.delete_snapshot(snapshot['name'])
|
deleted = self._powerscale_api.delete_snapshot(snapshot['name'])
|
||||||
if not deleted:
|
if not deleted:
|
||||||
message = (
|
message = (
|
||||||
_('Failed to delete snapshot "%(snap)s".') %
|
_('Failed to delete snapshot "%(snap)s".') %
|
||||||
@@ -280,7 +282,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
'name': share['name'], 'size': new_size
|
'name': share['name'], 'size': new_size
|
||||||
})
|
})
|
||||||
new_quota_size = new_size * units.Gi
|
new_quota_size = new_size * units.Gi
|
||||||
self._isilon_api.quota_set(
|
self._powerscale_api.quota_set(
|
||||||
self._get_container_path(share), 'directory', new_quota_size)
|
self._get_container_path(share), 'directory', new_quota_size)
|
||||||
|
|
||||||
def allow_access(self, context, share, access, share_server):
|
def allow_access(self, context, share, access, share_server):
|
||||||
@@ -295,7 +297,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
"""Check for setup error."""
|
"""Check for setup error."""
|
||||||
|
|
||||||
def connect(self, emc_share_driver, context):
|
def connect(self, emc_share_driver, context):
|
||||||
"""Connect to an Isilon cluster."""
|
"""Connect to an PowerScale cluster."""
|
||||||
LOG.debug('Reading configuration parameters for Manila'
|
LOG.debug('Reading configuration parameters for Manila'
|
||||||
' Dell PowerScale Driver.')
|
' Dell PowerScale Driver.')
|
||||||
config = emc_share_driver.configuration
|
config = emc_share_driver.configuration
|
||||||
@@ -320,13 +322,13 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
if self._verify_ssl_cert:
|
if self._verify_ssl_cert:
|
||||||
self._ssl_cert_path = config.safe_get("emc_ssl_cert_path")
|
self._ssl_cert_path = config.safe_get("emc_ssl_cert_path")
|
||||||
self._dir_permission = config.safe_get("powerscale_dir_permission")
|
self._dir_permission = config.safe_get("powerscale_dir_permission")
|
||||||
self._isilon_api = isilon_api.IsilonApi(
|
self._powerscale_api = powerscale_api.PowerScaleApi(
|
||||||
self._server_url, self._username, self._password,
|
self._server_url, self._username, self._password,
|
||||||
self._verify_ssl_cert, self._ssl_cert_path,
|
self._verify_ssl_cert, self._ssl_cert_path,
|
||||||
self._dir_permission,
|
self._dir_permission,
|
||||||
self._threshold_limit)
|
self._threshold_limit)
|
||||||
|
|
||||||
if not self._isilon_api.is_path_existent(self._root_dir):
|
if not self._powerscale_api.is_path_existent(self._root_dir):
|
||||||
self._create_directory(self._root_dir, recursive=True)
|
self._create_directory(self._root_dir, recursive=True)
|
||||||
|
|
||||||
# configuration for share status update
|
# configuration for share status update
|
||||||
@@ -367,11 +369,11 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
self.max_over_subscription_ratio,
|
self.max_over_subscription_ratio,
|
||||||
'thin_provisioning': True,
|
'thin_provisioning': True,
|
||||||
}
|
}
|
||||||
spaces = self._isilon_api.get_space_stats()
|
spaces = self._powerscale_api.get_space_stats()
|
||||||
if spaces:
|
if spaces:
|
||||||
pool_stat['total_capacity_gb'] = spaces['total'] // units.Gi
|
pool_stat['total_capacity_gb'] = spaces['total'] // units.Gi
|
||||||
pool_stat['free_capacity_gb'] = spaces['free'] // units.Gi
|
pool_stat['free_capacity_gb'] = spaces['free'] // units.Gi
|
||||||
allocated_space = self._isilon_api.get_allocated_space()
|
allocated_space = self._powerscale_api.get_allocated_space()
|
||||||
pool_stat['allocated_capacity_gb'] = allocated_space
|
pool_stat['allocated_capacity_gb'] = allocated_space
|
||||||
|
|
||||||
stats_dict['pools'] = [pool_stat]
|
stats_dict['pools'] = [pool_stat]
|
||||||
@@ -415,7 +417,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
elif rule['access_level'] == const.ACCESS_LEVEL_RO:
|
elif rule['access_level'] == const.ACCESS_LEVEL_RO:
|
||||||
nfs_ro_ips.add(rule['access_to'])
|
nfs_ro_ips.add(rule['access_to'])
|
||||||
|
|
||||||
export_id = self._isilon_api.lookup_nfs_export(
|
export_id = self._powerscale_api.lookup_nfs_export(
|
||||||
self._get_container_path(share))
|
self._get_container_path(share))
|
||||||
if export_id is None:
|
if export_id is None:
|
||||||
# share does not exist on backend (set all rules to error state)
|
# share does not exist on backend (set all rules to error state)
|
||||||
@@ -424,7 +426,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
LOG.error(message)
|
LOG.error(message)
|
||||||
return rule_state_map
|
return rule_state_map
|
||||||
|
|
||||||
r = self._isilon_api.modify_nfs_export_access(
|
r = self._powerscale_api.modify_nfs_export_access(
|
||||||
export_id, ro_ips=list(nfs_ro_ips), rw_ips=list(nfs_rw_ips))
|
export_id, ro_ips=list(nfs_ro_ips), rw_ips=list(nfs_rw_ips))
|
||||||
if not r:
|
if not r:
|
||||||
return rule_state_map
|
return rule_state_map
|
||||||
@@ -449,20 +451,22 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
) % {'type': rule['access_type']})
|
) % {'type': rule['access_type']})
|
||||||
LOG.error(message)
|
LOG.error(message)
|
||||||
rule_state_map.update({rule['access_id']: {'state': 'error'}})
|
rule_state_map.update({rule['access_id']: {'state': 'error'}})
|
||||||
|
|
||||||
ips = self._get_cifs_ip_list(ip_access_rules, rule_state_map)
|
ips = self._get_cifs_ip_list(ip_access_rules, rule_state_map)
|
||||||
user_permissions = self._get_cifs_user_permissions(
|
user_permissions = self._get_cifs_user_permissions(
|
||||||
user_access_rules, rule_state_map)
|
user_access_rules, rule_state_map)
|
||||||
|
|
||||||
share_updated = self._isilon_api.modify_smb_share_access(
|
share_updated = self._powerscale_api.modify_smb_share_access(
|
||||||
share['name'],
|
share['name'],
|
||||||
host_acl=ips,
|
host_acl=ips,
|
||||||
permissions=user_permissions)
|
permissions=user_permissions)
|
||||||
|
|
||||||
if not share_updated:
|
if not share_updated:
|
||||||
message = (
|
message = (
|
||||||
_('Failed to update access rules for CIFS share "%(share)s".'
|
_(
|
||||||
) % {'share': share['name']})
|
'Failed to update access rules for CIFS share '
|
||||||
|
'"%(share)s".'
|
||||||
|
) % {'share': share['name']}
|
||||||
|
)
|
||||||
LOG.error(message)
|
LOG.error(message)
|
||||||
for rule in access_rules:
|
for rule in access_rules:
|
||||||
rule_state_map[rule['access_id']] = {
|
rule_state_map[rule['access_id']] = {
|
||||||
@@ -490,9 +494,9 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
cifs_user_permissions = []
|
cifs_user_permissions = []
|
||||||
for rule in access_rules:
|
for rule in access_rules:
|
||||||
if rule['access_level'] == const.ACCESS_LEVEL_RW:
|
if rule['access_level'] == const.ACCESS_LEVEL_RW:
|
||||||
smb_permission = isilon_api.SmbPermission.rw
|
smb_permission = powerscale_api.SmbPermission.rw
|
||||||
elif rule['access_level'] == const.ACCESS_LEVEL_RO:
|
elif rule['access_level'] == const.ACCESS_LEVEL_RO:
|
||||||
smb_permission = isilon_api.SmbPermission.ro
|
smb_permission = powerscale_api.SmbPermission.ro
|
||||||
else:
|
else:
|
||||||
message = ('Only RW and RO access levels are supported '
|
message = ('Only RW and RO access levels are supported '
|
||||||
'for CIFS user access.')
|
'for CIFS user access.')
|
||||||
@@ -500,7 +504,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
rule_state_map.update({rule['access_id']: {'state': 'error'}})
|
rule_state_map.update({rule['access_id']: {'state': 'error'}})
|
||||||
continue
|
continue
|
||||||
|
|
||||||
user_sid = self._isilon_api.get_user_sid(rule['access_to'])
|
user_sid = self._powerscale_api.get_user_sid(rule['access_to'])
|
||||||
if user_sid:
|
if user_sid:
|
||||||
cifs_user_permissions.append({
|
cifs_user_permissions.append({
|
||||||
'permission': smb_permission.value,
|
'permission': smb_permission.value,
|
||||||
@@ -521,7 +525,7 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
:returns: A dictionary containing driver-specific info.
|
:returns: A dictionary containing driver-specific info.
|
||||||
"""
|
"""
|
||||||
LOG.debug("Retrieving PowerScale backend info.")
|
LOG.debug("Retrieving PowerScale backend info.")
|
||||||
cluster_version = self._isilon_api.get_cluster_version()
|
cluster_version = self._powerscale_api.get_cluster_version()
|
||||||
return {'driver_version': VERSION,
|
return {'driver_version': VERSION,
|
||||||
'cluster_version': cluster_version,
|
'cluster_version': cluster_version,
|
||||||
'rest_server': self._server,
|
'rest_server': self._server,
|
||||||
@@ -538,7 +542,8 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
for share in shares:
|
for share in shares:
|
||||||
if share['share_proto'] == 'NFS':
|
if share['share_proto'] == 'NFS':
|
||||||
container_path = self._get_container_path(share)
|
container_path = self._get_container_path(share)
|
||||||
share_id = self._isilon_api.lookup_nfs_export(container_path)
|
share_id = self._powerscale_api.lookup_nfs_export(
|
||||||
|
container_path)
|
||||||
if share_id:
|
if share_id:
|
||||||
location = self._format_nfs_path(container_path)
|
location = self._format_nfs_path(container_path)
|
||||||
updates[share['id']] = {
|
updates[share['id']] = {
|
||||||
@@ -549,7 +554,8 @@ class IsilonStorageConnection(base.StorageConnection):
|
|||||||
else:
|
else:
|
||||||
LOG.warning(f'NFS Share {share["name"]} is not found.')
|
LOG.warning(f'NFS Share {share["name"]} is not found.')
|
||||||
elif share['share_proto'] == 'CIFS':
|
elif share['share_proto'] == 'CIFS':
|
||||||
smb_share = self._isilon_api.lookup_smb_share(share['name'])
|
smb_share = self._powerscale_api.lookup_smb_share(
|
||||||
|
share['name'])
|
||||||
if smb_share:
|
if smb_share:
|
||||||
location = self._format_smb_path(share['name'])
|
location = self._format_smb_path(share['name'])
|
||||||
updates[share['id']] = {
|
updates[share['id']] = {
|
@@ -27,7 +27,7 @@ from manila.i18n import _
|
|||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class IsilonApi(object):
|
class PowerScaleApi(object):
|
||||||
|
|
||||||
def __init__(self, api_url, username, password,
|
def __init__(self, api_url, username, password,
|
||||||
verify_ssl_cert=False,
|
verify_ssl_cert=False,
|
@@ -22,18 +22,18 @@ from oslo_utils import units
|
|||||||
from manila.common import constants as const
|
from manila.common import constants as const
|
||||||
from manila import exception
|
from manila import exception
|
||||||
from manila.i18n import _
|
from manila.i18n import _
|
||||||
from manila.share.drivers.dell_emc.plugins.isilon import isilon
|
from manila.share.drivers.dell_emc.plugins.powerscale import powerscale
|
||||||
from manila import test
|
from manila import test
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class IsilonTest(test.TestCase):
|
class PowerScaleTest(test.TestCase):
|
||||||
"""Integration test for the Isilon Manila driver."""
|
"""Integration test for the PowerScale Manila driver."""
|
||||||
|
|
||||||
ISILON_ADDR = '10.0.0.1'
|
POWERSCALE_ADDR = '10.0.0.1'
|
||||||
API_URL = 'https://%s:8080' % ISILON_ADDR
|
API_URL = 'https://%s:8080' % POWERSCALE_ADDR
|
||||||
AUTH = ('admin', 'admin')
|
AUTH = ('admin', 'admin')
|
||||||
|
|
||||||
ROOT_DIR = '/ifs/manila-test'
|
ROOT_DIR = '/ifs/manila-test'
|
||||||
@@ -75,14 +75,13 @@ class IsilonTest(test.TestCase):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'manila.share.drivers.dell_emc.plugins.isilon.isilon.isilon_api.'
|
'manila.share.drivers.dell_emc.plugins.powerscale.powerscale.'
|
||||||
'IsilonApi',
|
'powerscale_api.PowerScaleApi', autospec=True)
|
||||||
autospec=True)
|
|
||||||
def setUp(self, mock_isi_api):
|
def setUp(self, mock_isi_api):
|
||||||
super(IsilonTest, self).setUp()
|
super(PowerScaleTest, self).setUp()
|
||||||
|
|
||||||
self._mock_isilon_api = mock_isi_api.return_value
|
self._mock_powerscale_api = mock_isi_api.return_value
|
||||||
self.storage_connection = isilon.IsilonStorageConnection(LOG)
|
self.storage_connection = powerscale.PowerScaleStorageConnection(LOG)
|
||||||
|
|
||||||
self.mock_context = mock.Mock('Context')
|
self.mock_context = mock.Mock('Context')
|
||||||
self.mock_emc_driver = mock.Mock('EmcDriver')
|
self.mock_emc_driver = mock.Mock('EmcDriver')
|
||||||
@@ -113,8 +112,8 @@ class IsilonTest(test.TestCase):
|
|||||||
|
|
||||||
def test_create_share_nfs(self):
|
def test_create_share_nfs(self):
|
||||||
share_path = self.SHARE_DIR
|
share_path = self.SHARE_DIR
|
||||||
self.assertFalse(self._mock_isilon_api.create_directory.called)
|
self.assertFalse(self._mock_powerscale_api.create_directory.called)
|
||||||
self.assertFalse(self._mock_isilon_api.create_nfs_export.called)
|
self.assertFalse(self._mock_powerscale_api.create_nfs_export.called)
|
||||||
|
|
||||||
# create the share
|
# create the share
|
||||||
share = {"name": self.SHARE_NAME, "share_proto": 'NFS', "size": 8}
|
share = {"name": self.SHARE_NAME, "share_proto": 'NFS', "size": 8}
|
||||||
@@ -122,42 +121,42 @@ class IsilonTest(test.TestCase):
|
|||||||
share, None)
|
share, None)
|
||||||
|
|
||||||
# verify location and API call made
|
# verify location and API call made
|
||||||
path = '%s:%s' % (self.ISILON_ADDR, self.SHARE_DIR)
|
path = '%s:%s' % (self.POWERSCALE_ADDR, self.SHARE_DIR)
|
||||||
expected_location = [{'is_admin_only': False,
|
expected_location = [{'is_admin_only': False,
|
||||||
'metadata': {"preferred": True},
|
'metadata': {"preferred": True},
|
||||||
'path': path}]
|
'path': path}]
|
||||||
|
|
||||||
self.assertEqual(expected_location, location)
|
self.assertEqual(expected_location, location)
|
||||||
self._mock_isilon_api.create_directory.assert_called_with(
|
self._mock_powerscale_api.create_directory.assert_called_with(
|
||||||
share_path, False)
|
share_path, False)
|
||||||
self._mock_isilon_api.create_nfs_export.assert_called_with(share_path)
|
self._mock_powerscale_api.create_nfs_export.assert_called_with(
|
||||||
|
share_path)
|
||||||
|
|
||||||
# verify directory quota call made
|
# verify directory quota call made
|
||||||
self._mock_isilon_api.quota_create.assert_called_with(
|
self._mock_powerscale_api.quota_create.assert_called_with(
|
||||||
share_path, 'directory', 8 * units.Gi)
|
share_path, 'directory', 8 * units.Gi)
|
||||||
|
|
||||||
def test_create_share_cifs(self):
|
def test_create_share_cifs(self):
|
||||||
self.assertFalse(self._mock_isilon_api.create_directory.called)
|
self.assertFalse(self._mock_powerscale_api.create_directory.called)
|
||||||
self.assertFalse(self._mock_isilon_api.create_smb_share.called)
|
self.assertFalse(self._mock_powerscale_api.create_smb_share.called)
|
||||||
|
|
||||||
# create the share
|
# create the share
|
||||||
share = {"name": self.SHARE_NAME, "share_proto": 'CIFS', "size": 8}
|
share = {"name": self.SHARE_NAME, "share_proto": 'CIFS', "size": 8}
|
||||||
location = self.storage_connection.create_share(self.mock_context,
|
location = self.storage_connection.create_share(self.mock_context,
|
||||||
share, None)
|
share, None)
|
||||||
|
path = '\\\\{0}\\{1}'.format(self.POWERSCALE_ADDR, self.SHARE_NAME)
|
||||||
path = '\\\\{0}\\{1}'.format(self.ISILON_ADDR, self.SHARE_NAME)
|
|
||||||
expected_location = [{'is_admin_only': False,
|
expected_location = [{'is_admin_only': False,
|
||||||
'metadata': {"preferred": True},
|
'metadata': {"preferred": True},
|
||||||
'path': path}]
|
'path': path}]
|
||||||
|
|
||||||
self.assertEqual(expected_location, location)
|
self.assertEqual(expected_location, location)
|
||||||
self._mock_isilon_api.create_directory.assert_called_once_with(
|
self._mock_powerscale_api.create_directory.assert_called_once_with(
|
||||||
self.SHARE_DIR, False)
|
self.SHARE_DIR, False)
|
||||||
self._mock_isilon_api.create_smb_share.assert_called_once_with(
|
self._mock_powerscale_api.create_smb_share.assert_called_once_with(
|
||||||
self.SHARE_NAME, self.SHARE_DIR)
|
self.SHARE_NAME, self.SHARE_DIR)
|
||||||
|
|
||||||
# verify directory quota call made
|
# verify directory quota call made
|
||||||
self._mock_isilon_api.quota_create.assert_called_with(
|
self._mock_powerscale_api.quota_create.assert_called_with(
|
||||||
self.SHARE_DIR, 'directory', 8 * units.Gi)
|
self.SHARE_DIR, 'directory', 8 * units.Gi)
|
||||||
|
|
||||||
def test_create_share_invalid_share_protocol(self):
|
def test_create_share_invalid_share_protocol(self):
|
||||||
@@ -169,7 +168,7 @@ class IsilonTest(test.TestCase):
|
|||||||
|
|
||||||
def test_create_share_nfs_backend_failure(self):
|
def test_create_share_nfs_backend_failure(self):
|
||||||
share = {"name": self.SHARE_NAME, "share_proto": 'NFS'}
|
share = {"name": self.SHARE_NAME, "share_proto": 'NFS'}
|
||||||
self._mock_isilon_api.create_nfs_export.return_value = False
|
self._mock_powerscale_api.create_nfs_export.return_value = False
|
||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.ShareBackendException,
|
exception.ShareBackendException,
|
||||||
@@ -178,7 +177,7 @@ class IsilonTest(test.TestCase):
|
|||||||
|
|
||||||
def test_create_share_cifs_backend_failure(self):
|
def test_create_share_cifs_backend_failure(self):
|
||||||
share = {"name": self.SHARE_NAME, "share_proto": 'CIFS'}
|
share = {"name": self.SHARE_NAME, "share_proto": 'CIFS'}
|
||||||
self._mock_isilon_api.create_smb_share.return_value = False
|
self._mock_powerscale_api.create_smb_share.return_value = False
|
||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.ShareBackendException,
|
exception.ShareBackendException,
|
||||||
@@ -187,7 +186,7 @@ class IsilonTest(test.TestCase):
|
|||||||
|
|
||||||
def test_create_directory_backend_failure(self):
|
def test_create_directory_backend_failure(self):
|
||||||
share = {"name": self.SHARE_NAME, "share_proto": 'NFS'}
|
share = {"name": self.SHARE_NAME, "share_proto": 'NFS'}
|
||||||
self._mock_isilon_api.create_directory.return_value = False
|
self._mock_powerscale_api.create_directory.return_value = False
|
||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.ShareBackendException,
|
exception.ShareBackendException,
|
||||||
@@ -204,14 +203,14 @@ class IsilonTest(test.TestCase):
|
|||||||
None)
|
None)
|
||||||
|
|
||||||
# verify the create snapshot API call is executed
|
# verify the create snapshot API call is executed
|
||||||
self._mock_isilon_api.create_snapshot.assert_called_with(snapshot_name,
|
self._mock_powerscale_api.create_snapshot.assert_called_with(
|
||||||
snapshot_path)
|
snapshot_name, snapshot_path)
|
||||||
|
|
||||||
def test_create_snapshot_backend_failure(self):
|
def test_create_snapshot_backend_failure(self):
|
||||||
snapshot_name = "snapshot01"
|
snapshot_name = "snapshot01"
|
||||||
snapshot_path = '/ifs/home/admin'
|
snapshot_path = '/ifs/home/admin'
|
||||||
snapshot = {'name': snapshot_name, 'share_name': snapshot_path}
|
snapshot = {'name': snapshot_name, 'share_name': snapshot_path}
|
||||||
self._mock_isilon_api.create_snapshot.return_value = False
|
self._mock_powerscale_api.create_snapshot.return_value = False
|
||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.ShareBackendException,
|
exception.ShareBackendException,
|
||||||
@@ -220,8 +219,8 @@ class IsilonTest(test.TestCase):
|
|||||||
|
|
||||||
def test_create_share_from_snapshot_nfs(self):
|
def test_create_share_from_snapshot_nfs(self):
|
||||||
# assertions
|
# assertions
|
||||||
self.assertFalse(self._mock_isilon_api.create_nfs_export.called)
|
self.assertFalse(self._mock_powerscale_api.create_nfs_export.called)
|
||||||
self.assertFalse(self._mock_isilon_api.clone_snapshot.called)
|
self.assertFalse(self._mock_powerscale_api.clone_snapshot.called)
|
||||||
|
|
||||||
snapshot_name = "snapshot01"
|
snapshot_name = "snapshot01"
|
||||||
snapshot_path = '/ifs/home/admin'
|
snapshot_path = '/ifs/home/admin'
|
||||||
@@ -233,14 +232,14 @@ class IsilonTest(test.TestCase):
|
|||||||
self.mock_context, share, snapshot, None)
|
self.mock_context, share, snapshot, None)
|
||||||
|
|
||||||
# verify NFS export created at expected location
|
# verify NFS export created at expected location
|
||||||
self._mock_isilon_api.create_nfs_export.assert_called_with(
|
self._mock_powerscale_api.create_nfs_export.assert_called_with(
|
||||||
self.SHARE_DIR)
|
self.SHARE_DIR)
|
||||||
|
|
||||||
# verify clone_directory(container_path) method called
|
# verify clone_directory(container_path) method called
|
||||||
self._mock_isilon_api.clone_snapshot.assert_called_once_with(
|
self._mock_powerscale_api.clone_snapshot.assert_called_once_with(
|
||||||
snapshot_name, self.SHARE_DIR)
|
snapshot_name, self.SHARE_DIR)
|
||||||
path = '{0}:{1}'.format(
|
path = '{0}:{1}'.format(
|
||||||
self.ISILON_ADDR, self.SHARE_DIR)
|
self.POWERSCALE_ADDR, self.SHARE_DIR)
|
||||||
expected_location = {'is_admin_only': False,
|
expected_location = {'is_admin_only': False,
|
||||||
'metadata': {"preferred": True},
|
'metadata': {"preferred": True},
|
||||||
'path': path}
|
'path': path}
|
||||||
@@ -248,13 +247,13 @@ class IsilonTest(test.TestCase):
|
|||||||
self.assertEqual(expected_location, location[0])
|
self.assertEqual(expected_location, location[0])
|
||||||
|
|
||||||
# verify directory quota call made
|
# verify directory quota call made
|
||||||
self._mock_isilon_api.quota_create.assert_called_with(
|
self._mock_powerscale_api.quota_create.assert_called_with(
|
||||||
self.SHARE_DIR, 'directory', 5 * units.Gi)
|
self.SHARE_DIR, 'directory', 5 * units.Gi)
|
||||||
|
|
||||||
def test_create_share_from_snapshot_cifs(self):
|
def test_create_share_from_snapshot_cifs(self):
|
||||||
# assertions
|
# assertions
|
||||||
self.assertFalse(self._mock_isilon_api.create_smb_share.called)
|
self.assertFalse(self._mock_powerscale_api.create_smb_share.called)
|
||||||
self.assertFalse(self._mock_isilon_api.clone_snapshot.called)
|
self.assertFalse(self._mock_powerscale_api.clone_snapshot.called)
|
||||||
# setup
|
# setup
|
||||||
snapshot_name = "snapshot01"
|
snapshot_name = "snapshot01"
|
||||||
snapshot_path = '/ifs/home/admin'
|
snapshot_path = '/ifs/home/admin'
|
||||||
@@ -267,11 +266,11 @@ class IsilonTest(test.TestCase):
|
|||||||
self.mock_context, share, snapshot, None)
|
self.mock_context, share, snapshot, None)
|
||||||
|
|
||||||
# verify call made to create new CIFS share
|
# verify call made to create new CIFS share
|
||||||
self._mock_isilon_api.create_smb_share.assert_called_once_with(
|
self._mock_powerscale_api.create_smb_share.assert_called_once_with(
|
||||||
new_share_name, self.CLONE_DIR)
|
new_share_name, self.CLONE_DIR)
|
||||||
self._mock_isilon_api.clone_snapshot.assert_called_once_with(
|
self._mock_powerscale_api.clone_snapshot.assert_called_once_with(
|
||||||
snapshot_name, self.CLONE_DIR)
|
snapshot_name, self.CLONE_DIR)
|
||||||
path = '\\\\{0}\\{1}'.format(self.ISILON_ADDR, new_share_name)
|
path = '\\\\{0}\\{1}'.format(self.POWERSCALE_ADDR, new_share_name)
|
||||||
expected_location = {'is_admin_only': False,
|
expected_location = {'is_admin_only': False,
|
||||||
'metadata': {"preferred": True},
|
'metadata': {"preferred": True},
|
||||||
'path': path}
|
'path': path}
|
||||||
@@ -279,34 +278,36 @@ class IsilonTest(test.TestCase):
|
|||||||
|
|
||||||
# verify directory quota call made
|
# verify directory quota call made
|
||||||
expected_share_path = '{0}/{1}'.format(self.ROOT_DIR, new_share_name)
|
expected_share_path = '{0}/{1}'.format(self.ROOT_DIR, new_share_name)
|
||||||
self._mock_isilon_api.quota_create.assert_called_with(
|
self._mock_powerscale_api.quota_create.assert_called_with(
|
||||||
expected_share_path, 'directory', 2 * units.Gi)
|
expected_share_path, 'directory', 2 * units.Gi)
|
||||||
|
|
||||||
def test_delete_share_nfs(self):
|
def test_delete_share_nfs(self):
|
||||||
share = {"name": self.SHARE_NAME, "share_proto": 'NFS'}
|
share = {"name": self.SHARE_NAME, "share_proto": 'NFS'}
|
||||||
fake_share_num = 42
|
fake_share_num = 42
|
||||||
self._mock_isilon_api.lookup_nfs_export.return_value = fake_share_num
|
self._mock_powerscale_api.lookup_nfs_export.return_value = (
|
||||||
self.assertFalse(self._mock_isilon_api.delete_nfs_share.called)
|
fake_share_num)
|
||||||
|
self.assertFalse(self._mock_powerscale_api.delete_nfs_share.called)
|
||||||
|
|
||||||
# delete the share
|
# delete the share
|
||||||
self.storage_connection.delete_share(self.mock_context, share, None)
|
self.storage_connection.delete_share(self.mock_context, share, None)
|
||||||
|
|
||||||
# verify share delete
|
# verify share delete
|
||||||
self._mock_isilon_api.delete_nfs_share.assert_called_with(
|
self._mock_powerscale_api.delete_nfs_share.assert_called_with(
|
||||||
fake_share_num)
|
fake_share_num)
|
||||||
|
|
||||||
def test_delete_share_cifs(self):
|
def test_delete_share_cifs(self):
|
||||||
self.assertFalse(self._mock_isilon_api.delete_smb_share.called)
|
self.assertFalse(self._mock_powerscale_api.delete_smb_share.called)
|
||||||
|
|
||||||
# delete the share
|
# delete the share
|
||||||
share = {"name": self.SHARE_NAME, "share_proto": 'CIFS'}
|
share = {"name": self.SHARE_NAME, "share_proto": 'CIFS'}
|
||||||
self.storage_connection.delete_share(self.mock_context, share, None)
|
self.storage_connection.delete_share(self.mock_context, share, None)
|
||||||
|
|
||||||
# verify share deleted
|
# verify share deleted
|
||||||
self._mock_isilon_api.delete_smb_share.assert_called_with(
|
self._mock_powerscale_api.delete_smb_share.assert_called_with(
|
||||||
self.SHARE_NAME)
|
self.SHARE_NAME)
|
||||||
|
|
||||||
@mock.patch('manila.share.drivers.dell_emc.plugins.isilon.isilon.LOG')
|
@mock.patch(
|
||||||
|
'manila.share.drivers.dell_emc.plugins.powerscale.powerscale.LOG')
|
||||||
def test_delete_share_invalid_share_proto(self, mock_log):
|
def test_delete_share_invalid_share_proto(self, mock_log):
|
||||||
share = {"name": self.SHARE_NAME, "share_proto": 'FOO_PROTOCOL'}
|
share = {"name": self.SHARE_NAME, "share_proto": 'FOO_PROTOCOL'}
|
||||||
|
|
||||||
@@ -317,7 +318,7 @@ class IsilonTest(test.TestCase):
|
|||||||
def test_delete_nfs_share_backend_failure(self):
|
def test_delete_nfs_share_backend_failure(self):
|
||||||
share = {"name": self.SHARE_NAME, "share_proto": 'NFS'}
|
share = {"name": self.SHARE_NAME, "share_proto": 'NFS'}
|
||||||
|
|
||||||
self._mock_isilon_api.delete_nfs_share.return_value = False
|
self._mock_powerscale_api.delete_nfs_share.return_value = False
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.ShareBackendException,
|
exception.ShareBackendException,
|
||||||
self.storage_connection.delete_share,
|
self.storage_connection.delete_share,
|
||||||
@@ -325,7 +326,7 @@ class IsilonTest(test.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_delete_nfs_share_share_does_not_exist(self):
|
def test_delete_nfs_share_share_does_not_exist(self):
|
||||||
self._mock_isilon_api.lookup_nfs_export.return_value = None
|
self._mock_powerscale_api.lookup_nfs_export.return_value = None
|
||||||
share = {"name": self.SHARE_NAME, "share_proto": 'NFS'}
|
share = {"name": self.SHARE_NAME, "share_proto": 'NFS'}
|
||||||
|
|
||||||
# verify the calling delete on a non-existent share returns and does
|
# verify the calling delete on a non-existent share returns and does
|
||||||
@@ -335,7 +336,7 @@ class IsilonTest(test.TestCase):
|
|||||||
def test_delete_cifs_share_backend_failure(self):
|
def test_delete_cifs_share_backend_failure(self):
|
||||||
share = {"name": self.SHARE_NAME, "share_proto": 'CIFS'}
|
share = {"name": self.SHARE_NAME, "share_proto": 'CIFS'}
|
||||||
|
|
||||||
self._mock_isilon_api.delete_smb_share.return_value = False
|
self._mock_powerscale_api.delete_smb_share.return_value = False
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.ShareBackendException,
|
exception.ShareBackendException,
|
||||||
self.storage_connection.delete_share,
|
self.storage_connection.delete_share,
|
||||||
@@ -344,37 +345,43 @@ class IsilonTest(test.TestCase):
|
|||||||
|
|
||||||
def test_delete_cifs_share_share_does_not_exist(self):
|
def test_delete_cifs_share_share_does_not_exist(self):
|
||||||
share = {"name": self.SHARE_NAME, "share_proto": 'CIFS'}
|
share = {"name": self.SHARE_NAME, "share_proto": 'CIFS'}
|
||||||
self._mock_isilon_api.lookup_smb_share.return_value = None
|
self._mock_powerscale_api.lookup_smb_share.return_value = None
|
||||||
|
|
||||||
# verify the calling delete on a non-existent share returns and does
|
# verify the calling delete on a non-existent share returns and does
|
||||||
# not throw exception
|
# not throw exception
|
||||||
self.storage_connection.delete_share(self.mock_context, share, None)
|
self.storage_connection.delete_share(self.mock_context, share, None)
|
||||||
|
|
||||||
@mock.patch('manila.share.drivers.dell_emc.plugins.isilon.isilon.LOG')
|
@mock.patch(
|
||||||
|
'manila.share.drivers.dell_emc.plugins.powerscale.powerscale.LOG'
|
||||||
|
)
|
||||||
def test_delete_quota_success(self, mock_log):
|
def test_delete_quota_success(self, mock_log):
|
||||||
path = '/path/to/quota'
|
path = '/path/to/quota'
|
||||||
quota_id = '123'
|
quota_id = '123'
|
||||||
quota_data = {'id': quota_id}
|
quota_data = {'id': quota_id}
|
||||||
self._mock_isilon_api.quota_get.return_value = quota_data
|
self._mock_powerscale_api.quota_get.return_value = quota_data
|
||||||
self._mock_isilon_api.delete_quota.return_value = True
|
self._mock_powerscale_api.delete_quota.return_value = True
|
||||||
self.storage_connection._delete_quota(path)
|
self.storage_connection._delete_quota(path)
|
||||||
self._mock_isilon_api.quota_get.assert_called_once_with(
|
self._mock_powerscale_api.quota_get.assert_called_once_with(
|
||||||
path, 'directory')
|
path, 'directory')
|
||||||
self._mock_isilon_api.delete_quota.assert_called_once_with(quota_id)
|
self._mock_powerscale_api.delete_quota.assert_called_once_with(
|
||||||
|
quota_id)
|
||||||
mock_log.debug.assert_called_once_with(f'Removing quota {quota_id}')
|
mock_log.debug.assert_called_once_with(f'Removing quota {quota_id}')
|
||||||
mock_log.warning.assert_not_called()
|
mock_log.warning.assert_not_called()
|
||||||
|
|
||||||
@mock.patch('manila.share.drivers.dell_emc.plugins.isilon.isilon.LOG')
|
@mock.patch(
|
||||||
|
'manila.share.drivers.dell_emc.plugins.powerscale.powerscale.LOG'
|
||||||
|
)
|
||||||
def test_delete_quota_failure(self, mock_log):
|
def test_delete_quota_failure(self, mock_log):
|
||||||
path = '/path/to/quota'
|
path = '/path/to/quota'
|
||||||
quota_id = '123'
|
quota_id = '123'
|
||||||
quota_data = {'id': quota_id}
|
quota_data = {'id': quota_id}
|
||||||
self._mock_isilon_api.quota_get.return_value = quota_data
|
self._mock_powerscale_api.quota_get.return_value = quota_data
|
||||||
self._mock_isilon_api.delete_quota.return_value = False
|
self._mock_powerscale_api.delete_quota.return_value = False
|
||||||
self.storage_connection._delete_quota(path)
|
self.storage_connection._delete_quota(path)
|
||||||
self._mock_isilon_api.quota_get.assert_called_once_with(
|
self._mock_powerscale_api.quota_get.assert_called_once_with(
|
||||||
path, 'directory')
|
path, 'directory')
|
||||||
self._mock_isilon_api.delete_quota.assert_called_once_with(quota_id)
|
self._mock_powerscale_api.delete_quota.assert_called_once_with(
|
||||||
|
quota_id)
|
||||||
mock_log.debug.assert_called_once_with(f'Removing quota {quota_id}')
|
mock_log.debug.assert_called_once_with(f'Removing quota {quota_id}')
|
||||||
mock_log.error.assert_called_once_with(
|
mock_log.error.assert_called_once_with(
|
||||||
_('Failed to delete quota "%(quota_id)s" for '
|
_('Failed to delete quota "%(quota_id)s" for '
|
||||||
@@ -382,35 +389,41 @@ class IsilonTest(test.TestCase):
|
|||||||
{'quota_id': quota_id, 'dir': path})
|
{'quota_id': quota_id, 'dir': path})
|
||||||
mock_log.warning.assert_not_called()
|
mock_log.warning.assert_not_called()
|
||||||
|
|
||||||
@mock.patch('manila.share.drivers.dell_emc.plugins.isilon.isilon.LOG')
|
@mock.patch(
|
||||||
|
'manila.share.drivers.dell_emc.plugins.powerscale.powerscale.LOG'
|
||||||
|
)
|
||||||
def test_delete_quota_not_found(self, mock_log):
|
def test_delete_quota_not_found(self, mock_log):
|
||||||
path = '/path/to/quota'
|
path = '/path/to/quota'
|
||||||
self._mock_isilon_api.quota_get.return_value = None
|
self._mock_powerscale_api.quota_get.return_value = None
|
||||||
self.storage_connection._delete_quota(path)
|
self.storage_connection._delete_quota(path)
|
||||||
self._mock_isilon_api.quota_get.assert_called_once_with(
|
self._mock_powerscale_api.quota_get.assert_called_once_with(
|
||||||
path, 'directory')
|
path, 'directory')
|
||||||
self._mock_isilon_api.delete_quota.assert_not_called()
|
self._mock_powerscale_api.delete_quota.assert_not_called()
|
||||||
mock_log.debug.assert_not_called()
|
mock_log.debug.assert_not_called()
|
||||||
mock_log.warning.assert_called_once_with(f'Quota not found for {path}')
|
mock_log.warning.assert_called_once_with(f'Quota not found for {path}')
|
||||||
|
|
||||||
@mock.patch('manila.share.drivers.dell_emc.plugins.isilon.isilon.LOG')
|
@mock.patch(
|
||||||
|
'manila.share.drivers.dell_emc.plugins.powerscale.powerscale.LOG'
|
||||||
|
)
|
||||||
def test_delete_directory_success(self, mock_log):
|
def test_delete_directory_success(self, mock_log):
|
||||||
path = '/path/to/directory'
|
path = '/path/to/directory'
|
||||||
self._mock_isilon_api.is_path_existent.return_value = True
|
self._mock_powerscale_api.is_path_existent.return_value = True
|
||||||
self._mock_isilon_api.delete_path.return_value = True
|
self._mock_powerscale_api.delete_path.return_value = True
|
||||||
self.storage_connection._delete_directory(path)
|
self.storage_connection._delete_directory(path)
|
||||||
self._mock_isilon_api.delete_path.assert_called_once_with(
|
self._mock_powerscale_api.delete_path.assert_called_once_with(
|
||||||
path, recursive=True)
|
path, recursive=True)
|
||||||
mock_log.debug.assert_called_once_with(f'Removing directory {path}')
|
mock_log.debug.assert_called_once_with(f'Removing directory {path}')
|
||||||
mock_log.warning.assert_not_called()
|
mock_log.warning.assert_not_called()
|
||||||
|
|
||||||
@mock.patch('manila.share.drivers.dell_emc.plugins.isilon.isilon.LOG')
|
@mock.patch(
|
||||||
|
'manila.share.drivers.dell_emc.plugins.powerscale.powerscale.LOG'
|
||||||
|
)
|
||||||
def test_delete_directory_failure(self, mock_log):
|
def test_delete_directory_failure(self, mock_log):
|
||||||
path = '/path/to/directory'
|
path = '/path/to/directory'
|
||||||
self._mock_isilon_api.is_path_existent.return_value = True
|
self._mock_powerscale_api.is_path_existent.return_value = True
|
||||||
self._mock_isilon_api.delete_path.return_value = False
|
self._mock_powerscale_api.delete_path.return_value = False
|
||||||
self.storage_connection._delete_directory(path)
|
self.storage_connection._delete_directory(path)
|
||||||
self._mock_isilon_api.delete_path.assert_called_once_with(
|
self._mock_powerscale_api.delete_path.assert_called_once_with(
|
||||||
path, recursive=True)
|
path, recursive=True)
|
||||||
mock_log.debug.assert_called_once_with(f'Removing directory {path}')
|
mock_log.debug.assert_called_once_with(f'Removing directory {path}')
|
||||||
mock_log.error.assert_called_once_with(
|
mock_log.error.assert_called_once_with(
|
||||||
@@ -418,12 +431,14 @@ class IsilonTest(test.TestCase):
|
|||||||
{'dir': path})
|
{'dir': path})
|
||||||
mock_log.warning.assert_not_called()
|
mock_log.warning.assert_not_called()
|
||||||
|
|
||||||
@mock.patch('manila.share.drivers.dell_emc.plugins.isilon.isilon.LOG')
|
@mock.patch(
|
||||||
|
'manila.share.drivers.dell_emc.plugins.powerscale.powerscale.LOG'
|
||||||
|
)
|
||||||
def test_delete_directory_not_found(self, mock_log):
|
def test_delete_directory_not_found(self, mock_log):
|
||||||
path = '/path/to/directory'
|
path = '/path/to/directory'
|
||||||
self._mock_isilon_api.is_path_existent.return_value = False
|
self._mock_powerscale_api.is_path_existent.return_value = False
|
||||||
self.storage_connection._delete_directory(path)
|
self.storage_connection._delete_directory(path)
|
||||||
self._mock_isilon_api.delete_path.assert_not_called()
|
self._mock_powerscale_api.delete_path.assert_not_called()
|
||||||
mock_log.warning.assert_called_once_with(
|
mock_log.warning.assert_called_once_with(
|
||||||
_('Directory not found for %s') % path)
|
_('Directory not found for %s') % path)
|
||||||
|
|
||||||
@@ -432,24 +447,24 @@ class IsilonTest(test.TestCase):
|
|||||||
snapshot_name = "snapshot01"
|
snapshot_name = "snapshot01"
|
||||||
snapshot_path = '/ifs/home/admin'
|
snapshot_path = '/ifs/home/admin'
|
||||||
snapshot = {'name': snapshot_name, 'share_name': snapshot_path}
|
snapshot = {'name': snapshot_name, 'share_name': snapshot_path}
|
||||||
self.assertFalse(self._mock_isilon_api.delete_snapshot.called)
|
self.assertFalse(self._mock_powerscale_api.delete_snapshot.called)
|
||||||
|
|
||||||
# delete the created snapshot
|
# delete the created snapshot
|
||||||
self.storage_connection.delete_snapshot(self.mock_context, snapshot,
|
self.storage_connection.delete_snapshot(self.mock_context, snapshot,
|
||||||
None)
|
None)
|
||||||
|
|
||||||
# verify the API call was made to delete the snapshot
|
# verify the API call was made to delete the snapshot
|
||||||
self._mock_isilon_api.delete_snapshot.assert_called_once_with(
|
self._mock_powerscale_api.delete_snapshot.assert_called_once_with(
|
||||||
snapshot_name)
|
snapshot_name)
|
||||||
|
|
||||||
def test_delete_snapshot_failure(self):
|
def test_delete_snapshot_failure(self):
|
||||||
snapshot = {'name': 'test_snapshot'}
|
snapshot = {'name': 'test_snapshot'}
|
||||||
self._mock_isilon_api.delete_snapshot.return_value = False
|
self._mock_powerscale_api.delete_snapshot.return_value = False
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.ShareBackendException,
|
exception.ShareBackendException,
|
||||||
self.storage_connection.delete_snapshot,
|
self.storage_connection.delete_snapshot,
|
||||||
self.mock_context, snapshot, None)
|
self.mock_context, snapshot, None)
|
||||||
self._mock_isilon_api.delete_snapshot.assert_called_once_with(
|
self._mock_powerscale_api.delete_snapshot.assert_called_once_with(
|
||||||
snapshot['name'])
|
snapshot['name'])
|
||||||
|
|
||||||
def test_ensure_share(self):
|
def test_ensure_share(self):
|
||||||
@@ -459,11 +474,10 @@ class IsilonTest(test.TestCase):
|
|||||||
self.mock_context, share, None)
|
self.mock_context, share, None)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'manila.share.drivers.dell_emc.plugins.isilon.isilon.isilon_api.'
|
'manila.share.drivers.dell_emc.plugins.powerscale.powerscale.'
|
||||||
'IsilonApi',
|
'powerscale_api.PowerScaleApi', autospec=True)
|
||||||
autospec=True)
|
|
||||||
def test_connect(self, mock_isi_api):
|
def test_connect(self, mock_isi_api):
|
||||||
storage_connection = isilon.IsilonStorageConnection(LOG)
|
storage_connection = powerscale.PowerScaleStorageConnection(LOG)
|
||||||
|
|
||||||
# execute method under test
|
# execute method under test
|
||||||
storage_connection.connect(
|
storage_connection.connect(
|
||||||
@@ -488,18 +502,17 @@ class IsilonTest(test.TestCase):
|
|||||||
storage_connection._dir_permission)
|
storage_connection._dir_permission)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'manila.share.drivers.dell_emc.plugins.isilon.isilon.isilon_api.'
|
'manila.share.drivers.dell_emc.plugins.powerscale.powerscale.'
|
||||||
'IsilonApi',
|
'powerscale_api.PowerScaleApi', autospec=True)
|
||||||
autospec=True)
|
|
||||||
def test_connect_root_dir_does_not_exist(self, mock_isi_api):
|
def test_connect_root_dir_does_not_exist(self, mock_isi_api):
|
||||||
mock_isilon_api = mock_isi_api.return_value
|
mock_powerscale_api = mock_isi_api.return_value
|
||||||
mock_isilon_api.is_path_existent.return_value = False
|
mock_powerscale_api.is_path_existent.return_value = False
|
||||||
storage_connection = isilon.IsilonStorageConnection(LOG)
|
storage_connection = powerscale.PowerScaleStorageConnection(LOG)
|
||||||
|
|
||||||
# call method under test
|
# call method under test
|
||||||
storage_connection.connect(self.mock_emc_driver, self.mock_context)
|
storage_connection.connect(self.mock_emc_driver, self.mock_context)
|
||||||
|
|
||||||
mock_isilon_api.create_directory.assert_called_once_with(
|
mock_powerscale_api.create_directory.assert_called_once_with(
|
||||||
self.ROOT_DIR, recursive=True)
|
self.ROOT_DIR, recursive=True)
|
||||||
|
|
||||||
def test_connect_invalid_config(self):
|
def test_connect_invalid_config(self):
|
||||||
@@ -513,11 +526,11 @@ class IsilonTest(test.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_update_share_stats(self):
|
def test_update_share_stats(self):
|
||||||
self._mock_isilon_api.get_space_stats.return_value = {
|
self._mock_powerscale_api.get_space_stats.return_value = {
|
||||||
'total': 1000 * units.Gi,
|
'total': 1000 * units.Gi,
|
||||||
'free': 100 * units.Gi,
|
'free': 100 * units.Gi,
|
||||||
}
|
}
|
||||||
self._mock_isilon_api.get_allocated_space.return_value = 2110.0
|
self._mock_powerscale_api.get_allocated_space.return_value = 2110.0
|
||||||
stats_dict = {'share_backend_name': 'PowerScale_backend'}
|
stats_dict = {'share_backend_name': 'PowerScale_backend'}
|
||||||
self.storage_connection.update_share_stats(stats_dict)
|
self.storage_connection.update_share_stats(stats_dict)
|
||||||
|
|
||||||
@@ -535,7 +548,7 @@ class IsilonTest(test.TestCase):
|
|||||||
}
|
}
|
||||||
expected_stats = {
|
expected_stats = {
|
||||||
'share_backend_name': 'PowerScale_backend',
|
'share_backend_name': 'PowerScale_backend',
|
||||||
'driver_version': isilon.VERSION,
|
'driver_version': powerscale.VERSION,
|
||||||
'storage_protocol': 'NFS_CIFS',
|
'storage_protocol': 'NFS_CIFS',
|
||||||
'pools': [expected_pool_stats]
|
'pools': [expected_pool_stats]
|
||||||
}
|
}
|
||||||
@@ -555,14 +568,14 @@ class IsilonTest(test.TestCase):
|
|||||||
"share_proto": 'NFS',
|
"share_proto": 'NFS',
|
||||||
"size": new_share_size
|
"size": new_share_size
|
||||||
}
|
}
|
||||||
self._mock_isilon_api.quota_get.return_value = {'id': quota_id}
|
self._mock_powerscale_api.quota_get.return_value = {'id': quota_id}
|
||||||
self.assertFalse(self._mock_isilon_api.quota_set.called)
|
self.assertFalse(self._mock_powerscale_api.quota_set.called)
|
||||||
|
|
||||||
self.storage_connection.extend_share(share, new_share_size)
|
self.storage_connection.extend_share(share, new_share_size)
|
||||||
|
|
||||||
share_path = '{0}/{1}'.format(self.ROOT_DIR, self.SHARE_NAME)
|
share_path = '{0}/{1}'.format(self.ROOT_DIR, self.SHARE_NAME)
|
||||||
expected_quota_size = new_share_size * units.Gi
|
expected_quota_size = new_share_size * units.Gi
|
||||||
self._mock_isilon_api.quota_set.assert_called_once_with(
|
self._mock_powerscale_api.quota_set.assert_called_once_with(
|
||||||
share_path, 'directory', expected_quota_size)
|
share_path, 'directory', expected_quota_size)
|
||||||
|
|
||||||
def test_update_access_add_nfs(self):
|
def test_update_access_add_nfs(self):
|
||||||
@@ -571,8 +584,9 @@ class IsilonTest(test.TestCase):
|
|||||||
"share_proto": 'NFS',
|
"share_proto": 'NFS',
|
||||||
}
|
}
|
||||||
fake_export_id = 4
|
fake_export_id = 4
|
||||||
self._mock_isilon_api.lookup_nfs_export.return_value = fake_export_id
|
self._mock_powerscale_api.lookup_nfs_export.return_value = (
|
||||||
self._mock_isilon_api.get_nfs_export.return_value = {
|
fake_export_id)
|
||||||
|
self._mock_powerscale_api.get_nfs_export.return_value = {
|
||||||
'clients': [],
|
'clients': [],
|
||||||
'read_only_clients': []
|
'read_only_clients': []
|
||||||
}
|
}
|
||||||
@@ -583,7 +597,7 @@ class IsilonTest(test.TestCase):
|
|||||||
'access_id': '09960614-8574-4e03-89cf-7cf267b0bd08'
|
'access_id': '09960614-8574-4e03-89cf-7cf267b0bd08'
|
||||||
}
|
}
|
||||||
access_rules = [nfs_access]
|
access_rules = [nfs_access]
|
||||||
self._mock_isilon_api.modify_nfs_export_access.return_value = True
|
self._mock_powerscale_api.modify_nfs_export_access.return_value = True
|
||||||
rule_map = self.storage_connection.update_access(
|
rule_map = self.storage_connection.update_access(
|
||||||
self.mock_context, share, access_rules, [],
|
self.mock_context, share, access_rules, [],
|
||||||
[], share_server=None)
|
[], share_server=None)
|
||||||
@@ -592,8 +606,8 @@ class IsilonTest(test.TestCase):
|
|||||||
'state': 'active'
|
'state': 'active'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self._mock_isilon_api.modify_nfs_export_access.assert_called_once_with(
|
self._mock_powerscale_api.modify_nfs_export_access. \
|
||||||
fake_export_id, [], ['10.1.1.10'])
|
assert_called_once_with(fake_export_id, [], ['10.1.1.10'])
|
||||||
self.assertEqual(expected_rule_map, rule_map)
|
self.assertEqual(expected_rule_map, rule_map)
|
||||||
|
|
||||||
def test_update_access_add_cifs(self):
|
def test_update_access_add_cifs(self):
|
||||||
@@ -609,7 +623,7 @@ class IsilonTest(test.TestCase):
|
|||||||
}
|
}
|
||||||
access_rules = [access]
|
access_rules = [access]
|
||||||
|
|
||||||
self._mock_isilon_api.get_user_sid.return_value = {
|
self._mock_powerscale_api.get_user_sid.return_value = {
|
||||||
'id': 'SID:S-1-5-22',
|
'id': 'SID:S-1-5-22',
|
||||||
'name': 'foo',
|
'name': 'foo',
|
||||||
'type': 'user',
|
'type': 'user',
|
||||||
@@ -628,8 +642,9 @@ class IsilonTest(test.TestCase):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
self._mock_isilon_api.modify_smb_share_access.assert_called_once_with(
|
self._mock_powerscale_api.modify_smb_share_access.\
|
||||||
self.SHARE_NAME, host_acl=[], permissions=expected_permissions)
|
assert_called_once_with(
|
||||||
|
self.SHARE_NAME, host_acl=[], permissions=expected_permissions)
|
||||||
expected_rule_map = {
|
expected_rule_map = {
|
||||||
'09960614-8574-4e03-89cf-7cf267b0bd08': {
|
'09960614-8574-4e03-89cf-7cf267b0bd08': {
|
||||||
'state': 'active'
|
'state': 'active'
|
||||||
@@ -643,20 +658,21 @@ class IsilonTest(test.TestCase):
|
|||||||
"share_proto": 'NFS',
|
"share_proto": 'NFS',
|
||||||
}
|
}
|
||||||
fake_export_id = 4
|
fake_export_id = 4
|
||||||
self._mock_isilon_api.lookup_nfs_export.return_value = fake_export_id
|
self._mock_powerscale_api.lookup_nfs_export.return_value = (
|
||||||
|
fake_export_id)
|
||||||
# simulate an IP added to the whitelist
|
# simulate an IP added to the whitelist
|
||||||
ip_addr = '10.0.0.4'
|
ip_addr = '10.0.0.4'
|
||||||
ip_addr_ro = '10.0.0.50'
|
ip_addr_ro = '10.0.0.50'
|
||||||
self._mock_isilon_api.get_nfs_export.return_value = {
|
self._mock_powerscale_api.get_nfs_export.return_value = {
|
||||||
'clients': [ip_addr], 'read_only_clients': [ip_addr_ro]}
|
'clients': [ip_addr], 'read_only_clients': [ip_addr_ro]}
|
||||||
access_rules = []
|
access_rules = []
|
||||||
self._mock_isilon_api.modify_nfs_export_access.return_value = True
|
self._mock_powerscale_api.modify_nfs_export_access.return_value = True
|
||||||
|
|
||||||
rule_map = self.storage_connection.update_access(
|
rule_map = self.storage_connection.update_access(
|
||||||
self.mock_context, share, access_rules, [], [])
|
self.mock_context, share, access_rules, [], [])
|
||||||
|
|
||||||
self._mock_isilon_api.modify_nfs_export_access.assert_called_once_with(
|
self._mock_powerscale_api.modify_nfs_export_access. \
|
||||||
fake_export_id, [], [])
|
assert_called_once_with(fake_export_id, [], [])
|
||||||
self.assertEqual({}, rule_map)
|
self.assertEqual({}, rule_map)
|
||||||
|
|
||||||
def test_update_access_delete_cifs(self):
|
def test_update_access_delete_cifs(self):
|
||||||
@@ -665,7 +681,7 @@ class IsilonTest(test.TestCase):
|
|||||||
"share_proto": 'CIFS',
|
"share_proto": 'CIFS',
|
||||||
}
|
}
|
||||||
access_rules = []
|
access_rules = []
|
||||||
self._mock_isilon_api.lookup_smb_share.return_value = {
|
self._mock_powerscale_api.lookup_smb_share.return_value = {
|
||||||
'permissions': [
|
'permissions': [
|
||||||
{
|
{
|
||||||
'permission': 'change',
|
'permission': 'change',
|
||||||
@@ -680,12 +696,13 @@ class IsilonTest(test.TestCase):
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
self._mock_isilon_api.modify_smb_share_access.return_value = None
|
self._mock_powerscale_api.modify_smb_share_access.return_value = None
|
||||||
rule_map = self.storage_connection.update_access(
|
rule_map = self.storage_connection.update_access(
|
||||||
self.mock_context, share, access_rules, [], [])
|
self.mock_context, share, access_rules, [], [])
|
||||||
|
|
||||||
self._mock_isilon_api.modify_smb_share_access.assert_called_once_with(
|
self._mock_powerscale_api.modify_smb_share_access.\
|
||||||
self.SHARE_NAME, host_acl=[], permissions=[])
|
assert_called_once_with(
|
||||||
|
self.SHARE_NAME, host_acl=[], permissions=[])
|
||||||
self.assertEqual({}, rule_map)
|
self.assertEqual({}, rule_map)
|
||||||
|
|
||||||
def test_update_access_nfs_share_not_found(self):
|
def test_update_access_nfs_share_not_found(self):
|
||||||
@@ -700,7 +717,7 @@ class IsilonTest(test.TestCase):
|
|||||||
'access_id': '09960614-8574-4e03-89cf-7cf267b0bd08'
|
'access_id': '09960614-8574-4e03-89cf-7cf267b0bd08'
|
||||||
}
|
}
|
||||||
access_rules = [access]
|
access_rules = [access]
|
||||||
self._mock_isilon_api.lookup_nfs_export.return_value = None
|
self._mock_powerscale_api.lookup_nfs_export.return_value = None
|
||||||
|
|
||||||
rule_map = self.storage_connection.update_access(
|
rule_map = self.storage_connection.update_access(
|
||||||
self.mock_context, share, access_rules, [], [])
|
self.mock_context, share, access_rules, [], [])
|
||||||
@@ -724,7 +741,7 @@ class IsilonTest(test.TestCase):
|
|||||||
'access_id': '09960614-8574-4e03-89cf-7cf267b0bd08'
|
'access_id': '09960614-8574-4e03-89cf-7cf267b0bd08'
|
||||||
}
|
}
|
||||||
access_rules = [access]
|
access_rules = [access]
|
||||||
self._mock_isilon_api.modify_nfs_export_access.return_value = False
|
self._mock_powerscale_api.modify_nfs_export_access.return_value = False
|
||||||
|
|
||||||
rule_map = self.storage_connection.update_access(
|
rule_map = self.storage_connection.update_access(
|
||||||
self.mock_context, share, access_rules, [], [])
|
self.mock_context, share, access_rules, [], [])
|
||||||
@@ -748,7 +765,7 @@ class IsilonTest(test.TestCase):
|
|||||||
'access_id': '09960614-8574-4e03-89cf-7cf267b0bd08'
|
'access_id': '09960614-8574-4e03-89cf-7cf267b0bd08'
|
||||||
}
|
}
|
||||||
access_rules = [access]
|
access_rules = [access]
|
||||||
self._mock_isilon_api.modify_smb_share_access.return_value = False
|
self._mock_powerscale_api.modify_smb_share_access.return_value = False
|
||||||
|
|
||||||
rule_map = self.storage_connection.update_access(
|
rule_map = self.storage_connection.update_access(
|
||||||
self.mock_context, share, access_rules, None, None)
|
self.mock_context, share, access_rules, None, None)
|
||||||
@@ -772,7 +789,7 @@ class IsilonTest(test.TestCase):
|
|||||||
'access_id': '09960614-8574-4e03-89cf-7cf267b0bd08'
|
'access_id': '09960614-8574-4e03-89cf-7cf267b0bd08'
|
||||||
}
|
}
|
||||||
access_rules = [access]
|
access_rules = [access]
|
||||||
self._mock_isilon_api.modify_smb_share_access.return_value = True
|
self._mock_powerscale_api.modify_smb_share_access.return_value = True
|
||||||
|
|
||||||
rule_map = self.storage_connection.update_access(
|
rule_map = self.storage_connection.update_access(
|
||||||
self.mock_context, share, access_rules, [], [])
|
self.mock_context, share, access_rules, [], [])
|
||||||
@@ -796,8 +813,8 @@ class IsilonTest(test.TestCase):
|
|||||||
'access_id': '09960614-8574-4e03-89cf-7cf267b0bd08'
|
'access_id': '09960614-8574-4e03-89cf-7cf267b0bd08'
|
||||||
}
|
}
|
||||||
access_rules = [access]
|
access_rules = [access]
|
||||||
self._mock_isilon_api.get_user_sid.return_value = None
|
self._mock_powerscale_api.get_user_sid.return_value = None
|
||||||
self._mock_isilon_api.modify_smb_share_access.return_value = True
|
self._mock_powerscale_api.modify_smb_share_access.return_value = True
|
||||||
|
|
||||||
rule_map = self.storage_connection.update_access(
|
rule_map = self.storage_connection.update_access(
|
||||||
self.mock_context, share, access_rules, [], [])
|
self.mock_context, share, access_rules, [], [])
|
||||||
@@ -839,8 +856,9 @@ class IsilonTest(test.TestCase):
|
|||||||
"share_proto": 'NFS',
|
"share_proto": 'NFS',
|
||||||
}
|
}
|
||||||
fake_export_id = 4
|
fake_export_id = 4
|
||||||
self._mock_isilon_api.lookup_nfs_export.return_value = fake_export_id
|
self._mock_powerscale_api.lookup_nfs_export.return_value = (
|
||||||
self._mock_isilon_api.get_nfs_export.return_value = {
|
fake_export_id)
|
||||||
|
self._mock_powerscale_api.get_nfs_export.return_value = {
|
||||||
'clients': ['10.1.1.8'],
|
'clients': ['10.1.1.8'],
|
||||||
'read_only_clients': ['10.2.0.2']
|
'read_only_clients': ['10.2.0.2']
|
||||||
}
|
}
|
||||||
@@ -858,7 +876,7 @@ class IsilonTest(test.TestCase):
|
|||||||
}
|
}
|
||||||
access_rules = [nfs_access_1, nfs_access_2]
|
access_rules = [nfs_access_1, nfs_access_2]
|
||||||
|
|
||||||
self._mock_isilon_api.modify_nfs_export_access.return_value = True
|
self._mock_powerscale_api.modify_nfs_export_access.return_value = True
|
||||||
|
|
||||||
rule_map = self.storage_connection.update_access(
|
rule_map = self.storage_connection.update_access(
|
||||||
self.mock_context, share, access_rules, [], [])
|
self.mock_context, share, access_rules, [], [])
|
||||||
@@ -871,8 +889,10 @@ class IsilonTest(test.TestCase):
|
|||||||
'state': 'active'
|
'state': 'active'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self._mock_isilon_api.modify_nfs_export_access.assert_called_once_with(
|
self._mock_powerscale_api.modify_nfs_export_access. \
|
||||||
fake_export_id, ['10.1.1.2'], ['10.1.1.10'])
|
assert_called_once_with(fake_export_id,
|
||||||
|
['10.1.1.2'],
|
||||||
|
['10.1.1.10'])
|
||||||
self.assertEqual(expected_rule_map, rule_map)
|
self.assertEqual(expected_rule_map, rule_map)
|
||||||
|
|
||||||
def test_update_access_recover_cifs(self):
|
def test_update_access_recover_cifs(self):
|
||||||
@@ -880,12 +900,12 @@ class IsilonTest(test.TestCase):
|
|||||||
"name": self.SHARE_NAME,
|
"name": self.SHARE_NAME,
|
||||||
"share_proto": 'CIFS',
|
"share_proto": 'CIFS',
|
||||||
}
|
}
|
||||||
self._mock_isilon_api.get_user_sid.return_value = {
|
self._mock_powerscale_api.get_user_sid.return_value = {
|
||||||
'id': 'SID:S-1-5-22',
|
'id': 'SID:S-1-5-22',
|
||||||
'name': 'testuser',
|
'name': 'testuser',
|
||||||
'type': 'user',
|
'type': 'user',
|
||||||
}
|
}
|
||||||
self._mock_isilon_api.modify_smb_share_access.return_value = True
|
self._mock_powerscale_api.modify_smb_share_access.return_value = True
|
||||||
access_1 = {
|
access_1 = {
|
||||||
'access_type': 'ip',
|
'access_type': 'ip',
|
||||||
'access_to': '10.1.1.10',
|
'access_to': '10.1.1.10',
|
||||||
@@ -925,13 +945,15 @@ class IsilonTest(test.TestCase):
|
|||||||
'state': 'active'
|
'state': 'active'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self._mock_isilon_api.lookup_smb_share.assert_not_called()
|
self._mock_powerscale_api.lookup_smb_share.assert_not_called()
|
||||||
self._mock_isilon_api.get_user_sid.assert_called_once_with('testuser')
|
self._mock_powerscale_api.get_user_sid.assert_called_once_with(
|
||||||
self._mock_isilon_api.modify_smb_share_access.assert_called_once_with(
|
'testuser')
|
||||||
self.SHARE_NAME,
|
self._mock_powerscale_api.modify_smb_share_access.\
|
||||||
host_acl=expected_data['host_acl'],
|
assert_called_once_with(
|
||||||
permissions=expected_data['permissions']
|
self.SHARE_NAME,
|
||||||
)
|
host_acl=expected_data['host_acl'],
|
||||||
|
permissions=expected_data['permissions']
|
||||||
|
)
|
||||||
self.assertEqual(expected_rule_map, rule_map)
|
self.assertEqual(expected_rule_map, rule_map)
|
||||||
|
|
||||||
def test_update_access_with_cifs_ip_readonly(self):
|
def test_update_access_with_cifs_ip_readonly(self):
|
||||||
@@ -951,46 +973,47 @@ class IsilonTest(test.TestCase):
|
|||||||
path = '/path/to/quota'
|
path = '/path/to/quota'
|
||||||
quota_id = '123'
|
quota_id = '123'
|
||||||
quota_data = {'id': quota_id}
|
quota_data = {'id': quota_id}
|
||||||
self._mock_isilon_api.quota_get.return_value = quota_data
|
self._mock_powerscale_api.quota_get.return_value = quota_data
|
||||||
self._mock_isilon_api.delete_quota.return_value = True
|
self._mock_powerscale_api.delete_quota.return_value = True
|
||||||
|
|
||||||
self.storage_connection._delete_quota(path)
|
self.storage_connection._delete_quota(path)
|
||||||
|
|
||||||
self._mock_isilon_api.quota_get.assert_called_once_with(
|
self._mock_powerscale_api.quota_get.assert_called_once_with(
|
||||||
path, 'directory')
|
path, 'directory')
|
||||||
self._mock_isilon_api.delete_quota.assert_called_once_with(quota_id)
|
self._mock_powerscale_api.delete_quota.assert_called_once_with(
|
||||||
|
quota_id)
|
||||||
|
|
||||||
def test_delete_quota_when_quota_does_not_exist(self):
|
def test_delete_quota_when_quota_does_not_exist(self):
|
||||||
path = '/path/to/quota'
|
path = '/path/to/quota'
|
||||||
self._mock_isilon_api.quota_get.return_value = None
|
self._mock_powerscale_api.quota_get.return_value = None
|
||||||
|
|
||||||
self.storage_connection._delete_quota(path)
|
self.storage_connection._delete_quota(path)
|
||||||
|
|
||||||
self._mock_isilon_api.quota_get.assert_called_once_with(
|
self._mock_powerscale_api.quota_get.assert_called_once_with(
|
||||||
path, 'directory')
|
path, 'directory')
|
||||||
self._mock_isilon_api.delete_quota.assert_not_called()
|
self._mock_powerscale_api.delete_quota.assert_not_called()
|
||||||
|
|
||||||
def test_delete_directory_when_path_exists(self):
|
def test_delete_directory_when_path_exists(self):
|
||||||
path = '/path/to/directory'
|
path = '/path/to/directory'
|
||||||
self.storage_connection._delete_directory(path)
|
self.storage_connection._delete_directory(path)
|
||||||
self._mock_isilon_api.is_path_existent.assert_called_with(path)
|
self._mock_powerscale_api.is_path_existent.assert_called_with(path)
|
||||||
self._mock_isilon_api.delete_path.assert_called_with(
|
self._mock_powerscale_api.delete_path.assert_called_with(
|
||||||
path, recursive=True)
|
path, recursive=True)
|
||||||
|
|
||||||
def test_delete_directory_when_path_does_not_exist(self):
|
def test_delete_directory_when_path_does_not_exist(self):
|
||||||
path = '/path/to/directory'
|
path = '/path/to/directory'
|
||||||
self._mock_isilon_api.is_path_existent.return_value = False
|
self._mock_powerscale_api.is_path_existent.return_value = False
|
||||||
self.storage_connection._delete_directory(path)
|
self.storage_connection._delete_directory(path)
|
||||||
self._mock_isilon_api.is_path_existent.assert_called_with(path)
|
self._mock_powerscale_api.is_path_existent.assert_called_with(path)
|
||||||
self._mock_isilon_api.delete_path.assert_not_called()
|
self._mock_powerscale_api.delete_path.assert_not_called()
|
||||||
|
|
||||||
def test_get_backend_info(self):
|
def test_get_backend_info(self):
|
||||||
self._mock_isilon_api.get_cluster_version.return_value = '1.0'
|
self._mock_powerscale_api.get_cluster_version.return_value = '1.0'
|
||||||
result = self.storage_connection.get_backend_info(None)
|
result = self.storage_connection.get_backend_info(None)
|
||||||
expected_info = {
|
expected_info = {
|
||||||
'driver_version': isilon.VERSION,
|
'driver_version': powerscale.VERSION,
|
||||||
'cluster_version': '1.0',
|
'cluster_version': '1.0',
|
||||||
'rest_server': self.ISILON_ADDR,
|
'rest_server': self.POWERSCALE_ADDR,
|
||||||
'rest_port': '8080',
|
'rest_port': '8080',
|
||||||
}
|
}
|
||||||
self.assertEqual(expected_info, result)
|
self.assertEqual(expected_info, result)
|
||||||
@@ -1005,7 +1028,7 @@ class IsilonTest(test.TestCase):
|
|||||||
location = '10.0.0.1:/ifs/my_share'
|
location = '10.0.0.1:/ifs/my_share'
|
||||||
self.storage_connection._get_container_path = mock.MagicMock(
|
self.storage_connection._get_container_path = mock.MagicMock(
|
||||||
return_value=container_path)
|
return_value=container_path)
|
||||||
self._mock_isilon_api.lookup_nfs_export.return_value = '123'
|
self._mock_powerscale_api.lookup_nfs_export.return_value = '123'
|
||||||
|
|
||||||
result = self.storage_connection.ensure_shares(None, [share])
|
result = self.storage_connection.ensure_shares(None, [share])
|
||||||
expected_result = {
|
expected_result = {
|
||||||
@@ -1024,7 +1047,7 @@ class IsilonTest(test.TestCase):
|
|||||||
'name': 'my_share',
|
'name': 'my_share',
|
||||||
}
|
}
|
||||||
location = '\\\\10.0.0.1\\my_share'
|
location = '\\\\10.0.0.1\\my_share'
|
||||||
self._mock_isilon_api.lookup_smb_share.return_value = share
|
self._mock_powerscale_api.lookup_smb_share.return_value = share
|
||||||
|
|
||||||
result = self.storage_connection.ensure_shares(None, [share])
|
result = self.storage_connection.ensure_shares(None, [share])
|
||||||
expected_result = {
|
expected_result = {
|
||||||
@@ -1042,7 +1065,7 @@ class IsilonTest(test.TestCase):
|
|||||||
'share_proto': 'NFS',
|
'share_proto': 'NFS',
|
||||||
'name': 'my_share',
|
'name': 'my_share',
|
||||||
}
|
}
|
||||||
self._mock_isilon_api.lookup_nfs_export.return_value = None
|
self._mock_powerscale_api.lookup_nfs_export.return_value = None
|
||||||
result = self.storage_connection.ensure_shares(None, [share])
|
result = self.storage_connection.ensure_shares(None, [share])
|
||||||
expected_result = {
|
expected_result = {
|
||||||
'123': {
|
'123': {
|
||||||
@@ -1059,7 +1082,7 @@ class IsilonTest(test.TestCase):
|
|||||||
'share_proto': 'CIFS',
|
'share_proto': 'CIFS',
|
||||||
'name': 'my_share',
|
'name': 'my_share',
|
||||||
}
|
}
|
||||||
self._mock_isilon_api.lookup_smb_share.return_value = None
|
self._mock_powerscale_api.lookup_smb_share.return_value = None
|
||||||
result = self.storage_connection.ensure_shares(None, [share])
|
result = self.storage_connection.ensure_shares(None, [share])
|
||||||
expected_result = {
|
expected_result = {
|
||||||
'123': {
|
'123': {
|
@@ -21,40 +21,40 @@ import requests
|
|||||||
import requests_mock
|
import requests_mock
|
||||||
|
|
||||||
from manila import exception
|
from manila import exception
|
||||||
from manila.share.drivers.dell_emc.plugins.isilon import isilon_api
|
from manila.share.drivers.dell_emc.plugins.powerscale import powerscale_api
|
||||||
from manila import test
|
from manila import test
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class IsilonApiTest(test.TestCase):
|
class PowerScaleApiTest(test.TestCase):
|
||||||
|
|
||||||
@mock.patch('manila.share.drivers.dell_emc.plugins.isilon.'
|
@mock.patch('manila.share.drivers.dell_emc.plugins.powerscale.'
|
||||||
'isilon_api.IsilonApi.create_session')
|
'powerscale_api.PowerScaleApi.create_session')
|
||||||
def setUp(self, mockup_create_session):
|
def setUp(self, mockup_create_session):
|
||||||
super(IsilonApiTest, self).setUp()
|
super(PowerScaleApiTest, self).setUp()
|
||||||
|
|
||||||
mockup_create_session.return_value = True
|
mockup_create_session.return_value = True
|
||||||
self._mock_url = 'https://localhost:8080'
|
self._mock_url = 'https://localhost:8080'
|
||||||
self.username = 'admin'
|
self.username = 'admin'
|
||||||
self.password = 'pwd'
|
self.password = 'pwd'
|
||||||
self.dir_permission = '0777'
|
self.dir_permission = '0777'
|
||||||
self.isilon_api = isilon_api.IsilonApi(
|
self.powerscale_api = powerscale_api.PowerScaleApi(
|
||||||
self._mock_url, self.username, self.password,
|
self._mock_url, self.username, self.password,
|
||||||
dir_permission=self.dir_permission
|
dir_permission=self.dir_permission
|
||||||
)
|
)
|
||||||
self.isilon_api_threshold = isilon_api.IsilonApi(
|
self.powerscale_api_threshold = powerscale_api.PowerScaleApi(
|
||||||
self._mock_url, self.username, self.password,
|
self._mock_url, self.username, self.password,
|
||||||
dir_permission=self.dir_permission,
|
dir_permission=self.dir_permission,
|
||||||
threshold_limit=80
|
threshold_limit=80
|
||||||
)
|
)
|
||||||
|
|
||||||
@mock.patch('manila.share.drivers.dell_emc.plugins.isilon.'
|
@mock.patch('manila.share.drivers.dell_emc.plugins.powerscale.'
|
||||||
'isilon_api.IsilonApi.create_session')
|
'powerscale_api.PowerScaleApi.create_session')
|
||||||
def test__init__login_failure(self, mockup_create_session):
|
def test__init__login_failure(self, mockup_create_session):
|
||||||
mockup_create_session.return_value = False
|
mockup_create_session.return_value = False
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.BadConfigurationException,
|
exception.BadConfigurationException,
|
||||||
self.isilon_api.__init__,
|
self.powerscale_api.__init__,
|
||||||
self._mock_url,
|
self._mock_url,
|
||||||
self.username,
|
self.username,
|
||||||
self.password,
|
self.password,
|
||||||
@@ -64,14 +64,14 @@ class IsilonApiTest(test.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test__verify_cert(self):
|
def test__verify_cert(self):
|
||||||
verify_cert = self.isilon_api.verify_ssl_cert
|
verify_cert = self.powerscale_api.verify_ssl_cert
|
||||||
certificate_path = self.isilon_api.certificate_path
|
certificate_path = self.powerscale_api.certificate_path
|
||||||
self.isilon_api.verify_ssl_cert = True
|
self.powerscale_api.verify_ssl_cert = True
|
||||||
self.isilon_api.certificate_path = "fake_certificate_path"
|
self.powerscale_api.certificate_path = "fake_certificate_path"
|
||||||
self.assertEqual(self.isilon_api._verify_cert,
|
self.assertEqual(self.powerscale_api._verify_cert,
|
||||||
self.isilon_api.certificate_path)
|
self.powerscale_api.certificate_path)
|
||||||
self.isilon_api.verify_ssl_cert = verify_cert
|
self.powerscale_api.verify_ssl_cert = verify_cert
|
||||||
self.isilon_api.certificate_path = certificate_path
|
self.powerscale_api.certificate_path = certificate_path
|
||||||
|
|
||||||
@mock.patch('requests.Session.request')
|
@mock.patch('requests.Session.request')
|
||||||
def test_create_session_success(self, mock_request):
|
def test_create_session_success(self, mock_request):
|
||||||
@@ -80,7 +80,8 @@ class IsilonApiTest(test.TestCase):
|
|||||||
mock_response.cookies = {'isisessid': 'test_session_token',
|
mock_response.cookies = {'isisessid': 'test_session_token',
|
||||||
'isicsrf': 'test_csrf_token'}
|
'isicsrf': 'test_csrf_token'}
|
||||||
mock_request.return_value = mock_response
|
mock_request.return_value = mock_response
|
||||||
result = self.isilon_api.create_session(self.username, self.password)
|
result = self.powerscale_api.create_session(
|
||||||
|
self.username, self.password)
|
||||||
mock_request.assert_called_once_with(
|
mock_request.assert_called_once_with(
|
||||||
'POST', self._mock_url + '/session/1/session',
|
'POST', self._mock_url + '/session/1/session',
|
||||||
headers={"Content-type": "application/json"},
|
headers={"Content-type": "application/json"},
|
||||||
@@ -90,8 +91,9 @@ class IsilonApiTest(test.TestCase):
|
|||||||
verify=False
|
verify=False
|
||||||
)
|
)
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
self.assertEqual(self.isilon_api.session_token, 'test_session_token')
|
self.assertEqual(self.powerscale_api.session_token,
|
||||||
self.assertEqual(self.isilon_api.csrf_token, 'test_csrf_token')
|
'test_session_token')
|
||||||
|
self.assertEqual(self.powerscale_api.csrf_token, 'test_csrf_token')
|
||||||
|
|
||||||
@mock.patch('requests.Session.request')
|
@mock.patch('requests.Session.request')
|
||||||
def test_create_session_failure(self, mock_request):
|
def test_create_session_failure(self, mock_request):
|
||||||
@@ -100,10 +102,11 @@ class IsilonApiTest(test.TestCase):
|
|||||||
mock_response.json.return_value = {
|
mock_response.json.return_value = {
|
||||||
'message': 'Username or password is incorrect.'}
|
'message': 'Username or password is incorrect.'}
|
||||||
mock_request.return_value = mock_response
|
mock_request.return_value = mock_response
|
||||||
result = self.isilon_api.create_session(self.username, self.password)
|
result = self.powerscale_api.create_session(
|
||||||
|
self.username, self.password)
|
||||||
self.assertFalse(result)
|
self.assertFalse(result)
|
||||||
self.assertIsNone(self.isilon_api.session_token)
|
self.assertIsNone(self.powerscale_api.session_token)
|
||||||
self.assertIsNone(self.isilon_api.csrf_token)
|
self.assertIsNone(self.powerscale_api.csrf_token)
|
||||||
|
|
||||||
@ddt.data(False, True)
|
@ddt.data(False, True)
|
||||||
def test_create_directory(self, is_recursive):
|
def test_create_directory(self, is_recursive):
|
||||||
@@ -112,8 +115,8 @@ class IsilonApiTest(test.TestCase):
|
|||||||
self.assertEqual(0, len(m.request_history))
|
self.assertEqual(0, len(m.request_history))
|
||||||
self._add_create_directory_response(m, path, is_recursive)
|
self._add_create_directory_response(m, path, is_recursive)
|
||||||
|
|
||||||
r = self.isilon_api.create_directory(path,
|
r = self.powerscale_api.create_directory(path,
|
||||||
recursive=is_recursive)
|
recursive=is_recursive)
|
||||||
|
|
||||||
self.assertTrue(r)
|
self.assertTrue(r)
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
@@ -123,14 +126,14 @@ class IsilonApiTest(test.TestCase):
|
|||||||
def test_create_directory_no_permission(self):
|
def test_create_directory_no_permission(self):
|
||||||
with requests_mock.Mocker() as m:
|
with requests_mock.Mocker() as m:
|
||||||
path = '/ifs/test'
|
path = '/ifs/test'
|
||||||
self.isilon_api.dir_permission = None
|
self.powerscale_api.dir_permission = None
|
||||||
self.assertEqual(0, len(m.request_history))
|
self.assertEqual(0, len(m.request_history))
|
||||||
self._add_create_directory_response(m, path, True)
|
self._add_create_directory_response(m, path, True)
|
||||||
|
|
||||||
r = self.isilon_api.create_directory(path,
|
r = self.powerscale_api.create_directory(path,
|
||||||
recursive=True)
|
recursive=True)
|
||||||
|
|
||||||
self.isilon_api.dir_permission = '0777'
|
self.powerscale_api.dir_permission = '0777'
|
||||||
self.assertTrue(r)
|
self.assertTrue(r)
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
request = m.request_history[0]
|
request = m.request_history[0]
|
||||||
@@ -195,7 +198,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
snapshot_name)
|
snapshot_name)
|
||||||
|
|
||||||
# Call method under test
|
# Call method under test
|
||||||
self.isilon_api.clone_snapshot(snapshot_name, fq_target_dir)
|
self.powerscale_api.clone_snapshot(snapshot_name, fq_target_dir)
|
||||||
|
|
||||||
# Verify calls needed to clone the source snapshot to the target dir
|
# Verify calls needed to clone the source snapshot to the target dir
|
||||||
expected_calls = []
|
expected_calls = []
|
||||||
@@ -203,8 +206,8 @@ class IsilonApiTest(test.TestCase):
|
|||||||
'file1', 'file2', 'dir1/file11', 'dir1/file12',
|
'file1', 'file2', 'dir1/file11', 'dir1/file12',
|
||||||
'dir2/file21', 'dir2/file22']
|
'dir2/file21', 'dir2/file22']
|
||||||
for path in clone_path_list:
|
for path in clone_path_list:
|
||||||
expected_call = IsilonApiTest.ExpectedCall(
|
expected_call = PowerScaleApiTest.ExpectedCall(
|
||||||
IsilonApiTest.ExpectedCall.FILE_CLONE,
|
PowerScaleApiTest.ExpectedCall.FILE_CLONE,
|
||||||
self._mock_url + '/namespace/ifs/admin/target/' + path,
|
self._mock_url + '/namespace/ifs/admin/target/' + path,
|
||||||
['/ifs/admin/target/' + path, '/ifs/admin/source/' + path,
|
['/ifs/admin/target/' + path, '/ifs/admin/source/' + path,
|
||||||
snapshot_name])
|
snapshot_name])
|
||||||
@@ -214,8 +217,8 @@ class IsilonApiTest(test.TestCase):
|
|||||||
('/dir2?recursive', '/dir2'),
|
('/dir2?recursive', '/dir2'),
|
||||||
('?recursive=', '')]
|
('?recursive=', '')]
|
||||||
for url, path in dir_path_list:
|
for url, path in dir_path_list:
|
||||||
expected_call = IsilonApiTest.ExpectedCall(
|
expected_call = PowerScaleApiTest.ExpectedCall(
|
||||||
IsilonApiTest.ExpectedCall.DIR_CREATION,
|
PowerScaleApiTest.ExpectedCall.DIR_CREATION,
|
||||||
self._mock_url + '/namespace/ifs/admin/target' + url,
|
self._mock_url + '/namespace/ifs/admin/target' + url,
|
||||||
['/ifs/admin/target' + path, False])
|
['/ifs/admin/target' + path, False])
|
||||||
expected_calls.append(expected_call)
|
expected_calls.append(expected_call)
|
||||||
@@ -258,7 +261,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
json_str = '{"my_json": "test123"}'
|
json_str = '{"my_json": "test123"}'
|
||||||
self._add_get_directory_listing_response(m, fq_dir_path, json_str)
|
self._add_get_directory_listing_response(m, fq_dir_path, json_str)
|
||||||
|
|
||||||
actual_json = self.isilon_api.get_directory_listing(fq_dir_path)
|
actual_json = self.powerscale_api.get_directory_listing(fq_dir_path)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
self.assertEqual(json.loads(json_str), actual_json)
|
self.assertEqual(json.loads(json_str), actual_json)
|
||||||
@@ -272,7 +275,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
m.head('{0}/namespace{1}'.format(self._mock_url, path),
|
m.head('{0}/namespace{1}'.format(self._mock_url, path),
|
||||||
status_code=status_code)
|
status_code=status_code)
|
||||||
|
|
||||||
r = self.isilon_api.is_path_existent(path)
|
r = self.powerscale_api.is_path_existent(path)
|
||||||
|
|
||||||
self.assertEqual(expected_return_value, r)
|
self.assertEqual(expected_return_value, r)
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
@@ -284,7 +287,8 @@ class IsilonApiTest(test.TestCase):
|
|||||||
status_code=400)
|
status_code=400)
|
||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
requests.exceptions.HTTPError, self.isilon_api.is_path_existent,
|
requests.exceptions.HTTPError,
|
||||||
|
self.powerscale_api.is_path_existent,
|
||||||
'/ifs/home/admin')
|
'/ifs/home/admin')
|
||||||
|
|
||||||
@ddt.data(
|
@ddt.data(
|
||||||
@@ -300,7 +304,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
self._add_get_snapshot_response(m, snapshot_name, json_body,
|
self._add_get_snapshot_response(m, snapshot_name, json_body,
|
||||||
status=status_code)
|
status=status_code)
|
||||||
|
|
||||||
r = self.isilon_api.get_snapshot(snapshot_name)
|
r = self.powerscale_api.get_snapshot(snapshot_name)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
self.assertEqual(expected_return_value, r)
|
self.assertEqual(expected_return_value, r)
|
||||||
@@ -313,7 +317,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
m, snapshot_name, json_body, status=400)
|
m, snapshot_name, json_body, status=400)
|
||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
requests.exceptions.HTTPError, self.isilon_api.get_snapshot,
|
requests.exceptions.HTTPError, self.powerscale_api.get_snapshot,
|
||||||
snapshot_name)
|
snapshot_name)
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
@@ -323,7 +327,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
m.get('{0}/platform/1/snapshot/snapshots'.format(self._mock_url),
|
m.get('{0}/platform/1/snapshot/snapshots'.format(self._mock_url),
|
||||||
status_code=200, json=json.loads(snapshot_json))
|
status_code=200, json=json.loads(snapshot_json))
|
||||||
|
|
||||||
r = self.isilon_api.get_snapshots()
|
r = self.powerscale_api.get_snapshots()
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
self.assertEqual(json.loads(snapshot_json), r)
|
self.assertEqual(json.loads(snapshot_json), r)
|
||||||
@@ -335,7 +339,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
status_code=404)
|
status_code=404)
|
||||||
|
|
||||||
self.assertRaises(requests.exceptions.HTTPError,
|
self.assertRaises(requests.exceptions.HTTPError,
|
||||||
self.isilon_api.get_snapshots)
|
self.powerscale_api.get_snapshots)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
|
|
||||||
@@ -355,7 +359,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
share_path.replace('/', '%2F')),
|
share_path.replace('/', '%2F')),
|
||||||
json=json.loads(response_json))
|
json=json.loads(response_json))
|
||||||
|
|
||||||
r = self.isilon_api.lookup_nfs_export(share_path)
|
r = self.powerscale_api.lookup_nfs_export(share_path)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
self.assertEqual(expected_return, r)
|
self.assertEqual(expected_return, r)
|
||||||
@@ -370,7 +374,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
.format(self._mock_url, export_id),
|
.format(self._mock_url, export_id),
|
||||||
json=json.loads(response_json), status_code=status_code)
|
json=json.loads(response_json), status_code=status_code)
|
||||||
|
|
||||||
r = self.isilon_api.get_nfs_export(export_id)
|
r = self.powerscale_api.get_nfs_export(export_id)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
self.assertEqual(json.loads('{"id": 1}'), r)
|
self.assertEqual(json.loads('{"id": 1}'), r)
|
||||||
@@ -385,7 +389,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
.format(self._mock_url, export_id),
|
.format(self._mock_url, export_id),
|
||||||
json=json.loads(response_json), status_code=status_code)
|
json=json.loads(response_json), status_code=status_code)
|
||||||
|
|
||||||
r = self.isilon_api.get_nfs_export(export_id)
|
r = self.powerscale_api.get_nfs_export(export_id)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
self.assertIsNone(r)
|
self.assertIsNone(r)
|
||||||
@@ -400,7 +404,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
.format(self._mock_url, share_name), status_code=200,
|
.format(self._mock_url, share_name), status_code=200,
|
||||||
json=json.loads(response_json))
|
json=json.loads(response_json))
|
||||||
|
|
||||||
r = self.isilon_api.lookup_smb_share(share_name)
|
r = self.powerscale_api.lookup_smb_share(share_name)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
self.assertEqual(json.loads(share_json), r)
|
self.assertEqual(json.loads(share_json), r)
|
||||||
@@ -412,7 +416,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
m.get('{0}/platform/1/protocols/smb/shares/{1}'.format(
|
m.get('{0}/platform/1/protocols/smb/shares/{1}'.format(
|
||||||
self._mock_url, share_name), status_code=404)
|
self._mock_url, share_name), status_code=404)
|
||||||
|
|
||||||
r = self.isilon_api.lookup_smb_share(share_name)
|
r = self.powerscale_api.lookup_smb_share(share_name)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
self.assertIsNone(r)
|
self.assertIsNone(r)
|
||||||
@@ -426,7 +430,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
m.post(self._mock_url + '/platform/1/protocols/nfs/exports',
|
m.post(self._mock_url + '/platform/1/protocols/nfs/exports',
|
||||||
status_code=status_code)
|
status_code=status_code)
|
||||||
|
|
||||||
r = self.isilon_api.create_nfs_export(export_path)
|
r = self.powerscale_api.create_nfs_export(export_path)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
call = m.request_history[0]
|
call = m.request_history[0]
|
||||||
@@ -445,7 +449,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
m.post(self._mock_url + '/platform/1/protocols/smb/shares',
|
m.post(self._mock_url + '/platform/1/protocols/smb/shares',
|
||||||
status_code=status_code)
|
status_code=status_code)
|
||||||
|
|
||||||
r = self.isilon_api.create_smb_share(share_name, share_path)
|
r = self.powerscale_api.create_smb_share(share_name, share_path)
|
||||||
|
|
||||||
self.assertEqual(expected_return_value, r)
|
self.assertEqual(expected_return_value, r)
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
@@ -465,7 +469,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
m.post(self._mock_url + '/platform/1/snapshot/snapshots',
|
m.post(self._mock_url + '/platform/1/snapshot/snapshots',
|
||||||
status_code=201)
|
status_code=201)
|
||||||
|
|
||||||
r = self.isilon_api.create_snapshot(snapshot_name, snapshot_path)
|
r = self.powerscale_api.create_snapshot(snapshot_name, snapshot_path)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
self.assertTrue(r)
|
self.assertTrue(r)
|
||||||
@@ -485,7 +489,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
status_code=404)
|
status_code=404)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.isilon_api.create_snapshot(snapshot_name, snapshot_path),
|
self.powerscale_api.create_snapshot(snapshot_name, snapshot_path),
|
||||||
False
|
False
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -497,7 +501,8 @@ class IsilonApiTest(test.TestCase):
|
|||||||
m.delete(self._mock_url + '/namespace' + fq_path + '?recursive='
|
m.delete(self._mock_url + '/namespace' + fq_path + '?recursive='
|
||||||
+ str(is_recursive_delete), status_code=204)
|
+ str(is_recursive_delete), status_code=204)
|
||||||
|
|
||||||
self.isilon_api.delete_path(fq_path, recursive=is_recursive_delete)
|
self.powerscale_api.delete_path(
|
||||||
|
fq_path, recursive=is_recursive_delete)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
|
|
||||||
@@ -507,8 +512,9 @@ class IsilonApiTest(test.TestCase):
|
|||||||
m.delete(self._mock_url + '/namespace' + fq_path + '?recursive=False',
|
m.delete(self._mock_url + '/namespace' + fq_path + '?recursive=False',
|
||||||
status_code=403)
|
status_code=403)
|
||||||
|
|
||||||
self.assertEqual(self.isilon_api.delete_path(fq_path, recursive=False),
|
self.assertEqual(
|
||||||
False)
|
self.powerscale_api.delete_path(
|
||||||
|
fq_path, recursive=False), False)
|
||||||
|
|
||||||
@ddt.data((204, True), (404, False))
|
@ddt.data((204, True), (404, False))
|
||||||
def test_delete_nfs_share(self, data):
|
def test_delete_nfs_share(self, data):
|
||||||
@@ -520,7 +526,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
.format(self._mock_url, share_number),
|
.format(self._mock_url, share_number),
|
||||||
status_code=status_code)
|
status_code=status_code)
|
||||||
|
|
||||||
r = self.isilon_api.delete_nfs_share(share_number)
|
r = self.powerscale_api.delete_nfs_share(share_number)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
self.assertEqual(expected_return_value, r)
|
self.assertEqual(expected_return_value, r)
|
||||||
@@ -536,7 +542,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
.format(self._mock_url, share_name),
|
.format(self._mock_url, share_name),
|
||||||
status_code=status_code)
|
status_code=status_code)
|
||||||
|
|
||||||
r = self.isilon_api.delete_smb_share(share_name)
|
r = self.powerscale_api.delete_smb_share(share_name)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
self.assertEqual(expected_return_value, r)
|
self.assertEqual(expected_return_value, r)
|
||||||
@@ -547,7 +553,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
m.delete(self._mock_url + '/platform/1/snapshot/snapshots/my_snapshot',
|
m.delete(self._mock_url + '/platform/1/snapshot/snapshots/my_snapshot',
|
||||||
status_code=204)
|
status_code=204)
|
||||||
|
|
||||||
self.isilon_api.delete_snapshot("my_snapshot")
|
self.powerscale_api.delete_snapshot("my_snapshot")
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
|
|
||||||
@@ -557,7 +563,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
status_code=403)
|
status_code=403)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.isilon_api.delete_snapshot("my_snapshot"), False)
|
self.powerscale_api.delete_snapshot("my_snapshot"), False)
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
def test_quota_create(self, m):
|
def test_quota_create(self, m):
|
||||||
@@ -566,7 +572,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
self.assertEqual(0, len(m.request_history))
|
self.assertEqual(0, len(m.request_history))
|
||||||
m.post(self._mock_url + '/platform/1/quota/quotas', status_code=201)
|
m.post(self._mock_url + '/platform/1/quota/quotas', status_code=201)
|
||||||
|
|
||||||
self.isilon_api.quota_create(quota_path, 'directory', quota_size)
|
self.powerscale_api.quota_create(quota_path, 'directory', quota_size)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
expected_request_json = {
|
expected_request_json = {
|
||||||
@@ -586,11 +592,14 @@ class IsilonApiTest(test.TestCase):
|
|||||||
quota_size = 100
|
quota_size = 100
|
||||||
self.assertEqual(0, len(m.request_history))
|
self.assertEqual(0, len(m.request_history))
|
||||||
m.post(self._mock_url + '/platform/1/quota/quotas', status_code=201)
|
m.post(self._mock_url + '/platform/1/quota/quotas', status_code=201)
|
||||||
self.isilon_api_threshold.quota_create(quota_path,
|
self.powerscale_api_threshold.quota_create(
|
||||||
'directory',
|
quota_path,
|
||||||
quota_size)
|
'directory',
|
||||||
|
quota_size
|
||||||
|
)
|
||||||
|
|
||||||
advisory_size = round(
|
advisory_size = round(
|
||||||
(quota_size * self.isilon_api_threshold.threshold_limit) / 100)
|
(quota_size * self.powerscale_api_threshold.threshold_limit) / 100)
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
expected_request_json = {
|
expected_request_json = {
|
||||||
'path': quota_path,
|
'path': quota_path,
|
||||||
@@ -612,7 +621,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
requests.exceptions.HTTPError,
|
requests.exceptions.HTTPError,
|
||||||
self.isilon_api.quota_create,
|
self.powerscale_api.quota_create,
|
||||||
quota_path, 'directory', 2
|
quota_path, 'directory', 2
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -625,7 +634,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
quota_path = "/ifs/manila/test"
|
quota_path = "/ifs/manila/test"
|
||||||
quota_type = "directory"
|
quota_type = "directory"
|
||||||
|
|
||||||
self.isilon_api.quota_get(quota_path, quota_type)
|
self.powerscale_api.quota_get(quota_path, quota_type)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
request_query_string = m.request_history[0].qs
|
request_query_string = m.request_history[0].qs
|
||||||
@@ -637,7 +646,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
self.assertEqual(0, len(m.request_history))
|
self.assertEqual(0, len(m.request_history))
|
||||||
m.get(self._mock_url + '/platform/1/quota/quotas', status_code=404)
|
m.get(self._mock_url + '/platform/1/quota/quotas', status_code=404)
|
||||||
|
|
||||||
response = self.isilon_api.quota_get(
|
response = self.powerscale_api.quota_get(
|
||||||
'/ifs/does_not_exist', 'directory')
|
'/ifs/does_not_exist', 'directory')
|
||||||
|
|
||||||
self.assertIsNone(response)
|
self.assertIsNone(response)
|
||||||
@@ -650,7 +659,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
m.put('{0}/platform/1/quota/quotas/{1}'.format(
|
m.put('{0}/platform/1/quota/quotas/{1}'.format(
|
||||||
self._mock_url, quota_id), status_code=204)
|
self._mock_url, quota_id), status_code=204)
|
||||||
|
|
||||||
self.isilon_api.quota_modify_size(quota_id, new_size)
|
self.powerscale_api.quota_modify_size(quota_id, new_size)
|
||||||
|
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
expected_request_body = {'thresholds': {'hard': new_size}}
|
expected_request_body = {'thresholds': {'hard': new_size}}
|
||||||
@@ -663,10 +672,10 @@ class IsilonApiTest(test.TestCase):
|
|||||||
quota_id = "ADEF1G"
|
quota_id = "ADEF1G"
|
||||||
new_size = 1024
|
new_size = 1024
|
||||||
advisory_size = round(
|
advisory_size = round(
|
||||||
(new_size * self.isilon_api_threshold.threshold_limit) / 100)
|
(new_size * self.powerscale_api_threshold.threshold_limit) / 100)
|
||||||
m.put('{0}/platform/1/quota/quotas/{1}'.format(
|
m.put('{0}/platform/1/quota/quotas/{1}'.format(
|
||||||
self._mock_url, quota_id), status_code=204)
|
self._mock_url, quota_id), status_code=204)
|
||||||
self.isilon_api_threshold.quota_modify_size(quota_id, new_size)
|
self.powerscale_api_threshold.quota_modify_size(quota_id, new_size)
|
||||||
self.assertEqual(1, len(m.request_history))
|
self.assertEqual(1, len(m.request_history))
|
||||||
expected_request_body = {'thresholds': {'hard': new_size,
|
expected_request_body = {'thresholds': {'hard': new_size,
|
||||||
'advisory': advisory_size}}
|
'advisory': advisory_size}}
|
||||||
@@ -681,7 +690,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
requests.exceptions.HTTPError,
|
requests.exceptions.HTTPError,
|
||||||
self.isilon_api.quota_modify_size,
|
self.powerscale_api.quota_modify_size,
|
||||||
quota_id, 1024
|
quota_id, 1024
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -700,7 +709,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
status_code=204
|
status_code=204
|
||||||
)
|
)
|
||||||
|
|
||||||
self.isilon_api.quota_set(quota_path, quota_type, quota_size)
|
self.powerscale_api.quota_set(quota_path, quota_type, quota_size)
|
||||||
|
|
||||||
expected_quota_modify_json = {'thresholds': {'hard': quota_size}}
|
expected_quota_modify_json = {'thresholds': {'hard': quota_size}}
|
||||||
quota_put_json = json.loads(m.request_history[1].body)
|
quota_put_json = json.loads(m.request_history[1].body)
|
||||||
@@ -717,7 +726,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
quota_type = 'directory'
|
quota_type = 'directory'
|
||||||
quota_size = 256
|
quota_size = 256
|
||||||
|
|
||||||
self.isilon_api.quota_set(quota_path, quota_type, quota_size)
|
self.powerscale_api.quota_set(quota_path, quota_type, quota_size)
|
||||||
|
|
||||||
# verify a call is made to create a quota
|
# verify a call is made to create a quota
|
||||||
expected_create_json = {
|
expected_create_json = {
|
||||||
@@ -737,7 +746,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
|
|
||||||
e = self.assertRaises(
|
e = self.assertRaises(
|
||||||
requests.exceptions.HTTPError,
|
requests.exceptions.HTTPError,
|
||||||
self.isilon_api.quota_set,
|
self.powerscale_api.quota_set,
|
||||||
'/ifs/does_not_exist', 'directory', 2048
|
'/ifs/does_not_exist', 'directory', 2048
|
||||||
)
|
)
|
||||||
self.assertEqual(400, e.response.status_code)
|
self.assertEqual(400, e.response.status_code)
|
||||||
@@ -746,29 +755,29 @@ class IsilonApiTest(test.TestCase):
|
|||||||
sid = {"id": "SID:S-1-22-1-0",
|
sid = {"id": "SID:S-1-22-1-0",
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"type": "user"}
|
"type": "user"}
|
||||||
self.isilon_api.auth_lookup_user = mock.MagicMock(
|
self.powerscale_api.auth_lookup_user = mock.MagicMock(
|
||||||
return_value={
|
return_value={
|
||||||
"mapping": [{"user": {"sid": sid}}]
|
"mapping": [{"user": {"sid": sid}}]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
expected_sid = self.isilon_api.get_user_sid('foo')
|
expected_sid = self.powerscale_api.get_user_sid('foo')
|
||||||
self.assertEqual(expected_sid, sid)
|
self.assertEqual(expected_sid, sid)
|
||||||
|
|
||||||
def test_get_user_sid_wrong_mappings(self):
|
def test_get_user_sid_wrong_mappings(self):
|
||||||
self.isilon_api.auth_lookup_user = mock.MagicMock(
|
self.powerscale_api.auth_lookup_user = mock.MagicMock(
|
||||||
return_value={
|
return_value={
|
||||||
"mapping": [{"user": {"sid": 'fake_sid1'}},
|
"mapping": [{"user": {"sid": 'fake_sid1'}},
|
||||||
{"user": {"sid": 'fake_sid2'}}]
|
{"user": {"sid": 'fake_sid2'}}]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
expected_sid = self.isilon_api.get_user_sid('foo')
|
expected_sid = self.powerscale_api.get_user_sid('foo')
|
||||||
self.assertIsNone(expected_sid)
|
self.assertIsNone(expected_sid)
|
||||||
|
|
||||||
def test_get_user_sid_user_not_found(self):
|
def test_get_user_sid_user_not_found(self):
|
||||||
self.isilon_api.auth_lookup_user = mock.MagicMock(
|
self.powerscale_api.auth_lookup_user = mock.MagicMock(
|
||||||
return_value=None
|
return_value=None
|
||||||
)
|
)
|
||||||
expected_sid = self.isilon_api.get_user_sid('foo')
|
expected_sid = self.powerscale_api.get_user_sid('foo')
|
||||||
self.assertIsNone(expected_sid)
|
self.assertIsNone(expected_sid)
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
@@ -789,7 +798,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
}
|
}
|
||||||
m.get(auth_url, status_code=200, json=auth_json)
|
m.get(auth_url, status_code=200, json=auth_json)
|
||||||
|
|
||||||
returned_auth_json = self.isilon_api.auth_lookup_user(user)
|
returned_auth_json = self.powerscale_api.auth_lookup_user(user)
|
||||||
self.assertEqual(auth_json, returned_auth_json)
|
self.assertEqual(auth_json, returned_auth_json)
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
@@ -798,7 +807,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
auth_url = '{0}/platform/1/auth/mapping/users/lookup?user={1}'.format(
|
auth_url = '{0}/platform/1/auth/mapping/users/lookup?user={1}'.format(
|
||||||
self._mock_url, user)
|
self._mock_url, user)
|
||||||
m.get(auth_url, status_code=404)
|
m.get(auth_url, status_code=404)
|
||||||
self.assertIsNone(self.isilon_api.auth_lookup_user(user))
|
self.assertIsNone(self.powerscale_api.auth_lookup_user(user))
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
def test_auth_lookup_user_with_backend_error(self, m):
|
def test_auth_lookup_user_with_backend_error(self, m):
|
||||||
@@ -806,7 +815,7 @@ class IsilonApiTest(test.TestCase):
|
|||||||
auth_url = '{0}/platform/1/auth/mapping/users/lookup?user={1}'.format(
|
auth_url = '{0}/platform/1/auth/mapping/users/lookup?user={1}'.format(
|
||||||
self._mock_url, user)
|
self._mock_url, user)
|
||||||
m.get(auth_url, status_code=400)
|
m.get(auth_url, status_code=400)
|
||||||
self.assertIsNone(self.isilon_api.auth_lookup_user(user))
|
self.assertIsNone(self.powerscale_api.auth_lookup_user(user))
|
||||||
|
|
||||||
def _add_create_directory_response(self, m, path, is_recursive):
|
def _add_create_directory_response(self, m, path, is_recursive):
|
||||||
url = '{0}/namespace{1}?recursive={2}'.format(
|
url = '{0}/namespace{1}?recursive={2}'.format(
|
||||||
@@ -854,87 +863,87 @@ class IsilonApiTest(test.TestCase):
|
|||||||
request.headers['x-isi-ifs-copy-source'])
|
request.headers['x-isi-ifs-copy-source'])
|
||||||
|
|
||||||
def test_modify_nfs_export_access_success(self):
|
def test_modify_nfs_export_access_success(self):
|
||||||
self.isilon_api.send_put_request = mock.MagicMock()
|
self.powerscale_api.send_put_request = mock.MagicMock()
|
||||||
share_id = '123'
|
share_id = '123'
|
||||||
ro_ips = ['10.0.0.1', '10.0.0.2']
|
ro_ips = ['10.0.0.1', '10.0.0.2']
|
||||||
rw_ips = ['10.0.0.3', '10.0.0.4']
|
rw_ips = ['10.0.0.3', '10.0.0.4']
|
||||||
self.isilon_api.modify_nfs_export_access(share_id, ro_ips, rw_ips)
|
self.powerscale_api.modify_nfs_export_access(share_id, ro_ips, rw_ips)
|
||||||
expected_url = '{0}/platform/1/protocols/nfs/exports/{1}'.format(
|
expected_url = '{0}/platform/1/protocols/nfs/exports/{1}'.format(
|
||||||
self.isilon_api.host_url, share_id)
|
self.powerscale_api.host_url, share_id)
|
||||||
expected_data = {'read_only_clients': ro_ips, 'clients': rw_ips}
|
expected_data = {'read_only_clients': ro_ips, 'clients': rw_ips}
|
||||||
self.isilon_api.send_put_request.assert_called_once_with(
|
self.powerscale_api.send_put_request.assert_called_once_with(
|
||||||
expected_url, data=expected_data)
|
expected_url, data=expected_data)
|
||||||
|
|
||||||
def test_modify_nfs_export_access_no_ro_ips(self):
|
def test_modify_nfs_export_access_no_ro_ips(self):
|
||||||
self.isilon_api.send_put_request = mock.MagicMock()
|
self.powerscale_api.send_put_request = mock.MagicMock()
|
||||||
share_id = '123'
|
share_id = '123'
|
||||||
rw_ips = ['10.0.0.3', '10.0.0.4']
|
rw_ips = ['10.0.0.3', '10.0.0.4']
|
||||||
self.isilon_api.modify_nfs_export_access(share_id, None, rw_ips)
|
self.powerscale_api.modify_nfs_export_access(share_id, None, rw_ips)
|
||||||
expected_url = '{0}/platform/1/protocols/nfs/exports/{1}'.format(
|
expected_url = '{0}/platform/1/protocols/nfs/exports/{1}'.format(
|
||||||
self.isilon_api.host_url, share_id)
|
self.powerscale_api.host_url, share_id)
|
||||||
expected_data = {'clients': rw_ips}
|
expected_data = {'clients': rw_ips}
|
||||||
self.isilon_api.send_put_request.assert_called_once_with(
|
self.powerscale_api.send_put_request.assert_called_once_with(
|
||||||
expected_url, data=expected_data)
|
expected_url, data=expected_data)
|
||||||
|
|
||||||
def test_modify_nfs_export_access_no_rw_ips(self):
|
def test_modify_nfs_export_access_no_rw_ips(self):
|
||||||
self.isilon_api.send_put_request = mock.MagicMock()
|
self.powerscale_api.send_put_request = mock.MagicMock()
|
||||||
share_id = '123'
|
share_id = '123'
|
||||||
ro_ips = ['10.0.0.1', '10.0.0.2']
|
ro_ips = ['10.0.0.1', '10.0.0.2']
|
||||||
self.isilon_api.modify_nfs_export_access(share_id, ro_ips, None)
|
self.powerscale_api.modify_nfs_export_access(share_id, ro_ips, None)
|
||||||
expected_url = '{0}/platform/1/protocols/nfs/exports/{1}'.format(
|
expected_url = '{0}/platform/1/protocols/nfs/exports/{1}'.format(
|
||||||
self.isilon_api.host_url, share_id)
|
self.powerscale_api.host_url, share_id)
|
||||||
expected_data = {'read_only_clients': ro_ips}
|
expected_data = {'read_only_clients': ro_ips}
|
||||||
self.isilon_api.send_put_request.assert_called_once_with(
|
self.powerscale_api.send_put_request.assert_called_once_with(
|
||||||
expected_url, data=expected_data)
|
expected_url, data=expected_data)
|
||||||
|
|
||||||
@mock.patch('requests.Session.request')
|
@mock.patch('requests.Session.request')
|
||||||
def test_request_with_401_response(self, mock_request):
|
def test_request_with_401_response(self, mock_request):
|
||||||
"""Test sending a request with a 401 Unauthorized response."""
|
"""Test sending a request with a 401 Unauthorized response."""
|
||||||
mock_request.return_value.status_code = 401
|
mock_request.return_value.status_code = 401
|
||||||
self.isilon_api.create_session = mock.MagicMock(return_value=True)
|
self.powerscale_api.create_session = mock.MagicMock(return_value=True)
|
||||||
self.isilon_api.request('GET', 'http://example.com/api/data')
|
self.powerscale_api.request('GET', 'http://example.com/api/data')
|
||||||
self.assertEqual(mock_request.call_count, 2)
|
self.assertEqual(mock_request.call_count, 2)
|
||||||
|
|
||||||
def test_delete_quota_sends_delete_request(self):
|
def test_delete_quota_sends_delete_request(self):
|
||||||
self.isilon_api.send_delete_request = mock.MagicMock()
|
self.powerscale_api.send_delete_request = mock.MagicMock()
|
||||||
quota_id = '123'
|
quota_id = '123'
|
||||||
self.isilon_api.delete_quota(quota_id)
|
self.powerscale_api.delete_quota(quota_id)
|
||||||
self.isilon_api.send_delete_request.assert_called_once_with(
|
self.powerscale_api.send_delete_request.assert_called_once_with(
|
||||||
'{0}/platform/1/quota/quotas/{1}'.format(
|
'{0}/platform/1/quota/quotas/{1}'.format(
|
||||||
self.isilon_api.host_url, quota_id)
|
self.powerscale_api.host_url, quota_id)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_delete_quota_raises_exception_on_error(self):
|
def test_delete_quota_raises_exception_on_error(self):
|
||||||
quota_id = '123'
|
quota_id = '123'
|
||||||
self.isilon_api.send_delete_request = mock.MagicMock(
|
self.powerscale_api.send_delete_request = mock.MagicMock(
|
||||||
side_effect=requests.exceptions.HTTPError)
|
side_effect=requests.exceptions.HTTPError)
|
||||||
self.assertRaises(requests.exceptions.HTTPError,
|
self.assertRaises(requests.exceptions.HTTPError,
|
||||||
self.isilon_api.delete_quota,
|
self.powerscale_api.delete_quota,
|
||||||
quota_id)
|
quota_id)
|
||||||
|
|
||||||
def test_get_space_stats_success(self):
|
def test_get_space_stats_success(self):
|
||||||
self.isilon_api.send_get_request = mock.MagicMock()
|
self.powerscale_api.send_get_request = mock.MagicMock()
|
||||||
self.isilon_api.send_get_request.return_value.status_code = 200
|
self.powerscale_api.send_get_request.return_value.status_code = 200
|
||||||
self.isilon_api.send_get_request.return_value.json.return_value = {
|
self.powerscale_api.send_get_request.return_value.json.return_value = {
|
||||||
'stats': [
|
'stats': [
|
||||||
{'key': 'ifs.bytes.free', 'value': 1000},
|
{'key': 'ifs.bytes.free', 'value': 1000},
|
||||||
{'key': 'ifs.bytes.total', 'value': 2000},
|
{'key': 'ifs.bytes.total', 'value': 2000},
|
||||||
{'key': 'ifs.bytes.used', 'value': 500}
|
{'key': 'ifs.bytes.used', 'value': 500}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
result = self.isilon_api.get_space_stats()
|
result = self.powerscale_api.get_space_stats()
|
||||||
self.assertEqual(result, {'total': 2000, 'free': 1000, 'used': 500})
|
self.assertEqual(result, {'total': 2000, 'free': 1000, 'used': 500})
|
||||||
|
|
||||||
def test_get_space_stats_failure(self):
|
def test_get_space_stats_failure(self):
|
||||||
self.isilon_api.send_get_request = mock.MagicMock()
|
self.powerscale_api.send_get_request = mock.MagicMock()
|
||||||
self.isilon_api.send_get_request.return_value.status_code = 400
|
self.powerscale_api.send_get_request.return_value.status_code = 400
|
||||||
self.assertRaises(exception.ShareBackendException,
|
self.assertRaises(exception.ShareBackendException,
|
||||||
self.isilon_api.get_space_stats)
|
self.powerscale_api.get_space_stats)
|
||||||
|
|
||||||
def test_get_allocated_space_success(self):
|
def test_get_allocated_space_success(self):
|
||||||
self.isilon_api.send_get_request = mock.MagicMock()
|
self.powerscale_api.send_get_request = mock.MagicMock()
|
||||||
self.isilon_api.send_get_request.return_value.status_code = 200
|
self.powerscale_api.send_get_request.return_value.status_code = 200
|
||||||
self.isilon_api.send_get_request.return_value.json.return_value = {
|
self.powerscale_api.send_get_request.return_value.json.return_value = {
|
||||||
'quotas': [
|
'quotas': [
|
||||||
{
|
{
|
||||||
'path': '/ifs/home',
|
'path': '/ifs/home',
|
||||||
@@ -962,86 +971,88 @@ class IsilonApiTest(test.TestCase):
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
result = self.isilon_api.get_allocated_space()
|
result = self.powerscale_api.get_allocated_space()
|
||||||
self.assertEqual(result, 2110.0)
|
self.assertEqual(result, 2110.0)
|
||||||
|
|
||||||
def test_get_allocated_space_failure(self):
|
def test_get_allocated_space_failure(self):
|
||||||
self.isilon_api.send_get_request = mock.MagicMock()
|
self.powerscale_api.send_get_request = mock.MagicMock()
|
||||||
self.isilon_api.send_get_request.return_value.status_code = 400
|
self.powerscale_api.send_get_request.return_value.status_code = 400
|
||||||
self.assertRaises(exception.ShareBackendException,
|
self.assertRaises(exception.ShareBackendException,
|
||||||
self.isilon_api.get_allocated_space)
|
self.powerscale_api.get_allocated_space)
|
||||||
|
|
||||||
def test_get_cluster_version_success(self):
|
def test_get_cluster_version_success(self):
|
||||||
self.isilon_api.send_get_request = mock.MagicMock()
|
self.powerscale_api.send_get_request = mock.MagicMock()
|
||||||
self.isilon_api.send_get_request.return_value.status_code = 200
|
self.powerscale_api.send_get_request.return_value.status_code = 200
|
||||||
self.isilon_api.send_get_request.return_value.json.return_value = {
|
self.powerscale_api.send_get_request.return_value.json.return_value = {
|
||||||
'nodes': [{'release': '1.0'}]}
|
'nodes': [{'release': '1.0'}]}
|
||||||
|
|
||||||
version = self.isilon_api.get_cluster_version()
|
version = self.powerscale_api.get_cluster_version()
|
||||||
self.assertEqual(version, '1.0')
|
self.assertEqual(version, '1.0')
|
||||||
self.isilon_api.send_get_request.assert_called_once_with(
|
self.powerscale_api.send_get_request.assert_called_once_with(
|
||||||
'{0}/platform/12/cluster/version'.format(self.isilon_api.host_url)
|
'{0}/platform/12/cluster/version'.format(
|
||||||
|
self.powerscale_api.host_url)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_get_cluster_version_failure(self):
|
def test_get_cluster_version_failure(self):
|
||||||
self.isilon_api.send_get_request = mock.MagicMock()
|
self.powerscale_api.send_get_request = mock.MagicMock()
|
||||||
self.isilon_api.send_get_request.return_value.status_code = 404
|
self.powerscale_api.send_get_request.return_value.status_code = 404
|
||||||
|
|
||||||
self.assertRaises(exception.ShareBackendException,
|
self.assertRaises(exception.ShareBackendException,
|
||||||
self.isilon_api.get_cluster_version)
|
self.powerscale_api.get_cluster_version)
|
||||||
|
|
||||||
self.isilon_api.send_get_request.assert_called_once_with(
|
self.powerscale_api.send_get_request.assert_called_once_with(
|
||||||
'{0}/platform/12/cluster/version'.format(self.isilon_api.host_url)
|
'{0}/platform/12/cluster/version'.format(
|
||||||
|
self.powerscale_api.host_url)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_modify_smb_share_access_with_host_acl_and_smb_permission(self):
|
def test_modify_smb_share_access_with_host_acl_and_smb_permission(self):
|
||||||
self.isilon_api.send_put_request = mock.MagicMock()
|
self.powerscale_api.send_put_request = mock.MagicMock()
|
||||||
share_name = 'my_share'
|
share_name = 'my_share'
|
||||||
host_acl = 'host1,host2'
|
host_acl = 'host1,host2'
|
||||||
smb_permission = 'read'
|
smb_permission = 'read'
|
||||||
self.isilon_api.modify_smb_share_access(
|
self.powerscale_api.modify_smb_share_access(
|
||||||
share_name, host_acl, smb_permission)
|
share_name, host_acl, smb_permission)
|
||||||
expected_url = '{0}/platform/1/protocols/smb/shares/{1}'.format(
|
expected_url = '{0}/platform/1/protocols/smb/shares/{1}'.format(
|
||||||
self.isilon_api.host_url, share_name)
|
self.powerscale_api.host_url, share_name)
|
||||||
expected_data = {'host_acl': host_acl, 'permissions': smb_permission}
|
expected_data = {'host_acl': host_acl, 'permissions': smb_permission}
|
||||||
self.isilon_api.send_put_request.assert_called_with(
|
self.powerscale_api.send_put_request.assert_called_with(
|
||||||
expected_url, data=expected_data)
|
expected_url, data=expected_data)
|
||||||
|
|
||||||
def test_modify_smb_share_access_with_host_acl_only(self):
|
def test_modify_smb_share_access_with_host_acl_only(self):
|
||||||
self.isilon_api.send_put_request = mock.MagicMock()
|
self.powerscale_api.send_put_request = mock.MagicMock()
|
||||||
share_name = 'my_share'
|
share_name = 'my_share'
|
||||||
host_acl = 'host1,host2'
|
host_acl = 'host1,host2'
|
||||||
self.isilon_api.modify_smb_share_access(share_name, host_acl)
|
self.powerscale_api.modify_smb_share_access(share_name, host_acl)
|
||||||
expected_url = '{0}/platform/1/protocols/smb/shares/{1}'.format(
|
expected_url = '{0}/platform/1/protocols/smb/shares/{1}'.format(
|
||||||
self.isilon_api.host_url, share_name)
|
self.powerscale_api.host_url, share_name)
|
||||||
expected_data = {'host_acl': host_acl}
|
expected_data = {'host_acl': host_acl}
|
||||||
self.isilon_api.send_put_request.assert_called_with(
|
self.powerscale_api.send_put_request.assert_called_with(
|
||||||
expected_url, data=expected_data)
|
expected_url, data=expected_data)
|
||||||
|
|
||||||
def test_modify_smb_share_access_with_smb_permission_only(self):
|
def test_modify_smb_share_access_with_smb_permission_only(self):
|
||||||
self.isilon_api.send_put_request = mock.MagicMock()
|
self.powerscale_api.send_put_request = mock.MagicMock()
|
||||||
share_name = 'my_share'
|
share_name = 'my_share'
|
||||||
smb_permission = 'read'
|
smb_permission = 'read'
|
||||||
self.isilon_api.modify_smb_share_access(
|
self.powerscale_api.modify_smb_share_access(
|
||||||
share_name, permissions=smb_permission)
|
share_name, permissions=smb_permission)
|
||||||
expected_url = '{0}/platform/1/protocols/smb/shares/{1}'.format(
|
expected_url = '{0}/platform/1/protocols/smb/shares/{1}'.format(
|
||||||
self.isilon_api.host_url, share_name)
|
self.powerscale_api.host_url, share_name)
|
||||||
expected_data = {'permissions': smb_permission}
|
expected_data = {'permissions': smb_permission}
|
||||||
self.isilon_api.send_put_request.assert_called_with(
|
self.powerscale_api.send_put_request.assert_called_with(
|
||||||
expected_url, data=expected_data)
|
expected_url, data=expected_data)
|
||||||
|
|
||||||
def test_modify_smb_share_access_with_no_arguments(self):
|
def test_modify_smb_share_access_with_no_arguments(self):
|
||||||
self.isilon_api.send_put_request = mock.MagicMock()
|
self.powerscale_api.send_put_request = mock.MagicMock()
|
||||||
share_name = 'my_share'
|
share_name = 'my_share'
|
||||||
self.isilon_api.modify_smb_share_access(share_name)
|
self.powerscale_api.modify_smb_share_access(share_name)
|
||||||
expected_url = '{0}/platform/1/protocols/smb/shares/{1}'.format(
|
expected_url = '{0}/platform/1/protocols/smb/shares/{1}'.format(
|
||||||
self.isilon_api.host_url, share_name)
|
self.powerscale_api.host_url, share_name)
|
||||||
expected_data = {}
|
expected_data = {}
|
||||||
self.isilon_api.send_put_request.assert_called_with(
|
self.powerscale_api.send_put_request.assert_called_with(
|
||||||
expected_url, data=expected_data)
|
expected_url, data=expected_data)
|
||||||
|
|
||||||
def test_modify_smb_share_access_with_http_error(self):
|
def test_modify_smb_share_access_with_http_error(self):
|
||||||
self.isilon_api.send_put_request = mock.MagicMock(
|
self.powerscale_api.send_put_request = mock.MagicMock(
|
||||||
side_effect=requests.exceptions.HTTPError
|
side_effect=requests.exceptions.HTTPError
|
||||||
)
|
)
|
||||||
share_name = 'my_share'
|
share_name = 'my_share'
|
||||||
@@ -1049,5 +1060,5 @@ class IsilonApiTest(test.TestCase):
|
|||||||
smb_permission = 'read'
|
smb_permission = 'read'
|
||||||
|
|
||||||
self.assertRaises(requests.exceptions.HTTPError,
|
self.assertRaises(requests.exceptions.HTTPError,
|
||||||
self.isilon_api.modify_smb_share_access,
|
self.powerscale_api.modify_smb_share_access,
|
||||||
share_name, host_acl, smb_permission)
|
share_name, host_acl, smb_permission)
|
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Rebrand from Isilon to PowerScale includes changing of tag names, directory
|
||||||
|
structure, file names and documentation.
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
Dell PowerScale Driver was previously the EMC Isilon Driver. If the
|
||||||
|
extra-spec``share_backend_name`` was set to ``isilon`` in share types
|
||||||
|
in the past, this needs to be changed to ``powerscale``.
|
||||||
|
``emc_share_backend`` configuration option must be switched from
|
||||||
|
``isilon`` to ``powerscale`` in manila.conf when you add the storage
|
||||||
|
backend.
|
@@ -76,7 +76,7 @@ oslo.policy.policies =
|
|||||||
manila.share.drivers.dell_emc.plugins =
|
manila.share.drivers.dell_emc.plugins =
|
||||||
vnx = manila.share.drivers.dell_emc.plugins.vnx.connection:VNXStorageConnection
|
vnx = manila.share.drivers.dell_emc.plugins.vnx.connection:VNXStorageConnection
|
||||||
unity = manila.share.drivers.dell_emc.plugins.unity.connection:UnityStorageConnection
|
unity = manila.share.drivers.dell_emc.plugins.unity.connection:UnityStorageConnection
|
||||||
isilon = manila.share.drivers.dell_emc.plugins.isilon.isilon:IsilonStorageConnection
|
powerscale = manila.share.drivers.dell_emc.plugins.powerscale.powerscale:PowerScaleStorageConnection
|
||||||
powermax = manila.share.drivers.dell_emc.plugins.powermax.connection:PowerMaxStorageConnection
|
powermax = manila.share.drivers.dell_emc.plugins.powermax.connection:PowerMaxStorageConnection
|
||||||
powerstore = manila.share.drivers.dell_emc.plugins.powerstore.connection:PowerStoreStorageConnection
|
powerstore = manila.share.drivers.dell_emc.plugins.powerstore.connection:PowerStoreStorageConnection
|
||||||
powerflex = manila.share.drivers.dell_emc.plugins.powerflex.connection:PowerFlexStorageConnection
|
powerflex = manila.share.drivers.dell_emc.plugins.powerflex.connection:PowerFlexStorageConnection
|
||||||
|
Reference in New Issue
Block a user