Merge "Refactor HP 3PAR share driver to now be HPE"
This commit is contained in:
commit
0c549ead18
@ -13,16 +13,21 @@
|
|||||||
License for the specific language governing permissions and limitations
|
License for the specific language governing permissions and limitations
|
||||||
under the License.
|
under the License.
|
||||||
|
|
||||||
HP 3PAR Driver
|
HPE 3PAR Driver
|
||||||
==============
|
==============
|
||||||
|
|
||||||
The HP 3PAR Manila driver provides NFS and CIFS shared file systems to
|
The HPE 3PAR Manila driver provides NFS and CIFS shared file systems to
|
||||||
OpenStack using HP 3PAR's File Persona capabilities.
|
OpenStack using HPE 3PAR's File Persona capabilities.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
In OpenStack releases prior to Mitaka this driver was called the
|
||||||
|
HP 3PAR driver. The Liberty configuration reference can be found
|
||||||
|
at: http://docs.openstack.org/liberty/config-reference/content/hp-3par-share-driver.html
|
||||||
|
|
||||||
Supported Operations
|
Supported Operations
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
The following operations are supported with HP 3PAR File Persona:
|
The following operations are supported with HPE 3PAR File Persona:
|
||||||
|
|
||||||
- Create/delete NFS and CIFS shares
|
- Create/delete NFS and CIFS shares
|
||||||
|
|
||||||
@ -58,18 +63,18 @@ Requirements
|
|||||||
|
|
||||||
On the system running the Manila share service:
|
On the system running the Manila share service:
|
||||||
|
|
||||||
- hp3parclient version 3.2.1 or newer from PyPI
|
- python-3parclient 4.0.0 or newer from PyPI.
|
||||||
|
|
||||||
On the HP 3PAR array:
|
On the HPE 3PAR array:
|
||||||
|
|
||||||
- HP 3PAR Operating System software version 3.2.1 MU3 or higher
|
- HPE 3PAR Operating System software version 3.2.1 MU3 or higher
|
||||||
- A license that enables the File Persona feature
|
- A license that enables the File Persona feature
|
||||||
- The array class and hardware configuration must support File Persona
|
- The array class and hardware configuration must support File Persona
|
||||||
|
|
||||||
Pre-Configuration on the HP 3PAR
|
Pre-Configuration on the HPE 3PAR
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
- HP 3PAR File Persona must be initialized and started (:code:`startfs`)
|
- HPE 3PAR File Persona must be initialized and started (:code:`startfs`)
|
||||||
- A File Provisioning Group (FPG) must be created for use with Manila
|
- A File Provisioning Group (FPG) must be created for use with Manila
|
||||||
- A Virtual File Server (VFS) must be created for the FPG
|
- A Virtual File Server (VFS) must be created for the FPG
|
||||||
- The VFS must be configured with an appropriate share export IP address
|
- The VFS must be configured with an appropriate share export IP address
|
||||||
@ -79,22 +84,22 @@ Backend Configuration
|
|||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
The following parameters need to be configured in the Manila configuration
|
The following parameters need to be configured in the Manila configuration
|
||||||
file for the HP 3PAR driver:
|
file for the HPE 3PAR driver:
|
||||||
|
|
||||||
- `share_backend_name` = <backend name to enable>
|
- `share_backend_name` = <backend name to enable>
|
||||||
- `share_driver` = manila.share.drivers.hp.hp_3par_driver.HP3ParShareDriver
|
- `share_driver` = manila.share.drivers.hpe.hpe_3par_driver.HPE3ParShareDriver
|
||||||
- `driver_handles_share_servers` = False
|
- `driver_handles_share_servers` = False
|
||||||
- `hp3par_fpg` = <FPG to use for share creation>
|
- `hpe3par_fpg` = <FPG to use for share creation>
|
||||||
- `hp3par_share_ip_address` = <IP address to use for share export location>
|
- `hpe3par_share_ip_address` = <IP address to use for share export location>
|
||||||
- `hp3par_san_ip` = <IP address for SSH access to the SAN controller>
|
- `hpe3par_san_ip` = <IP address for SSH access to the SAN controller>
|
||||||
- `hp3par_api_url` = <3PAR WS API Server URL>
|
- `hpe3par_api_url` = <3PAR WS API Server URL>
|
||||||
- `hp3par_username` = <3PAR username with the 'edit' role>
|
- `hpe3par_username` = <3PAR username with the 'edit' role>
|
||||||
- `hp3par_password` = <3PAR password for the user specified in hp3par_username>
|
- `hpe3par_password` = <3PAR password for the user specified in hpe3par_username>
|
||||||
- `hp3par_san_login` = <Username for SSH access to the SAN controller>
|
- `hpe3par_san_login` = <Username for SSH access to the SAN controller>
|
||||||
- `hp3par_san_password` = <Password for SSH access to the SAN controller>
|
- `hpe3par_san_password` = <Password for SSH access to the SAN controller>
|
||||||
- `hp3par_debug` = <False or True for extra debug logging>
|
- `hpe3par_debug` = <False or True for extra debug logging>
|
||||||
|
|
||||||
The `hp3par_share_ip_address` must be a valid IP address for the configured
|
The `hpe3par_share_ip_address` must be a valid IP address for the configured
|
||||||
FPG's VFS. This IP address is used in export locations for shares that are
|
FPG's VFS. This IP address is used in export locations for shares that are
|
||||||
created. Networking must be configured to allow connectivity from clients to
|
created. Networking must be configured to allow connectivity from clients to
|
||||||
shares.
|
shares.
|
||||||
@ -127,23 +132,23 @@ Manila requires that the share type includes the
|
|||||||
`driver_handles_share_servers` extra-spec. This ensures that the share
|
`driver_handles_share_servers` extra-spec. This ensures that the share
|
||||||
will be created on a backend that supports the requested
|
will be created on a backend that supports the requested
|
||||||
driver_handles_share_servers (share networks) capability.
|
driver_handles_share_servers (share networks) capability.
|
||||||
For the HP 3PAR driver, this must be set to False.
|
For the HPE 3PAR driver, this must be set to False.
|
||||||
|
|
||||||
Another common Manila extra-spec used to determine where a share is created
|
Another common Manila extra-spec used to determine where a share is created
|
||||||
is `share_backend_name`. When this extra-spec is defined in the share type,
|
is `share_backend_name`. When this extra-spec is defined in the share type,
|
||||||
the share will be created on a backend with a matching share_backend_name.
|
the share will be created on a backend with a matching share_backend_name.
|
||||||
|
|
||||||
The HP 3PAR driver automatically reports capabilities based on the FPG used
|
The HPE 3PAR driver automatically reports capabilities based on the FPG used
|
||||||
for each backend. Share types with extra specs can be created by an
|
for each backend. Share types with extra specs can be created by an
|
||||||
administrator to control which share types are allowed to use FPGs with or
|
administrator to control which share types are allowed to use FPGs with or
|
||||||
without specific capabilities. The following extra-specs are used with
|
without specific capabilities. The following extra-specs are used with
|
||||||
the capabilities filter and the HP 3PAR driver:
|
the capabilities filter and the HPE 3PAR driver:
|
||||||
|
|
||||||
- `hp3par_flash_cache` = '<is> True' or '<is> False'
|
- `hpe3par_flash_cache` = '<is> True' or '<is> False'
|
||||||
- `thin_provisioning` = '<is> True' or '<is> False'
|
- `thin_provisioning` = '<is> True' or '<is> False'
|
||||||
- `dedupe` = '<is> True' or '<is> False'
|
- `dedupe` = '<is> True' or '<is> False'
|
||||||
|
|
||||||
`hp3par_flash_cache` will be reported as True for backends that have
|
`hpe3par_flash_cache` will be reported as True for backends that have
|
||||||
3PAR's Adaptive Flash Cache enabled.
|
3PAR's Adaptive Flash Cache enabled.
|
||||||
|
|
||||||
`thin_provisioning` will be reported as True for backends that use thin
|
`thin_provisioning` will be reported as True for backends that use thin
|
||||||
@ -155,14 +160,16 @@ over-subscription feature.
|
|||||||
technology.
|
technology.
|
||||||
|
|
||||||
Scoped extra-specs are used to influence vendor-specific implementation
|
Scoped extra-specs are used to influence vendor-specific implementation
|
||||||
details. Scoped extra-specs use a prefix followed by a colon. For HP 3PAR
|
details. Scoped extra-specs use a prefix followed by a colon. For HPE 3PAR
|
||||||
these extra-specs have a prefix of `hp3par`.
|
these extra-specs have a prefix of `hpe3par`. For HP 3PAR these extra-specs
|
||||||
|
have a prefix of `hp3par`.
|
||||||
|
|
||||||
The following HP 3PAR extra-specs are used when creating CIFS (SMB) shares:
|
The following HPE 3PAR extra-specs are used when creating CIFS (SMB) shares:
|
||||||
|
|
||||||
|
- `hpe3par:smb_access_based_enum` = true or false
|
||||||
|
- `hpe3par:smb_continuous_avail` = true or false
|
||||||
|
- `hpe3par:smb_cache` = off, manual, optimized or auto
|
||||||
|
|
||||||
- `hp3par:smb_access_based_enum` = true or false
|
|
||||||
- `hp3par:smb_continuous_avail` = true or false
|
|
||||||
- `hp3par:smb_cache` = off, manual, optimized or auto
|
|
||||||
|
|
||||||
`smb_access_based_enum` (Access Based Enumeration) specifies if users can see
|
`smb_access_based_enum` (Access Based Enumeration) specifies if users can see
|
||||||
only the files and directories to which they have been allowed access on the
|
only the files and directories to which they have been allowed access on the
|
||||||
@ -188,25 +195,25 @@ or earlier.
|
|||||||
documents.
|
documents.
|
||||||
* If this is not specified, the default is `manual`.
|
* If this is not specified, the default is `manual`.
|
||||||
|
|
||||||
The following HP 3PAR extra-specs are used when creating NFS shares:
|
The following HPE 3PAR extra-specs are used when creating NFS shares:
|
||||||
|
|
||||||
- `hp3par:nfs_options` = Comma separated list of NFS export options
|
- `hpe3par:nfs_options` = Comma separated list of NFS export options
|
||||||
|
|
||||||
The NFS export options have the following limitations:
|
The NFS export options have the following limitations:
|
||||||
|
|
||||||
* `ro` and `rw` are not allowed (Manila will determine the read-only option)
|
* `ro` and `rw` are not allowed (Manila will determine the read-only option)
|
||||||
* `no_subtree_check` and `fsid` are not allowed per HP 3PAR CLI support
|
* `no_subtree_check` and `fsid` are not allowed per HPE 3PAR CLI support
|
||||||
* `(in)secure` and `(no_)root_squash` are not allowed because the HP 3PAR
|
* `(in)secure` and `(no_)root_squash` are not allowed because the HPE 3PAR
|
||||||
driver controls those settings
|
driver controls those settings
|
||||||
|
|
||||||
All other NFS options are forwarded to the HP 3PAR as part of share creation.
|
All other NFS options are forwarded to the HPE 3PAR as part of share creation.
|
||||||
The HP 3PAR will do additional validation at share creation time. Refer to
|
The HPE 3PAR will do additional validation at share creation time. Refer to
|
||||||
HP 3PAR CLI help for more details.
|
HPE 3PAR CLI help for more details.
|
||||||
|
|
||||||
The :mod:`manila.share.drivers.hp.hp_3par_driver` Module
|
The :mod:`manila.share.drivers.hpe.hpe_3par_driver` Module
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. automodule:: manila.share.drivers.hp.hp_3par_driver
|
.. automodule:: manila.share.drivers.hpe.hpe_3par_driver
|
||||||
:noindex:
|
:noindex:
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
@ -107,7 +107,7 @@ Share backends
|
|||||||
huawei_nas_driver
|
huawei_nas_driver
|
||||||
hdfs_native_driver
|
hdfs_native_driver
|
||||||
hds_hnas_driver
|
hds_hnas_driver
|
||||||
hp_3par_driver
|
hpe_3par_driver
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
------------------
|
------------------
|
||||||
|
@ -49,7 +49,7 @@ Mapping of share drivers and share features support
|
|||||||
+----------------------------------------+-----------------------------+-----------------------+--------------+--------------+------------------------+----------------------------+
|
+----------------------------------------+-----------------------------+-----------------------+--------------+--------------+------------------------+----------------------------+
|
||||||
| Hitachi HNAS | DHSS = False (L) | L | L | \- | L | L |
|
| Hitachi HNAS | DHSS = False (L) | L | L | \- | L | L |
|
||||||
+----------------------------------------+-----------------------------+-----------------------+--------------+--------------+------------------------+----------------------------+
|
+----------------------------------------+-----------------------------+-----------------------+--------------+--------------+------------------------+----------------------------+
|
||||||
| HP 3PAR | DHSS = True (L) & False (K) | \- | \- | \- | K | K |
|
| HPE 3PAR | DHSS = True (L) & False (K) | \- | \- | \- | K | K |
|
||||||
+----------------------------------------+-----------------------------+-----------------------+--------------+--------------+------------------------+----------------------------+
|
+----------------------------------------+-----------------------------+-----------------------+--------------+--------------+------------------------+----------------------------+
|
||||||
| Huawei | DHSS = False(K) | L | L | L | K | \- |
|
| Huawei | DHSS = False(K) | L | L | L | K | \- |
|
||||||
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
@ -90,7 +90,7 @@ Mapping of share drivers and share access rules support
|
|||||||
+----------------------------------------+--------------+------------+------------+--------------+------------+------------+
|
+----------------------------------------+--------------+------------+------------+--------------+------------+------------+
|
||||||
| Hitachi HNAS | NFS (L) | \- | \- | NFS (L) | \- | \- |
|
| Hitachi HNAS | NFS (L) | \- | \- | NFS (L) | \- | \- |
|
||||||
+----------------------------------------+--------------+------------+------------+--------------+------------+------------+
|
+----------------------------------------+--------------+------------+------------+--------------+------------+------------+
|
||||||
| HP 3PAR | NFS,CIFS (K) | CIFS (K) | \- | \- | \- | \- |
|
| HPE 3PAR | NFS,CIFS (K) | CIFS (K) | \- | \- | \- | \- |
|
||||||
+----------------------------------------+--------------+------------+------------+--------------+------------+------------+
|
+----------------------------------------+--------------+------------+------------+--------------+------------+------------+
|
||||||
| Huawei | NFS (K) | CIFS (K) | \- | NFS (K) | CIFS (K) | \- |
|
| Huawei | NFS (K) | CIFS (K) | \- | NFS (K) | CIFS (K) | \- |
|
||||||
+----------------------------------------+--------------+------------+------------+--------------+------------+------------+
|
+----------------------------------------+--------------+------------+------------+--------------+------------+------------+
|
||||||
@ -125,7 +125,7 @@ Mapping of share drivers and security services support
|
|||||||
+----------------------------------------+------------------+-----------------+------------------+
|
+----------------------------------------+------------------+-----------------+------------------+
|
||||||
| Hitachi HNAS | \- | \- | \- |
|
| Hitachi HNAS | \- | \- | \- |
|
||||||
+----------------------------------------+------------------+-----------------+------------------+
|
+----------------------------------------+------------------+-----------------+------------------+
|
||||||
| HP 3PAR | \- | \- | \- |
|
| HPE 3PAR | \- | \- | \- |
|
||||||
+----------------------------------------+------------------+-----------------+------------------+
|
+----------------------------------------+------------------+-----------------+------------------+
|
||||||
| Huawei | \- | \- | \- |
|
| Huawei | \- | \- | \- |
|
||||||
+----------------------------------------+------------------+-----------------+------------------+
|
+----------------------------------------+------------------+-----------------+------------------+
|
||||||
|
@ -599,15 +599,15 @@ class EMCVnxInvalidMoverID(ManilaException):
|
|||||||
message = _("Invalid mover or vdm %(id)s.")
|
message = _("Invalid mover or vdm %(id)s.")
|
||||||
|
|
||||||
|
|
||||||
class HP3ParInvalidClient(Invalid):
|
class HPE3ParInvalidClient(Invalid):
|
||||||
message = _("%(err)s")
|
message = _("%(err)s")
|
||||||
|
|
||||||
|
|
||||||
class HP3ParInvalid(Invalid):
|
class HPE3ParInvalid(Invalid):
|
||||||
message = _("%(err)s")
|
message = _("%(err)s")
|
||||||
|
|
||||||
|
|
||||||
class HP3ParUnexpectedError(ManilaException):
|
class HPE3ParUnexpectedError(ManilaException):
|
||||||
message = _("%(err)s")
|
message = _("%(err)s")
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ import manila.share.drivers.glusterfs.layout_directory
|
|||||||
import manila.share.drivers.glusterfs.layout_volume
|
import manila.share.drivers.glusterfs.layout_volume
|
||||||
import manila.share.drivers.hdfs.hdfs_native
|
import manila.share.drivers.hdfs.hdfs_native
|
||||||
import manila.share.drivers.hitachi.hds_hnas
|
import manila.share.drivers.hitachi.hds_hnas
|
||||||
import manila.share.drivers.hp.hp_3par_driver
|
import manila.share.drivers.hpe.hpe_3par_driver
|
||||||
import manila.share.drivers.huawei.huawei_nas
|
import manila.share.drivers.huawei.huawei_nas
|
||||||
import manila.share.drivers.ibm.gpfs
|
import manila.share.drivers.ibm.gpfs
|
||||||
import manila.share.drivers.netapp.options
|
import manila.share.drivers.netapp.options
|
||||||
@ -122,7 +122,7 @@ _global_opt_lists = [
|
|||||||
manila.share.drivers.glusterfs.layout_volume.glusterfs_volume_mapped_opts,
|
manila.share.drivers.glusterfs.layout_volume.glusterfs_volume_mapped_opts,
|
||||||
manila.share.drivers.hdfs.hdfs_native.hdfs_native_share_opts,
|
manila.share.drivers.hdfs.hdfs_native.hdfs_native_share_opts,
|
||||||
manila.share.drivers.hitachi.hds_hnas.hds_hnas_opts,
|
manila.share.drivers.hitachi.hds_hnas.hds_hnas_opts,
|
||||||
manila.share.drivers.hp.hp_3par_driver.HP3PAR_OPTS,
|
manila.share.drivers.hpe.hpe_3par_driver.HPE3PAR_OPTS,
|
||||||
manila.share.drivers.huawei.huawei_nas.huawei_opts,
|
manila.share.drivers.huawei.huawei_nas.huawei_opts,
|
||||||
manila.share.drivers.ibm.gpfs.gpfs_share_opts,
|
manila.share.drivers.ibm.gpfs.gpfs_share_opts,
|
||||||
manila.share.drivers.netapp.options.netapp_proxy_opts,
|
manila.share.drivers.netapp.options.netapp_proxy_opts,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright 2015 Hewlett Packard Development Company, L.P.
|
# Copyright 2015 Hewlett Packard Enterprise Development LP
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@ -12,7 +12,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
"""HP 3PAR Driver for OpenStack Manila."""
|
"""HPE 3PAR Driver for OpenStack Manila."""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import hashlib
|
import hashlib
|
||||||
@ -29,79 +29,93 @@ from manila import exception
|
|||||||
from manila.i18n import _
|
from manila.i18n import _
|
||||||
from manila.i18n import _LI
|
from manila.i18n import _LI
|
||||||
from manila.share import driver
|
from manila.share import driver
|
||||||
from manila.share.drivers.hp import hp_3par_mediator
|
from manila.share.drivers.hpe import hpe_3par_mediator
|
||||||
from manila.share import share_types
|
from manila.share import share_types
|
||||||
from manila import utils
|
from manila import utils
|
||||||
|
|
||||||
HP3PAR_OPTS = [
|
HPE3PAR_OPTS = [
|
||||||
cfg.StrOpt('hp3par_api_url',
|
cfg.StrOpt('hpe3par_api_url',
|
||||||
default='',
|
default='',
|
||||||
help="3PAR WSAPI Server Url like "
|
help="3PAR WSAPI Server Url like "
|
||||||
"https://<3par ip>:8080/api/v1"),
|
"https://<3par ip>:8080/api/v1",
|
||||||
cfg.StrOpt('hp3par_username',
|
deprecated_name='hp3par_api_url'),
|
||||||
|
cfg.StrOpt('hpe3par_username',
|
||||||
default='',
|
default='',
|
||||||
help="3PAR username with the 'edit' role"),
|
help="3PAR username with the 'edit' role",
|
||||||
cfg.StrOpt('hp3par_password',
|
deprecated_name='hp3par_username'),
|
||||||
|
cfg.StrOpt('hpe3par_password',
|
||||||
default='',
|
default='',
|
||||||
help="3PAR password for the user specified in hp3par_username",
|
help="3PAR password for the user specified in hpe3par_username",
|
||||||
secret=True),
|
secret=True,
|
||||||
cfg.StrOpt('hp3par_san_ip',
|
deprecated_name='hp3par_password'),
|
||||||
|
cfg.StrOpt('hpe3par_san_ip',
|
||||||
default='',
|
default='',
|
||||||
help="IP address of SAN controller"),
|
help="IP address of SAN controller",
|
||||||
cfg.StrOpt('hp3par_san_login',
|
deprecated_name='hp3par_san_ip'),
|
||||||
|
cfg.StrOpt('hpe3par_san_login',
|
||||||
default='',
|
default='',
|
||||||
help="Username for SAN controller"),
|
help="Username for SAN controller",
|
||||||
cfg.StrOpt('hp3par_san_password',
|
deprecated_name='hp3par_san_login'),
|
||||||
|
cfg.StrOpt('hpe3par_san_password',
|
||||||
default='',
|
default='',
|
||||||
help="Password for SAN controller",
|
help="Password for SAN controller",
|
||||||
secret=True),
|
secret=True,
|
||||||
cfg.PortOpt('hp3par_san_ssh_port',
|
deprecated_name='hp3par_san_password'),
|
||||||
|
cfg.PortOpt('hpe3par_san_ssh_port',
|
||||||
default=22,
|
default=22,
|
||||||
help='SSH port to use with SAN'),
|
help='SSH port to use with SAN',
|
||||||
cfg.StrOpt('hp3par_fpg',
|
deprecated_name='hp3par_san_ssh_port'),
|
||||||
|
cfg.StrOpt('hpe3par_fpg',
|
||||||
default="OpenStack",
|
default="OpenStack",
|
||||||
help="The File Provisioning Group (FPG) to use"),
|
help="The File Provisioning Group (FPG) to use",
|
||||||
cfg.StrOpt('hp3par_share_ip_address',
|
deprecated_name='hp3par_fpg'),
|
||||||
|
cfg.StrOpt('hpe3par_share_ip_address',
|
||||||
default='',
|
default='',
|
||||||
help="The IP address for shares not using a share server"),
|
help="The IP address for shares not using a share server",
|
||||||
cfg.BoolOpt('hp3par_fstore_per_share',
|
deprecated_name='hp3par_share_ip_address'),
|
||||||
|
cfg.BoolOpt('hpe3par_fstore_per_share',
|
||||||
default=False,
|
default=False,
|
||||||
help="Use one filestore per share"),
|
help="Use one filestore per share",
|
||||||
cfg.BoolOpt('hp3par_debug',
|
deprecated_name='hp3par_fstore_per_share'),
|
||||||
|
cfg.BoolOpt('hpe3par_debug',
|
||||||
default=False,
|
default=False,
|
||||||
help="Enable HTTP debugging to 3PAR"),
|
help="Enable HTTP debugging to 3PAR",
|
||||||
|
deprecated_name='hp3par_debug'),
|
||||||
]
|
]
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
CONF.register_opts(HP3PAR_OPTS)
|
CONF.register_opts(HPE3PAR_OPTS)
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class HP3ParShareDriver(driver.ShareDriver):
|
class HPE3ParShareDriver(driver.ShareDriver):
|
||||||
"""HP 3PAR driver for Manila.
|
"""HPE 3PAR driver for Manila.
|
||||||
|
|
||||||
Supports NFS and CIFS protocols on arrays with File Persona.
|
Supports NFS and CIFS protocols on arrays with File Persona.
|
||||||
|
|
||||||
Version history:
|
Version history:
|
||||||
1.0.00 - Begin Liberty development (post-Kilo)
|
1.0.0 - Begin Liberty development (post-Kilo)
|
||||||
1.0.01 - Report thin/dedup/hp_flash_cache capabilities
|
1.0.1 - Report thin/dedup/hp_flash_cache capabilities
|
||||||
1.0.02 - Add share server/share network support
|
1.0.2 - Add share server/share network support
|
||||||
|
2.0.0 - Rebranded HP to HPE
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
VERSION = "1.0.02"
|
VERSION = "2.0.0"
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(HP3ParShareDriver, self).__init__((True, False), *args, **kwargs)
|
super(HPE3ParShareDriver, self).__init__((True, False),
|
||||||
|
*args,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
self.configuration = kwargs.get('configuration', None)
|
self.configuration = kwargs.get('configuration', None)
|
||||||
self.configuration.append_config_values(HP3PAR_OPTS)
|
self.configuration.append_config_values(HPE3PAR_OPTS)
|
||||||
self.configuration.append_config_values(driver.ssh_opts)
|
self.configuration.append_config_values(driver.ssh_opts)
|
||||||
self.fpg = None
|
self.fpg = None
|
||||||
self.vfs = None
|
self.vfs = None
|
||||||
self.share_ip_address = None
|
self.share_ip_address = None
|
||||||
self._hp3par = None # mediator between driver and client
|
self._hpe3par = None # mediator between driver and client
|
||||||
|
|
||||||
def do_setup(self, context):
|
def do_setup(self, context):
|
||||||
"""Any initialization the share driver does while starting."""
|
"""Any initialization the share driver does while starting."""
|
||||||
@ -111,46 +125,47 @@ class HP3ParShareDriver(driver.ShareDriver):
|
|||||||
'version': self.VERSION})
|
'version': self.VERSION})
|
||||||
|
|
||||||
if not self.driver_handles_share_servers:
|
if not self.driver_handles_share_servers:
|
||||||
self.share_ip_address = self.configuration.hp3par_share_ip_address
|
self.share_ip_address = self.configuration.hpe3par_share_ip_address
|
||||||
if not self.share_ip_address:
|
if not self.share_ip_address:
|
||||||
raise exception.HP3ParInvalid(
|
raise exception.HPE3ParInvalid(
|
||||||
_("Unsupported configuration. "
|
_("Unsupported configuration. "
|
||||||
"hp3par_share_ip_address must be set when "
|
"hpe3par_share_ip_address must be set when "
|
||||||
"driver_handles_share_servers is False."))
|
"driver_handles_share_servers is False."))
|
||||||
|
|
||||||
mediator = hp_3par_mediator.HP3ParMediator(
|
mediator = hpe_3par_mediator.HPE3ParMediator(
|
||||||
hp3par_username=self.configuration.hp3par_username,
|
hpe3par_username=self.configuration.hpe3par_username,
|
||||||
hp3par_password=self.configuration.hp3par_password,
|
hpe3par_password=self.configuration.hpe3par_password,
|
||||||
hp3par_api_url=self.configuration.hp3par_api_url,
|
hpe3par_api_url=self.configuration.hpe3par_api_url,
|
||||||
hp3par_debug=self.configuration.hp3par_debug,
|
hpe3par_debug=self.configuration.hpe3par_debug,
|
||||||
hp3par_san_ip=self.configuration.hp3par_san_ip,
|
hpe3par_san_ip=self.configuration.hpe3par_san_ip,
|
||||||
hp3par_san_login=self.configuration.hp3par_san_login,
|
hpe3par_san_login=self.configuration.hpe3par_san_login,
|
||||||
hp3par_san_password=self.configuration.hp3par_san_password,
|
hpe3par_san_password=self.configuration.hpe3par_san_password,
|
||||||
hp3par_san_ssh_port=self.configuration.hp3par_san_ssh_port,
|
hpe3par_san_ssh_port=self.configuration.hpe3par_san_ssh_port,
|
||||||
hp3par_fstore_per_share=self.configuration.hp3par_fstore_per_share,
|
hpe3par_fstore_per_share=(self.configuration
|
||||||
|
.hpe3par_fstore_per_share),
|
||||||
ssh_conn_timeout=self.configuration.ssh_conn_timeout,
|
ssh_conn_timeout=self.configuration.ssh_conn_timeout,
|
||||||
)
|
)
|
||||||
|
|
||||||
mediator.do_setup()
|
mediator.do_setup()
|
||||||
|
|
||||||
# FPG must be configured and must exist.
|
# FPG must be configured and must exist.
|
||||||
self.fpg = self.configuration.safe_get('hp3par_fpg')
|
self.fpg = self.configuration.safe_get('hpe3par_fpg')
|
||||||
# Validate the FPG and discover the VFS
|
# Validate the FPG and discover the VFS
|
||||||
# This also validates the client, connection, firmware, WSAPI, FPG...
|
# This also validates the client, connection, firmware, WSAPI, FPG...
|
||||||
self.vfs = mediator.get_vfs_name(self.fpg)
|
self.vfs = mediator.get_vfs_name(self.fpg)
|
||||||
|
|
||||||
# Don't set _hp3par until it is ready. Otherwise _update_stats fails.
|
# Don't set _hpe3par until it is ready. Otherwise _update_stats fails.
|
||||||
self._hp3par = mediator
|
self._hpe3par = mediator
|
||||||
|
|
||||||
def check_for_setup_error(self):
|
def check_for_setup_error(self):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Log the source SHA for support. Only do this with DEBUG.
|
# Log the source SHA for support. Only do this with DEBUG.
|
||||||
if LOG.isEnabledFor(logging.DEBUG):
|
if LOG.isEnabledFor(logging.DEBUG):
|
||||||
LOG.debug('HP3ParShareDriver SHA1: %s',
|
LOG.debug('HPE3ParShareDriver SHA1: %s',
|
||||||
self.sha1_hash(HP3ParShareDriver))
|
self.sha1_hash(HPE3ParShareDriver))
|
||||||
LOG.debug('HP3ParMediator SHA1: %s',
|
LOG.debug('HPE3ParMediator SHA1: %s',
|
||||||
self.sha1_hash(hp_3par_mediator.HP3ParMediator))
|
self.sha1_hash(hpe_3par_mediator.HPE3ParMediator))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Don't let any exceptions during the SHA1 logging interfere
|
# Don't let any exceptions during the SHA1 logging interfere
|
||||||
# with startup. This is just debug info to identify the source
|
# with startup. This is just debug info to identify the source
|
||||||
@ -192,7 +207,7 @@ class HP3ParShareDriver(driver.ShareDriver):
|
|||||||
subnet = utils.cidr_to_netmask(network_info['cidr'])
|
subnet = utils.cidr_to_netmask(network_info['cidr'])
|
||||||
vlantag = network_info['segmentation_id']
|
vlantag = network_info['segmentation_id']
|
||||||
|
|
||||||
self._hp3par.create_fsip(ip, subnet, vlantag, self.fpg, self.vfs)
|
self._hpe3par.create_fsip(ip, subnet, vlantag, self.fpg, self.vfs)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'share_server_name': network_info['server_id'],
|
'share_server_name': network_info['server_id'],
|
||||||
@ -207,9 +222,9 @@ class HP3ParShareDriver(driver.ShareDriver):
|
|||||||
def _teardown_server(self, server_details, security_services=None):
|
def _teardown_server(self, server_details, security_services=None):
|
||||||
LOG.debug("begin _teardown_server with %s", server_details)
|
LOG.debug("begin _teardown_server with %s", server_details)
|
||||||
|
|
||||||
self._hp3par.remove_fsip(server_details.get('ip'),
|
self._hpe3par.remove_fsip(server_details.get('ip'),
|
||||||
server_details.get('fpg'),
|
server_details.get('fpg'),
|
||||||
server_details.get('vfs'))
|
server_details.get('vfs'))
|
||||||
|
|
||||||
def _get_share_ip(self, share_server):
|
def _get_share_ip(self, share_server):
|
||||||
return share_server['backend_details'].get('ip') if share_server else (
|
return share_server['backend_details'].get('ip') if share_server else (
|
||||||
@ -261,7 +276,7 @@ class HP3ParShareDriver(driver.ShareDriver):
|
|||||||
protocol = share['share_proto']
|
protocol = share['share_proto']
|
||||||
extra_specs = share_types.get_extra_specs_from_share(share)
|
extra_specs = share_types.get_extra_specs_from_share(share)
|
||||||
|
|
||||||
path = self._hp3par.create_share(
|
path = self._hpe3par.create_share(
|
||||||
share['project_id'],
|
share['project_id'],
|
||||||
share['id'],
|
share['id'],
|
||||||
protocol,
|
protocol,
|
||||||
@ -282,7 +297,7 @@ class HP3ParShareDriver(driver.ShareDriver):
|
|||||||
protocol = share['share_proto']
|
protocol = share['share_proto']
|
||||||
extra_specs = share_types.get_extra_specs_from_share(share)
|
extra_specs = share_types.get_extra_specs_from_share(share)
|
||||||
|
|
||||||
path = self._hp3par.create_share_from_snapshot(
|
path = self._hpe3par.create_share_from_snapshot(
|
||||||
share['id'],
|
share['id'],
|
||||||
protocol,
|
protocol,
|
||||||
extra_specs,
|
extra_specs,
|
||||||
@ -300,38 +315,48 @@ class HP3ParShareDriver(driver.ShareDriver):
|
|||||||
def delete_share(self, context, share, share_server=None):
|
def delete_share(self, context, share, share_server=None):
|
||||||
"""Deletes share and its fstore."""
|
"""Deletes share and its fstore."""
|
||||||
|
|
||||||
self._hp3par.delete_share(share['project_id'],
|
self._hpe3par.delete_share(share['project_id'],
|
||||||
share['id'],
|
share['id'],
|
||||||
share['share_proto'],
|
share['share_proto'],
|
||||||
self.fpg,
|
self.fpg,
|
||||||
self.vfs)
|
self.vfs)
|
||||||
|
|
||||||
def create_snapshot(self, context, snapshot, share_server=None):
|
def create_snapshot(self, context, snapshot, share_server=None):
|
||||||
"""Creates a snapshot of a share."""
|
"""Creates a snapshot of a share."""
|
||||||
|
|
||||||
self._hp3par.create_snapshot(snapshot['share']['project_id'],
|
self._hpe3par.create_snapshot(snapshot['share']['project_id'],
|
||||||
snapshot['share']['id'],
|
snapshot['share']['id'],
|
||||||
snapshot['share']['share_proto'],
|
snapshot['share']['share_proto'],
|
||||||
snapshot['id'],
|
snapshot['id'],
|
||||||
self.fpg,
|
self.fpg,
|
||||||
self.vfs)
|
self.vfs)
|
||||||
|
|
||||||
def delete_snapshot(self, context, snapshot, share_server=None):
|
def delete_snapshot(self, context, snapshot, share_server=None):
|
||||||
"""Deletes a snapshot of a share."""
|
"""Deletes a snapshot of a share."""
|
||||||
|
|
||||||
self._hp3par.delete_snapshot(snapshot['share']['project_id'],
|
self._hpe3par.delete_snapshot(snapshot['share']['project_id'],
|
||||||
snapshot['share']['id'],
|
snapshot['share']['id'],
|
||||||
snapshot['share']['share_proto'],
|
snapshot['share']['share_proto'],
|
||||||
snapshot['id'],
|
snapshot['id'],
|
||||||
self.fpg,
|
self.fpg,
|
||||||
self.vfs)
|
self.vfs)
|
||||||
|
|
||||||
def ensure_share(self, context, share, share_server=None):
|
def ensure_share(self, context, share, share_server=None):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def allow_access(self, context, share, access, share_server=None):
|
def allow_access(self, context, share, access, share_server=None):
|
||||||
"""Allow access to the share."""
|
"""Allow access to the share."""
|
||||||
self._hp3par.allow_access(share['project_id'],
|
self._hpe3par.allow_access(share['project_id'],
|
||||||
|
share['id'],
|
||||||
|
share['share_proto'],
|
||||||
|
access['access_type'],
|
||||||
|
access['access_to'],
|
||||||
|
self.fpg,
|
||||||
|
self.vfs)
|
||||||
|
|
||||||
|
def deny_access(self, context, share, access, share_server=None):
|
||||||
|
"""Deny access to the share."""
|
||||||
|
self._hpe3par.deny_access(share['project_id'],
|
||||||
share['id'],
|
share['id'],
|
||||||
share['share_proto'],
|
share['share_proto'],
|
||||||
access['access_type'],
|
access['access_type'],
|
||||||
@ -339,21 +364,11 @@ class HP3ParShareDriver(driver.ShareDriver):
|
|||||||
self.fpg,
|
self.fpg,
|
||||||
self.vfs)
|
self.vfs)
|
||||||
|
|
||||||
def deny_access(self, context, share, access, share_server=None):
|
|
||||||
"""Deny access to the share."""
|
|
||||||
self._hp3par.deny_access(share['project_id'],
|
|
||||||
share['id'],
|
|
||||||
share['share_proto'],
|
|
||||||
access['access_type'],
|
|
||||||
access['access_to'],
|
|
||||||
self.fpg,
|
|
||||||
self.vfs)
|
|
||||||
|
|
||||||
def _update_share_stats(self):
|
def _update_share_stats(self):
|
||||||
"""Retrieve stats info from share group."""
|
"""Retrieve stats info from share group."""
|
||||||
|
|
||||||
backend_name = self.configuration.safe_get(
|
backend_name = self.configuration.safe_get(
|
||||||
'share_backend_name') or "HP_3PAR"
|
'share_backend_name') or "HPE_3PAR"
|
||||||
|
|
||||||
max_over_subscription_ratio = self.configuration.safe_get(
|
max_over_subscription_ratio = self.configuration.safe_get(
|
||||||
'max_over_subscription_ratio')
|
'max_over_subscription_ratio')
|
||||||
@ -366,7 +381,7 @@ class HP3ParShareDriver(driver.ShareDriver):
|
|||||||
stats = {
|
stats = {
|
||||||
'share_backend_name': backend_name,
|
'share_backend_name': backend_name,
|
||||||
'driver_handles_share_servers': self.driver_handles_share_servers,
|
'driver_handles_share_servers': self.driver_handles_share_servers,
|
||||||
'vendor_name': 'HP',
|
'vendor_name': 'HPE',
|
||||||
'driver_version': self.VERSION,
|
'driver_version': self.VERSION,
|
||||||
'storage_protocol': 'NFS_CIFS',
|
'storage_protocol': 'NFS_CIFS',
|
||||||
'total_capacity_gb': 0,
|
'total_capacity_gb': 0,
|
||||||
@ -378,13 +393,13 @@ class HP3ParShareDriver(driver.ShareDriver):
|
|||||||
'thin_provisioning': True, # 3PAR default is thin
|
'thin_provisioning': True, # 3PAR default is thin
|
||||||
}
|
}
|
||||||
|
|
||||||
if not self._hp3par:
|
if not self._hpe3par:
|
||||||
LOG.info(
|
LOG.info(
|
||||||
_LI("Skipping capacity and capabilities update. Setup has not "
|
_LI("Skipping capacity and capabilities update. Setup has not "
|
||||||
"completed."))
|
"completed."))
|
||||||
else:
|
else:
|
||||||
fpg_status = self._hp3par.get_fpg_status(self.fpg)
|
fpg_status = self._hpe3par.get_fpg_status(self.fpg)
|
||||||
LOG.debug("FPG status = %s.", fpg_status)
|
LOG.debug("FPG status = %s.", fpg_status)
|
||||||
stats.update(fpg_status)
|
stats.update(fpg_status)
|
||||||
|
|
||||||
super(HP3ParShareDriver, self)._update_share_stats(stats)
|
super(HPE3ParShareDriver, self)._update_share_stats(stats)
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright 2015 Hewlett Packard Development Company, L.P.
|
# Copyright 2015 Hewlett Packard Enterprise Development LP
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@ -12,7 +12,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
"""HP 3PAR Mediator for OpenStack Manila.
|
"""HPE 3PAR Mediator for OpenStack Manila.
|
||||||
|
|
||||||
This 'mediator' de-couples the 3PAR focused client from the OpenStack focused
|
This 'mediator' de-couples the 3PAR focused client from the OpenStack focused
|
||||||
driver.
|
driver.
|
||||||
@ -26,14 +26,13 @@ import six
|
|||||||
from manila import exception
|
from manila import exception
|
||||||
from manila.i18n import _, _LI, _LW
|
from manila.i18n import _, _LI, _LW
|
||||||
|
|
||||||
hp3parclient = importutils.try_import("hp3parclient")
|
hpe3parclient = importutils.try_import("hpe3parclient")
|
||||||
if hp3parclient:
|
if hpe3parclient:
|
||||||
from hp3parclient import file_client
|
from hpe3parclient import file_client
|
||||||
|
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
MIN_CLIENT_VERSION = (3, 2, 1)
|
MIN_CLIENT_VERSION = (4, 0, 0)
|
||||||
MIN_SMB_CA_VERSION = (3, 2, 2)
|
|
||||||
DENY = '-'
|
DENY = '-'
|
||||||
ALLOW = '+'
|
ALLOW = '+'
|
||||||
OPEN_STACK_MANILA = 'OpenStack Manila'
|
OPEN_STACK_MANILA = 'OpenStack Manila'
|
||||||
@ -52,31 +51,32 @@ SMB_EXTRA_SPECS_MAP = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class HP3ParMediator(object):
|
class HPE3ParMediator(object):
|
||||||
"""3PAR client-facing code for the 3PAR driver.
|
"""3PAR client-facing code for the 3PAR driver.
|
||||||
|
|
||||||
Version history:
|
Version history:
|
||||||
1.0.00 - Begin Liberty development (post-Kilo)
|
1.0.0 - Begin Liberty development (post-Kilo)
|
||||||
1.0.01 - Report thin/dedup/hp_flash_cache capabilities
|
1.0.1 - Report thin/dedup/hp_flash_cache capabilities
|
||||||
1.0.02 - Add share server/share network support
|
1.0.2 - Add share server/share network support
|
||||||
1.0.03 - Use hp3par prefix for share types and capabilities
|
1.0.3 - Use hp3par prefix for share types and capabilities
|
||||||
|
2.0.0 - Rebranded HP to HPE
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
VERSION = "1.0.03"
|
VERSION = "2.0.0"
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
|
|
||||||
self.hp3par_username = kwargs.get('hp3par_username')
|
self.hpe3par_username = kwargs.get('hpe3par_username')
|
||||||
self.hp3par_password = kwargs.get('hp3par_password')
|
self.hpe3par_password = kwargs.get('hpe3par_password')
|
||||||
self.hp3par_api_url = kwargs.get('hp3par_api_url')
|
self.hpe3par_api_url = kwargs.get('hpe3par_api_url')
|
||||||
self.hp3par_debug = kwargs.get('hp3par_debug')
|
self.hpe3par_debug = kwargs.get('hpe3par_debug')
|
||||||
self.hp3par_san_ip = kwargs.get('hp3par_san_ip')
|
self.hpe3par_san_ip = kwargs.get('hpe3par_san_ip')
|
||||||
self.hp3par_san_login = kwargs.get('hp3par_san_login')
|
self.hpe3par_san_login = kwargs.get('hpe3par_san_login')
|
||||||
self.hp3par_san_password = kwargs.get('hp3par_san_password')
|
self.hpe3par_san_password = kwargs.get('hpe3par_san_password')
|
||||||
self.hp3par_san_ssh_port = kwargs.get('hp3par_san_ssh_port')
|
self.hpe3par_san_ssh_port = kwargs.get('hpe3par_san_ssh_port')
|
||||||
self.hp3par_san_private_key = kwargs.get('hp3par_san_private_key')
|
self.hpe3par_san_private_key = kwargs.get('hpe3par_san_private_key')
|
||||||
self.hp3par_fstore_per_share = kwargs.get('hp3par_fstore_per_share')
|
self.hpe3par_fstore_per_share = kwargs.get('hpe3par_fstore_per_share')
|
||||||
|
|
||||||
self.ssh_conn_timeout = kwargs.get('ssh_conn_timeout')
|
self.ssh_conn_timeout = kwargs.get('ssh_conn_timeout')
|
||||||
self._client = None
|
self._client = None
|
||||||
@ -84,61 +84,61 @@ class HP3ParMediator(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def no_client():
|
def no_client():
|
||||||
return hp3parclient is None
|
return hpe3parclient is None
|
||||||
|
|
||||||
def do_setup(self):
|
def do_setup(self):
|
||||||
|
|
||||||
if self.no_client():
|
if self.no_client():
|
||||||
msg = _('You must install hp3parclient before using the 3PAR '
|
msg = _('You must install hpe3parclient before using the 3PAR '
|
||||||
'driver.')
|
'driver.')
|
||||||
LOG.error(msg)
|
LOG.error(msg)
|
||||||
raise exception.HP3ParInvalidClient(message=msg)
|
raise exception.HPE3ParInvalidClient(message=msg)
|
||||||
|
|
||||||
self.client_version = hp3parclient.version_tuple
|
self.client_version = hpe3parclient.version_tuple
|
||||||
if self.client_version < MIN_CLIENT_VERSION:
|
if self.client_version < MIN_CLIENT_VERSION:
|
||||||
msg = (_('Invalid hp3parclient version found (%(found)s). '
|
msg = (_('Invalid hpe3parclient version found (%(found)s). '
|
||||||
'Version %(minimum)s or greater required.') %
|
'Version %(minimum)s or greater required.') %
|
||||||
{'found': '.'.join(map(six.text_type, self.client_version)),
|
{'found': '.'.join(map(six.text_type, self.client_version)),
|
||||||
'minimum': '.'.join(map(six.text_type,
|
'minimum': '.'.join(map(six.text_type,
|
||||||
MIN_CLIENT_VERSION))})
|
MIN_CLIENT_VERSION))})
|
||||||
LOG.error(msg)
|
LOG.error(msg)
|
||||||
raise exception.HP3ParInvalidClient(message=msg)
|
raise exception.HPE3ParInvalidClient(message=msg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._client = file_client.HP3ParFilePersonaClient(
|
self._client = file_client.HPE3ParFilePersonaClient(
|
||||||
self.hp3par_api_url)
|
self.hpe3par_api_url)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
msg = (_('Failed to connect to HP 3PAR File Persona Client: %s') %
|
msg = (_('Failed to connect to HPE 3PAR File Persona Client: %s') %
|
||||||
six.text_type(e))
|
six.text_type(e))
|
||||||
LOG.exception(msg)
|
LOG.exception(msg)
|
||||||
raise exception.ShareBackendException(message=msg)
|
raise exception.ShareBackendException(message=msg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ssh_kwargs = {}
|
ssh_kwargs = {}
|
||||||
if self.hp3par_san_ssh_port:
|
if self.hpe3par_san_ssh_port:
|
||||||
ssh_kwargs['port'] = self.hp3par_san_ssh_port
|
ssh_kwargs['port'] = self.hpe3par_san_ssh_port
|
||||||
if self.ssh_conn_timeout:
|
if self.ssh_conn_timeout:
|
||||||
ssh_kwargs['conn_timeout'] = self.ssh_conn_timeout
|
ssh_kwargs['conn_timeout'] = self.ssh_conn_timeout
|
||||||
if self.hp3par_san_private_key:
|
if self.hpe3par_san_private_key:
|
||||||
ssh_kwargs['privatekey'] = self.hp3par_san_private_key
|
ssh_kwargs['privatekey'] = self.hpe3par_san_private_key
|
||||||
|
|
||||||
self._client.setSSHOptions(
|
self._client.setSSHOptions(
|
||||||
self.hp3par_san_ip,
|
self.hpe3par_san_ip,
|
||||||
self.hp3par_san_login,
|
self.hpe3par_san_login,
|
||||||
self.hp3par_san_password,
|
self.hpe3par_san_password,
|
||||||
**ssh_kwargs
|
**ssh_kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
msg = (_('Failed to set SSH options for HP 3PAR File Persona '
|
msg = (_('Failed to set SSH options for HPE 3PAR File Persona '
|
||||||
'Client: %s') % six.text_type(e))
|
'Client: %s') % six.text_type(e))
|
||||||
LOG.exception(msg)
|
LOG.exception(msg)
|
||||||
raise exception.ShareBackendException(message=msg)
|
raise exception.ShareBackendException(message=msg)
|
||||||
|
|
||||||
LOG.info(_LI("HP3ParMediator %(version)s, "
|
LOG.info(_LI("HPE3ParMediator %(version)s, "
|
||||||
"hp3parclient %(client_version)s"),
|
"hpe3parclient %(client_version)s"),
|
||||||
{"version": self.VERSION,
|
{"version": self.VERSION,
|
||||||
"client_version": hp3parclient.get_version_string()})
|
"client_version": hpe3parclient.get_version_string()})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
wsapi_version = self._client.getWsApiVersion()['build']
|
wsapi_version = self._client.getWsApiVersion()['build']
|
||||||
@ -149,17 +149,17 @@ class HP3ParMediator(object):
|
|||||||
LOG.exception(msg)
|
LOG.exception(msg)
|
||||||
raise exception.ShareBackendException(message=msg)
|
raise exception.ShareBackendException(message=msg)
|
||||||
|
|
||||||
if self.hp3par_debug:
|
if self.hpe3par_debug:
|
||||||
self._client.debug_rest(True) # Includes SSH debug (setSSH above)
|
self._client.debug_rest(True) # Includes SSH debug (setSSH above)
|
||||||
|
|
||||||
def _wsapi_login(self):
|
def _wsapi_login(self):
|
||||||
try:
|
try:
|
||||||
self._client.login(self.hp3par_username, self.hp3par_password)
|
self._client.login(self.hpe3par_username, self.hpe3par_password)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
msg = (_("Failed to Login to 3PAR (%(url)s) as %(user)s "
|
msg = (_("Failed to Login to 3PAR (%(url)s) as %(user)s "
|
||||||
"because: %(err)s") %
|
"because: %(err)s") %
|
||||||
{'url': self.hp3par_api_url,
|
{'url': self.hpe3par_api_url,
|
||||||
'user': self.hp3par_username,
|
'user': self.hpe3par_username,
|
||||||
'err': six.text_type(e)})
|
'err': six.text_type(e)})
|
||||||
LOG.error(msg)
|
LOG.error(msg)
|
||||||
raise exception.ShareBackendException(msg=msg)
|
raise exception.ShareBackendException(msg=msg)
|
||||||
@ -169,7 +169,7 @@ class HP3ParMediator(object):
|
|||||||
self._client.http.unauthenticate()
|
self._client.http.unauthenticate()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
msg = _LW("Failed to Logout from 3PAR (%(url)s) because %(err)s")
|
msg = _LW("Failed to Logout from 3PAR (%(url)s) because %(err)s")
|
||||||
LOG.warning(msg, {'url': self.hp3par_api_url,
|
LOG.warning(msg, {'url': self.hpe3par_api_url,
|
||||||
'err': six.text_type(e)})
|
'err': six.text_type(e)})
|
||||||
# don't raise exception on logout()
|
# don't raise exception on logout()
|
||||||
|
|
||||||
@ -236,14 +236,15 @@ class HP3ParMediator(object):
|
|||||||
thin_provisioning = provisioning_type in (THIN, DEDUPE)
|
thin_provisioning = provisioning_type in (THIN, DEDUPE)
|
||||||
|
|
||||||
flash_cache_policy = volume_set.get('flashCachePolicy', DISABLED)
|
flash_cache_policy = volume_set.get('flashCachePolicy', DISABLED)
|
||||||
hp3par_flash_cache = flash_cache_policy == ENABLED
|
hpe3par_flash_cache = flash_cache_policy == ENABLED
|
||||||
|
|
||||||
status = {
|
status = {
|
||||||
'total_capacity_gb': total_capacity_gb,
|
'total_capacity_gb': total_capacity_gb,
|
||||||
'free_capacity_gb': free_capacity_gb,
|
'free_capacity_gb': free_capacity_gb,
|
||||||
'thin_provisioning': thin_provisioning,
|
'thin_provisioning': thin_provisioning,
|
||||||
'dedupe': dedupe,
|
'dedupe': dedupe,
|
||||||
'hp3par_flash_cache': hp3par_flash_cache,
|
'hpe3par_flash_cache': hpe3par_flash_cache,
|
||||||
|
'hp3par_flash_cache': hpe3par_flash_cache,
|
||||||
}
|
}
|
||||||
|
|
||||||
if thin_provisioning:
|
if thin_provisioning:
|
||||||
@ -266,7 +267,7 @@ class HP3ParMediator(object):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def other_protocol(share_proto):
|
def other_protocol(share_proto):
|
||||||
"""Given 'nfs' or 'smb' (or equivalent) return the other one."""
|
"""Given 'nfs' or 'smb' (or equivalent) return the other one."""
|
||||||
protocol = HP3ParMediator.ensure_supported_protocol(share_proto)
|
protocol = HPE3ParMediator.ensure_supported_protocol(share_proto)
|
||||||
return 'nfs' if protocol == 'smb' else 'smb'
|
return 'nfs' if protocol == 'smb' else 'smb'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -275,7 +276,7 @@ class HP3ParMediator(object):
|
|||||||
return uid
|
return uid
|
||||||
elif protocol:
|
elif protocol:
|
||||||
return 'osf-%s-%s' % (
|
return 'osf-%s-%s' % (
|
||||||
HP3ParMediator.ensure_supported_protocol(protocol), uid)
|
HPE3ParMediator.ensure_supported_protocol(protocol), uid)
|
||||||
else:
|
else:
|
||||||
return 'osf-%s' % uid
|
return 'osf-%s' % uid
|
||||||
|
|
||||||
@ -283,7 +284,14 @@ class HP3ParMediator(object):
|
|||||||
def _get_nfs_options(extra_specs, readonly):
|
def _get_nfs_options(extra_specs, readonly):
|
||||||
"""Validate the NFS extra_specs and return the options to use."""
|
"""Validate the NFS extra_specs and return the options to use."""
|
||||||
|
|
||||||
nfs_options = extra_specs.get('hp3par:nfs_options')
|
nfs_options = extra_specs.get('hpe3par:nfs_options')
|
||||||
|
if nfs_options is None:
|
||||||
|
nfs_options = extra_specs.get('hp3par:nfs_options')
|
||||||
|
if nfs_options:
|
||||||
|
msg = _LW("hp3par:nfs_options is deprecated. Use "
|
||||||
|
"hpe3par:nfs_options instead.")
|
||||||
|
LOG.warning(msg)
|
||||||
|
|
||||||
if nfs_options:
|
if nfs_options:
|
||||||
options = nfs_options.split(',')
|
options = nfs_options.split(',')
|
||||||
else:
|
else:
|
||||||
@ -304,7 +312,8 @@ class HP3ParMediator(object):
|
|||||||
]
|
]
|
||||||
|
|
||||||
if invalid_options:
|
if invalid_options:
|
||||||
raise exception.InvalidInput(_('Invalid hp3par:nfs_options in '
|
raise exception.InvalidInput(_('Invalid hp3par:nfs_options or '
|
||||||
|
'hpe3par:nfs_options in '
|
||||||
'extra-specs. The following '
|
'extra-specs. The following '
|
||||||
'options are not allowed: %s') %
|
'options are not allowed: %s') %
|
||||||
invalid_options)
|
invalid_options)
|
||||||
@ -321,6 +330,12 @@ class HP3ParMediator(object):
|
|||||||
fstore=fstore,
|
fstore=fstore,
|
||||||
sharedir=sharedir,
|
sharedir=sharedir,
|
||||||
comment=comment)
|
comment=comment)
|
||||||
|
|
||||||
|
if 'hp3par_flash_cache' in extra_specs:
|
||||||
|
msg = _LW("hp3par_flash_cache is deprecated. Use "
|
||||||
|
"hpe3par_flash_cache instead.")
|
||||||
|
LOG.warning(msg)
|
||||||
|
|
||||||
if protocol == 'nfs':
|
if protocol == 'nfs':
|
||||||
createfshare_kwargs['clientip'] = '127.0.0.1'
|
createfshare_kwargs['clientip'] = '127.0.0.1'
|
||||||
options = self._get_nfs_options(extra_specs, readonly)
|
options = self._get_nfs_options(extra_specs, readonly)
|
||||||
@ -328,13 +343,17 @@ class HP3ParMediator(object):
|
|||||||
else:
|
else:
|
||||||
createfshare_kwargs['allowip'] = '127.0.0.1'
|
createfshare_kwargs['allowip'] = '127.0.0.1'
|
||||||
|
|
||||||
if self.client_version < MIN_SMB_CA_VERSION:
|
smb_opts = (ACCESS_BASED_ENUM, CONTINUOUS_AVAIL, CACHE)
|
||||||
smb_opts = (ACCESS_BASED_ENUM, CACHE)
|
|
||||||
else:
|
|
||||||
smb_opts = (ACCESS_BASED_ENUM, CONTINUOUS_AVAIL, CACHE)
|
|
||||||
|
|
||||||
for smb_opt in smb_opts:
|
for smb_opt in smb_opts:
|
||||||
opt_value = extra_specs.get('hp3par:smb_%s' % smb_opt)
|
opt_value = extra_specs.get('hpe3par:smb_%s' % smb_opt)
|
||||||
|
if opt_value is None:
|
||||||
|
opt_value = extra_specs.get('hp3par:smb_%s' % smb_opt)
|
||||||
|
if opt_value:
|
||||||
|
msg = _LW("hp3par:smb_* is deprecated. Use "
|
||||||
|
"hpe3par:smb_* instead.")
|
||||||
|
LOG.warning(msg)
|
||||||
|
|
||||||
if opt_value:
|
if opt_value:
|
||||||
opt_key = SMB_EXTRA_SPECS_MAP[smb_opt]
|
opt_key = SMB_EXTRA_SPECS_MAP[smb_opt]
|
||||||
createfshare_kwargs[opt_key] = opt_value
|
createfshare_kwargs[opt_key] = opt_value
|
||||||
@ -367,14 +386,14 @@ class HP3ParMediator(object):
|
|||||||
protocol = self.ensure_supported_protocol(share_proto)
|
protocol = self.ensure_supported_protocol(share_proto)
|
||||||
share_name = self.ensure_prefix(share_id)
|
share_name = self.ensure_prefix(share_id)
|
||||||
|
|
||||||
if not (sharedir or self.hp3par_fstore_per_share):
|
if not (sharedir or self.hpe3par_fstore_per_share):
|
||||||
sharedir = share_name
|
sharedir = share_name
|
||||||
|
|
||||||
if fstore:
|
if fstore:
|
||||||
use_existing_fstore = True
|
use_existing_fstore = True
|
||||||
else:
|
else:
|
||||||
use_existing_fstore = False
|
use_existing_fstore = False
|
||||||
if self.hp3par_fstore_per_share:
|
if self.hpe3par_fstore_per_share:
|
||||||
fstore = share_name
|
fstore = share_name
|
||||||
else:
|
else:
|
||||||
fstore = self.ensure_prefix(project_id, protocol)
|
fstore = self.ensure_prefix(project_id, protocol)
|
||||||
@ -401,7 +420,7 @@ class HP3ParMediator(object):
|
|||||||
raise exception.ShareBackendException(msg)
|
raise exception.ShareBackendException(msg)
|
||||||
|
|
||||||
if size:
|
if size:
|
||||||
if self.hp3par_fstore_per_share:
|
if self.hpe3par_fstore_per_share:
|
||||||
hcapacity = six.text_type(size * units.Ki)
|
hcapacity = six.text_type(size * units.Ki)
|
||||||
scapacity = hcapacity
|
scapacity = hcapacity
|
||||||
else:
|
else:
|
||||||
@ -706,10 +725,10 @@ class HP3ParMediator(object):
|
|||||||
raise exception.InvalidInput(msg)
|
raise exception.InvalidInput(msg)
|
||||||
|
|
||||||
if protocol == 'nfs' and access_type != 'ip':
|
if protocol == 'nfs' and access_type != 'ip':
|
||||||
msg = (_("Invalid NFS access type. HP 3PAR NFS supports 'ip'. "
|
msg = (_("Invalid NFS access type. HPE 3PAR NFS supports 'ip'. "
|
||||||
"Actual '%s'.") % access_type)
|
"Actual '%s'.") % access_type)
|
||||||
LOG.error(msg)
|
LOG.error(msg)
|
||||||
raise exception.HP3ParInvalid(msg)
|
raise exception.HPE3ParInvalid(msg)
|
||||||
|
|
||||||
return protocol
|
return protocol
|
||||||
|
|
||||||
@ -748,7 +767,7 @@ class HP3ParMediator(object):
|
|||||||
msg = (_("Unexpected error: After ensure_supported_protocol "
|
msg = (_("Unexpected error: After ensure_supported_protocol "
|
||||||
"only 'nfs' or 'smb' strings are allowed, but found: "
|
"only 'nfs' or 'smb' strings are allowed, but found: "
|
||||||
"%s.") % protocol)
|
"%s.") % protocol)
|
||||||
raise exception.HP3ParUnexpectedError(msg)
|
raise exception.HPE3ParUnexpectedError(msg)
|
||||||
|
|
||||||
LOG.debug("setfshare result=%s", result)
|
LOG.debug("setfshare result=%s", result)
|
||||||
except Exception as e:
|
except Exception as e:
|
@ -98,7 +98,10 @@ CONF.import_opt('periodic_hooks_interval', 'manila.share.hook')
|
|||||||
# old/new path here to maintain backward compatibility.
|
# old/new path here to maintain backward compatibility.
|
||||||
MAPPING = {
|
MAPPING = {
|
||||||
'manila.share.drivers.netapp.cluster_mode.NetAppClusteredShareDriver':
|
'manila.share.drivers.netapp.cluster_mode.NetAppClusteredShareDriver':
|
||||||
'manila.share.drivers.netapp.common.NetAppDriver', }
|
'manila.share.drivers.netapp.common.NetAppDriver',
|
||||||
|
'manila.share.drivers.hp.hp_3par_driver.HP3ParShareDriver':
|
||||||
|
'manila.share.drivers.hpe.hpe_3par_driver.HPE3ParShareDriver',
|
||||||
|
}
|
||||||
|
|
||||||
QUOTAS = quota.QUOTAS
|
QUOTAS = quota.QUOTAS
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright 2015 Hewlett Packard Development Company, L.P.
|
# Copyright 2015 Hewlett Packard Enterprise Development LP
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@ -48,7 +48,7 @@ EXPECTED_STATS = {'test': 'stats'}
|
|||||||
EXPECTED_FPG = 'FPG_1'
|
EXPECTED_FPG = 'FPG_1'
|
||||||
EXPECTED_FSTORE = EXPECTED_PROJECT_ID
|
EXPECTED_FSTORE = EXPECTED_PROJECT_ID
|
||||||
EXPECTED_VFS = 'test_vfs'
|
EXPECTED_VFS = 'test_vfs'
|
||||||
EXPECTED_HP_DEBUG = True
|
EXPECTED_HPE_DEBUG = True
|
||||||
EXPECTED_EXTRA_SPECS = {}
|
EXPECTED_EXTRA_SPECS = {}
|
||||||
|
|
||||||
GET_FSQUOTA = {'message': None,
|
GET_FSQUOTA = {'message': None,
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright 2015 Hewlett Packard Development Company, L.P.
|
# Copyright 2015 Hewlett Packard Enterprise Development LP
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@ -16,37 +16,37 @@ import sys
|
|||||||
|
|
||||||
import ddt
|
import ddt
|
||||||
import mock
|
import mock
|
||||||
if 'hp3parclient' not in sys.modules:
|
if 'hpe3parclient' not in sys.modules:
|
||||||
sys.modules['hp3parclient'] = mock.Mock()
|
sys.modules['hpe3parclient'] = mock.Mock()
|
||||||
|
|
||||||
from manila import exception
|
from manila import exception
|
||||||
from manila.share.drivers.hp import hp_3par_driver as hp3pardriver
|
from manila.share.drivers.hpe import hpe_3par_driver as hpe3pardriver
|
||||||
from manila.share.drivers.hp import hp_3par_mediator as hp3parmediator
|
from manila.share.drivers.hpe import hpe_3par_mediator as hpe3parmediator
|
||||||
from manila import test
|
from manila import test
|
||||||
from manila.tests.share.drivers.hp import test_hp_3par_constants as constants
|
from manila.tests.share.drivers.hpe import test_hpe_3par_constants as constants
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class HP3ParDriverTestCase(test.TestCase):
|
class HPE3ParDriverTestCase(test.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(HP3ParDriverTestCase, self).setUp()
|
super(HPE3ParDriverTestCase, self).setUp()
|
||||||
|
|
||||||
# Create a mock configuration with attributes and a safe_get()
|
# Create a mock configuration with attributes and a safe_get()
|
||||||
self.conf = mock.Mock()
|
self.conf = mock.Mock()
|
||||||
self.conf.driver_handles_share_servers = True
|
self.conf.driver_handles_share_servers = True
|
||||||
self.conf.hp3par_debug = constants.EXPECTED_HP_DEBUG
|
self.conf.hpe3par_debug = constants.EXPECTED_HPE_DEBUG
|
||||||
self.conf.hp3par_username = constants.USERNAME
|
self.conf.hpe3par_username = constants.USERNAME
|
||||||
self.conf.hp3par_password = constants.PASSWORD
|
self.conf.hpe3par_password = constants.PASSWORD
|
||||||
self.conf.hp3par_api_url = constants.API_URL
|
self.conf.hpe3par_api_url = constants.API_URL
|
||||||
self.conf.hp3par_san_login = constants.SAN_LOGIN
|
self.conf.hpe3par_san_login = constants.SAN_LOGIN
|
||||||
self.conf.hp3par_san_password = constants.SAN_PASSWORD
|
self.conf.hpe3par_san_password = constants.SAN_PASSWORD
|
||||||
self.conf.hp3par_san_ip = constants.EXPECTED_IP_1234
|
self.conf.hpe3par_san_ip = constants.EXPECTED_IP_1234
|
||||||
self.conf.hp3par_fpg = constants.EXPECTED_FPG
|
self.conf.hpe3par_fpg = constants.EXPECTED_FPG
|
||||||
self.conf.hp3par_san_ssh_port = constants.PORT
|
self.conf.hpe3par_san_ssh_port = constants.PORT
|
||||||
self.conf.ssh_conn_timeout = constants.TIMEOUT
|
self.conf.ssh_conn_timeout = constants.TIMEOUT
|
||||||
self.conf.hp3par_share_ip_address = None
|
self.conf.hpe3par_share_ip_address = None
|
||||||
self.conf.hp3par_fstore_per_share = False
|
self.conf.hpe3par_fstore_per_share = False
|
||||||
self.conf.network_config_group = 'test_network_config_group'
|
self.conf.network_config_group = 'test_network_config_group'
|
||||||
|
|
||||||
def safe_get(attr):
|
def safe_get(attr):
|
||||||
@ -56,12 +56,12 @@ class HP3ParDriverTestCase(test.TestCase):
|
|||||||
return None
|
return None
|
||||||
self.conf.safe_get = safe_get
|
self.conf.safe_get = safe_get
|
||||||
|
|
||||||
self.real_hp_3par_mediator = hp3parmediator.HP3ParMediator
|
self.real_hpe_3par_mediator = hpe3parmediator.HPE3ParMediator
|
||||||
self.mock_object(hp3parmediator, 'HP3ParMediator')
|
self.mock_object(hpe3parmediator, 'HPE3ParMediator')
|
||||||
self.mock_mediator_constructor = hp3parmediator.HP3ParMediator
|
self.mock_mediator_constructor = hpe3parmediator.HPE3ParMediator
|
||||||
self.mock_mediator = self.mock_mediator_constructor()
|
self.mock_mediator = self.mock_mediator_constructor()
|
||||||
|
|
||||||
self.driver = hp3pardriver.HP3ParShareDriver(
|
self.driver = hpe3pardriver.HPE3ParShareDriver(
|
||||||
configuration=self.conf)
|
configuration=self.conf)
|
||||||
|
|
||||||
def test_driver_setup_success(self):
|
def test_driver_setup_success(self):
|
||||||
@ -72,20 +72,20 @@ class HP3ParDriverTestCase(test.TestCase):
|
|||||||
self.driver.do_setup(None)
|
self.driver.do_setup(None)
|
||||||
conf = self.conf
|
conf = self.conf
|
||||||
self.mock_mediator_constructor.assert_has_calls([
|
self.mock_mediator_constructor.assert_has_calls([
|
||||||
mock.call(hp3par_san_ssh_port=conf.hp3par_san_ssh_port,
|
mock.call(hpe3par_san_ssh_port=conf.hpe3par_san_ssh_port,
|
||||||
hp3par_san_password=conf.hp3par_san_password,
|
hpe3par_san_password=conf.hpe3par_san_password,
|
||||||
hp3par_username=conf.hp3par_username,
|
hpe3par_username=conf.hpe3par_username,
|
||||||
hp3par_san_login=conf.hp3par_san_login,
|
hpe3par_san_login=conf.hpe3par_san_login,
|
||||||
hp3par_debug=conf.hp3par_debug,
|
hpe3par_debug=conf.hpe3par_debug,
|
||||||
hp3par_api_url=conf.hp3par_api_url,
|
hpe3par_api_url=conf.hpe3par_api_url,
|
||||||
hp3par_password=conf.hp3par_password,
|
hpe3par_password=conf.hpe3par_password,
|
||||||
hp3par_san_ip=conf.hp3par_san_ip,
|
hpe3par_san_ip=conf.hpe3par_san_ip,
|
||||||
hp3par_fstore_per_share=conf.hp3par_fstore_per_share,
|
hpe3par_fstore_per_share=conf.hpe3par_fstore_per_share,
|
||||||
ssh_conn_timeout=conf.ssh_conn_timeout)])
|
ssh_conn_timeout=conf.ssh_conn_timeout)])
|
||||||
|
|
||||||
self.mock_mediator.assert_has_calls([
|
self.mock_mediator.assert_has_calls([
|
||||||
mock.call.do_setup(),
|
mock.call.do_setup(),
|
||||||
mock.call.get_vfs_name(conf.hp3par_fpg)])
|
mock.call.get_vfs_name(conf.hpe3par_fpg)])
|
||||||
|
|
||||||
self.assertEqual(constants.EXPECTED_VFS, self.driver.vfs)
|
self.assertEqual(constants.EXPECTED_VFS, self.driver.vfs)
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ class HP3ParDriverTestCase(test.TestCase):
|
|||||||
"""Driver do_setup without any errors with dhss=False."""
|
"""Driver do_setup without any errors with dhss=False."""
|
||||||
|
|
||||||
self.conf.driver_handles_share_servers = False
|
self.conf.driver_handles_share_servers = False
|
||||||
self.conf.hp3par_share_ip_address = constants.EXPECTED_IP_10203040
|
self.conf.hpe3par_share_ip_address = constants.EXPECTED_IP_10203040
|
||||||
|
|
||||||
self.test_driver_setup_success()
|
self.test_driver_setup_success()
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ class HP3ParDriverTestCase(test.TestCase):
|
|||||||
"""Configured IP address is required for dhss=False."""
|
"""Configured IP address is required for dhss=False."""
|
||||||
|
|
||||||
self.conf.driver_handles_share_servers = False
|
self.conf.driver_handles_share_servers = False
|
||||||
self.assertRaises(exception.HP3ParInvalid,
|
self.assertRaises(exception.HPE3ParInvalid,
|
||||||
self.driver.do_setup, None)
|
self.driver.do_setup, None)
|
||||||
|
|
||||||
def test_driver_with_setup_error(self):
|
def test_driver_with_setup_error(self):
|
||||||
@ -115,15 +115,15 @@ class HP3ParDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
conf = self.conf
|
conf = self.conf
|
||||||
self.mock_mediator_constructor.assert_has_calls([
|
self.mock_mediator_constructor.assert_has_calls([
|
||||||
mock.call(hp3par_san_ssh_port=conf.hp3par_san_ssh_port,
|
mock.call(hpe3par_san_ssh_port=conf.hpe3par_san_ssh_port,
|
||||||
hp3par_san_password=conf.hp3par_san_password,
|
hpe3par_san_password=conf.hpe3par_san_password,
|
||||||
hp3par_username=conf.hp3par_username,
|
hpe3par_username=conf.hpe3par_username,
|
||||||
hp3par_san_login=conf.hp3par_san_login,
|
hpe3par_san_login=conf.hpe3par_san_login,
|
||||||
hp3par_debug=conf.hp3par_debug,
|
hpe3par_debug=conf.hpe3par_debug,
|
||||||
hp3par_api_url=conf.hp3par_api_url,
|
hpe3par_api_url=conf.hpe3par_api_url,
|
||||||
hp3par_password=conf.hp3par_password,
|
hpe3par_password=conf.hpe3par_password,
|
||||||
hp3par_san_ip=conf.hp3par_san_ip,
|
hpe3par_san_ip=conf.hpe3par_san_ip,
|
||||||
hp3par_fstore_per_share=conf.hp3par_fstore_per_share,
|
hpe3par_fstore_per_share=conf.hpe3par_fstore_per_share,
|
||||||
ssh_conn_timeout=conf.ssh_conn_timeout)])
|
ssh_conn_timeout=conf.ssh_conn_timeout)])
|
||||||
|
|
||||||
self.mock_mediator.assert_has_calls([mock.call.do_setup()])
|
self.mock_mediator.assert_has_calls([mock.call.do_setup()])
|
||||||
@ -139,29 +139,29 @@ class HP3ParDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
conf = self.conf
|
conf = self.conf
|
||||||
self.mock_mediator_constructor.assert_has_calls([
|
self.mock_mediator_constructor.assert_has_calls([
|
||||||
mock.call(hp3par_san_ssh_port=conf.hp3par_san_ssh_port,
|
mock.call(hpe3par_san_ssh_port=conf.hpe3par_san_ssh_port,
|
||||||
hp3par_san_password=conf.hp3par_san_password,
|
hpe3par_san_password=conf.hpe3par_san_password,
|
||||||
hp3par_username=conf.hp3par_username,
|
hpe3par_username=conf.hpe3par_username,
|
||||||
hp3par_san_login=conf.hp3par_san_login,
|
hpe3par_san_login=conf.hpe3par_san_login,
|
||||||
hp3par_debug=conf.hp3par_debug,
|
hpe3par_debug=conf.hpe3par_debug,
|
||||||
hp3par_api_url=conf.hp3par_api_url,
|
hpe3par_api_url=conf.hpe3par_api_url,
|
||||||
hp3par_password=conf.hp3par_password,
|
hpe3par_password=conf.hpe3par_password,
|
||||||
hp3par_san_ip=conf.hp3par_san_ip,
|
hpe3par_san_ip=conf.hpe3par_san_ip,
|
||||||
hp3par_fstore_per_share=conf.hp3par_fstore_per_share,
|
hpe3par_fstore_per_share=conf.hpe3par_fstore_per_share,
|
||||||
ssh_conn_timeout=conf.ssh_conn_timeout)])
|
ssh_conn_timeout=conf.ssh_conn_timeout)])
|
||||||
|
|
||||||
self.mock_mediator.assert_has_calls([
|
self.mock_mediator.assert_has_calls([
|
||||||
mock.call.do_setup(),
|
mock.call.do_setup(),
|
||||||
mock.call.get_vfs_name(conf.hp3par_fpg)])
|
mock.call.get_vfs_name(conf.hpe3par_fpg)])
|
||||||
|
|
||||||
def init_driver(self):
|
def init_driver(self):
|
||||||
"""Simple driver setup for re-use with tests that need one."""
|
"""Simple driver setup for re-use with tests that need one."""
|
||||||
|
|
||||||
self.driver._hp3par = self.mock_mediator
|
self.driver._hpe3par = self.mock_mediator
|
||||||
self.driver.vfs = constants.EXPECTED_VFS
|
self.driver.vfs = constants.EXPECTED_VFS
|
||||||
self.driver.fpg = constants.EXPECTED_FPG
|
self.driver.fpg = constants.EXPECTED_FPG
|
||||||
self.mock_object(hp3pardriver, 'share_types')
|
self.mock_object(hpe3pardriver, 'share_types')
|
||||||
get_extra_specs = hp3pardriver.share_types.get_extra_specs_from_share
|
get_extra_specs = hpe3pardriver.share_types.get_extra_specs_from_share
|
||||||
get_extra_specs.return_value = constants.EXPECTED_EXTRA_SPECS
|
get_extra_specs.return_value = constants.EXPECTED_EXTRA_SPECS
|
||||||
|
|
||||||
def do_create_share(self, protocol, share_type_id, expected_project_id,
|
def do_create_share(self, protocol, share_type_id, expected_project_id,
|
||||||
@ -213,29 +213,29 @@ class HP3ParDriverTestCase(test.TestCase):
|
|||||||
"""check_for_setup_error when things go well."""
|
"""check_for_setup_error when things go well."""
|
||||||
|
|
||||||
# Generally this is always mocked, but here we reference the class.
|
# Generally this is always mocked, but here we reference the class.
|
||||||
hp3parmediator.HP3ParMediator = self.real_hp_3par_mediator
|
hpe3parmediator.HPE3ParMediator = self.real_hpe_3par_mediator
|
||||||
|
|
||||||
self.mock_object(hp3pardriver, 'LOG')
|
self.mock_object(hpe3pardriver, 'LOG')
|
||||||
self.init_driver()
|
self.init_driver()
|
||||||
self.driver.check_for_setup_error()
|
self.driver.check_for_setup_error()
|
||||||
expected_calls = [
|
expected_calls = [
|
||||||
mock.call.debug('HP3ParShareDriver SHA1: %s', mock.ANY),
|
mock.call.debug('HPE3ParShareDriver SHA1: %s', mock.ANY),
|
||||||
mock.call.debug('HP3ParMediator SHA1: %s', mock.ANY)
|
mock.call.debug('HPE3ParMediator SHA1: %s', mock.ANY)
|
||||||
]
|
]
|
||||||
hp3pardriver.LOG.assert_has_calls(expected_calls)
|
hpe3pardriver.LOG.assert_has_calls(expected_calls)
|
||||||
|
|
||||||
def test_driver_check_for_setup_error_exception(self):
|
def test_driver_check_for_setup_error_exception(self):
|
||||||
"""check_for_setup_error catch and log any exceptions."""
|
"""check_for_setup_error catch and log any exceptions."""
|
||||||
|
|
||||||
# Since HP3ParMediator is mocked, we'll hit the except/log.
|
# Since HPE3ParMediator is mocked, we'll hit the except/log.
|
||||||
self.mock_object(hp3pardriver, 'LOG')
|
self.mock_object(hpe3pardriver, 'LOG')
|
||||||
self.init_driver()
|
self.init_driver()
|
||||||
self.driver.check_for_setup_error()
|
self.driver.check_for_setup_error()
|
||||||
expected_calls = [
|
expected_calls = [
|
||||||
mock.call.debug('HP3ParShareDriver SHA1: %s', mock.ANY),
|
mock.call.debug('HPE3ParShareDriver SHA1: %s', mock.ANY),
|
||||||
mock.call.debug('Source code SHA1 not logged due to: %s', mock.ANY)
|
mock.call.debug('Source code SHA1 not logged due to: %s', mock.ANY)
|
||||||
]
|
]
|
||||||
hp3pardriver.LOG.assert_has_calls(expected_calls)
|
hpe3pardriver.LOG.assert_has_calls(expected_calls)
|
||||||
|
|
||||||
def test_driver_create_cifs_share(self):
|
def test_driver_create_cifs_share(self):
|
||||||
self.init_driver()
|
self.init_driver()
|
||||||
@ -458,7 +458,7 @@ class HP3ParDriverTestCase(test.TestCase):
|
|||||||
def test_driver_get_share_stats_not_ready(self):
|
def test_driver_get_share_stats_not_ready(self):
|
||||||
"""Protect against stats update before driver is ready."""
|
"""Protect against stats update before driver is ready."""
|
||||||
|
|
||||||
self.mock_object(hp3pardriver, 'LOG')
|
self.mock_object(hpe3pardriver, 'LOG')
|
||||||
|
|
||||||
expected_result = {
|
expected_result = {
|
||||||
'driver_handles_share_servers': True,
|
'driver_handles_share_servers': True,
|
||||||
@ -468,12 +468,12 @@ class HP3ParDriverTestCase(test.TestCase):
|
|||||||
'max_over_subscription_ratio': None,
|
'max_over_subscription_ratio': None,
|
||||||
'reserved_percentage': 0,
|
'reserved_percentage': 0,
|
||||||
'provisioned_capacity_gb': 0,
|
'provisioned_capacity_gb': 0,
|
||||||
'share_backend_name': 'HP_3PAR',
|
'share_backend_name': 'HPE_3PAR',
|
||||||
'snapshot_support': True,
|
'snapshot_support': True,
|
||||||
'storage_protocol': 'NFS_CIFS',
|
'storage_protocol': 'NFS_CIFS',
|
||||||
'thin_provisioning': True,
|
'thin_provisioning': True,
|
||||||
'total_capacity_gb': 0,
|
'total_capacity_gb': 0,
|
||||||
'vendor_name': 'HP',
|
'vendor_name': 'HPE',
|
||||||
'pools': None,
|
'pools': None,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,7 +484,7 @@ class HP3ParDriverTestCase(test.TestCase):
|
|||||||
mock.call.info('Skipping capacity and capabilities update. '
|
mock.call.info('Skipping capacity and capabilities update. '
|
||||||
'Setup has not completed.')
|
'Setup has not completed.')
|
||||||
]
|
]
|
||||||
hp3pardriver.LOG.assert_has_calls(expected_calls)
|
hpe3pardriver.LOG.assert_has_calls(expected_calls)
|
||||||
|
|
||||||
def test_driver_get_share_stats_no_refresh(self):
|
def test_driver_get_share_stats_no_refresh(self):
|
||||||
"""Driver does not call mediator when refresh=False."""
|
"""Driver does not call mediator when refresh=False."""
|
||||||
@ -511,6 +511,7 @@ class HP3ParDriverTestCase(test.TestCase):
|
|||||||
'thin_provisioning': True,
|
'thin_provisioning': True,
|
||||||
'dedupe': False,
|
'dedupe': False,
|
||||||
'hpe3par_flash_cache': False,
|
'hpe3par_flash_cache': False,
|
||||||
|
'hp3par_flash_cache': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
expected_result = {
|
expected_result = {
|
||||||
@ -522,13 +523,14 @@ class HP3ParDriverTestCase(test.TestCase):
|
|||||||
'pools': None,
|
'pools': None,
|
||||||
'provisioned_capacity_gb': 0,
|
'provisioned_capacity_gb': 0,
|
||||||
'reserved_percentage': 0,
|
'reserved_percentage': 0,
|
||||||
'share_backend_name': 'HP_3PAR',
|
'share_backend_name': 'HPE_3PAR',
|
||||||
'storage_protocol': 'NFS_CIFS',
|
'storage_protocol': 'NFS_CIFS',
|
||||||
'total_capacity_gb': expected_capacity,
|
'total_capacity_gb': expected_capacity,
|
||||||
'vendor_name': 'HP',
|
'vendor_name': 'HPE',
|
||||||
'thin_provisioning': True,
|
'thin_provisioning': True,
|
||||||
'dedupe': False,
|
'dedupe': False,
|
||||||
'hpe3par_flash_cache': False,
|
'hpe3par_flash_cache': False,
|
||||||
|
'hp3par_flash_cache': False,
|
||||||
'snapshot_support': True,
|
'snapshot_support': True,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,11 +559,11 @@ class HP3ParDriverTestCase(test.TestCase):
|
|||||||
'pools': None,
|
'pools': None,
|
||||||
'provisioned_capacity_gb': 0,
|
'provisioned_capacity_gb': 0,
|
||||||
'reserved_percentage': 0,
|
'reserved_percentage': 0,
|
||||||
'share_backend_name': 'HP_3PAR',
|
'share_backend_name': 'HPE_3PAR',
|
||||||
'storage_protocol': 'NFS_CIFS',
|
'storage_protocol': 'NFS_CIFS',
|
||||||
'thin_provisioning': True,
|
'thin_provisioning': True,
|
||||||
'total_capacity_gb': 0,
|
'total_capacity_gb': 0,
|
||||||
'vendor_name': 'HP',
|
'vendor_name': 'HPE',
|
||||||
'snapshot_support': True,
|
'snapshot_support': True,
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright 2015 Hewlett Packard Development Company, L.P.
|
# Copyright 2015 Hewlett Packard Enterprise Development LP
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@ -16,60 +16,60 @@ import sys
|
|||||||
|
|
||||||
import ddt
|
import ddt
|
||||||
import mock
|
import mock
|
||||||
if 'hp3parclient' not in sys.modules:
|
if 'hpe3parclient' not in sys.modules:
|
||||||
sys.modules['hp3parclient'] = mock.Mock()
|
sys.modules['hpe3parclient'] = mock.Mock()
|
||||||
|
|
||||||
from manila import exception
|
from manila import exception
|
||||||
from manila.share.drivers.hp import hp_3par_mediator as hp3parmediator
|
from manila.share.drivers.hpe import hpe_3par_mediator as hpe3parmediator
|
||||||
from manila import test
|
from manila import test
|
||||||
from manila.tests.share.drivers.hp import test_hp_3par_constants as constants
|
from manila.tests.share.drivers.hpe import test_hpe_3par_constants as constants
|
||||||
|
|
||||||
from oslo_utils import units
|
from oslo_utils import units
|
||||||
import six
|
import six
|
||||||
|
|
||||||
CLIENT_VERSION_MIN_OK = hp3parmediator.MIN_CLIENT_VERSION
|
CLIENT_VERSION_MIN_OK = hpe3parmediator.MIN_CLIENT_VERSION
|
||||||
TEST_WSAPI_VERSION_STR = '30201292'
|
TEST_WSAPI_VERSION_STR = '30201292'
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class HP3ParMediatorTestCase(test.TestCase):
|
class HPE3ParMediatorTestCase(test.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(HP3ParMediatorTestCase, self).setUp()
|
super(HPE3ParMediatorTestCase, self).setUp()
|
||||||
|
|
||||||
# This is the fake client to use.
|
# This is the fake client to use.
|
||||||
self.mock_client = mock.Mock()
|
self.mock_client = mock.Mock()
|
||||||
|
|
||||||
# Take over the hp3parclient module and stub the constructor.
|
# Take over the hpe3parclient module and stub the constructor.
|
||||||
hp3parclient = sys.modules['hp3parclient']
|
hpe3parclient = sys.modules['hpe3parclient']
|
||||||
hp3parclient.version_tuple = CLIENT_VERSION_MIN_OK
|
hpe3parclient.version_tuple = CLIENT_VERSION_MIN_OK
|
||||||
|
|
||||||
# Need a fake constructor to return the fake client.
|
# Need a fake constructor to return the fake client.
|
||||||
# This is also be used for constructor error tests.
|
# This is also be used for constructor error tests.
|
||||||
self.mock_object(hp3parclient.file_client, 'HP3ParFilePersonaClient')
|
self.mock_object(hpe3parclient.file_client, 'HPE3ParFilePersonaClient')
|
||||||
self.mock_client_constructor = (
|
self.mock_client_constructor = (
|
||||||
hp3parclient.file_client.HP3ParFilePersonaClient
|
hpe3parclient.file_client.HPE3ParFilePersonaClient
|
||||||
)
|
)
|
||||||
self.mock_client = self.mock_client_constructor()
|
self.mock_client = self.mock_client_constructor()
|
||||||
|
|
||||||
# Set the mediator to use in tests.
|
# Set the mediator to use in tests.
|
||||||
self.mediator = hp3parmediator.HP3ParMediator(
|
self.mediator = hpe3parmediator.HPE3ParMediator(
|
||||||
hp3par_username=constants.USERNAME,
|
hpe3par_username=constants.USERNAME,
|
||||||
hp3par_password=constants.PASSWORD,
|
hpe3par_password=constants.PASSWORD,
|
||||||
hp3par_api_url=constants.API_URL,
|
hpe3par_api_url=constants.API_URL,
|
||||||
hp3par_debug=constants.EXPECTED_HP_DEBUG,
|
hpe3par_debug=constants.EXPECTED_HPE_DEBUG,
|
||||||
hp3par_san_ip=constants.EXPECTED_IP_1234,
|
hpe3par_san_ip=constants.EXPECTED_IP_1234,
|
||||||
hp3par_san_login=constants.SAN_LOGIN,
|
hpe3par_san_login=constants.SAN_LOGIN,
|
||||||
hp3par_san_password=constants.SAN_PASSWORD,
|
hpe3par_san_password=constants.SAN_PASSWORD,
|
||||||
hp3par_san_ssh_port=constants.PORT,
|
hpe3par_san_ssh_port=constants.PORT,
|
||||||
ssh_conn_timeout=constants.TIMEOUT)
|
ssh_conn_timeout=constants.TIMEOUT)
|
||||||
|
|
||||||
def test_mediator_no_client(self):
|
def test_mediator_no_client(self):
|
||||||
"""Test missing hp3parclient error."""
|
"""Test missing hpe3parclient error."""
|
||||||
|
|
||||||
self.mock_object(hp3parmediator.HP3ParMediator, 'no_client', None)
|
self.mock_object(hpe3parmediator.HPE3ParMediator, 'no_client', None)
|
||||||
|
|
||||||
self.assertRaises(exception.HP3ParInvalidClient,
|
self.assertRaises(exception.HPE3ParInvalidClient,
|
||||||
self.mediator.do_setup)
|
self.mediator.do_setup)
|
||||||
|
|
||||||
def test_mediator_setup_client_init_error(self):
|
def test_mediator_setup_client_init_error(self):
|
||||||
@ -154,7 +154,7 @@ class HP3ParMediatorTestCase(test.TestCase):
|
|||||||
port=constants.PORT,
|
port=constants.PORT,
|
||||||
conn_timeout=constants.TIMEOUT),
|
conn_timeout=constants.TIMEOUT),
|
||||||
mock.call.getWsApiVersion(),
|
mock.call.getWsApiVersion(),
|
||||||
mock.call.debug_rest(constants.EXPECTED_HP_DEBUG)
|
mock.call.debug_rest(constants.EXPECTED_HPE_DEBUG)
|
||||||
]
|
]
|
||||||
self.mock_client.assert_has_calls(expected_calls)
|
self.mock_client.assert_has_calls(expected_calls)
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ class HP3ParMediatorTestCase(test.TestCase):
|
|||||||
"""Test exception during logout."""
|
"""Test exception during logout."""
|
||||||
self.init_mediator()
|
self.init_mediator()
|
||||||
|
|
||||||
mock_log = self.mock_object(hp3parmediator, 'LOG')
|
mock_log = self.mock_object(hpe3parmediator, 'LOG')
|
||||||
fake_exception = constants.FAKE_EXCEPTION
|
fake_exception = constants.FAKE_EXCEPTION
|
||||||
self.mock_client.http.unauthenticate.side_effect = fake_exception
|
self.mock_client.http.unauthenticate.side_effect = fake_exception
|
||||||
|
|
||||||
@ -189,21 +189,21 @@ class HP3ParMediatorTestCase(test.TestCase):
|
|||||||
def test_mediator_client_version_unsupported(self):
|
def test_mediator_client_version_unsupported(self):
|
||||||
"""Try a client with version less than minimum."""
|
"""Try a client with version less than minimum."""
|
||||||
|
|
||||||
self.hp3parclient = sys.modules['hp3parclient']
|
self.hpe3parclient = sys.modules['hpe3parclient']
|
||||||
self.hp3parclient.version_tuple = (CLIENT_VERSION_MIN_OK[0],
|
self.hpe3parclient.version_tuple = (CLIENT_VERSION_MIN_OK[0],
|
||||||
CLIENT_VERSION_MIN_OK[1],
|
CLIENT_VERSION_MIN_OK[1],
|
||||||
CLIENT_VERSION_MIN_OK[2] - 1)
|
CLIENT_VERSION_MIN_OK[2] - 1)
|
||||||
self.assertRaises(exception.HP3ParInvalidClient,
|
self.assertRaises(exception.HPE3ParInvalidClient,
|
||||||
self.init_mediator)
|
self.init_mediator)
|
||||||
|
|
||||||
def test_mediator_client_version_supported(self):
|
def test_mediator_client_version_supported(self):
|
||||||
"""Try a client with a version greater than the minimum."""
|
"""Try a client with a version greater than the minimum."""
|
||||||
|
|
||||||
# The setup success already tests the min version. Try version > min.
|
# The setup success already tests the min version. Try version > min.
|
||||||
self.hp3parclient = sys.modules['hp3parclient']
|
self.hpe3parclient = sys.modules['hpe3parclient']
|
||||||
self.hp3parclient.version_tuple = (CLIENT_VERSION_MIN_OK[0],
|
self.hpe3parclient.version_tuple = (CLIENT_VERSION_MIN_OK[0],
|
||||||
CLIENT_VERSION_MIN_OK[1],
|
CLIENT_VERSION_MIN_OK[1],
|
||||||
CLIENT_VERSION_MIN_OK[2] + 1)
|
CLIENT_VERSION_MIN_OK[2] + 1)
|
||||||
self.init_mediator()
|
self.init_mediator()
|
||||||
expected_calls = [
|
expected_calls = [
|
||||||
mock.call.setSSHOptions(constants.EXPECTED_IP_1234,
|
mock.call.setSSHOptions(constants.EXPECTED_IP_1234,
|
||||||
@ -212,7 +212,7 @@ class HP3ParMediatorTestCase(test.TestCase):
|
|||||||
port=constants.PORT,
|
port=constants.PORT,
|
||||||
conn_timeout=constants.TIMEOUT),
|
conn_timeout=constants.TIMEOUT),
|
||||||
mock.call.getWsApiVersion(),
|
mock.call.getWsApiVersion(),
|
||||||
mock.call.debug_rest(constants.EXPECTED_HP_DEBUG)
|
mock.call.debug_rest(constants.EXPECTED_HPE_DEBUG)
|
||||||
]
|
]
|
||||||
self.mock_client.assert_has_calls(expected_calls)
|
self.mock_client.assert_has_calls(expected_calls)
|
||||||
|
|
||||||
@ -251,7 +251,7 @@ class HP3ParMediatorTestCase(test.TestCase):
|
|||||||
createfshare_kwargs['clientip'] = '127.0.0.1'
|
createfshare_kwargs['clientip'] = '127.0.0.1'
|
||||||
|
|
||||||
# Options from extra-specs.
|
# Options from extra-specs.
|
||||||
opt_string = extra_specs.get('hp3par:nfs_options', [])
|
opt_string = extra_specs.get('hpe3par:nfs_options', [])
|
||||||
opt_list = opt_string.split(',')
|
opt_list = opt_string.split(',')
|
||||||
# Options that the mediator adds.
|
# Options that the mediator adds.
|
||||||
nfs_options = ['rw', 'no_root_squash', 'insecure']
|
nfs_options = ['rw', 'no_root_squash', 'insecure']
|
||||||
@ -282,18 +282,14 @@ class HP3ParMediatorTestCase(test.TestCase):
|
|||||||
else:
|
else:
|
||||||
createfshare_kwargs['allowip'] = '127.0.0.1'
|
createfshare_kwargs['allowip'] = '127.0.0.1'
|
||||||
|
|
||||||
if client_version < hp3parmediator.MIN_SMB_CA_VERSION:
|
smb_opts = (hpe3parmediator.ACCESS_BASED_ENUM,
|
||||||
smb_opts = (hp3parmediator.ACCESS_BASED_ENUM,
|
hpe3parmediator.CONTINUOUS_AVAIL,
|
||||||
hp3parmediator.CACHE)
|
hpe3parmediator.CACHE)
|
||||||
else:
|
|
||||||
smb_opts = (hp3parmediator.ACCESS_BASED_ENUM,
|
|
||||||
hp3parmediator.CONTINUOUS_AVAIL,
|
|
||||||
hp3parmediator.CACHE)
|
|
||||||
|
|
||||||
for smb_opt in smb_opts:
|
for smb_opt in smb_opts:
|
||||||
opt_value = extra_specs.get('hp3par:smb_%s' % smb_opt)
|
opt_value = extra_specs.get('hpe3par:smb_%s' % smb_opt)
|
||||||
if opt_value:
|
if opt_value:
|
||||||
opt_key = hp3parmediator.SMB_EXTRA_SPECS_MAP[smb_opt]
|
opt_key = hpe3parmediator.SMB_EXTRA_SPECS_MAP[smb_opt]
|
||||||
createfshare_kwargs[opt_key] = opt_value
|
createfshare_kwargs[opt_key] = opt_value
|
||||||
|
|
||||||
expected_calls = [
|
expected_calls = [
|
||||||
@ -320,25 +316,19 @@ class HP3ParMediatorTestCase(test.TestCase):
|
|||||||
def _build_smb_extra_specs(**kwargs):
|
def _build_smb_extra_specs(**kwargs):
|
||||||
extra_specs = {'driver_handles_share_servers': False}
|
extra_specs = {'driver_handles_share_servers': False}
|
||||||
for k, v in kwargs.items():
|
for k, v in kwargs.items():
|
||||||
extra_specs['hp3par:smb_%s' % k] = v
|
extra_specs['hpe3par:smb_%s' % k] = v
|
||||||
return extra_specs
|
return extra_specs
|
||||||
|
|
||||||
@ddt.data(((3, 2, 1), None, None, None),
|
@ddt.data(((4, 0, 0), None, None, None),
|
||||||
((3, 2, 1), 'true', None, None),
|
((4, 0, 0), 'true', None, None),
|
||||||
((3, 2, 1), None, 'false', None),
|
((4, 0, 0), None, 'false', None),
|
||||||
((3, 2, 1), None, 'false', None),
|
((4, 0, 0), None, 'false', None),
|
||||||
((3, 2, 1), None, None, 'optimized'),
|
((4, 0, 0), None, None, 'optimized'),
|
||||||
((3, 2, 1), 'true', 'false', 'optimized'),
|
((4, 0, 0), 'true', 'false', 'optimized'))
|
||||||
((3, 2, 2), None, None, None),
|
|
||||||
((3, 2, 2), 'true', None, None),
|
|
||||||
((3, 2, 2), None, 'false', None),
|
|
||||||
((3, 2, 2), None, 'false', None),
|
|
||||||
((3, 2, 2), None, None, 'optimized'),
|
|
||||||
((3, 2, 2), 'true', 'false', 'optimized'))
|
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_mediator_create_cifs_share(self, client_version, abe, ca, cache):
|
def test_mediator_create_cifs_share(self, client_version, abe, ca, cache):
|
||||||
self.hp3parclient = sys.modules['hp3parclient']
|
self.hpe3parclient = sys.modules['hpe3parclient']
|
||||||
self.hp3parclient.version_tuple = client_version
|
self.hpe3parclient.version_tuple = client_version
|
||||||
self.init_mediator()
|
self.init_mediator()
|
||||||
|
|
||||||
self.mock_client.getfshare.return_value = {
|
self.mock_client.getfshare.return_value = {
|
||||||
@ -384,7 +374,7 @@ class HP3ParMediatorTestCase(test.TestCase):
|
|||||||
def test_mediator_create_nfs_share_bad_options(self, nfs_options):
|
def test_mediator_create_nfs_share_bad_options(self, nfs_options):
|
||||||
self.init_mediator()
|
self.init_mediator()
|
||||||
|
|
||||||
extra_specs = {'hp3par:nfs_options': nfs_options}
|
extra_specs = {'hpe3par:nfs_options': nfs_options}
|
||||||
|
|
||||||
self.assertRaises(exception.InvalidInput,
|
self.assertRaises(exception.InvalidInput,
|
||||||
self.mediator.create_share,
|
self.mediator.create_share,
|
||||||
@ -411,7 +401,7 @@ class HP3ParMediatorTestCase(test.TestCase):
|
|||||||
|
|
||||||
self.mock_client.getfsquota.return_value = constants.GET_FSQUOTA
|
self.mock_client.getfsquota.return_value = constants.GET_FSQUOTA
|
||||||
|
|
||||||
extra_specs = {'hp3par:nfs_options': nfs_options}
|
extra_specs = {'hpe3par:nfs_options': nfs_options}
|
||||||
|
|
||||||
location = self.mediator.create_share(constants.EXPECTED_PROJECT_ID,
|
location = self.mediator.create_share(constants.EXPECTED_PROJECT_ID,
|
||||||
constants.EXPECTED_SHARE_ID,
|
constants.EXPECTED_SHARE_ID,
|
||||||
@ -424,7 +414,7 @@ class HP3ParMediatorTestCase(test.TestCase):
|
|||||||
self.assertEqual(constants.EXPECTED_SHARE_PATH, location)
|
self.assertEqual(constants.EXPECTED_SHARE_PATH, location)
|
||||||
|
|
||||||
expected_calls = self.get_expected_calls_for_create_share(
|
expected_calls = self.get_expected_calls_for_create_share(
|
||||||
hp3parmediator.MIN_CLIENT_VERSION,
|
hpe3parmediator.MIN_CLIENT_VERSION,
|
||||||
constants.EXPECTED_FPG,
|
constants.EXPECTED_FPG,
|
||||||
constants.EXPECTED_VFS,
|
constants.EXPECTED_VFS,
|
||||||
constants.NFS.lower(),
|
constants.NFS.lower(),
|
||||||
@ -853,7 +843,7 @@ class HP3ParMediatorTestCase(test.TestCase):
|
|||||||
# startfsnapclean exception (logged, not raised)
|
# startfsnapclean exception (logged, not raised)
|
||||||
self.mock_client.startfsnapclean.side_effect = Exception(
|
self.mock_client.startfsnapclean.side_effect = Exception(
|
||||||
'startfsnapclean fail.')
|
'startfsnapclean fail.')
|
||||||
mock_log = self.mock_object(hp3parmediator, 'LOG')
|
mock_log = self.mock_object(hpe3parmediator, 'LOG')
|
||||||
|
|
||||||
self.mediator.delete_snapshot(constants.EXPECTED_PROJECT_ID,
|
self.mediator.delete_snapshot(constants.EXPECTED_PROJECT_ID,
|
||||||
constants.EXPECTED_SHARE_ID,
|
constants.EXPECTED_SHARE_ID,
|
||||||
@ -917,10 +907,11 @@ class HP3ParMediatorTestCase(test.TestCase):
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.mock_client.getVolume.return_value = {
|
self.mock_client.getVolume.return_value = {
|
||||||
'provisioningType': hp3parmediator.DEDUPE}
|
'provisioningType': hpe3parmediator.DEDUPE}
|
||||||
|
|
||||||
expected_result = {
|
expected_result = {
|
||||||
'free_capacity_gb': expected_free,
|
'free_capacity_gb': expected_free,
|
||||||
|
'hpe3par_flash_cache': False,
|
||||||
'hp3par_flash_cache': False,
|
'hp3par_flash_cache': False,
|
||||||
'dedupe': True,
|
'dedupe': True,
|
||||||
'thin_provisioning': True,
|
'thin_provisioning': True,
|
||||||
@ -1163,7 +1154,7 @@ class HP3ParMediatorTestCase(test.TestCase):
|
|||||||
""""Allow user access to nfs share is not supported."""
|
""""Allow user access to nfs share is not supported."""
|
||||||
self.init_mediator()
|
self.init_mediator()
|
||||||
|
|
||||||
self.assertRaises(exception.HP3ParInvalid,
|
self.assertRaises(exception.HPE3ParInvalid,
|
||||||
self.mediator.allow_access,
|
self.mediator.allow_access,
|
||||||
constants.EXPECTED_PROJECT_ID,
|
constants.EXPECTED_PROJECT_ID,
|
||||||
constants.EXPECTED_SHARE_ID,
|
constants.EXPECTED_SHARE_ID,
|
||||||
@ -1207,13 +1198,13 @@ class HP3ParMediatorTestCase(test.TestCase):
|
|||||||
def test_other_protocol(self, protocols, expected_other):
|
def test_other_protocol(self, protocols, expected_other):
|
||||||
for protocol in protocols:
|
for protocol in protocols:
|
||||||
self.assertEqual(expected_other,
|
self.assertEqual(expected_other,
|
||||||
hp3parmediator.HP3ParMediator().other_protocol(
|
hpe3parmediator.HPE3ParMediator().other_protocol(
|
||||||
protocol))
|
protocol))
|
||||||
|
|
||||||
@ddt.data('', 'bogus')
|
@ddt.data('', 'bogus')
|
||||||
def test_other_protocol_exception(self, protocol):
|
def test_other_protocol_exception(self, protocol):
|
||||||
self.assertRaises(exception.InvalidInput,
|
self.assertRaises(exception.InvalidInput,
|
||||||
hp3parmediator.HP3ParMediator().other_protocol,
|
hpe3parmediator.HPE3ParMediator().other_protocol,
|
||||||
protocol)
|
protocol)
|
||||||
|
|
||||||
@ddt.data(('osf-uid', None, 'osf-uid'),
|
@ddt.data(('osf-uid', None, 'osf-uid'),
|
||||||
@ -1223,7 +1214,7 @@ class HP3ParMediatorTestCase(test.TestCase):
|
|||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_ensure_prefix(self, uid, protocol, expected):
|
def test_ensure_prefix(self, uid, protocol, expected):
|
||||||
self.assertEqual(expected,
|
self.assertEqual(expected,
|
||||||
hp3parmediator.HP3ParMediator().ensure_prefix(
|
hpe3parmediator.HPE3ParMediator().ensure_prefix(
|
||||||
uid, protocol=protocol))
|
uid, protocol=protocol))
|
||||||
|
|
||||||
def test_find_fstore_search(self):
|
def test_find_fstore_search(self):
|
Loading…
Reference in New Issue
Block a user